Merge lp:~axwalk/juju-core/refactor-environs-manual into lp:~go-bot/juju-core/trunk

Proposed by Andrew Wilkins
Status: Merged
Approved by: Andrew Wilkins
Approved revision: no longer in the source branch.
Merged at revision: 2065
Proposed branch: lp:~axwalk/juju-core/refactor-environs-manual
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 473 lines (+89/-130)
8 files modified
container/userdata.go (+3/-1)
environs/cloudinit.go (+3/-2)
environs/cloudinit/cloudinit.go (+16/-21)
environs/cloudinit/cloudinit_test.go (+8/-9)
environs/manual/agent.go (+10/-54)
environs/manual/agent_test.go (+19/-15)
environs/manual/bootstrap.go (+14/-12)
environs/manual/provisioner.go (+16/-16)
To merge this branch: bzr merge lp:~axwalk/juju-core/refactor-environs-manual
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+195342@code.launchpad.net

Commit message

Refactor environs/{cloudinit,manual}

environs/cloudinit has been modified to
have two sub-Configure methods:
ConfigureBase and ConfigureJuju. The
former initialises a cloud-init config
to setup a base OS with SSH keys; the
latter does the rest.

environs/manual has been modified to
expose provisionMachineAgent (now with
a capital P), which now just takes a
hostname and *cloudinit.MachineConfig.
We will use this later to install
machine agents into cloud images.

https://codereview.appspot.com/26570047/

Description of the change

Refactor environs/{cloudinit,manual}

environs/cloudinit has been modified to
have two sub-Configure methods:
ConfigureBase and ConfigureJuju. The
former initialises a cloud-init config
to setup a base OS with SSH keys; the
latter does the rest.

environs/manual has been modified to
expose provisionMachineAgent (now with
a capital P), which now just takes a
hostname and *cloudinit.MachineConfig.
We will use this later to install
machine agents into cloud images.

https://codereview.appspot.com/26570047/

To post a comment you must log in.
Revision history for this message
Andrew Wilkins (axwalk) wrote :

Reviewers: mp+195342_code.launchpad.net,

Message:
Please take a look.

Description:
Refactor environs/{cloudinit,manual}

environs/cloudinit has been modified to
have two sub-Configure methods:
ConfigureBase and ConfigureJuju. The
former initialises a cloud-init config
to setup a base OS with SSH keys; the
latter does the rest.

environs/manual has been modified to
expose provisionMachineAgent (now with
a capital P), which now just takes a
hostname and *cloudinit.MachineConfig.
We will use this later to install
machine agents into cloud images.

https://code.launchpad.net/~axwalk/juju-core/refactor-environs-manual/+merge/195342

(do not edit description out of merge proposal)

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

Affected files (+108, -130 lines):
   A [revision details]
   M container/userdata.go
   M environs/cloudinit.go
   M environs/cloudinit/cloudinit.go
   M environs/cloudinit/cloudinit_test.go
   M environs/manual/agent.go
   M environs/manual/agent_test.go
   M environs/manual/bootstrap.go
   M environs/manual/provisioner.go

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

LGTM with one thought below.

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go
File environs/cloudinit/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go#newcode145
environs/cloudinit/cloudinit.go:145: func ConfigureBase(authorizedKeys
string, c *cloudinit.Config) error {
Passing thought: I wonder if this function and the above might work
better with the cloudinit.Config as the first argument, as if it was the
receiver.

Also I'm not entirely sure that "Base" is quite right as a name - with
that name, it sounds as if it's a necessary base that others must build
on, but since the cloudinit config is passed in, that's not necessarily
the case.

As an alternative, we could make it return the new config:

func BaseConfig(authorizedKeys string) *cloudinit.Config

(no need to return an error, I think). Then it really would be a base,
because everything would start with it.

Or alternatively rename it to something else; ConfigureBasic perhaps?
I think my preference is for the above though.

https://codereview.appspot.com/26570047/diff/1/environs/manual/agent.go
File environs/manual/agent.go (left):

https://codereview.appspot.com/26570047/diff/1/environs/manual/agent.go#oldcode70
environs/manual/agent.go:70: var mcfg *cloudinit.MachineConfig
It's great to see all this go.

https://codereview.appspot.com/26570047/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go
File environs/cloudinit/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go#newcode145
environs/cloudinit/cloudinit.go:145: func ConfigureBase(authorizedKeys
string, c *cloudinit.Config) error {
On 2013/11/15 08:36:09, rog wrote:
> Passing thought: I wonder if this function and the above might work
better with
> the cloudinit.Config as the first argument, as if it was the receiver.

Making it a receiver seems wrong to me, as that would suggest to me that
it's the cloudinit.Config configuring something else.

As for the order here: I don't have a strong preference, I was just
keeping it consistent with Configure (input first, output second).

> Also I'm not entirely sure that "Base" is quite right as a name - with
that
> name, it sounds as if it's a necessary base that others must build on,
but since
> the cloudinit config is passed in, that's not necessarily the case.

I think it may just be confusing, given how generic the word "base" is.

ConfigureBase produces cloud-init that configures a "base OS image".
That is then built on by adding the juju bits (via ConfigureJuju).

> As an alternative, we could make it return the new config:

> func BaseConfig(authorizedKeys string) *cloudinit.Config

> (no need to return an error, I think). Then it really would be a base,
because
> everything would start with it.

The thing is, not *everything* starts with it. Manual
bootstrap/provisioning doesn't use ConfigureBase, as they already have a
"base".

> Or alternatively rename it to something else; ConfigureBasic perhaps?
> I think my preference is for the above though.

To me, Basic and Base have more or less the same connotations (except
Basic has an additional meaning of not-complex). I want to say
ConfigurePristine, but it isn't exactly (it adds SSH keys...).

https://codereview.appspot.com/26570047/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2013/11/15 09:10:42, axw wrote:

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go
> File environs/cloudinit/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/1/environs/cloudinit/cloudinit.go#newcode145
> environs/cloudinit/cloudinit.go:145: func ConfigureBase(authorizedKeys
string, c
> *cloudinit.Config) error {
> On 2013/11/15 08:36:09, rog wrote:
> > Passing thought: I wonder if this function and the above might work
better
> with
> > the cloudinit.Config as the first argument, as if it was the
receiver.

> Making it a receiver seems wrong to me, as that would suggest to me
that it's
> the cloudinit.Config configuring something else.

> As for the order here: I don't have a strong preference, I was just
keeping it
> consistent with Configure (input first, output second).

> > Also I'm not entirely sure that "Base" is quite right as a name -
with that
> > name, it sounds as if it's a necessary base that others must build
on, but
> since
> > the cloudinit config is passed in, that's not necessarily the case.

> I think it may just be confusing, given how generic the word "base"
is.

> ConfigureBase produces cloud-init that configures a "base OS image".
That is
> then built on by adding the juju bits (via ConfigureJuju).

> > As an alternative, we could make it return the new config:
> >
> > func BaseConfig(authorizedKeys string) *cloudinit.Config
> >
> > (no need to return an error, I think). Then it really would be a
base, because
> > everything would start with it.

> The thing is, not *everything* starts with it. Manual
bootstrap/provisioning
> doesn't use ConfigureBase, as they already have a "base".

> > Or alternatively rename it to something else; ConfigureBasic
perhaps?
> > I think my preference is for the above though.

> To me, Basic and Base have more or less the same connotations (except
Basic has
> an additional meaning of not-complex). I want to say
ConfigurePristine, but it
> isn't exactly (it adds SSH keys...).

As per discussion on IRC, ConfigureBase and ConfigureJuju can be
rejoined. I had thought I would need to split them, but as it turns out
I won't.

https://codereview.appspot.com/26570047/

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

LGTM with a couple of trivial thoughts below.

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit.go
File environs/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit.go#newcode127
environs/cloudinit.go:127: // to run on the instance. Use with care.
We should probably document that the scripts run before anything else.

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit/cloudinit.go
File environs/cloudinit/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit/cloudinit.go#newcode129
environs/cloudinit/cloudinit.go:129: // configuration to initialise a
Juju machine agent.
s/initialise/initialize/

might as well use the usual american spelling everywhere.

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit/cloudinit.go#newcode138
environs/cloudinit/cloudinit.go:138: c.SetOutput(cloudinit.OutAll, "|
tee -a /var/log/cloud-init-output.log", "")
Much nicer having this at the start, thanks.

https://codereview.appspot.com/26570047/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

Please take a look.

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit.go
File environs/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit.go#newcode127
environs/cloudinit.go:127: // to run on the instance. Use with care.
On 2013/11/15 10:01:44, rog wrote:
> We should probably document that the scripts run before anything else.

Done. Not quite before *everything* else, just the runcmds.

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit/cloudinit.go
File environs/cloudinit/cloudinit.go (right):

https://codereview.appspot.com/26570047/diff/20001/environs/cloudinit/cloudinit.go#newcode129
environs/cloudinit/cloudinit.go:129: // configuration to initialise a
Juju machine agent.
On 2013/11/15 10:01:44, rog wrote:
> s/initialise/initialize/

> might as well use the usual american spelling everywhere.

Done.

https://codereview.appspot.com/26570047/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2013/11/15 10:12:35, axw wrote:
> Please take a look.

I'm an idiot. We *do* need separate Configure methods: for (non-manual)
synchronous bootstrap. There we only want a base OS image with SSH keys
and cloud-init output logs configured. For manual bootstrap we don't
care, but for non-manual we do care.

I'll have to reinstate the two methods, but I'll try to come up with a
better name.

https://codereview.appspot.com/26570047/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'container/userdata.go'
2--- container/userdata.go 2013-11-11 21:54:29 +0000
3+++ container/userdata.go 2013-11-15 10:10:33 +0000
4@@ -11,6 +11,7 @@
5
6 "launchpad.net/loggo"
7
8+ coreCloudinit "launchpad.net/juju-core/cloudinit"
9 "launchpad.net/juju-core/environs/cloudinit"
10 "launchpad.net/juju-core/utils"
11 )
12@@ -37,7 +38,8 @@
13 func cloudInitUserData(machineConfig *cloudinit.MachineConfig) ([]byte, error) {
14 // consider not having this line hardcoded...
15 machineConfig.DataDir = "/var/lib/juju"
16- cloudConfig, err := cloudinit.New(machineConfig)
17+ cloudConfig := coreCloudinit.New()
18+ err := cloudinit.Configure(machineConfig, cloudConfig)
19 if err != nil {
20 return nil, err
21 }
22
23=== modified file 'environs/cloudinit.go'
24--- environs/cloudinit.go 2013-11-07 09:09:55 +0000
25+++ environs/cloudinit.go 2013-11-15 10:10:33 +0000
26@@ -124,13 +124,14 @@
27
28 // ComposeUserData puts together a binary (gzipped) blob of user data.
29 // The additionalScripts are additional command lines that you need cloudinit
30-// to run on the instance. Use with care.
31+// to run on the instance; they are executed before all other cloud-init
32+// runcmds. Use with care.
33 func ComposeUserData(cfg *cloudinit.MachineConfig, additionalScripts ...string) ([]byte, error) {
34 cloudcfg := coreCloudinit.New()
35 for _, script := range additionalScripts {
36 cloudcfg.AddRunCmd(script)
37 }
38- cloudcfg, err := cloudinit.Configure(cfg, cloudcfg)
39+ err := cloudinit.Configure(cfg, cloudcfg)
40 if err != nil {
41 return nil, err
42 }
43
44=== modified file 'environs/cloudinit/cloudinit.go'
45--- environs/cloudinit/cloudinit.go 2013-11-01 04:00:55 +0000
46+++ environs/cloudinit/cloudinit.go 2013-11-15 10:10:33 +0000
47@@ -125,16 +125,19 @@
48 return base64.StdEncoding.EncodeToString(data)
49 }
50
51-func New(cfg *MachineConfig) (*cloudinit.Config, error) {
52- c := cloudinit.New()
53- return Configure(cfg, c)
54-}
55-
56-func Configure(cfg *MachineConfig, c *cloudinit.Config) (*cloudinit.Config, error) {
57+// Configure updates the provided cloudinit.Config with
58+// configuration to initialize a Juju machine agent.
59+func Configure(cfg *MachineConfig, c *cloudinit.Config) error {
60 if err := verifyConfig(cfg); err != nil {
61- return nil, err
62+ return err
63 }
64+
65+ // General options.
66+ c.SetAptUpgrade(true)
67+ c.SetAptUpdate(true)
68+ c.SetOutput(cloudinit.OutAll, "| tee -a /var/log/cloud-init-output.log", "")
69 c.AddSSHAuthorizedKeys(cfg.AuthorizedKeys)
70+
71 c.AddPackage("git")
72 // Perfectly reasonable to install lxc on environment instances and kvm
73 // containers.
74@@ -161,7 +164,7 @@
75 }
76 toolsJson, err := json.Marshal(cfg.Tools)
77 if err != nil {
78- return nil, err
79+ return err
80 }
81 c.AddScripts(
82 "bin="+shquote(cfg.jujuTools()),
83@@ -176,7 +179,7 @@
84 )
85
86 if err := cfg.addLogging(c); err != nil {
87- return nil, err
88+ return err
89 }
90
91 // We add the machine agent's configuration info
92@@ -188,7 +191,7 @@
93 machineTag := names.MachineTag(cfg.MachineId)
94 _, err = cfg.addAgentInfo(c, machineTag)
95 if err != nil {
96- return nil, err
97+ return err
98 }
99
100 // Add the cloud archive cloud-tools pocket to apt sources
101@@ -212,7 +215,7 @@
102 certKey := string(cfg.StateServerCert) + string(cfg.StateServerKey)
103 c.AddFile(cfg.dataFile("server.pem"), certKey, 0600)
104 if err := cfg.addMongoToBoot(c); err != nil {
105- return nil, err
106+ return err
107 }
108 // We temporarily give bootstrap-state a directory
109 // of its own so that it can get the state info via the
110@@ -223,7 +226,7 @@
111 // We leave it for the time being for backward compatibility.
112 acfg, err := cfg.addAgentInfo(c, "bootstrap")
113 if err != nil {
114- return nil, err
115+ return err
116 }
117 cons := cfg.Constraints.String()
118 if cons != "" {
119@@ -241,15 +244,7 @@
120 )
121 }
122
123- if err := cfg.addMachineAgentToBoot(c, machineTag, cfg.MachineId); err != nil {
124- return nil, err
125- }
126-
127- // general options
128- c.SetAptUpgrade(true)
129- c.SetAptUpdate(true)
130- c.SetOutput(cloudinit.OutAll, "| tee -a /var/log/cloud-init-output.log", "")
131- return c, nil
132+ return cfg.addMachineAgentToBoot(c, machineTag, cfg.MachineId)
133 }
134
135 func (cfg *MachineConfig) addLogging(c *cloudinit.Config) error {
136
137=== modified file 'environs/cloudinit/cloudinit_test.go'
138--- environs/cloudinit/cloudinit_test.go 2013-10-23 23:54:55 +0000
139+++ environs/cloudinit/cloudinit_test.go 2013-11-15 10:10:33 +0000
140@@ -352,7 +352,8 @@
141 if test.setEnvConfig {
142 test.cfg.Config = minimalConfig(c)
143 }
144- ci, err := cloudinit.New(&test.cfg)
145+ ci := coreCloudinit.New()
146+ err := cloudinit.Configure(&test.cfg, ci)
147 c.Assert(err, gc.IsNil)
148 c.Check(ci, gc.NotNil)
149 // render the cloudinit config to bytes, and then
150@@ -394,9 +395,8 @@
151 test.cfg.Config = minimalConfig(c)
152 c.Logf("test %d (Configure)", i)
153 cloudcfg := coreCloudinit.New()
154- ci, err := cloudinit.Configure(&test.cfg, cloudcfg)
155+ err := cloudinit.Configure(&test.cfg, cloudcfg)
156 c.Assert(err, gc.IsNil)
157- c.Check(ci, gc.NotNil)
158 }
159 }
160
161@@ -406,10 +406,9 @@
162 script := "test script"
163 cloudcfg.AddRunCmd(script)
164 cloudinitTests[0].cfg.Config = minimalConfig(c)
165- ci, err := cloudinit.Configure(&cloudinitTests[0].cfg, cloudcfg)
166+ err := cloudinit.Configure(&cloudinitTests[0].cfg, cloudcfg)
167 c.Assert(err, gc.IsNil)
168- c.Check(ci, gc.NotNil)
169- data, err := ci.Render()
170+ data, err := cloudcfg.Render()
171 c.Assert(err, gc.IsNil)
172
173 ciContent := make(map[interface{}]interface{})
174@@ -683,16 +682,16 @@
175 MachineNonce: "FAKE_NONCE",
176 }
177 // check that the base configuration does not give an error
178- _, err := cloudinit.New(cfg)
179+ ci := coreCloudinit.New()
180+ err := cloudinit.Configure(cfg, ci)
181 c.Assert(err, gc.IsNil)
182
183 for i, test := range verifyTests {
184 c.Logf("test %d. %s", i, test.err)
185 cfg1 := *cfg
186 test.mutate(&cfg1)
187- t, err := cloudinit.New(&cfg1)
188+ err = cloudinit.Configure(&cfg1, ci)
189 c.Assert(err, gc.ErrorMatches, "invalid machine configuration: "+test.err)
190- c.Assert(t, gc.IsNil)
191 }
192 }
193
194
195=== modified file 'environs/manual/agent.go'
196--- environs/manual/agent.go 2013-11-01 04:06:00 +0000
197+++ environs/manual/agent.go 2013-11-15 10:10:33 +0000
198@@ -9,49 +9,23 @@
199 "os"
200 "strings"
201
202- "launchpad.net/juju-core/agent"
203 corecloudinit "launchpad.net/juju-core/cloudinit"
204- "launchpad.net/juju-core/constraints"
205- "launchpad.net/juju-core/environs"
206 "launchpad.net/juju-core/environs/cloudinit"
207- "launchpad.net/juju-core/environs/config"
208- "launchpad.net/juju-core/provider"
209- "launchpad.net/juju-core/state"
210- "launchpad.net/juju-core/state/api"
211- "launchpad.net/juju-core/tools"
212 "launchpad.net/juju-core/utils"
213 )
214
215-type provisionMachineAgentArgs struct {
216- host string
217- dataDir string
218- bootstrap bool
219- environConfig *config.Config
220- machineId string
221- nonce string
222- stateFileURL string
223- stateInfo *state.Info
224- apiInfo *api.Info
225- tools *tools.Tools
226-
227- // agentEnv is an optional map of
228- // arbitrary key/value pairs to pass
229- // into the machine agent.
230- agentEnv map[string]string
231-}
232-
233-// provisionMachineAgent connects to a machine over SSH,
234-// copies across the tools, and installs a machine agent.
235-func provisionMachineAgent(args provisionMachineAgentArgs) error {
236- logger.Infof("Provisioning machine agent on %s", args.host)
237- script, err := provisionMachineAgentScript(args)
238+// ProvisionMachineAgent connects to a machine over SSH,
239+// and installs a machine agent.
240+func ProvisionMachineAgent(host string, mcfg *cloudinit.MachineConfig) error {
241+ logger.Infof("Provisioning machine agent on %s", host)
242+ script, err := provisionMachineAgentScript(mcfg)
243 if err != nil {
244 return err
245 }
246 scriptBase64 := base64.StdEncoding.EncodeToString([]byte(script))
247 script = fmt.Sprintf(`F=$(mktemp); echo %s | base64 -d > $F; . $F`, scriptBase64)
248 cmd := sshCommand(
249- args.host,
250+ host,
251 fmt.Sprintf("sudo bash -c '%s'", script),
252 allocateTTY,
253 )
254@@ -62,31 +36,13 @@
255 }
256
257 // provisionMachineAgentScript generates the script necessary
258-// to install a machine agent on the specified host.
259-func provisionMachineAgentScript(args provisionMachineAgentArgs) (string, error) {
260+// to install a machine agent with the provided MachineConfig.
261+func provisionMachineAgentScript(mcfg *cloudinit.MachineConfig) (string, error) {
262 // We generate a cloud-init config, which we'll then pull the runcmds
263 // and prerequisite packages out of. Rather than generating a cloud-config,
264 // we'll just generate a shell script.
265- var mcfg *cloudinit.MachineConfig
266- if args.bootstrap {
267- mcfg = environs.NewBootstrapMachineConfig(args.stateFileURL)
268- } else {
269- mcfg = environs.NewMachineConfig(args.machineId, args.nonce, args.stateInfo, args.apiInfo)
270- }
271- if args.dataDir != "" {
272- mcfg.DataDir = args.dataDir
273- }
274- mcfg.Tools = args.tools
275- err := environs.FinishMachineConfig(mcfg, args.environConfig, constraints.Value{})
276- if err != nil {
277- return "", err
278- }
279- mcfg.AgentEnvironment[agent.ProviderType] = provider.Null
280- for k, v := range args.agentEnv {
281- mcfg.AgentEnvironment[k] = v
282- }
283 cloudcfg := corecloudinit.New()
284- if cloudcfg, err = cloudinit.Configure(mcfg, cloudcfg); err != nil {
285+ if err := cloudinit.Configure(mcfg, cloudcfg); err != nil {
286 return "", err
287 }
288
289@@ -148,7 +104,7 @@
290 }
291 cmds = append(cmds, "apt-add-repository -y "+utils.ShQuote(src.Source))
292 }
293- if cfg.AptUpdate() {
294+ if len(cfg.AptSources()) > 0 {
295 cmds = append(cmds, "apt-get -y update")
296 }
297 // Note: explicitly ignoring apt_upgrade, so as not to trample the target
298
299=== modified file 'environs/manual/agent_test.go'
300--- environs/manual/agent_test.go 2013-11-01 04:06:00 +0000
301+++ environs/manual/agent_test.go 2013-11-15 10:10:33 +0000
302@@ -6,6 +6,9 @@
303 import (
304 gc "launchpad.net/gocheck"
305
306+ "launchpad.net/juju-core/constraints"
307+ "launchpad.net/juju-core/environs"
308+ "launchpad.net/juju-core/environs/cloudinit"
309 "launchpad.net/juju-core/environs/config"
310 envtools "launchpad.net/juju-core/environs/tools"
311 _ "launchpad.net/juju-core/provider/dummy"
312@@ -34,20 +37,21 @@
313 return testConfig
314 }
315
316-func (s *agentSuite) getArgs(c *gc.C, stateServer bool, vers version.Binary) provisionMachineAgentArgs {
317- tools := &tools.Tools{Version: vers}
318- tools.URL = "file:///var/lib/juju/storage/" + envtools.StorageName(vers)
319- return provisionMachineAgentArgs{
320- bootstrap: stateServer,
321- environConfig: dummyConfig(c, stateServer, vers),
322- machineId: "0",
323- nonce: "ya",
324- stateFileURL: "http://whatever/dotcom",
325- tools: tools,
326- // stateInfo *state.Info
327- // apiInfo *api.Info
328- agentEnv: make(map[string]string),
329- }
330+func (s *agentSuite) getMachineConfig(c *gc.C, stateServer bool, vers version.Binary) *cloudinit.MachineConfig {
331+ var mcfg *cloudinit.MachineConfig
332+ if stateServer {
333+ mcfg = environs.NewBootstrapMachineConfig("http://whatever/dotcom")
334+ } else {
335+ mcfg = environs.NewMachineConfig("0", "ya", nil, nil)
336+ }
337+ mcfg.Tools = &tools.Tools{
338+ Version: vers,
339+ URL: "file:///var/lib/juju/storage/" + envtools.StorageName(vers),
340+ }
341+ environConfig := dummyConfig(c, stateServer, vers)
342+ err := environs.FinishMachineConfig(mcfg, environConfig, constraints.Value{})
343+ c.Assert(err, gc.IsNil)
344+ return mcfg
345 }
346
347 var allSeries = [...]string{"precise", "quantal", "raring", "saucy"}
348@@ -62,7 +66,7 @@
349 func (s *agentSuite) TestAptSources(c *gc.C) {
350 for _, series := range allSeries {
351 vers := version.MustParseBinary("1.16.0-" + series + "-amd64")
352- script, err := provisionMachineAgentScript(s.getArgs(c, true, vers))
353+ script, err := provisionMachineAgentScript(s.getMachineConfig(c, true, vers))
354 c.Assert(err, gc.IsNil)
355
356 // Only Precise requires the cloud-tools pocket.
357
358=== modified file 'environs/manual/bootstrap.go'
359--- environs/manual/bootstrap.go 2013-10-02 10:38:04 +0000
360+++ environs/manual/bootstrap.go 2013-11-15 10:10:33 +0000
361@@ -7,11 +7,11 @@
362 "errors"
363 "fmt"
364
365+ "launchpad.net/juju-core/constraints"
366 "launchpad.net/juju-core/environs"
367 envtools "launchpad.net/juju-core/environs/tools"
368 "launchpad.net/juju-core/instance"
369 "launchpad.net/juju-core/provider/common"
370- "launchpad.net/juju-core/state"
371 "launchpad.net/juju-core/tools"
372 "launchpad.net/juju-core/worker/localstorage"
373 )
374@@ -108,15 +108,17 @@
375
376 // Finally, provision the machine agent.
377 stateFileURL := fmt.Sprintf("file://%s/%s", storageDir, common.StateFile)
378- err = provisionMachineAgent(provisionMachineAgentArgs{
379- host: args.Host,
380- dataDir: args.DataDir,
381- environConfig: args.Environ.Config(),
382- stateFileURL: stateFileURL,
383- bootstrap: true,
384- nonce: state.BootstrapNonce,
385- tools: &tools,
386- agentEnv: agentEnv,
387- })
388- return err
389+ mcfg := environs.NewBootstrapMachineConfig(stateFileURL)
390+ if args.DataDir != "" {
391+ mcfg.DataDir = args.DataDir
392+ }
393+ mcfg.Tools = &tools
394+ err = environs.FinishMachineConfig(mcfg, args.Environ.Config(), constraints.Value{})
395+ if err != nil {
396+ return err
397+ }
398+ for k, v := range agentEnv {
399+ mcfg.AgentEnvironment[k] = v
400+ }
401+ return ProvisionMachineAgent(args.Host, mcfg)
402 }
403
404=== modified file 'environs/manual/provisioner.go'
405--- environs/manual/provisioner.go 2013-11-08 02:52:25 +0000
406+++ environs/manual/provisioner.go 2013-11-15 10:10:33 +0000
407@@ -11,6 +11,9 @@
408
409 "launchpad.net/loggo"
410
411+ "launchpad.net/juju-core/constraints"
412+ "launchpad.net/juju-core/environs"
413+ "launchpad.net/juju-core/environs/cloudinit"
414 "launchpad.net/juju-core/environs/config"
415 "launchpad.net/juju-core/instance"
416 "launchpad.net/juju-core/juju"
417@@ -80,16 +83,13 @@
418 }
419
420 // Gather the information needed by the machine agent to run the provisioning script.
421- provisioningArgs, err := createProvisioningArgs(client, machineId, series, arch)
422+ mcfg, err := createMachineConfig(client, machineId, series, arch, nonce, args.DataDir)
423 if err != nil {
424 return machineId, err
425 }
426- provisioningArgs.host = args.Host
427- provisioningArgs.dataDir = args.DataDir
428- provisioningArgs.nonce = nonce
429
430 // Finally, provision the machine agent.
431- err = provisionMachineAgent(*provisioningArgs)
432+ err = ProvisionMachineAgent(args.Host, mcfg)
433 if err != nil {
434 return machineId, err
435 }
436@@ -170,12 +170,11 @@
437 return machineInfo.Machine, series, *hc.Arch, nil
438 }
439
440-func createProvisioningArgs(client *api.Client, machineId, series, arch string) (*provisionMachineAgentArgs, error) {
441+func createMachineConfig(client *api.Client, machineId, series, arch, nonce, dataDir string) (*cloudinit.MachineConfig, error) {
442 configParameters, err := client.MachineConfig(machineId, series, arch)
443 if err != nil {
444 return nil, err
445 }
446-
447 stateInfo := &state.Info{
448 Addrs: configParameters.StateAddrs,
449 Password: configParameters.Password,
450@@ -192,13 +191,14 @@
451 if err != nil {
452 return nil, err
453 }
454-
455- return &provisionMachineAgentArgs{
456- environConfig: environConfig,
457- machineId: machineId,
458- bootstrap: false,
459- stateInfo: stateInfo,
460- apiInfo: apiInfo,
461- tools: configParameters.Tools,
462- }, nil
463+ mcfg := environs.NewMachineConfig(machineId, nonce, stateInfo, apiInfo)
464+ if dataDir != "" {
465+ mcfg.DataDir = dataDir
466+ }
467+ mcfg.Tools = configParameters.Tools
468+ err = environs.FinishMachineConfig(mcfg, environConfig, constraints.Value{})
469+ if err != nil {
470+ return nil, err
471+ }
472+ return mcfg, nil
473 }

Subscribers

People subscribed via source and target branches

to status/vote changes: