Merge lp:~dimitern/juju-core/350-api-service-deploy-with-networks into lp:~go-bot/juju-core/trunk

Proposed by Dimiter Naydenov
Status: Merged
Approved by: Dimiter Naydenov
Approved revision: no longer in the source branch.
Merged at revision: 2487
Proposed branch: lp:~dimitern/juju-core/350-api-service-deploy-with-networks
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 427 lines (+183/-49)
9 files modified
juju/conn_test.go (+19/-1)
juju/deploy.go (+21/-5)
state/api/client.go (+19/-2)
state/api/params/params.go (+4/-0)
state/apiserver/client/client.go (+15/-6)
state/apiserver/client/client_test.go (+45/-23)
state/apiserver/client/perm_test.go (+12/-0)
state/assign_test.go (+16/-1)
state/unit.go (+32/-11)
To merge this branch: bzr merge lp:~dimitern/juju-core/350-api-service-deploy-with-networks
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+211773@code.launchpad.net

Commit message

state/api: Add Client.ServiceDeployWithNetworks

This adds a new client API call: ServiceDeployWithNetworks,
which works exactly like ServiceDeploy, but takes two extra
arguments: IncludeNetworks and ExcludeNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.

AddUnits is also changed (and its tests) to respect networks
set on the service and pass them through MachineTemplate when
deploying or a new machine or container.

https://codereview.appspot.com/76910044/

R=gz, rogpeppe

Description of the change

state/api: Add Client.ServiceDeployWithNetworks

This adds a new client API call: ServiceDeployWithNetworks,
which works exactly like ServiceDeploy, but takes two extra
arguments: IncludeNetworks and ExcludeNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.

AddUnits is also changed (and its tests) to respect networks
set on the service and pass them through MachineTemplate when
deploying or a new machine or container.

https://codereview.appspot.com/76910044/

To post a comment you must log in.
Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Reviewers: mp+211773_code.launchpad.net,

Message:
Please take a look.

Description:
state/api: Add Client.ServiceDeployWithNetworks

This adds a new client API call: ServiceDeployWithNetworks,
which works exactly like ServiceDeploy, but takes two extra
arguments (required) IncludedNetworks and ExcludedNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.

Right now, the new API does not change the service and/or
machine documents to add the networks, because there's another
branch mgz is doing for that right now.

https://code.launchpad.net/~dimitern/juju-core/350-api-service-deploy-with-networks/+merge/211773

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/76910044/

Affected files (+162, -37 lines):
   A [revision details]
   M juju/deploy.go
   M state/api/client.go
   M state/api/params/params.go
   M state/apiserver/client/client.go
   M state/apiserver/client/client_test.go
   M state/apiserver/client/perm_test.go

Revision history for this message
William Reade (fwereade) wrote :

1) it's hard to approve this without an implementation in the background

2) should we be talking network tags?

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go
File state/apiserver/client/client.go (right):

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go#newcode243
state/apiserver/client/client.go:243: return c.serviceDeploy(&args, nil)
might be nicer to copy args into a ServiceDeployWithNetworks...

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go#newcode256
state/apiserver/client/client.go:256: func (c *Client)
serviceDeploy(args0 *params.ServiceDeploy, args1
*params.ServiceDeployWithNetworks) error {
...and just handle one arg type here?

https://codereview.appspot.com/76910044/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

https://codereview.appspot.com/76910044/diff/20001/state/api/params/params.go
File state/api/params/params.go (right):

https://codereview.appspot.com/76910044/diff/20001/state/api/params/params.go#newcode155
state/api/params/params.go:155: type ServiceDeployWithNetworks struct {
I suggest that instead of making a new set of parameters, we could just
add the networks parameters to ServiceDeploy, and make
ServiceDeployWithNetworks an alias of Deploy.

We can document the new fields as recognised only in 1.18 (1.19? 1.20?)
API servers.

This means that clients that care that the networks fields are
recognised can use ServiceDeployWithNetworks, but existing clients can
continue to use Deploy, and eventually we should be able to deprecate
ServiceDeployWithNetworks.

This adds minimal clutter to the code, and provides the same
functionality AFAICS.

https://codereview.appspot.com/76910044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Please take a look.

https://codereview.appspot.com/76910044/diff/20001/state/api/params/params.go
File state/api/params/params.go (right):

https://codereview.appspot.com/76910044/diff/20001/state/api/params/params.go#newcode155
state/api/params/params.go:155: type ServiceDeployWithNetworks struct {
On 2014/03/20 14:06:23, rog wrote:
> I suggest that instead of making a new set of parameters, we could
just add the
> networks parameters to ServiceDeploy, and make
ServiceDeployWithNetworks an
> alias of Deploy.

> We can document the new fields as recognised only in 1.18 (1.19?
1.20?) API
> servers.

> This means that clients that care that the networks fields are
recognised can
> use ServiceDeployWithNetworks, but existing clients can continue to
use Deploy,
> and eventually we should be able to deprecate
ServiceDeployWithNetworks.

> This adds minimal clutter to the code, and provides the same
functionality
> AFAICS.

Done.

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go
File state/apiserver/client/client.go (right):

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go#newcode243
state/apiserver/client/client.go:243: return c.serviceDeploy(&args, nil)
On 2014/03/20 13:42:50, fwereade wrote:
> might be nicer to copy args into a ServiceDeployWithNetworks...

Done as rog suggested - ServiceDeployWithNetworks as an alias for
ServiceDeploy.

https://codereview.appspot.com/76910044/diff/20001/state/apiserver/client/client.go#newcode256
state/apiserver/client/client.go:256: func (c *Client)
serviceDeploy(args0 *params.ServiceDeploy, args1
*params.ServiceDeployWithNetworks) error {
On 2014/03/20 13:42:50, fwereade wrote:
> ...and just handle one arg type here?

Done differently.

https://codereview.appspot.com/76910044/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

much nicer, thanks.
LGTM with one suggestion below.

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go
File state/apiserver/client/client.go (right):

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go#newcode298
state/apiserver/client/client.go:298: if len(args.IncludedNetworks) == 0
&& len(args.ExcludedNetworks) == 0 {
I'd remove this and make the two commands exactly the same. Then clients
can use this call for all Deploy purposes if they wish.

https://codereview.appspot.com/76910044/

Revision history for this message
John A Meinel (jameinel) wrote :

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go
File state/apiserver/client/client.go (right):

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go#newcode298
state/apiserver/client/client.go:298: if len(args.IncludedNetworks) == 0
&& len(args.ExcludedNetworks) == 0 {
On 2014/03/20 15:45:03, rog wrote:
> I'd remove this and make the two commands exactly the same. Then
clients can use
> this call for all Deploy purposes if they wish.

As William pointed out in IRC, I think the "ideal" would be to have API
versioning and then we'd just have ServiceDeploy that accepts
everything. However, I think lacking that I agree with Roger. I'd rather
have just 1 API that is always called.
(So we effectively have API versioning, just via a clumsy renaming of
the API each time.)

https://codereview.appspot.com/76910044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :

Please take a look.

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go
File state/apiserver/client/client.go (right):

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go#newcode298
state/apiserver/client/client.go:298: if len(args.IncludedNetworks) == 0
&& len(args.ExcludedNetworks) == 0 {
On 2014/03/20 15:45:03, rog wrote:
> I'd remove this and make the two commands exactly the same. Then
clients can use
> this call for all Deploy purposes if they wish.

Done.

https://codereview.appspot.com/76910044/diff/40001/state/apiserver/client/client.go#newcode298
state/apiserver/client/client.go:298: if len(args.IncludedNetworks) == 0
&& len(args.ExcludedNetworks) == 0 {
On 2014/03/20 20:38:22, jameinel wrote:
> On 2014/03/20 15:45:03, rog wrote:
> > I'd remove this and make the two commands exactly the same. Then
clients can
> use
> > this call for all Deploy purposes if they wish.

> As William pointed out in IRC, I think the "ideal" would be to have
API
> versioning and then we'd just have ServiceDeploy that accepts
everything.
> However, I think lacking that I agree with Roger. I'd rather have just
1 API
> that is always called.
> (So we effectively have API versioning, just via a clumsy renaming of
the API
> each time.)

Done as rog suggested. Also, I'm not landing this until mgz's branch
lands. Then I'll integrate the two and drop the related TODOs.

https://codereview.appspot.com/76910044/

Revision history for this message
William Reade (fwereade) wrote :

On 2014/03/20 20:38:21, jameinel wrote:
> As William pointed out in IRC, I think the "ideal" would be to have
API
> versioning and then we'd just have ServiceDeploy that accepts
everything.
> However, I think lacking that I agree with Roger. I'd rather have just
1 API
> that is always called.
> (So we effectively have API versioning, just via a clumsy renaming of
the API
> each time.)

I can bear it on this occasion, but this is only suitable in the
ultra-short-term: it will now look as though the old version supports
networks, even though it doesn't (especially if we start autogenerating
docs etc).

https://codereview.appspot.com/76910044/

Revision history for this message
Dimiter Naydenov (dimitern) wrote :
Revision history for this message
Martin Packman (gz) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'juju/conn_test.go'
2--- juju/conn_test.go 2014-03-25 15:48:47 +0000
3+++ juju/conn_test.go 2014-03-26 10:43:53 +0000
4@@ -398,15 +398,30 @@
5 c.Assert(sch.Revision(), gc.Equals, rev+1)
6 }
7
8+func (s *ConnSuite) assertAssignedMachineNetworks(c *gc.C, unit *state.Unit, expectInclude, expectExclude []string) {
9+ machineId, err := unit.AssignedMachineId()
10+ c.Assert(err, gc.IsNil)
11+ machine, err := s.conn.State.Machine(machineId)
12+ c.Assert(err, gc.IsNil)
13+ include, exclude, err := machine.Networks()
14+ c.Assert(err, gc.IsNil)
15+ c.Assert(include, jc.DeepEquals, expectInclude)
16+ c.Assert(exclude, jc.DeepEquals, expectExclude)
17+}
18+
19 func (s *ConnSuite) TestAddUnits(c *gc.C) {
20+ withNets := []string{"net1", "net2"}
21+ withoutNets := []string{"net3", "net4"}
22 curl := coretesting.Charms.ClonedURL(s.repo.Path, "quantal", "riak")
23 sch, err := s.conn.PutCharm(curl, s.repo, false)
24 c.Assert(err, gc.IsNil)
25- svc, err := s.conn.State.AddService("testriak", "user-admin", sch, nil, nil)
26+ svc, err := s.conn.State.AddService("testriak", "user-admin", sch, withNets, withoutNets)
27 c.Assert(err, gc.IsNil)
28 units, err := juju.AddUnits(s.conn.State, svc, 2, "")
29 c.Assert(err, gc.IsNil)
30 c.Assert(units, gc.HasLen, 2)
31+ s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets)
32+ s.assertAssignedMachineNetworks(c, units[1], withNets, withoutNets)
33
34 id0, err := units[0].AssignedMachineId()
35 c.Assert(err, gc.IsNil)
36@@ -419,16 +434,19 @@
37
38 units, err = juju.AddUnits(s.conn.State, svc, 1, "0")
39 c.Assert(err, gc.IsNil)
40+ s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets)
41 id2, err := units[0].AssignedMachineId()
42 c.Assert(id2, gc.Equals, id0)
43
44 units, err = juju.AddUnits(s.conn.State, svc, 1, "lxc:0")
45 c.Assert(err, gc.IsNil)
46+ s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets)
47 id3, err := units[0].AssignedMachineId()
48 c.Assert(id3, gc.Equals, id0+"/lxc/0")
49
50 units, err = juju.AddUnits(s.conn.State, svc, 1, "lxc:"+id3)
51 c.Assert(err, gc.IsNil)
52+ s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets)
53 id4, err := units[0].AssignedMachineId()
54 c.Assert(id4, gc.Equals, id0+"/lxc/0/lxc/0")
55
56
57=== modified file 'juju/deploy.go'
58--- juju/deploy.go 2014-03-25 15:06:31 +0000
59+++ juju/deploy.go 2014-03-26 10:43:53 +0000
60@@ -28,6 +28,10 @@
61 // - a new container on an existing machine eg "lxc:1"
62 // Use string to avoid ambiguity around machine 0.
63 ToMachineSpec string
64+ // IncludeNetworks holds a list of networks to start on boot.
65+ IncludeNetworks []string
66+ // ExcludeNetworks holds a list of networks to disable on boot.
67+ ExcludeNetworks []string
68 }
69
70 // DeployService takes a charm and various parameters and deploys it.
71@@ -49,8 +53,13 @@
72 }
73 // TODO(fwereade): transactional State.AddService including settings, constraints
74 // (minimumUnitCount, initialMachineIds?).
75- // TODO(gz): pass through real includeNetworks and excludeNetworks vals
76- service, err := st.AddService(args.ServiceName, "user-admin", args.Charm, nil, nil)
77+ service, err := st.AddService(
78+ args.ServiceName,
79+ "user-admin",
80+ args.Charm,
81+ args.IncludeNetworks,
82+ args.ExcludeNetworks,
83+ )
84 if err != nil {
85 return nil, err
86 }
87@@ -81,6 +90,11 @@
88 units := make([]*state.Unit, n)
89 // Hard code for now till we implement a different approach.
90 policy := state.AssignCleanEmpty
91+ // All units should have the same networks as the service.
92+ includeNetworks, excludeNetworks, err := svc.Networks()
93+ if err != nil {
94+ return nil, fmt.Errorf("cannot get service %q networks: %v", svc.Name(), err)
95+ }
96 // TODO what do we do if we fail half-way through this process?
97 for i := 0; i < n; i++ {
98 unit, err := svc.AddUnit()
99@@ -116,9 +130,11 @@
100 // Create the new machine marked as dirty so that
101 // nothing else will grab it before we assign the unit to it.
102 template := state.MachineTemplate{
103- Series: unit.Series(),
104- Jobs: []state.MachineJob{state.JobHostUnits},
105- Dirty: true,
106+ Series: unit.Series(),
107+ Jobs: []state.MachineJob{state.JobHostUnits},
108+ Dirty: true,
109+ IncludeNetworks: includeNetworks,
110+ ExcludeNetworks: excludeNetworks,
111 }
112 m, err = st.AddMachineInsideMachine(template, mid, containerType)
113 } else {
114
115=== modified file 'state/api/client.go'
116--- state/api/client.go 2014-03-26 07:01:48 +0000
117+++ state/api/client.go 2014-03-26 10:43:53 +0000
118@@ -256,12 +256,29 @@
119 return c.call("ServiceUnexpose", params, nil)
120 }
121
122+// ServiceDeployWithNetworks works exactly like ServiceDeploy, but
123+// allows specifying networks to either include or exclude on the
124+// machine where the charm is deployed.
125+func (c *Client) ServiceDeployWithNetworks(charmURL string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string, includeNetworks, excludeNetworks []string) error {
126+ params := params.ServiceDeploy{
127+ ServiceName: serviceName,
128+ CharmUrl: charmURL,
129+ NumUnits: numUnits,
130+ ConfigYAML: configYAML,
131+ Constraints: cons,
132+ ToMachineSpec: toMachineSpec,
133+ IncludeNetworks: includeNetworks,
134+ ExcludeNetworks: excludeNetworks,
135+ }
136+ return c.st.Call("Client", "", "ServiceDeployWithNetworks", params, nil)
137+}
138+
139 // ServiceDeploy obtains the charm, either locally or from the charm store,
140 // and deploys it.
141-func (c *Client) ServiceDeploy(charmUrl string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string) error {
142+func (c *Client) ServiceDeploy(charmURL string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string) error {
143 params := params.ServiceDeploy{
144 ServiceName: serviceName,
145- CharmUrl: charmUrl,
146+ CharmUrl: charmURL,
147 NumUnits: numUnits,
148 ConfigYAML: configYAML,
149 Constraints: cons,
150
151=== modified file 'state/api/params/params.go'
152--- state/api/params/params.go 2014-03-26 07:01:48 +0000
153+++ state/api/params/params.go 2014-03-26 10:43:53 +0000
154@@ -149,6 +149,10 @@
155 ConfigYAML string // Takes precedence over config if both are present.
156 Constraints constraints.Value
157 ToMachineSpec string
158+ // The following fields are supported from 1.17.7 onwards and
159+ // ignored before that.
160+ IncludeNetworks []string
161+ ExcludeNetworks []string
162 }
163
164 // ServiceUpdate holds the parameters for making the ServiceUpdate call.
165
166=== modified file 'state/apiserver/client/client.go'
167--- state/apiserver/client/client.go 2014-03-26 07:01:48 +0000
168+++ state/apiserver/client/client.go 2014-03-26 10:43:53 +0000
169@@ -282,16 +282,25 @@
170
171 _, err = juju.DeployService(c.api.state,
172 juju.DeployServiceParams{
173- ServiceName: args.ServiceName,
174- Charm: ch,
175- NumUnits: args.NumUnits,
176- ConfigSettings: settings,
177- Constraints: args.Constraints,
178- ToMachineSpec: args.ToMachineSpec,
179+ ServiceName: args.ServiceName,
180+ Charm: ch,
181+ NumUnits: args.NumUnits,
182+ ConfigSettings: settings,
183+ Constraints: args.Constraints,
184+ ToMachineSpec: args.ToMachineSpec,
185+ IncludeNetworks: args.IncludeNetworks,
186+ ExcludeNetworks: args.ExcludeNetworks,
187 })
188 return err
189 }
190
191+// ServiceDeployWithNetworks works exactly like ServiceDeploy, but
192+// allows specifying networks to include or exclude on the machine
193+// where the charm gets deployed.
194+func (c *Client) ServiceDeployWithNetworks(args params.ServiceDeploy) error {
195+ return c.ServiceDeploy(args)
196+}
197+
198 // ServiceUpdate updates the service attributes, including charm URL,
199 // minimum number of units, settings and constraints.
200 // All parameters in params.ServiceUpdate except the service name are optional.
201
202=== modified file 'state/apiserver/client/client_test.go'
203--- state/apiserver/client/client_test.go 2014-03-26 07:01:48 +0000
204+++ state/apiserver/client/client_test.go 2014-03-26 10:43:53 +0000
205@@ -680,6 +680,50 @@
206 }
207 }
208
209+func (s *clientSuite) TestClientServiceDeployWithNetworks(c *gc.C) {
210+ store, restore := makeMockCharmStore()
211+ defer restore()
212+ curl, bundle := addCharm(c, store, "dummy")
213+ mem4g := constraints.MustParse("mem=4G")
214+ err := s.APIState.Client().ServiceDeployWithNetworks(
215+ curl.String(), "service", 3, "", mem4g, "", []string{"net1", "net2"}, []string{"net3"},
216+ )
217+ c.Assert(err, gc.IsNil)
218+ service := s.assertPrincipalDeployed(c, "service", curl, false, bundle, mem4g)
219+
220+ include, exclude, err := service.Networks()
221+ c.Assert(err, gc.IsNil)
222+ c.Assert(include, gc.DeepEquals, []string{"net1", "net2"})
223+ c.Assert(exclude, gc.DeepEquals, []string{"net3"})
224+}
225+
226+func (s *clientSuite) assertPrincipalDeployed(c *gc.C, serviceName string, curl *charm.URL, forced bool, bundle charm.Charm, cons constraints.Value) *state.Service {
227+ service, err := s.State.Service(serviceName)
228+ c.Assert(err, gc.IsNil)
229+ charm, force, err := service.Charm()
230+ c.Assert(err, gc.IsNil)
231+ c.Assert(force, gc.Equals, forced)
232+ c.Assert(charm.URL(), gc.DeepEquals, curl)
233+ c.Assert(charm.Meta(), gc.DeepEquals, bundle.Meta())
234+ c.Assert(charm.Config(), gc.DeepEquals, bundle.Config())
235+
236+ serviceCons, err := service.Constraints()
237+ c.Assert(err, gc.IsNil)
238+ c.Assert(serviceCons, gc.DeepEquals, cons)
239+ units, err := service.AllUnits()
240+ c.Assert(err, gc.IsNil)
241+ for _, unit := range units {
242+ mid, err := unit.AssignedMachineId()
243+ c.Assert(err, gc.IsNil)
244+ machine, err := s.State.Machine(mid)
245+ c.Assert(err, gc.IsNil)
246+ machineCons, err := machine.Constraints()
247+ c.Assert(err, gc.IsNil)
248+ c.Assert(machineCons, gc.DeepEquals, cons)
249+ }
250+ return service
251+}
252+
253 func (s *clientSuite) TestClientServiceDeployPrincipal(c *gc.C) {
254 // TODO(fwereade): test ToMachineSpec directly on srvClient, when we
255 // manage to extract it as a package and can thus do it conveniently.
256@@ -691,29 +735,7 @@
257 curl.String(), "service", 3, "", mem4g, "",
258 )
259 c.Assert(err, gc.IsNil)
260- service, err := s.State.Service("service")
261- c.Assert(err, gc.IsNil)
262- charm, force, err := service.Charm()
263- c.Assert(err, gc.IsNil)
264- c.Assert(force, gc.Equals, false)
265- c.Assert(charm.URL(), gc.DeepEquals, curl)
266- c.Assert(charm.Meta(), gc.DeepEquals, bundle.Meta())
267- c.Assert(charm.Config(), gc.DeepEquals, bundle.Config())
268-
269- cons, err := service.Constraints()
270- c.Assert(err, gc.IsNil)
271- c.Assert(cons, gc.DeepEquals, mem4g)
272- units, err := service.AllUnits()
273- c.Assert(err, gc.IsNil)
274- for _, unit := range units {
275- mid, err := unit.AssignedMachineId()
276- c.Assert(err, gc.IsNil)
277- machine, err := s.State.Machine(mid)
278- c.Assert(err, gc.IsNil)
279- cons, err := machine.Constraints()
280- c.Assert(err, gc.IsNil)
281- c.Assert(cons, gc.DeepEquals, mem4g)
282- }
283+ s.assertPrincipalDeployed(c, "service", curl, false, bundle, mem4g)
284 }
285
286 func (s *clientSuite) TestClientServiceDeploySubordinate(c *gc.C) {
287
288=== modified file 'state/apiserver/client/perm_test.go'
289--- state/apiserver/client/perm_test.go 2014-03-13 07:54:56 +0000
290+++ state/apiserver/client/perm_test.go 2014-03-26 10:43:53 +0000
291@@ -69,6 +69,10 @@
292 op: opClientServiceDeploy,
293 allow: []string{"user-admin", "user-other"},
294 }, {
295+ about: "Client.ServiceDeployWithNetworks",
296+ op: opClientServiceDeployWithNetworks,
297+ allow: []string{"user-admin", "user-other"},
298+}, {
299 about: "Client.ServiceUpdate",
300 op: opClientServiceUpdate,
301 allow: []string{"user-admin", "user-other"},
302@@ -321,6 +325,14 @@
303 return func() {}, err
304 }
305
306+func opClientServiceDeployWithNetworks(c *gc.C, st *api.State, mst *state.State) (func(), error) {
307+ err := st.Client().ServiceDeployWithNetworks("mad:bad/url-1", "x", 1, "", constraints.Value{}, "", nil, nil)
308+ if err.Error() == `charm URL has invalid schema: "mad:bad/url-1"` {
309+ err = nil
310+ }
311+ return func() {}, err
312+}
313+
314 func opClientServiceUpdate(c *gc.C, st *api.State, mst *state.State) (func(), error) {
315 args := params.ServiceUpdate{
316 ServiceName: "no-such-charm",
317
318=== modified file 'state/assign_test.go'
319--- state/assign_test.go 2014-03-13 07:54:56 +0000
320+++ state/assign_test.go 2014-03-26 10:43:53 +0000
321@@ -28,7 +28,13 @@
322
323 func (s *AssignSuite) SetUpTest(c *gc.C) {
324 s.ConnSuite.SetUpTest(c)
325- wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress"))
326+ wordpress := s.AddTestingServiceWithNetworks(
327+ c,
328+ "wordpress",
329+ s.AddTestingCharm(c, "wordpress"),
330+ []string{"net1", "net2"},
331+ []string{"net3", "net4"},
332+ )
333 s.wordpress = wordpress
334 }
335
336@@ -312,12 +318,21 @@
337 }
338
339 func (s *AssignSuite) assertAssignedUnit(c *gc.C, unit *state.Unit) string {
340+ // Get service networks.
341+ service, err := unit.Service()
342+ c.Assert(err, gc.IsNil)
343+ includeNetworks, excludeNetworks, err := service.Networks()
344+ c.Assert(err, gc.IsNil)
345 // Check the machine on the unit is set.
346 machineId, err := unit.AssignedMachineId()
347 c.Assert(err, gc.IsNil)
348 // Check that the principal is set on the machine.
349 machine, err := s.State.Machine(machineId)
350 c.Assert(err, gc.IsNil)
351+ include, exclude, err := machine.Networks()
352+ c.Assert(err, gc.IsNil)
353+ c.Assert(include, gc.DeepEquals, includeNetworks)
354+ c.Assert(exclude, gc.DeepEquals, excludeNetworks)
355 machineUnits, err := machine.Units()
356 c.Assert(err, gc.IsNil)
357 c.Assert(machineUnits, gc.HasLen, 1)
358
359=== modified file 'state/unit.go'
360--- state/unit.go 2014-03-19 23:07:33 +0000
361+++ state/unit.go 2014-03-26 10:43:53 +0000
362@@ -991,11 +991,12 @@
363 return &cons, nil
364 }
365
366-// AssignToNewMachineOrContainer assigns the unit to a new machine, with constraints
367-// determined according to the service and environment constraints at the time of unit creation.
368-// If a container is required, a clean, empty machine instance is required on which to create
369-// the container. An existing clean, empty instance is first searched for, and if not found,
370-// a new one is created.
371+// AssignToNewMachineOrContainer assigns the unit to a new machine,
372+// with constraints determined according to the service and
373+// environment constraints at the time of unit creation. If a
374+// container is required, a clean, empty machine instance is required
375+// on which to create the container. An existing clean, empty instance
376+// is first searched for, and if not found, a new one is created.
377 func (u *Unit) AssignToNewMachineOrContainer() (err error) {
378 defer assignContextf(&err, u, "new machine or container")
379 if u.doc.Principal != "" {
380@@ -1026,10 +1027,20 @@
381 } else if err != nil {
382 return err
383 }
384+ svc, err := u.Service()
385+ if err != nil {
386+ return err
387+ }
388+ includeNetworks, excludeNetworks, err := svc.Networks()
389+ if err != nil {
390+ return err
391+ }
392 template := MachineTemplate{
393- Series: u.doc.Series,
394- Constraints: *cons,
395- Jobs: []MachineJob{JobHostUnits},
396+ Series: u.doc.Series,
397+ Constraints: *cons,
398+ Jobs: []MachineJob{JobHostUnits},
399+ IncludeNetworks: includeNetworks,
400+ ExcludeNetworks: excludeNetworks,
401 }
402 err = u.assignToNewMachine(template, host.Id, *cons.Container)
403 if err == machineNotCleanErr {
404@@ -1059,10 +1070,20 @@
405 if cons.HasContainer() {
406 containerType = *cons.Container
407 }
408+ svc, err := u.Service()
409+ if err != nil {
410+ return err
411+ }
412+ includeNetworks, excludeNetworks, err := svc.Networks()
413+ if err != nil {
414+ return err
415+ }
416 template := MachineTemplate{
417- Series: u.doc.Series,
418- Constraints: *cons,
419- Jobs: []MachineJob{JobHostUnits},
420+ Series: u.doc.Series,
421+ Constraints: *cons,
422+ Jobs: []MachineJob{JobHostUnits},
423+ IncludeNetworks: includeNetworks,
424+ ExcludeNetworks: excludeNetworks,
425 }
426 return u.assignToNewMachine(template, "", containerType)
427 }

Subscribers

People subscribed via source and target branches

to status/vote changes: