Merge lp:~wallyworld/juju-core/machiner-access-for-uniter into lp:~go-bot/juju-core/trunk
- machiner-access-for-uniter
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | William Reade |
Proposed branch: | lp:~wallyworld/juju-core/machiner-access-for-uniter |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
345 lines (+245/-21) 5 files modified
state/apiserver/common/auth.go (+38/-0) state/apiserver/machine/common_test.go (+7/-7) state/apiserver/machine/machiner.go (+2/-4) state/apiserver/machine/machiner_test.go (+10/-10) state/apiserver/machine/uniter_test.go (+188/-0) |
To merge this branch: | bzr merge lp:~wallyworld/juju-core/machiner-access-for-uniter |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+205290@code.launchpad.net |
Commit message
Description of the change
Allow assigned units read access to machines
This branch allows unit agents to use the machiner
API to get a machine object for their assigned
machine. The server side api looks up the machine
life and the necessary auth function is modified
to allow assigned units as well as the machine
owner.
The implementation is done as a helper function
because a downstream branch also uses it. This
work will be used by the unit agent upgrade worker.
Ian Booth (wallyworld) wrote : | # |
Dimiter Naydenov (dimitern) wrote : | # |
Looks great so far, I have just a few suggestions.
https:/
File state/apiserver
https:/
state/apiserver
provides an AuthFunc which returns true if the caller
I still think this ought to be in the Authorizer interfaces, and should
be called AuthOwnerOrDepl
apiserver/root.go, as the other auth funcs, and it could be simplified
as well (no need to call GetAuthTag and GetAuthEntity, because you have
direct access to both).
https:/
File state/apiserver
https:/
state/apiserver
has read access to the assigned machine for it's unit.
Please put this suite in a separate file, like uniter_test.go.
https:/
state/apiserver
I'd add "machine-0" and "machine-42" to the list of entities, just to be
extra careful and check for ErrPerm.
https:/
state/apiserver
Addresses: addresses},
ditto
Ian Booth (wallyworld) wrote : | # |
Please take a look.
https:/
File state/apiserver
https:/
state/apiserver
provides an AuthFunc which returns true if the caller
On 2014/02/10 08:41:29, dimitern wrote:
> I still think this ought to be in the Authorizer interfaces, and
should be
> called AuthOwnerOrDepl
apiserver/root.go,
> as the other auth funcs, and it could be simplified as well (no need
to call
> GetAuthTag and GetAuthEntity, because you have direct access to both).
That doesn't work so well. The OwnerOrDeployed
little involved, and also needs to be implemented properly on the
FakeAuthorizer. It's better to have a common helper function and pass in
the authorizer to use, allowing the OwnerOrDeployed
the primitives offered by the respective authorisers. As an aside, there
a similarly complex bit of auth logic in deployer which could also be
pulled out as a separate function.
https:/
File state/apiserver
https:/
state/apiserver
has read access to the assigned machine for it's unit.
On 2014/02/10 08:41:29, dimitern wrote:
> Please put this suite in a separate file, like uniter_test.go.
Done.
https:/
state/apiserver
On 2014/02/10 08:41:29, dimitern wrote:
> I'd add "machine-0" and "machine-42" to the list of entities, just to
be extra
> careful and check for ErrPerm.
Done.
https:/
state/apiserver
On 2014/02/10 08:41:29, dimitern wrote:
> I'd add "machine-0" and "machine-42" to the list of entities, just to
be extra
> careful and check for ErrPerm.
Done.
https:/
state/apiserver
Addresses: addresses},
On 2014/02/10 08:41:29, dimitern wrote:
> ditto
Done.
https:/
state/apiserver
Addresses: addresses},
On 2014/02/10 08:41:29, dimitern wrote:
> ditto
Done.
Dimiter Naydenov (dimitern) wrote : | # |
The diff is screwed, but otherwise LGTM assuming you made what you said.
William Reade (fwereade) wrote : | # |
On 2014/02/11 09:53:47, dimitern wrote:
> The diff is screwed, but otherwise LGTM assuming you made what you
said.
as discussed live, the upgrader doesn't need changes so not lgtm
Preview Diff
1 | === added file 'state/apiserver/common/auth.go' | |||
2 | --- state/apiserver/common/auth.go 1970-01-01 00:00:00 +0000 | |||
3 | +++ state/apiserver/common/auth.go 2014-02-11 01:14:25 +0000 | |||
4 | @@ -0,0 +1,38 @@ | |||
5 | 1 | // Copyright 2014 Canonical Ltd. | ||
6 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | ||
7 | 3 | |||
8 | 4 | package common | ||
9 | 5 | |||
10 | 6 | import ( | ||
11 | 7 | "fmt" | ||
12 | 8 | |||
13 | 9 | "launchpad.net/juju-core/names" | ||
14 | 10 | "launchpad.net/juju-core/state" | ||
15 | 11 | ) | ||
16 | 12 | |||
17 | 13 | // OwnerOrDeployedUnitAuthFunc provides an AuthFunc which returns true if the caller | ||
18 | 14 | // is the machine owner or a unit agent for a unit which is deployed on the machine. | ||
19 | 15 | func OwnerOrDeployedUnitAuthFunc(authorizer Authorizer) func() (AuthFunc, error) { | ||
20 | 16 | return func() (AuthFunc, error) { | ||
21 | 17 | tag := authorizer.GetAuthTag() | ||
22 | 18 | kind, _, err := names.ParseTag(tag, "") | ||
23 | 19 | if err != nil { | ||
24 | 20 | return nil, err | ||
25 | 21 | } | ||
26 | 22 | if kind == names.MachineTagKind { | ||
27 | 23 | return authorizer.AuthOwner, nil | ||
28 | 24 | } | ||
29 | 25 | unit, ok := authorizer.GetAuthEntity().(*state.Unit) | ||
30 | 26 | if !ok { | ||
31 | 27 | return nil, fmt.Errorf("%v is not a unit", authorizer.GetAuthTag()) | ||
32 | 28 | } | ||
33 | 29 | id, err := unit.AssignedMachineId() | ||
34 | 30 | if err != nil { | ||
35 | 31 | return nil, err | ||
36 | 32 | } | ||
37 | 33 | return func(tag string) bool { | ||
38 | 34 | assignedMachineTag := names.MachineTag(id) | ||
39 | 35 | return tag == assignedMachineTag | ||
40 | 36 | }, nil | ||
41 | 37 | } | ||
42 | 38 | } | ||
43 | 0 | 39 | ||
44 | === modified file 'state/apiserver/machine/common_test.go' | |||
45 | --- state/apiserver/machine/common_test.go 2014-01-22 19:28:08 +0000 | |||
46 | +++ state/apiserver/machine/common_test.go 2014-02-11 01:14:25 +0000 | |||
47 | @@ -7,6 +7,8 @@ | |||
48 | 7 | 7 | ||
49 | 8 | "launchpad.net/juju-core/juju/testing" | 8 | "launchpad.net/juju-core/juju/testing" |
50 | 9 | "launchpad.net/juju-core/state" | 9 | "launchpad.net/juju-core/state" |
51 | 10 | "launchpad.net/juju-core/state/apiserver/common" | ||
52 | 11 | "launchpad.net/juju-core/state/apiserver/machine" | ||
53 | 10 | apiservertesting "launchpad.net/juju-core/state/apiserver/testing" | 12 | apiservertesting "launchpad.net/juju-core/state/apiserver/testing" |
54 | 11 | coretesting "launchpad.net/juju-core/testing" | 13 | coretesting "launchpad.net/juju-core/testing" |
55 | 12 | ) | 14 | ) |
56 | @@ -19,6 +21,8 @@ | |||
57 | 19 | testing.JujuConnSuite | 21 | testing.JujuConnSuite |
58 | 20 | 22 | ||
59 | 21 | authorizer apiservertesting.FakeAuthorizer | 23 | authorizer apiservertesting.FakeAuthorizer |
60 | 24 | resources *common.Resources | ||
61 | 25 | machiner *machine.MachinerAPI | ||
62 | 22 | 26 | ||
63 | 23 | machine0 *state.Machine | 27 | machine0 *state.Machine |
64 | 24 | machine1 *state.Machine | 28 | machine1 *state.Machine |
65 | @@ -34,11 +38,7 @@ | |||
66 | 34 | s.machine1, err = s.State.AddMachine("quantal", state.JobHostUnits) | 38 | s.machine1, err = s.State.AddMachine("quantal", state.JobHostUnits) |
67 | 35 | c.Assert(err, gc.IsNil) | 39 | c.Assert(err, gc.IsNil) |
68 | 36 | 40 | ||
76 | 37 | // Create a FakeAuthorizer so we can check permissions, | 41 | // Create the resource registry separately to track invocations to |
77 | 38 | // set up assuming machine 1 has logged in. | 42 | // Register. |
78 | 39 | s.authorizer = apiservertesting.FakeAuthorizer{ | 43 | s.resources = common.NewResources() |
72 | 40 | Tag: s.machine1.Tag(), | ||
73 | 41 | LoggedIn: true, | ||
74 | 42 | MachineAgent: true, | ||
75 | 43 | } | ||
79 | 44 | } | 44 | } |
80 | 45 | 45 | ||
81 | === modified file 'state/apiserver/machine/machiner.go' | |||
82 | --- state/apiserver/machine/machiner.go 2014-01-20 21:29:08 +0000 | |||
83 | +++ state/apiserver/machine/machiner.go 2014-02-11 01:14:25 +0000 | |||
84 | @@ -27,15 +27,13 @@ | |||
85 | 27 | 27 | ||
86 | 28 | // NewMachinerAPI creates a new instance of the Machiner API. | 28 | // NewMachinerAPI creates a new instance of the Machiner API. |
87 | 29 | func NewMachinerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*MachinerAPI, error) { | 29 | func NewMachinerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*MachinerAPI, error) { |
89 | 30 | if !authorizer.AuthMachineAgent() { | 30 | if !authorizer.AuthMachineAgent() && !authorizer.AuthUnitAgent() { |
90 | 31 | return nil, common.ErrPerm | 31 | return nil, common.ErrPerm |
91 | 32 | } | 32 | } |
92 | 33 | getCanModify := func() (common.AuthFunc, error) { | 33 | getCanModify := func() (common.AuthFunc, error) { |
93 | 34 | return authorizer.AuthOwner, nil | 34 | return authorizer.AuthOwner, nil |
94 | 35 | } | 35 | } |
98 | 36 | getCanRead := func() (common.AuthFunc, error) { | 36 | getCanRead := common.OwnerOrDeployedUnitAuthFunc(authorizer) |
96 | 37 | return authorizer.AuthOwner, nil | ||
97 | 38 | } | ||
99 | 39 | return &MachinerAPI{ | 37 | return &MachinerAPI{ |
100 | 40 | LifeGetter: common.NewLifeGetter(st, getCanRead), | 38 | LifeGetter: common.NewLifeGetter(st, getCanRead), |
101 | 41 | StatusSetter: common.NewStatusSetter(st, getCanModify), | 39 | StatusSetter: common.NewStatusSetter(st, getCanModify), |
102 | 42 | 40 | ||
103 | === modified file 'state/apiserver/machine/machiner_test.go' | |||
104 | --- state/apiserver/machine/machiner_test.go 2014-01-20 21:00:43 +0000 | |||
105 | +++ state/apiserver/machine/machiner_test.go 2014-02-11 01:14:25 +0000 | |||
106 | @@ -9,7 +9,6 @@ | |||
107 | 9 | "launchpad.net/juju-core/instance" | 9 | "launchpad.net/juju-core/instance" |
108 | 10 | "launchpad.net/juju-core/state" | 10 | "launchpad.net/juju-core/state" |
109 | 11 | "launchpad.net/juju-core/state/api/params" | 11 | "launchpad.net/juju-core/state/api/params" |
110 | 12 | "launchpad.net/juju-core/state/apiserver/common" | ||
111 | 13 | "launchpad.net/juju-core/state/apiserver/machine" | 12 | "launchpad.net/juju-core/state/apiserver/machine" |
112 | 14 | apiservertesting "launchpad.net/juju-core/state/apiserver/testing" | 13 | apiservertesting "launchpad.net/juju-core/state/apiserver/testing" |
113 | 15 | statetesting "launchpad.net/juju-core/state/testing" | 14 | statetesting "launchpad.net/juju-core/state/testing" |
114 | @@ -17,9 +16,6 @@ | |||
115 | 17 | 16 | ||
116 | 18 | type machinerSuite struct { | 17 | type machinerSuite struct { |
117 | 19 | commonSuite | 18 | commonSuite |
118 | 20 | |||
119 | 21 | resources *common.Resources | ||
120 | 22 | machiner *machine.MachinerAPI | ||
121 | 23 | } | 19 | } |
122 | 24 | 20 | ||
123 | 25 | var _ = gc.Suite(&machinerSuite{}) | 21 | var _ = gc.Suite(&machinerSuite{}) |
124 | @@ -27,18 +23,22 @@ | |||
125 | 27 | func (s *machinerSuite) SetUpTest(c *gc.C) { | 23 | func (s *machinerSuite) SetUpTest(c *gc.C) { |
126 | 28 | s.commonSuite.SetUpTest(c) | 24 | s.commonSuite.SetUpTest(c) |
127 | 29 | 25 | ||
132 | 30 | // Create the resource registry separately to track invocations to | 26 | // Create a FakeAuthorizer so we can check permissions, |
133 | 31 | // Register. | 27 | // set up assuming machine 1 has logged in. |
134 | 32 | s.resources = common.NewResources() | 28 | s.authorizer = apiservertesting.FakeAuthorizer{ |
135 | 33 | 29 | Tag: s.machine1.Tag(), | |
136 | 30 | LoggedIn: true, | ||
137 | 31 | MachineAgent: true, | ||
138 | 32 | } | ||
139 | 33 | var err error | ||
140 | 34 | // Create a machiner API for machine 1. | 34 | // Create a machiner API for machine 1. |
142 | 35 | machiner, err := machine.NewMachinerAPI( | 35 | s.machiner, err = machine.NewMachinerAPI( |
143 | 36 | s.State, | 36 | s.State, |
144 | 37 | s.resources, | 37 | s.resources, |
145 | 38 | s.authorizer, | 38 | s.authorizer, |
146 | 39 | ) | 39 | ) |
147 | 40 | c.Assert(err, gc.IsNil) | 40 | c.Assert(err, gc.IsNil) |
149 | 41 | s.machiner = machiner | 41 | c.Assert(s.machiner, gc.NotNil) |
150 | 42 | } | 42 | } |
151 | 43 | 43 | ||
152 | 44 | func (s *machinerSuite) TestMachinerFailsWithNonMachineAgentUser(c *gc.C) { | 44 | func (s *machinerSuite) TestMachinerFailsWithNonMachineAgentUser(c *gc.C) { |
153 | 45 | 45 | ||
154 | === added file 'state/apiserver/machine/uniter_test.go' | |||
155 | --- state/apiserver/machine/uniter_test.go 1970-01-01 00:00:00 +0000 | |||
156 | +++ state/apiserver/machine/uniter_test.go 2014-02-11 01:14:25 +0000 | |||
157 | @@ -0,0 +1,188 @@ | |||
158 | 1 | // Copyright 2013 Canonical Ltd. | ||
159 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | ||
160 | 3 | |||
161 | 4 | package machine_test | ||
162 | 5 | |||
163 | 6 | import ( | ||
164 | 7 | gc "launchpad.net/gocheck" | ||
165 | 8 | |||
166 | 9 | "launchpad.net/juju-core/instance" | ||
167 | 10 | "launchpad.net/juju-core/state" | ||
168 | 11 | "launchpad.net/juju-core/state/api/params" | ||
169 | 12 | "launchpad.net/juju-core/state/apiserver/machine" | ||
170 | 13 | apiservertesting "launchpad.net/juju-core/state/apiserver/testing" | ||
171 | 14 | statetesting "launchpad.net/juju-core/state/testing" | ||
172 | 15 | ) | ||
173 | 16 | |||
174 | 17 | // Test that a unit agent has read access to the assigned machine for it's unit. | ||
175 | 18 | type uniterSuite struct { | ||
176 | 19 | commonSuite | ||
177 | 20 | } | ||
178 | 21 | |||
179 | 22 | var _ = gc.Suite(&uniterSuite{}) | ||
180 | 23 | |||
181 | 24 | func (s *uniterSuite) SetUpTest(c *gc.C) { | ||
182 | 25 | s.commonSuite.SetUpTest(c) | ||
183 | 26 | |||
184 | 27 | // Deploy a unit to machine 1. | ||
185 | 28 | mysql := s.AddTestingService(c, "mysql", s.AddTestingCharm(c, "mysql")) | ||
186 | 29 | mysql0, err := mysql.AddUnit() | ||
187 | 30 | c.Assert(err, gc.IsNil) | ||
188 | 31 | err = mysql0.AssignToMachine(s.machine1) | ||
189 | 32 | c.Assert(err, gc.IsNil) | ||
190 | 33 | // Create another unit not on machine 1. | ||
191 | 34 | _, err = mysql.AddUnit() | ||
192 | 35 | c.Assert(err, gc.IsNil) | ||
193 | 36 | |||
194 | 37 | // Create a FakeAuthorizer so we can check permissions, | ||
195 | 38 | // set up assuming mysql/0 has logged in. | ||
196 | 39 | s.authorizer = apiservertesting.FakeAuthorizer{ | ||
197 | 40 | LoggedIn: true, | ||
198 | 41 | UnitAgent: true, | ||
199 | 42 | Tag: mysql0.Tag(), | ||
200 | 43 | Entity: mysql0, | ||
201 | 44 | } | ||
202 | 45 | |||
203 | 46 | // Create a machiner API for mysql/0. | ||
204 | 47 | s.machiner, err = machine.NewMachinerAPI( | ||
205 | 48 | s.State, | ||
206 | 49 | s.resources, | ||
207 | 50 | s.authorizer, | ||
208 | 51 | ) | ||
209 | 52 | c.Assert(err, gc.IsNil) | ||
210 | 53 | c.Assert(s.machiner, gc.NotNil) | ||
211 | 54 | } | ||
212 | 55 | |||
213 | 56 | func (s *uniterSuite) TestMachinerFailsWithNonUnitAgentUser(c *gc.C) { | ||
214 | 57 | anAuthorizer := s.authorizer | ||
215 | 58 | anAuthorizer.UnitAgent = false | ||
216 | 59 | aMachiner, err := machine.NewMachinerAPI(s.State, s.resources, anAuthorizer) | ||
217 | 60 | c.Assert(err, gc.NotNil) | ||
218 | 61 | c.Assert(aMachiner, gc.IsNil) | ||
219 | 62 | c.Assert(err, gc.ErrorMatches, "permission denied") | ||
220 | 63 | } | ||
221 | 64 | |||
222 | 65 | func (s *uniterSuite) TestSetStatusFails(c *gc.C) { | ||
223 | 66 | err := s.machine1.SetStatus(params.StatusStarted, "foo", nil) | ||
224 | 67 | c.Assert(err, gc.IsNil) | ||
225 | 68 | |||
226 | 69 | args := params.SetStatus{ | ||
227 | 70 | Entities: []params.SetEntityStatus{ | ||
228 | 71 | {Tag: "machine-1", Status: params.StatusError, Info: "not really"}, | ||
229 | 72 | }} | ||
230 | 73 | result, err := s.machiner.SetStatus(args) | ||
231 | 74 | c.Assert(err, gc.IsNil) | ||
232 | 75 | c.Assert(result, gc.DeepEquals, params.ErrorResults{ | ||
233 | 76 | Results: []params.ErrorResult{ | ||
234 | 77 | {apiservertesting.ErrUnauthorized}, | ||
235 | 78 | }, | ||
236 | 79 | }) | ||
237 | 80 | |||
238 | 81 | // Verify machine 1 - no change. | ||
239 | 82 | status, info, _, err := s.machine1.Status() | ||
240 | 83 | c.Assert(err, gc.IsNil) | ||
241 | 84 | c.Assert(status, gc.Equals, params.StatusStarted) | ||
242 | 85 | c.Assert(info, gc.Equals, "foo") | ||
243 | 86 | } | ||
244 | 87 | |||
245 | 88 | func (s *uniterSuite) TestLife(c *gc.C) { | ||
246 | 89 | c.Assert(s.machine1.Life(), gc.Equals, state.Alive) | ||
247 | 90 | |||
248 | 91 | args := params.Entities{Entities: []params.Entity{ | ||
249 | 92 | {Tag: "machine-1"}, | ||
250 | 93 | {Tag: "machine-0"}, | ||
251 | 94 | {Tag: "machine-42"}, | ||
252 | 95 | }} | ||
253 | 96 | result, err := s.machiner.Life(args) | ||
254 | 97 | c.Assert(err, gc.IsNil) | ||
255 | 98 | c.Assert(result, gc.DeepEquals, params.LifeResults{ | ||
256 | 99 | Results: []params.LifeResult{ | ||
257 | 100 | {Life: "alive"}, | ||
258 | 101 | {Error: apiservertesting.ErrUnauthorized}, | ||
259 | 102 | {Error: apiservertesting.ErrUnauthorized}, | ||
260 | 103 | }, | ||
261 | 104 | }) | ||
262 | 105 | } | ||
263 | 106 | |||
264 | 107 | func (s *uniterSuite) TestEnsureDeadFails(c *gc.C) { | ||
265 | 108 | c.Assert(s.machine1.Life(), gc.Equals, state.Alive) | ||
266 | 109 | |||
267 | 110 | args := params.Entities{Entities: []params.Entity{ | ||
268 | 111 | {Tag: "machine-0"}, | ||
269 | 112 | {Tag: "machine-1"}, | ||
270 | 113 | {Tag: "machine-42"}, | ||
271 | 114 | }} | ||
272 | 115 | result, err := s.machiner.EnsureDead(args) | ||
273 | 116 | c.Assert(err, gc.IsNil) | ||
274 | 117 | c.Assert(result, gc.DeepEquals, params.ErrorResults{ | ||
275 | 118 | Results: []params.ErrorResult{ | ||
276 | 119 | {apiservertesting.ErrUnauthorized}, | ||
277 | 120 | {apiservertesting.ErrUnauthorized}, | ||
278 | 121 | {apiservertesting.ErrUnauthorized}, | ||
279 | 122 | }, | ||
280 | 123 | }) | ||
281 | 124 | |||
282 | 125 | err = s.machine1.Refresh() | ||
283 | 126 | c.Assert(err, gc.IsNil) | ||
284 | 127 | c.Assert(s.machine1.Life(), gc.Equals, state.Alive) | ||
285 | 128 | } | ||
286 | 129 | |||
287 | 130 | func (s *uniterSuite) TestSetMachineAddresses(c *gc.C) { | ||
288 | 131 | c.Assert(s.machine0.Addresses(), gc.HasLen, 0) | ||
289 | 132 | c.Assert(s.machine1.Addresses(), gc.HasLen, 0) | ||
290 | 133 | |||
291 | 134 | addresses := []instance.Address{ | ||
292 | 135 | instance.NewAddress("127.0.0.1"), | ||
293 | 136 | instance.NewAddress("8.8.8.8"), | ||
294 | 137 | } | ||
295 | 138 | |||
296 | 139 | args := params.SetMachinesAddresses{MachineAddresses: []params.MachineAddresses{ | ||
297 | 140 | {Tag: "machine-0", Addresses: addresses}, | ||
298 | 141 | {Tag: "machine-1", Addresses: addresses}, | ||
299 | 142 | {Tag: "machine-42", Addresses: addresses}, | ||
300 | 143 | }} | ||
301 | 144 | |||
302 | 145 | result, err := s.machiner.SetMachineAddresses(args) | ||
303 | 146 | c.Assert(err, gc.IsNil) | ||
304 | 147 | c.Assert(result, gc.DeepEquals, params.ErrorResults{ | ||
305 | 148 | Results: []params.ErrorResult{ | ||
306 | 149 | {apiservertesting.ErrUnauthorized}, | ||
307 | 150 | {apiservertesting.ErrUnauthorized}, | ||
308 | 151 | {apiservertesting.ErrUnauthorized}, | ||
309 | 152 | }, | ||
310 | 153 | }) | ||
311 | 154 | |||
312 | 155 | err = s.machine1.Refresh() | ||
313 | 156 | c.Assert(err, gc.IsNil) | ||
314 | 157 | c.Assert(s.machine1.MachineAddresses(), gc.HasLen, 0) | ||
315 | 158 | } | ||
316 | 159 | |||
317 | 160 | func (s *uniterSuite) TestWatch(c *gc.C) { | ||
318 | 161 | c.Assert(s.resources.Count(), gc.Equals, 0) | ||
319 | 162 | |||
320 | 163 | args := params.Entities{Entities: []params.Entity{ | ||
321 | 164 | {Tag: "machine-1"}, | ||
322 | 165 | {Tag: "machine-0"}, | ||
323 | 166 | {Tag: "machine-42"}, | ||
324 | 167 | }} | ||
325 | 168 | result, err := s.machiner.Watch(args) | ||
326 | 169 | c.Assert(err, gc.IsNil) | ||
327 | 170 | c.Assert(result, gc.DeepEquals, params.NotifyWatchResults{ | ||
328 | 171 | Results: []params.NotifyWatchResult{ | ||
329 | 172 | {NotifyWatcherId: "1"}, | ||
330 | 173 | {Error: apiservertesting.ErrUnauthorized}, | ||
331 | 174 | {Error: apiservertesting.ErrUnauthorized}, | ||
332 | 175 | }, | ||
333 | 176 | }) | ||
334 | 177 | |||
335 | 178 | // Verify the resource was registered and stop when done | ||
336 | 179 | c.Assert(s.resources.Count(), gc.Equals, 1) | ||
337 | 180 | c.Assert(result.Results[0].NotifyWatcherId, gc.Equals, "1") | ||
338 | 181 | resource := s.resources.Get("1") | ||
339 | 182 | defer statetesting.AssertStop(c, resource) | ||
340 | 183 | |||
341 | 184 | // Check that the Watch has consumed the initial event ("returned" in | ||
342 | 185 | // the Watch call) | ||
343 | 186 | wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) | ||
344 | 187 | wc.AssertNoChange() | ||
345 | 188 | } |
Reviewers: mp+205290_ code.launchpad. net,
Message:
Please take a look.
Description:
Allow assigned units read access to machines
This branch allows unit agents to use the machiner
API to get a machine object for their assigned
machine. The server side api looks up the machine
life and the necessary auth function is modified
to allow assigned units as well as the machine
owner.
The implementation is done as a helper function
because a downstream branch also uses it. This
work will be used by the unit agent upgrade worker.
https:/ /code.launchpad .net/~wallyworl d/juju- core/machiner- access- for-uniter/ +merge/ 205290
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/60920043/
Affected files (+224, -21 lines): /common/ auth.go /machine/ common_ test.go /machine/ machiner. go /machine/ machiner_ test.go
A [revision details]
A state/apiserver
M state/apiserver
M state/apiserver
M state/apiserver