~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/apiserver/proxyupdater/proxyupdater.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2016 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package proxyupdater
 
5
 
 
6
import (
 
7
        "strings"
 
8
 
 
9
        "github.com/juju/juju/apiserver/common"
 
10
        "github.com/juju/juju/apiserver/facade"
 
11
        "github.com/juju/juju/apiserver/params"
 
12
        "github.com/juju/juju/environs/config"
 
13
        "github.com/juju/juju/network"
 
14
        "github.com/juju/juju/state"
 
15
        "github.com/juju/juju/state/watcher"
 
16
        "github.com/juju/utils/proxy"
 
17
        "github.com/juju/utils/set"
 
18
        "gopkg.in/juju/names.v2"
 
19
)
 
20
 
 
21
// Backend defines the state methods this facade needs, so they can be
 
22
// mocked for testing.
 
23
type Backend interface {
 
24
        ModelConfig() (*config.Config, error)
 
25
        APIHostPorts() ([][]network.HostPort, error)
 
26
        WatchAPIHostPorts() state.NotifyWatcher
 
27
        WatchForModelConfigChanges() state.NotifyWatcher
 
28
}
 
29
 
 
30
type ProxyUpdaterAPI struct {
 
31
        backend    Backend
 
32
        resources  facade.Resources
 
33
        authorizer facade.Authorizer
 
34
}
 
35
 
 
36
// NewAPIWithBacking creates a new server-side API facade with the given Backing.
 
37
func NewAPIWithBacking(st Backend, resources facade.Resources, authorizer facade.Authorizer) (*ProxyUpdaterAPI, error) {
 
38
        if !(authorizer.AuthMachineAgent() || authorizer.AuthUnitAgent()) {
 
39
                return &ProxyUpdaterAPI{}, common.ErrPerm
 
40
        }
 
41
        return &ProxyUpdaterAPI{
 
42
                backend:    st,
 
43
                resources:  resources,
 
44
                authorizer: authorizer,
 
45
        }, nil
 
46
}
 
47
 
 
48
func (api *ProxyUpdaterAPI) oneWatch() params.NotifyWatchResult {
 
49
        var result params.NotifyWatchResult
 
50
 
 
51
        watch := common.NewMultiNotifyWatcher(
 
52
                api.backend.WatchForModelConfigChanges(),
 
53
                api.backend.WatchAPIHostPorts())
 
54
 
 
55
        if _, ok := <-watch.Changes(); ok {
 
56
                result = params.NotifyWatchResult{
 
57
                        NotifyWatcherId: api.resources.Register(watch),
 
58
                }
 
59
        } else {
 
60
                result.Error = common.ServerError(watcher.EnsureErr(watch))
 
61
        }
 
62
        return result
 
63
}
 
64
 
 
65
// WatchForProxyConfigAndAPIHostPortChanges watches for cleanups to be perfomed in state
 
66
func (api *ProxyUpdaterAPI) WatchForProxyConfigAndAPIHostPortChanges(args params.Entities) params.NotifyWatchResults {
 
67
        results := params.NotifyWatchResults{
 
68
                Results: make([]params.NotifyWatchResult, len(args.Entities)),
 
69
        }
 
70
        errors, _ := api.authEntities(args)
 
71
 
 
72
        for i := range args.Entities {
 
73
                if errors.Results[i].Error == nil {
 
74
                        results.Results[i] = api.oneWatch()
 
75
                } else {
 
76
                        results.Results[i].Error = errors.Results[i].Error
 
77
                }
 
78
        }
 
79
 
 
80
        return results
 
81
}
 
82
 
 
83
func proxyUtilsSettingsToProxySettingsParam(settings proxy.Settings) params.ProxyConfig {
 
84
        return params.ProxyConfig{
 
85
                HTTP:    settings.Http,
 
86
                HTTPS:   settings.Https,
 
87
                FTP:     settings.Ftp,
 
88
                NoProxy: settings.NoProxy,
 
89
        }
 
90
}
 
91
 
 
92
func (api *ProxyUpdaterAPI) authEntities(args params.Entities) (params.ErrorResults, bool) {
 
93
        result := params.ErrorResults{
 
94
                Results: make([]params.ErrorResult, len(args.Entities)),
 
95
        }
 
96
 
 
97
        var ok bool
 
98
 
 
99
        for i, entity := range args.Entities {
 
100
                tag, err := names.ParseTag(entity.Tag)
 
101
                if err != nil {
 
102
                        result.Results[i].Error = common.ServerError(common.ErrPerm)
 
103
                        continue
 
104
                }
 
105
                err = common.ErrPerm
 
106
                if !api.authorizer.AuthOwner(tag) {
 
107
                        result.Results[i].Error = common.ServerError(err)
 
108
                        continue
 
109
                }
 
110
                ok = true
 
111
        }
 
112
        return result, ok
 
113
}
 
114
 
 
115
func (api *ProxyUpdaterAPI) proxyConfig() params.ProxyConfigResult {
 
116
        var result params.ProxyConfigResult
 
117
        env, err := api.backend.ModelConfig()
 
118
        if err != nil {
 
119
                result.Error = common.ServerError(err)
 
120
                return result
 
121
        }
 
122
 
 
123
        apiHostPorts, err := api.backend.APIHostPorts()
 
124
        if err != nil {
 
125
                result.Error = common.ServerError(err)
 
126
                return result
 
127
        }
 
128
 
 
129
        result.ProxySettings = proxyUtilsSettingsToProxySettingsParam(env.ProxySettings())
 
130
        result.APTProxySettings = proxyUtilsSettingsToProxySettingsParam(env.AptProxySettings())
 
131
 
 
132
        var noProxy []string
 
133
        if result.ProxySettings.NoProxy != "" {
 
134
                noProxy = strings.Split(result.ProxySettings.NoProxy, ",")
 
135
        }
 
136
 
 
137
        noProxySet := set.NewStrings(noProxy...)
 
138
        for _, host := range apiHostPorts {
 
139
                for _, hp := range host {
 
140
                        noProxySet.Add(hp.Address.Value)
 
141
                }
 
142
        }
 
143
        result.ProxySettings.NoProxy = strings.Join(noProxySet.SortedValues(), ",")
 
144
 
 
145
        return result
 
146
}
 
147
 
 
148
// ProxyConfig returns the proxy settings for the current environment
 
149
func (api *ProxyUpdaterAPI) ProxyConfig(args params.Entities) params.ProxyConfigResults {
 
150
        var result params.ProxyConfigResult
 
151
        errors, ok := api.authEntities(args)
 
152
 
 
153
        if ok {
 
154
                result = api.proxyConfig()
 
155
        }
 
156
 
 
157
        results := params.ProxyConfigResults{
 
158
                Results: make([]params.ProxyConfigResult, len(args.Entities)),
 
159
        }
 
160
        for i := range args.Entities {
 
161
                if errors.Results[i].Error == nil {
 
162
                        results.Results[i] = result
 
163
                }
 
164
                results.Results[i].Error = errors.Results[i].Error
 
165
        }
 
166
 
 
167
        return results
 
168
}