Merge lp:~rogpeppe/juju-core/037-startinstance-returns-tools into lp:~juju/juju-core/trunk

Proposed by Roger Peppe
Status: Work in progress
Proposed branch: lp:~rogpeppe/juju-core/037-startinstance-returns-tools
Merge into: lp:~juju/juju-core/trunk
Diff against target: 418 lines (+77/-40)
10 files modified
cmd/juju/status_test.go (+2/-2)
environs/dummy/environs.go (+11/-4)
environs/ec2/ec2.go (+10/-10)
environs/ec2/live_test.go (+5/-5)
environs/ec2/local_test.go (+1/-1)
environs/interface.go (+3/-2)
environs/jujutest/livetests.go (+32/-6)
environs/jujutest/tests.go (+5/-2)
worker/firewaller/firewaller_test.go (+7/-7)
worker/provisioner/provisioner.go (+1/-1)
To merge this branch: bzr merge lp:~rogpeppe/juju-core/037-startinstance-returns-tools
Reviewer Review Type Date Requested Status
The Go Language Gophers Pending
Review via email: mp+121248@code.launchpad.net

Description of the change

environs: make StartInstance return the chosen tools.

This means that the provisioner can set the proposed tools
for a new machine without trying to second-guess the
provider choice.

This requires lp:~rogpeppe/goamz/predictable-urls
for the tests to pass.

https://codereview.appspot.com/6475058/

To post a comment you must log in.
Revision history for this message
Roger Peppe (rogpeppe) wrote :

Reviewers: mp+121248_code.launchpad.net,

Message:
Please take a look.

Description:
environs: make StartInstance return the chosen tools.

This means that the provisioner can set the proposed tools
for a new machine without trying to second-guess the
provider choice.

We also make the provisioner and the bootstrap init set the proposed
tools for
the new machine.

This requires lp:~rogpeppe/goamz/predictable-urls
for the tests to pass.

https://code.launchpad.net/~rogpeppe/juju-core/037-startinstance-returns-tools/+merge/121248

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M cmd/juju/status_test.go
   M cmd/jujud/bootstrap.go
   M environs/dummy/environs.go
   M environs/ec2/ec2.go
   M environs/ec2/live_test.go
   M environs/ec2/local_test.go
   M environs/interface.go
   M environs/jujutest/livetests.go
   M environs/jujutest/tests.go
   M worker/firewaller/firewaller_test.go
   M worker/provisioner/provisioner.go

430. By Roger Peppe

revert SetProposedTools behaviour

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

worker/provisioner: fix StartInstance call

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

https://codereview.appspot.com/6475058/diff/6001/environs/ec2/ec2.go
File environs/ec2/ec2.go (right):

https://codereview.appspot.com/6475058/diff/6001/environs/ec2/ec2.go#newcode339
environs/ec2/ec2.go:339: tools, err = environs.FindTools(e,
version.Current)
Right now we're passing a nil tools parameter to the provider, and then
calling back onto generic logic to decide which tools to use in that
case. This seems like a bad choice. It means the decision of what to do
is distributed, and as a side effect we're having to have it both as an
incoming parameter and as an out-going one so we can manage the fact
everybody is responsible for the decision, but no one is.

Instead, what about never providing nil tools, and instead asserting
that StartInstance *needs* good tools? The algorithm to decide what to
run is already generic, and already lives outside the environment.

https://codereview.appspot.com/6475058/

Unmerged revisions

431. By Roger Peppe

worker/provisioner: fix StartInstance call

430. By Roger Peppe

revert SetProposedTools behaviour

429. By Roger Peppe

gofmt

428. By Roger Peppe

environs: make StartInstance return tools

427. By Aram Hăvărneanu

mstate: add config node

R=niemeyer
CC=
https://codereview.appspot.com/6460105

426. By Aram Hăvărneanu

mstate: use juju-core/testing for MongoDB

Use juju-core/testing for starting MongoDB instead of starting it
by hand.

R=niemeyer
CC=
https://codereview.appspot.com/6459100

425. By Aram Hăvărneanu

testing: add MongoDB support

R=niemeyer
CC=
https://codereview.appspot.com/6443148

424. By Frank Mueller

mstate: changed lifecycle implementation in unit

Unit now has Life(), Kill() and Die() and uses the utility
function ensureLife(). The test for removing a unit has
been changed.

R=aram, niemeyer
CC=
https://codereview.appspot.com/6476044

423. By Dave Cheney

state: add initial config map to Initialise

state.Initialise now takes a config map that is inserted into
/environment on creation.

R=niemeyer
CC=
https://codereview.appspot.com/6458161

422. By Roger Peppe

environs: tweaks to ListTools interface

This makes it easier for upgrade logic to operate on the set of all
available tools.

R=niemeyer
CC=
https://codereview.appspot.com/6485044

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmd/juju/status_test.go'
2--- cmd/juju/status_test.go 2012-08-16 10:24:36 +0000
3+++ cmd/juju/status_test.go 2012-08-24 17:44:18 +0000
4@@ -88,7 +88,7 @@
5 func(st *state.State, conn *juju.Conn, c *C) {
6 m, err := st.Machine(0)
7 c.Assert(err, IsNil)
8- inst, err := conn.Environ.StartInstance(m.Id(), nil, nil)
9+ inst, _, err := conn.Environ.StartInstance(m.Id(), nil, nil)
10 c.Assert(err, IsNil)
11 err = m.SetInstanceId(inst.Id())
12 c.Assert(err, IsNil)
13@@ -207,7 +207,7 @@
14 m, err := st.AddMachine()
15 c.Assert(err, IsNil)
16 c.Assert(m.Id(), Equals, i)
17- inst, err := conn.Environ.StartInstance(m.Id(), nil, nil)
18+ inst, _, err := conn.Environ.StartInstance(m.Id(), nil, nil)
19 c.Assert(err, IsNil)
20 err = m.SetInstanceId(inst.Id())
21 c.Assert(err, IsNil)
22
23=== modified file 'environs/dummy/environs.go'
24--- environs/dummy/environs.go 2012-08-24 01:45:40 +0000
25+++ environs/dummy/environs.go 2012-08-24 17:44:18 +0000
26@@ -29,6 +29,7 @@
27 "launchpad.net/juju-core/schema"
28 "launchpad.net/juju-core/state"
29 "launchpad.net/juju-core/testing"
30+ "launchpad.net/juju-core/version"
31 "net"
32 "net/http"
33 "strings"
34@@ -417,15 +418,21 @@
35 return nil
36 }
37
38-func (e *environ) StartInstance(machineId int, info *state.Info, tools *state.Tools) (environs.Instance, error) {
39+func (e *environ) StartInstance(machineId int, info *state.Info, tools *state.Tools) (environs.Instance, *state.Tools, error) {
40 log.Printf("dummy startinstance, machine %d", machineId)
41 if err := e.checkBroken("StartInstance"); err != nil {
42- return nil, err
43+ return nil, nil, err
44 }
45 e.state.mu.Lock()
46 defer e.state.mu.Unlock()
47 if tools != nil && (strings.HasPrefix(tools.Series, "unknown") || strings.HasPrefix(tools.Arch, "unknown")) {
48- return nil, fmt.Errorf("cannot find image for %s-%s", tools.Series, tools.Arch)
49+ return nil, nil, fmt.Errorf("cannot find image for %s-%s", tools.Series, tools.Arch)
50+ }
51+ if tools == nil {
52+ tools = &state.Tools{
53+ Binary: version.Current,
54+ URL: "fake url for dummy tools",
55+ }
56 }
57 i := &instance{
58 state: e.state,
59@@ -441,7 +448,7 @@
60 Instance: i,
61 Info: info,
62 }
63- return i, nil
64+ return i, tools, nil
65 }
66
67 func (e *environ) StopInstances(is []environs.Instance) error {
68
69=== modified file 'environs/ec2/ec2.go'
70--- environs/ec2/ec2.go 2012-08-22 03:06:05 +0000
71+++ environs/ec2/ec2.go 2012-08-24 17:44:18 +0000
72@@ -246,7 +246,7 @@
73 if err != nil {
74 return fmt.Errorf("unable to determine inital configuration: %v", err)
75 }
76- inst, err := e.startInstance(0, nil, tools, true, config)
77+ inst, _, err := e.startInstance(0, nil, tools, true, config)
78 if err != nil {
79 return fmt.Errorf("cannot start bootstrap instance: %v", err)
80 }
81@@ -307,7 +307,7 @@
82 return state.AssignUnused
83 }
84
85-func (e *environ) StartInstance(machineId int, info *state.Info, tools *state.Tools) (environs.Instance, error) {
86+func (e *environ) StartInstance(machineId int, info *state.Info, tools *state.Tools) (environs.Instance, *state.Tools, error) {
87 return e.startInstance(machineId, info, tools, false, nil)
88 }
89
90@@ -333,12 +333,12 @@
91 // startInstance is the internal version of StartInstance, used by Bootstrap
92 // as well as via StartInstance itself. If master is true, a bootstrap
93 // instance will be started.
94-func (e *environ) startInstance(machineId int, info *state.Info, tools *state.Tools, master bool, config map[string]interface{}) (environs.Instance, error) {
95+func (e *environ) startInstance(machineId int, info *state.Info, tools *state.Tools, master bool, config map[string]interface{}) (environs.Instance, *state.Tools, error) {
96 if tools == nil {
97 var err error
98 tools, err = environs.FindTools(e, version.Current)
99 if err != nil {
100- return nil, err
101+ return nil, nil, err
102 }
103 }
104 log.Printf("environs/ec2: starting machine %d in %q running tools version %q from %q", machineId, e.name, tools.Binary, tools.URL)
105@@ -348,16 +348,16 @@
106 region: e.ecfg().region(),
107 })
108 if err != nil {
109- return nil, fmt.Errorf("cannot find image satisfying constraints: %v", err)
110+ return nil, nil, fmt.Errorf("cannot find image satisfying constraints: %v", err)
111 }
112 // TODO quick sanity check that we can access the tools URL?
113 userData, err := e.userData(machineId, info, tools, master, config)
114 if err != nil {
115- return nil, fmt.Errorf("cannot make user data: %v", err)
116+ return nil, nil, fmt.Errorf("cannot make user data: %v", err)
117 }
118 groups, err := e.setUpGroups(machineId)
119 if err != nil {
120- return nil, fmt.Errorf("cannot set up groups: %v", err)
121+ return nil, nil, fmt.Errorf("cannot set up groups: %v", err)
122 }
123 var instances *ec2.RunInstancesResp
124
125@@ -375,14 +375,14 @@
126 }
127 }
128 if err != nil {
129- return nil, fmt.Errorf("cannot run instances: %v", err)
130+ return nil, nil, fmt.Errorf("cannot run instances: %v", err)
131 }
132 if len(instances.Instances) != 1 {
133- return nil, fmt.Errorf("expected 1 started instance, got %d", len(instances.Instances))
134+ return nil, nil, fmt.Errorf("expected 1 started instance, got %d", len(instances.Instances))
135 }
136 inst := &instance{e, &instances.Instances[0]}
137 log.Printf("environs/ec2: started instance %q", inst.Id())
138- return inst, nil
139+ return inst, tools, nil
140 }
141
142 func (e *environ) StopInstances(insts []environs.Instance) error {
143
144=== modified file 'environs/ec2/live_test.go'
145--- environs/ec2/live_test.go 2012-07-30 16:37:39 +0000
146+++ environs/ec2/live_test.go 2012-08-24 17:44:18 +0000
147@@ -98,7 +98,7 @@
148 }
149
150 func (t *LiveTests) TestInstanceDNSName(c *C) {
151- inst, err := t.Env.StartInstance(30, jujutest.InvalidStateInfo, nil)
152+ inst, _, err := t.Env.StartInstance(30, jujutest.InvalidStateInfo, nil)
153 c.Assert(err, IsNil)
154 defer t.Env.StopInstances([]environs.Instance{inst})
155 dns, err := inst.WaitDNSName()
156@@ -148,7 +148,7 @@
157 })
158 c.Assert(err, IsNil)
159
160- inst0, err := t.Env.StartInstance(98, jujutest.InvalidStateInfo, nil)
161+ inst0, _, err := t.Env.StartInstance(98, jujutest.InvalidStateInfo, nil)
162 c.Assert(err, IsNil)
163 defer t.Env.StopInstances([]environs.Instance{inst0})
164
165@@ -156,7 +156,7 @@
166 // before starting it, to check that it's reused correctly.
167 oldMachineGroup := createGroup(c, ec2conn, groups[2].Name, "old machine group")
168
169- inst1, err := t.Env.StartInstance(99, jujutest.InvalidStateInfo, nil)
170+ inst1, _, err := t.Env.StartInstance(99, jujutest.InvalidStateInfo, nil)
171 c.Assert(err, IsNil)
172 defer t.Env.StopInstances([]environs.Instance{inst1})
173
174@@ -258,12 +258,12 @@
175 // It would be nice if this test was in jujutest, but
176 // there's no way for jujutest to fabricate a valid-looking
177 // instance id.
178- inst0, err := t.Env.StartInstance(40, jujutest.InvalidStateInfo, nil)
179+ inst0, _, err := t.Env.StartInstance(40, jujutest.InvalidStateInfo, nil)
180 c.Assert(err, IsNil)
181
182 inst1 := ec2.FabricateInstance(inst0, "i-aaaaaaaa")
183
184- inst2, err := t.Env.StartInstance(41, jujutest.InvalidStateInfo, nil)
185+ inst2, _, err := t.Env.StartInstance(41, jujutest.InvalidStateInfo, nil)
186 c.Assert(err, IsNil)
187
188 err = t.Env.StopInstances([]environs.Instance{inst0, inst1, inst2})
189
190=== modified file 'environs/ec2/local_test.go'
191--- environs/ec2/local_test.go 2012-08-22 02:53:44 +0000
192+++ environs/ec2/local_test.go 2012-08-24 17:44:18 +0000
193@@ -239,7 +239,7 @@
194 // check that a new instance will be started without
195 // zookeeper, with a machine agent, and without a
196 // provisioning agent.
197- inst1, err := t.env.StartInstance(1, info, nil)
198+ inst1, _, err := t.env.StartInstance(1, info, nil)
199 c.Assert(err, IsNil)
200 inst = t.srv.ec2srv.Instance(inst1.Id())
201 c.Assert(inst, NotNil)
202
203=== modified file 'environs/interface.go'
204--- environs/interface.go 2012-08-09 09:58:22 +0000
205+++ environs/interface.go 2012-08-24 17:44:18 +0000
206@@ -147,9 +147,10 @@
207 // can lead to undefined results. The juju tools that will run
208 // on the new machine are given by tools - if nil,
209 // the Environ will find a set of tools compatible with the
210- // current version.
211+ // current version. StartInstance returns the new
212+ // instance and the set of tools it will run.
213 // TODO add arguments to specify type of new machine.
214- StartInstance(machineId int, info *state.Info, tools *state.Tools) (Instance, error)
215+ StartInstance(machineId int, info *state.Info, tools *state.Tools) (Instance, *state.Tools, error)
216
217 // StopInstances shuts down the given instances.
218 StopInstances([]Instance) error
219
220=== modified file 'environs/jujutest/livetests.go'
221--- environs/jujutest/livetests.go 2012-08-24 01:45:40 +0000
222+++ environs/jujutest/livetests.go 2012-08-24 17:44:18 +0000
223@@ -17,9 +17,10 @@
224 c.Assert(err, IsNil)
225 c.Check(insts, HasLen, 0)
226
227- inst, err := t.Env.StartInstance(0, InvalidStateInfo, nil)
228+ inst, tools, err := t.Env.StartInstance(0, InvalidStateInfo, nil)
229 c.Assert(err, IsNil)
230 c.Assert(inst, NotNil)
231+ c.Assert(tools.Binary, Equals, version.Current)
232 id0 := inst.Id()
233
234 insts, err = t.Env.Instances([]string{id0, id0})
235@@ -62,7 +63,7 @@
236 }
237
238 func (t *LiveTests) TestPorts(c *C) {
239- inst1, err := t.Env.StartInstance(1, InvalidStateInfo, nil)
240+ inst1, _, err := t.Env.StartInstance(1, InvalidStateInfo, nil)
241 c.Assert(err, IsNil)
242 c.Assert(inst1, NotNil)
243 defer t.Env.StopInstances([]environs.Instance{inst1})
244@@ -71,7 +72,7 @@
245 c.Assert(err, IsNil)
246 c.Assert(ports, HasLen, 0)
247
248- inst2, err := t.Env.StartInstance(2, InvalidStateInfo, nil)
249+ inst2, _, err := t.Env.StartInstance(2, InvalidStateInfo, nil)
250 c.Assert(err, IsNil)
251 c.Assert(inst2, NotNil)
252 ports, err = inst2.Ports(2)
253@@ -185,7 +186,7 @@
254 m, err = st.AddMachine()
255 c.Assert(err, IsNil)
256
257- t.assertStartInstance(c, m)
258+ t.assertStartedInstance(c, m)
259
260 // now remove it
261 c.Assert(st.RemoveMachine(m.Id()), IsNil)
262@@ -240,7 +241,7 @@
263 Delay: 1 * time.Second,
264 }
265
266-func (t *LiveTests) assertStartInstance(c *C, m *state.Machine) {
267+func (t *LiveTests) assertStartedInstance(c *C, m *state.Machine) {
268 // Wait for machine to get an instance id.
269 for a := waitAgent.Start(); a.Next(); {
270 instId, err := m.InstanceId()
271@@ -351,11 +352,36 @@
272 URL: url,
273 }
274
275- inst, err := t.Env.StartInstance(4, InvalidStateInfo, tools)
276+ inst, gotTools, err := t.Env.StartInstance(4, InvalidStateInfo, tools)
277 if inst != nil {
278 err := t.Env.StopInstances([]environs.Instance{inst})
279 c.Check(err, IsNil)
280 }
281 c.Assert(inst, IsNil)
282+ c.Assert(gotTools, IsNil)
283 c.Assert(err, ErrorMatches, "cannot find image.*")
284 }
285+
286+// Check that StartInstance returns the same tools we passed it.
287+func (t *LiveTests) TestStartInstanceReturnsSameTools(c *C) {
288+ name := environs.ToolsStoragePath(version.Current)
289+ storage := t.Env.Storage()
290+ checkPutFile(c, storage, name, []byte("fake tools on invalid series"))
291+ defer storage.Remove(name)
292+
293+ url, err := storage.URL(name)
294+ c.Assert(err, IsNil)
295+ tools := &state.Tools{
296+ Binary: version.Current,
297+ URL: url,
298+ }
299+
300+ inst, gotTools, err := t.Env.StartInstance(4, InvalidStateInfo, tools)
301+ if inst != nil {
302+ err := t.Env.StopInstances([]environs.Instance{inst})
303+ c.Check(err, IsNil)
304+ }
305+ c.Assert(err, IsNil)
306+ c.Assert(gotTools, Equals, tools)
307+ c.Assert(inst, NotNil)
308+}
309
310=== modified file 'environs/jujutest/tests.go'
311--- environs/jujutest/tests.go 2012-07-30 16:37:39 +0000
312+++ environs/jujutest/tests.go 2012-08-24 17:44:18 +0000
313@@ -6,6 +6,7 @@
314 "io/ioutil"
315 . "launchpad.net/gocheck"
316 "launchpad.net/juju-core/environs"
317+ "launchpad.net/juju-core/version"
318 "net/http"
319 "time"
320 )
321@@ -17,14 +18,16 @@
322 c.Assert(err, IsNil)
323 c.Assert(insts, HasLen, 0)
324
325- inst0, err := e.StartInstance(0, InvalidStateInfo, nil)
326+ inst0, tools0, err := e.StartInstance(0, InvalidStateInfo, nil)
327 c.Assert(err, IsNil)
328 c.Assert(inst0, NotNil)
329+ c.Assert(tools0.Binary, Equals, version.Current)
330 id0 := inst0.Id()
331
332- inst1, err := e.StartInstance(1, InvalidStateInfo, nil)
333+ inst1, tools1, err := e.StartInstance(1, InvalidStateInfo, nil)
334 c.Assert(err, IsNil)
335 c.Assert(inst1, NotNil)
336+ c.Assert(tools1, DeepEquals, tools0)
337 id1 := inst1.Id()
338
339 insts, err = e.Instances([]string{id0, id1})
340
341=== modified file 'worker/firewaller/firewaller_test.go'
342--- worker/firewaller/firewaller_test.go 2012-08-17 09:31:37 +0000
343+++ worker/firewaller/firewaller_test.go 2012-08-24 17:44:18 +0000
344@@ -66,7 +66,7 @@
345
346 m, err := s.State.AddMachine()
347 c.Assert(err, IsNil)
348- inst, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
349+ inst, _, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
350 c.Assert(err, IsNil)
351 err = m.SetInstanceId(inst.Id())
352 c.Assert(err, IsNil)
353@@ -96,7 +96,7 @@
354
355 m, err := s.State.AddMachine()
356 c.Assert(err, IsNil)
357- inst, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
358+ inst, _, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
359 c.Assert(err, IsNil)
360 err = m.SetInstanceId(inst.Id())
361 c.Assert(err, IsNil)
362@@ -136,14 +136,14 @@
363 m1, err := s.State.AddMachine()
364 c.Assert(err, IsNil)
365
366- inst1, err := s.Conn.Environ.StartInstance(m1.Id(), s.StateInfo(c), nil)
367+ inst1, _, err := s.Conn.Environ.StartInstance(m1.Id(), s.StateInfo(c), nil)
368 c.Assert(err, IsNil)
369 err = m1.SetInstanceId(inst1.Id())
370 c.Assert(err, IsNil)
371
372 m2, err := s.State.AddMachine()
373 c.Assert(err, IsNil)
374- inst2, err := s.Conn.Environ.StartInstance(m2.Id(), s.StateInfo(c), nil)
375+ inst2, _, err := s.Conn.Environ.StartInstance(m2.Id(), s.StateInfo(c), nil)
376 c.Assert(err, IsNil)
377 err = m2.SetInstanceId(inst2.Id())
378 c.Assert(err, IsNil)
379@@ -180,7 +180,7 @@
380 func (s *FirewallerSuite) TestFirewallerStartWithState(c *C) {
381 m, err := s.State.AddMachine()
382 c.Assert(err, IsNil)
383- inst, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
384+ inst, _, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
385 c.Assert(err, IsNil)
386 err = m.SetInstanceId(inst.Id())
387 c.Assert(err, IsNil)
388@@ -211,7 +211,7 @@
389 func (s *FirewallerSuite) TestFirewallerStartWithPartialState(c *C) {
390 m, err := s.State.AddMachine()
391 c.Assert(err, IsNil)
392- inst, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
393+ inst, _, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
394 c.Assert(err, IsNil)
395 err = m.SetInstanceId(inst.Id())
396 c.Assert(err, IsNil)
397@@ -244,7 +244,7 @@
398
399 m, err := s.State.AddMachine()
400 c.Assert(err, IsNil)
401- inst, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
402+ inst, _, err := s.Conn.Environ.StartInstance(m.Id(), s.StateInfo(c), nil)
403 c.Assert(err, IsNil)
404 err = m.SetInstanceId(inst.Id())
405 c.Assert(err, IsNil)
406
407=== modified file 'worker/provisioner/provisioner.go'
408--- worker/provisioner/provisioner.go 2012-08-15 15:29:08 +0000
409+++ worker/provisioner/provisioner.go 2012-08-24 17:44:18 +0000
410@@ -225,7 +225,7 @@
411 // however as the PA only knows one state.Info, and that info is used by MAs and
412 // UAs to locate the ZK for this environment, it is logical to use the same
413 // state.Info as the PA.
414- inst, err := p.environ.StartInstance(m.Id(), p.info, nil)
415+ inst, _, err := p.environ.StartInstance(m.Id(), p.info, nil)
416 if err != nil {
417 log.Printf("provisioner cannot start machine %s: %v", m, err)
418 return err

Subscribers

People subscribed via source and target branches