Merge lp:~dave-cheney/juju-core/080-conn-update-secrets-only-if-needed into lp:~juju/juju-core/trunk
- 080-conn-update-secrets-only-if-needed
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Dave Cheney |
Proposed branch: | lp:~dave-cheney/juju-core/080-conn-update-secrets-only-if-needed |
Merge into: | lp:~juju/juju-core/trunk |
Diff against target: |
1047 lines (+354/-195) (has conflicts) 14 files modified
cmd/juju/cmd_test.go (+1/-1) cmd/juju/main_test.go (+2/-2) environs/cloudinit/cloudinit.go (+8/-8) environs/cloudinit/cloudinit_test.go (+36/-16) environs/config.go (+19/-0) environs/config/config.go (+3/-1) environs/dummy/environs.go (+28/-7) environs/ec2/ec2.go (+11/-24) environs/jujutest/test.go (+14/-19) environs/tools.go (+35/-14) environs/tools_test.go (+152/-101) juju/conn.go (+20/-0) juju/conn_test.go (+24/-1) state/machine.go (+1/-1) Text conflict in juju/conn.go |
To merge this branch: | bzr merge lp:~dave-cheney/juju-core/080-conn-update-secrets-only-if-needed |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
The Go Language Gophers | Pending | ||
Review via email: mp+121979@code.launchpad.net |
Commit message
Description of the change
juju: update unknown config attrs once
Additional UnknownAttrs from the local environment
will only be applied if they do not already exist in
the state.
Dave Cheney (dave-cheney) wrote : | # |
Gustavo Niemeyer (niemeyer) wrote : | # |
http://
File juju/conn.go (right):
http://
juju/conn.go:92: env.Set(k, v)
Aug 30 22:15:25 <niemeyer> I suspect it's a bit more involved than
that
Aug 30 22:15:52 <niemeyer> As the comment suggests, we should only
push secrets when they are not yet set, and should push *only* secrets
Gustavo Niemeyer (niemeyer) wrote : | # |
Cool, I added some comments for the record, and.. well, not sure if we
should close this one?
Gustavo Niemeyer (niemeyer) wrote : | # |
Ah, nevermind.. it looks already rejected. I probably looked at
out-of-date information, sorry.
Unmerged revisions
- 452. By Dave Cheney
-
merge from prereq
- 451. By Dave Cheney
-
wip
- 450. By Dave Cheney
-
only update non existing UnknownAttrs
- 449. By Dave Cheney
-
merge from trunk
- 448. By Dave Cheney
-
wip
- 447. By Dave Cheney
-
environs/dummy: add delay
This proposal implements a delay in most dummy operations. The delay
can be set test wide by setting JUJU_DUMMY_DELAY to a time.Duration
parsable value.R=niemeyer
CC=
https://codereview. appspot. com/6482081 - 446. By Dave Cheney
-
environs/ec2: log open/close port details
https:/
/bugs.launchpad .net/juju- core/+bug/ 1042073 Added logging of security group name to successful
open/close port operation.R=niemeyer
CC=
https://codereview. appspot. com/6490049 - 445. By Dave Cheney
-
environs/cloudinit: deploy mongo debs
Install mongo debs alongside zookeeper ones.
R=niemeyer
CC=
https://codereview. appspot. com/6501054 - 444. By Dave Cheney
-
environs/cloudinit: ZooKeeper -> StateServer
This proposal is part of a set to add support for deploying
an environment on MongoDB in parallel with ZooKeeper.R=niemeyer
CC=
https://codereview. appspot. com/6497051 - 443. By Roger Peppe
-
testing: define and use all fixture methods.
When a helper suite defines only a subset of the available
fixture methods, it invites problems if that subset changes.
By making all helper suites define all fixture methods,
we make it easy to mechanically check that
a helper suite is being used correctly without going
to look at the source for that suite.R=niemeyer
CC=
https://codereview. appspot. com/6472053
Preview Diff
1 | === modified file 'cmd/juju/cmd_test.go' |
2 | --- cmd/juju/cmd_test.go 2012-08-28 17:33:59 +0000 |
3 | +++ cmd/juju/cmd_test.go 2012-08-31 02:04:18 +0000 |
4 | @@ -149,7 +149,7 @@ |
5 | }() |
6 | environs.VarDir = c.MkDir() |
7 | |
8 | - tools, err := environs.FindTools(env, version.Current) |
9 | + tools, err := environs.FindTools(env, version.Current, environs.CompatVersion) |
10 | c.Assert(err, IsNil) |
11 | resp, err := http.Get(tools.URL) |
12 | c.Assert(err, IsNil) |
13 | |
14 | === modified file 'cmd/juju/main_test.go' |
15 | --- cmd/juju/main_test.go 2012-08-09 01:37:27 +0000 |
16 | +++ cmd/juju/main_test.go 2012-08-31 02:04:18 +0000 |
17 | @@ -121,7 +121,7 @@ |
18 | c.Assert(out, Equals, "error: "+msg+"\n") |
19 | content, err := ioutil.ReadFile(logpath) |
20 | c.Assert(err, IsNil) |
21 | - fullmsg := fmt.Sprintf(`.* JUJU:DEBUG juju bootstrap command failed: %s\n`, msg) |
22 | + fullmsg := fmt.Sprintf(`(.|\n)*JUJU:DEBUG juju bootstrap command failed: %s\n`, msg) |
23 | c.Assert(string(content), Matches, fullmsg) |
24 | } |
25 | |
26 | @@ -134,7 +134,7 @@ |
27 | c.Assert(out, Equals, "error: "+msg+"\n") |
28 | content, err := ioutil.ReadFile(logpath) |
29 | c.Assert(err, IsNil) |
30 | - fullmsg := fmt.Sprintf(`.* JUJU:DEBUG juju bootstrap command failed: %s\n`, msg) |
31 | + fullmsg := fmt.Sprintf(`(.|\n)*JUJU:DEBUG juju bootstrap command failed: %s\n`, msg) |
32 | c.Assert(string(content), Matches, fullmsg) |
33 | } |
34 | |
35 | |
36 | === modified file 'environs/cloudinit/cloudinit.go' |
37 | --- environs/cloudinit/cloudinit.go 2012-08-29 22:46:46 +0000 |
38 | +++ environs/cloudinit/cloudinit.go 2012-08-31 02:04:18 +0000 |
39 | @@ -6,7 +6,7 @@ |
40 | "launchpad.net/goyaml" |
41 | "launchpad.net/juju-core/cloudinit" |
42 | "launchpad.net/juju-core/environs" |
43 | - "launchpad.net/juju-core/log" |
44 | + "launchpad.net/juju-core/environs/config" |
45 | "launchpad.net/juju-core/state" |
46 | "launchpad.net/juju-core/upstart" |
47 | "path" |
48 | @@ -56,9 +56,8 @@ |
49 | // commands cannot work. |
50 | AuthorizedKeys string |
51 | |
52 | - // Config is map that is provided to juju bootstrap-state's --env-config |
53 | - // option for initializing the environment configuration. |
54 | - Config map[string]interface{} |
55 | + // Config holds the initial environment configuration. |
56 | + Config *config.Config |
57 | } |
58 | |
59 | type requiresError string |
60 | @@ -73,8 +72,8 @@ |
61 | } |
62 | } |
63 | |
64 | -func base64yaml(m map[string]interface{}) string { |
65 | - data, err := goyaml.Marshal(m) |
66 | +func base64yaml(m *config.Config) string { |
67 | + data, err := goyaml.Marshal(m.AllAttrs()) |
68 | if err != nil { |
69 | // can't happen, these values have been validated a number of times |
70 | panic(err) |
71 | @@ -119,9 +118,7 @@ |
72 | ) |
73 | |
74 | debugFlag := "" |
75 | - if log.Debug { |
76 | debugFlag = " --debug" |
77 | - } |
78 | |
79 | if cfg.StateServer { |
80 | // zookeeper scripts |
81 | @@ -223,6 +220,9 @@ |
82 | if cfg.InstanceIdAccessor == "" { |
83 | return requiresError("instance id accessor") |
84 | } |
85 | + if cfg.Config == nil { |
86 | + return requiresError("environment configuration") |
87 | + } |
88 | } else { |
89 | if cfg.StateInfo == nil || len(cfg.StateInfo.Addrs) == 0 { |
90 | return requiresError("zookeeper hosts") |
91 | |
92 | === modified file 'environs/cloudinit/cloudinit_test.go' |
93 | --- environs/cloudinit/cloudinit_test.go 2012-08-29 22:50:49 +0000 |
94 | +++ environs/cloudinit/cloudinit_test.go 2012-08-31 02:04:18 +0000 |
95 | @@ -4,6 +4,7 @@ |
96 | "encoding/base64" |
97 | . "launchpad.net/gocheck" |
98 | "launchpad.net/goyaml" |
99 | + "launchpad.net/juju-core/environs/config" |
100 | "launchpad.net/juju-core/environs" |
101 | "launchpad.net/juju-core/environs/cloudinit" |
102 | "launchpad.net/juju-core/state" |
103 | @@ -18,6 +19,21 @@ |
104 | |
105 | var _ = Suite(cloudinitSuite{}) |
106 | |
107 | +var envConfig = mustNewConfig(map[string] interface{} { |
108 | + "type": "ec2", |
109 | + "name": "foo", |
110 | + "default-series": "series", |
111 | + "authorized-keys": "keys", |
112 | + }) |
113 | + |
114 | +func mustNewConfig(m map[string] interface{}) *config.Config { |
115 | + cfg, err := config.New(m) |
116 | + if err != nil { |
117 | + panic(err) |
118 | + } |
119 | + return cfg |
120 | +} |
121 | + |
122 | // Each test gives a cloudinit config - we check the |
123 | // output to see if it looks correct. |
124 | var cloudinitTests = []cloudinit.MachineConfig{ |
125 | @@ -29,7 +45,7 @@ |
126 | AuthorizedKeys: "sshkey1", |
127 | Tools: newSimpleTools("1.2.3-linux-amd64"), |
128 | StateServer: true, |
129 | - Config: map[string]interface{}{"name": "foo", "zookeeper": true}, |
130 | + Config: envConfig, |
131 | }, |
132 | { |
133 | MachineId: 99, |
134 | @@ -65,15 +81,16 @@ |
135 | if t.cfg.StateServer { |
136 | // TODO(dfc) remove this after the switch to mstate |
137 | t.checkPackage(c, "zookeeperd") |
138 | - |
139 | t.checkPackage(c, "mongodb-server") |
140 | t.checkScripts(c, "jujud bootstrap-state") |
141 | - t.checkEnvConfig(c) |
142 | t.checkScripts(c, regexp.QuoteMeta(t.cfg.InstanceIdAccessor)) |
143 | t.checkScripts(c, "JUJU_ZOOKEEPER='localhost"+cloudinit.ZkPortSuffix+"'") |
144 | } else { |
145 | t.checkScripts(c, "JUJU_ZOOKEEPER='"+strings.Join(t.cfg.StateInfo.Addrs, ",")+"'") |
146 | } |
147 | + if t.cfg.Config != nil { |
148 | + t.checkEnvConfig(c) |
149 | + } |
150 | t.checkPackage(c, "libzookeeper-mt2") |
151 | t.checkScripts(c, "JUJU_MACHINE_ID=[0-9]+") |
152 | |
153 | @@ -96,20 +113,20 @@ |
154 | return |
155 | } |
156 | scripts := scripts0.([]interface{}) |
157 | - re := regexp.MustCompile(`--env-config '[\w,=]+'`) |
158 | + re := regexp.MustCompile(`--env-config '([\w,=]+)'`) |
159 | found := false |
160 | for _, s0 := range scripts { |
161 | - if s := re.FindString(s0.(string)); len(s) > 0 { |
162 | - found = true |
163 | - v := strings.Split(s, `'`) |
164 | - c.Assert(len(v), Equals, 3) |
165 | - buf, err := base64.StdEncoding.DecodeString(v[1]) |
166 | - c.Assert(err, IsNil) |
167 | - actual := make(map[string]interface{}) |
168 | - err = goyaml.Unmarshal(buf, &actual) |
169 | - c.Assert(err, IsNil) |
170 | - c.Assert(t.cfg.Config, DeepEquals, actual) |
171 | + m := re.FindStringSubmatch(s0.(string)) |
172 | + if m == nil { |
173 | + continue |
174 | } |
175 | + found = true |
176 | + buf, err := base64.StdEncoding.DecodeString(m[1]) |
177 | + c.Assert(err, IsNil) |
178 | + var actual map[string]interface{} |
179 | + err = goyaml.Unmarshal(buf, &actual) |
180 | + c.Assert(err, IsNil) |
181 | + c.Assert(t.cfg.Config.AllAttrs(), DeepEquals, actual) |
182 | } |
183 | c.Assert(found, Equals, true) |
184 | } |
185 | @@ -182,7 +199,7 @@ |
186 | // in cloudinitTests is well formed. |
187 | func (cloudinitSuite) TestCloudInit(c *C) { |
188 | for i, cfg := range cloudinitTests { |
189 | - c.Logf("check %d", i) |
190 | + c.Logf("test %d, config %v, envConfig %v", i, cfg.Config, envConfig) |
191 | ci, err := cloudinit.New(&cfg) |
192 | c.Assert(err, IsNil) |
193 | c.Check(ci, NotNil) |
194 | @@ -217,9 +234,11 @@ |
195 | {"negative machine id", func(cfg *cloudinit.MachineConfig) { cfg.MachineId = -1 }}, |
196 | {"missing provider type", func(cfg *cloudinit.MachineConfig) { cfg.ProviderType = "" }}, |
197 | {"missing instance id accessor", func(cfg *cloudinit.MachineConfig) { |
198 | - cfg.StateServer = true |
199 | cfg.InstanceIdAccessor = "" |
200 | }}, |
201 | + {"missing environment configuration", func(cfg *cloudinit.MachineConfig) { |
202 | + cfg.Config = nil |
203 | + }}, |
204 | {"missing zookeeper hosts", func(cfg *cloudinit.MachineConfig) { |
205 | cfg.StateServer = false |
206 | cfg.StateInfo = nil |
207 | @@ -250,6 +269,7 @@ |
208 | Tools: newSimpleTools("9.9.9-linux-arble"), |
209 | AuthorizedKeys: "sshkey1", |
210 | StateInfo: &state.Info{Addrs: []string{"zkhost"}}, |
211 | + Config: envConfig, |
212 | } |
213 | // check that the base configuration does not give an error |
214 | _, err := cloudinit.New(cfg) |
215 | |
216 | === modified file 'environs/config.go' |
217 | --- environs/config.go 2012-07-26 13:37:51 +0000 |
218 | +++ environs/config.go 2012-08-31 02:04:18 +0000 |
219 | @@ -6,6 +6,7 @@ |
220 | "io/ioutil" |
221 | "launchpad.net/goyaml" |
222 | "launchpad.net/juju-core/environs/config" |
223 | + "launchpad.net/juju-core/state" |
224 | "os" |
225 | "path/filepath" |
226 | ) |
227 | @@ -138,3 +139,21 @@ |
228 | } |
229 | return e, nil |
230 | } |
231 | + |
232 | +// BootstrapConfig returns an environment configuration suitable for |
233 | +// priming the juju state using the given provider, configuration and |
234 | +// tools. |
235 | +// |
236 | +// The returned configuration contains no secret attributes. |
237 | +func BootstrapConfig(p EnvironProvider, cfg *config.Config, tools *state.Tools) (*config.Config, error) { |
238 | + secrets, err := p.SecretAttrs(cfg) |
239 | + if err != nil { |
240 | + return nil, err |
241 | + } |
242 | + m := cfg.AllAttrs() |
243 | + for k, _ := range secrets { |
244 | + delete(m, k) |
245 | + } |
246 | + m["agent-version"] = tools.Number.String() |
247 | + return config.New(m) |
248 | +} |
249 | |
250 | === modified file 'environs/config/config.go' |
251 | --- environs/config/config.go 2012-08-30 12:21:22 +0000 |
252 | +++ environs/config/config.go 2012-08-31 02:04:18 +0000 |
253 | @@ -15,6 +15,8 @@ |
254 | // Fields that are common to all environment providers are verified, |
255 | // and authorized-keys-path is also translated into authorized-keys |
256 | // by loading the content from respective file. |
257 | +// |
258 | +// The required keys are: "name", "type", "default-series" and "authorized-keys". |
259 | func New(attrs map[string]interface{}) (*Config, error) { |
260 | m, err := checker.Coerce(attrs, nil) |
261 | if err != nil { |
262 | @@ -63,7 +65,7 @@ |
263 | return c, nil |
264 | } |
265 | |
266 | -// Type returns the enviornment type. |
267 | +// Type returns the environment type. |
268 | func (c *Config) Type() string { |
269 | return c.m["type"].(string) |
270 | } |
271 | |
272 | === modified file 'environs/dummy/environs.go' |
273 | --- environs/dummy/environs.go 2012-08-30 02:34:58 +0000 |
274 | +++ environs/dummy/environs.go 2012-08-31 02:04:18 +0000 |
275 | @@ -29,6 +29,7 @@ |
276 | "launchpad.net/juju-core/schema" |
277 | "launchpad.net/juju-core/state" |
278 | "launchpad.net/juju-core/testing" |
279 | + "launchpad.net/juju-core/version" |
280 | "net" |
281 | "net/http" |
282 | "os" |
283 | @@ -179,10 +180,24 @@ |
284 | } |
285 | s.storage = newStorage(s, "/"+name+"/private") |
286 | s.publicStorage = newStorage(s, "/"+name+"/public") |
287 | + putFakeTools(s.publicStorage) |
288 | s.listen() |
289 | return s |
290 | } |
291 | |
292 | +// putFakeTools writes something |
293 | +// that looks like a tools archive so Bootstrap can |
294 | +// find some tools and initialise the state correctly. |
295 | +func putFakeTools(s environs.StorageWriter) { |
296 | + log.Printf("putting fake tools") |
297 | + path := environs.ToolsStoragePath(version.Current) |
298 | + toolsContents := "tools archive, honest guv" |
299 | + err := s.Put(path, strings.NewReader(toolsContents), int64(len(toolsContents))) |
300 | + if err != nil { |
301 | + panic(err) |
302 | + } |
303 | +} |
304 | + |
305 | // listen starts a network listener listening for http |
306 | // requests to retrieve files in the state's storage. |
307 | func (s *environState) listen() { |
308 | @@ -340,8 +355,16 @@ |
309 | if err := e.checkBroken("Bootstrap"); err != nil { |
310 | return err |
311 | } |
312 | + var tools *state.Tools |
313 | + var err error |
314 | if uploadTools { |
315 | - _, err := environs.PutTools(e.Storage(), nil) |
316 | + tools, err = environs.PutTools(e.Storage(), nil) |
317 | + if err != nil { |
318 | + return err |
319 | + } |
320 | + } else { |
321 | + flags := environs.HighestVersion|environs.CompatVersion |
322 | + tools, err = environs.FindTools(e, version.Current, flags) |
323 | if err != nil { |
324 | return err |
325 | } |
326 | @@ -354,13 +377,11 @@ |
327 | } |
328 | if e.ecfg().zookeeper() { |
329 | info := stateInfo() |
330 | - config := map[string]interface{}{ |
331 | - "type": "dummy", |
332 | - "zookeeper": true, |
333 | - "name": e.ecfg().Name(), |
334 | - "authorized-keys": e.ecfg().AuthorizedKeys(), |
335 | + cfg, err := environs.BootstrapConfig(&providerInstance, e.ecfg().Config, tools) |
336 | + if err != nil { |
337 | + return err |
338 | } |
339 | - st, err := state.Initialize(info, config) |
340 | + st, err := state.Initialize(info, cfg.AllAttrs()) |
341 | if err != nil { |
342 | panic(err) |
343 | } |
344 | |
345 | === modified file 'environs/ec2/ec2.go' |
346 | --- environs/ec2/ec2.go 2012-08-29 23:08:25 +0000 |
347 | +++ environs/ec2/ec2.go 2012-08-31 02:04:18 +0000 |
348 | @@ -123,25 +123,6 @@ |
349 | return m, nil |
350 | } |
351 | |
352 | -func (environProvider) publicAttrs(cfg *config.Config) (map[string]interface{}, error) { |
353 | - m := make(map[string]interface{}) |
354 | - ecfg, err := providerInstance.newConfig(cfg) |
355 | - if err != nil { |
356 | - return nil, err |
357 | - } |
358 | - for k, v := range ecfg.UnknownAttrs() { |
359 | - m[k] = v |
360 | - } |
361 | - secret, err := providerInstance.SecretAttrs(cfg) |
362 | - if err != nil { |
363 | - return nil, err |
364 | - } |
365 | - for k, _ := range secret { |
366 | - delete(m, k) |
367 | - } |
368 | - return m, nil |
369 | -} |
370 | - |
371 | func (environProvider) PublicAddress() (string, error) { |
372 | return fetchMetadata("public-hostname") |
373 | } |
374 | @@ -240,9 +221,14 @@ |
375 | if err != nil { |
376 | return fmt.Errorf("cannot upload tools: %v", err) |
377 | } |
378 | + } else { |
379 | + flags := environs.HighestVersion|environs.CompatVersion |
380 | + tools, err = environs.FindTools(e, version.Current, flags) |
381 | + if err != nil { |
382 | + return fmt.Errorf("cannot find tools: %v", err) |
383 | + } |
384 | } |
385 | - |
386 | - config, err := providerInstance.publicAttrs(e.Config()) |
387 | + config, err := environs.BootstrapConfig(providerInstance, e.Config(), tools) |
388 | if err != nil { |
389 | return fmt.Errorf("unable to determine inital configuration: %v", err) |
390 | } |
391 | @@ -311,7 +297,7 @@ |
392 | return e.startInstance(machineId, info, tools, false, nil) |
393 | } |
394 | |
395 | -func (e *environ) userData(machineId int, info *state.Info, tools *state.Tools, master bool, config map[string]interface{}) ([]byte, error) { |
396 | +func (e *environ) userData(machineId int, info *state.Info, tools *state.Tools, master bool, config *config.Config) ([]byte, error) { |
397 | cfg := &cloudinit.MachineConfig{ |
398 | Provisioner: master, |
399 | StateServer: master, |
400 | @@ -333,10 +319,11 @@ |
401 | // startInstance is the internal version of StartInstance, used by Bootstrap |
402 | // as well as via StartInstance itself. If master is true, a bootstrap |
403 | // instance will be started. |
404 | -func (e *environ) startInstance(machineId int, info *state.Info, tools *state.Tools, master bool, config map[string]interface{}) (environs.Instance, error) { |
405 | +func (e *environ) startInstance(machineId int, info *state.Info, tools *state.Tools, master bool, config *config.Config) (environs.Instance, error) { |
406 | if tools == nil { |
407 | var err error |
408 | - tools, err = environs.FindTools(e, version.Current) |
409 | + flags := environs.HighestVersion|environs.CompatVersion |
410 | + tools, err = environs.FindTools(e, version.Current, flags) |
411 | if err != nil { |
412 | return nil, err |
413 | } |
414 | |
415 | === modified file 'environs/jujutest/test.go' |
416 | --- environs/jujutest/test.go 2012-07-06 05:32:25 +0000 |
417 | +++ environs/jujutest/test.go 2012-08-31 02:04:18 +0000 |
418 | @@ -4,6 +4,7 @@ |
419 | . "launchpad.net/gocheck" |
420 | "launchpad.net/juju-core/environs" |
421 | "launchpad.net/juju-core/state" |
422 | + "launchpad.net/juju-core/testing" |
423 | "time" |
424 | ) |
425 | |
426 | @@ -19,6 +20,7 @@ |
427 | // is opened once for each test, and some potentially expensive operations |
428 | // may be executed. |
429 | type Tests struct { |
430 | + testing.LoggingSuite |
431 | Environs *environs.Environs |
432 | Name string |
433 | Env environs.Environ |
434 | @@ -32,25 +34,22 @@ |
435 | return e |
436 | } |
437 | |
438 | -func (t *Tests) SetUpSuite(*C) { |
439 | -} |
440 | - |
441 | -func (t *Tests) TearDownSuite(*C) { |
442 | -} |
443 | - |
444 | func (t *Tests) SetUpTest(c *C) { |
445 | + t.LoggingSuite.SetUpTest(c) |
446 | t.Env = t.Open(c) |
447 | } |
448 | |
449 | -func (t *Tests) TearDownTest(*C) { |
450 | +func (t *Tests) TearDownTest(c *C) { |
451 | t.Env.Destroy(nil) |
452 | t.Env = nil |
453 | + t.LoggingSuite.TearDownTest(c) |
454 | } |
455 | |
456 | // LiveTests contains tests that are designed to run against a live server |
457 | // (e.g. Amazon EC2). The Environ is opened once only for all the tests |
458 | // in the suite, stored in Env, and Destroyed after the suite has completed. |
459 | type LiveTests struct { |
460 | + testing.LoggingSuite |
461 | Environs *environs.Environs |
462 | Name string |
463 | Env environs.Environ |
464 | @@ -70,12 +69,20 @@ |
465 | } |
466 | |
467 | func (t *LiveTests) SetUpSuite(c *C) { |
468 | + t.LoggingSuite.SetUpSuite(c) |
469 | e, err := t.Environs.Open(t.Name) |
470 | c.Assert(err, IsNil, Commentf("opening environ %q", t.Name)) |
471 | c.Assert(e, NotNil) |
472 | t.Env = e |
473 | } |
474 | |
475 | +func (t *LiveTests) TearDownSuite(c *C) { |
476 | + err := t.Env.Destroy(nil) |
477 | + c.Check(err, IsNil) |
478 | + t.Env = nil |
479 | + t.LoggingSuite.TearDownSuite(c) |
480 | +} |
481 | + |
482 | func (t *LiveTests) BootstrapOnce(c *C) { |
483 | if t.bootstrapped { |
484 | return |
485 | @@ -90,15 +97,3 @@ |
486 | c.Assert(err, IsNil) |
487 | t.bootstrapped = false |
488 | } |
489 | - |
490 | -func (t *LiveTests) TearDownSuite(c *C) { |
491 | - err := t.Env.Destroy(nil) |
492 | - c.Check(err, IsNil) |
493 | - t.Env = nil |
494 | -} |
495 | - |
496 | -func (t *LiveTests) SetUpTest(*C) { |
497 | -} |
498 | - |
499 | -func (t *LiveTests) TearDownTest(*C) { |
500 | -} |
501 | |
502 | === modified file 'environs/tools.go' |
503 | --- environs/tools.go 2012-08-29 16:54:01 +0000 |
504 | +++ environs/tools.go 2012-08-31 02:04:18 +0000 |
505 | @@ -204,27 +204,29 @@ |
506 | |
507 | // BestTools returns the most recent version |
508 | // from the set of tools in the ToolsList that are |
509 | -// compatible with the given version, and with a version |
510 | -// number <= vers.Number, or nil if no such tools are found. |
511 | -// If dev is true, it will consider development versions of the tools |
512 | -// even if vers is not a development version. |
513 | -func BestTools(list *ToolsList, vers version.Binary, dev bool) *state.Tools { |
514 | - if tools := bestTools(list.Private, vers, dev); tools != nil { |
515 | +// compatible with the given version, using flags |
516 | +// to determine possible candidates. |
517 | +// It returns nil if no such tools are found. |
518 | +func BestTools(list *ToolsList, vers version.Binary, flags ToolsSearchFlags) *state.Tools { |
519 | + if flags&CompatVersion == 0 { |
520 | + panic("CompatVersion not implemented") |
521 | + } |
522 | + if tools := bestTools(list.Private, vers, flags); tools != nil { |
523 | return tools |
524 | } |
525 | - return bestTools(list.Public, vers, dev) |
526 | + return bestTools(list.Public, vers, flags) |
527 | } |
528 | |
529 | // bestTools is like BestTools but operates on a single list of tools. |
530 | -func bestTools(toolsList []*state.Tools, vers version.Binary, dev bool) *state.Tools { |
531 | +func bestTools(toolsList []*state.Tools, vers version.Binary, flags ToolsSearchFlags) *state.Tools { |
532 | var bestTools *state.Tools |
533 | - allowDev := vers.IsDev() || dev |
534 | + allowDev := vers.IsDev() || flags&DevVersion != 0 |
535 | for _, t := range toolsList { |
536 | if t.Major != vers.Major || |
537 | t.Series != vers.Series || |
538 | t.Arch != vers.Arch || |
539 | !allowDev && t.IsDev() || |
540 | - vers.Number.Less(t.Number) { |
541 | + flags&HighestVersion == 0 && vers.Number.Less(t.Number) { |
542 | continue |
543 | } |
544 | if bestTools == nil || bestTools.Number.Less(t.Number) { |
545 | @@ -379,19 +381,38 @@ |
546 | return path.Join(VarDir, "tools", agentName) |
547 | } |
548 | |
549 | +// ToolsSearchFlags gives options when searching |
550 | +// for tools. |
551 | +type ToolsSearchFlags int |
552 | +const ( |
553 | + // HighestVersion specifies that the highest (minor, patch) version number should |
554 | + // be chosen. The default is to choose a version no higher than specified. |
555 | + HighestVersion ToolsSearchFlags = 1<<iota |
556 | + |
557 | + // DevVersion specifies "dev mode" - it allows a development version to |
558 | + // be chosen even when the specified version is not a development |
559 | + // version. |
560 | + DevVersion |
561 | + |
562 | + // CompatVersion specifies that the major version number |
563 | + // must be the same as specified. It is not yet implemented. |
564 | + CompatVersion |
565 | +) |
566 | + |
567 | // FindTools tries to find a set of tools compatible with the given |
568 | -// version from the given environment. The latest version found with a |
569 | -// number <= vers.Number will be used. |
570 | +// version from the given environment, using flags to determine |
571 | +// possible candidates. |
572 | // |
573 | // If no tools are found and there's no other error, a NotFoundError is |
574 | // returned. If there's anything compatible in the environ's Storage, |
575 | // it gets precedence over anything in its PublicStorage. |
576 | -func FindTools(env Environ, vers version.Binary) (*state.Tools, error) { |
577 | +func FindTools(env Environ, vers version.Binary, flags ToolsSearchFlags) (*state.Tools, error) { |
578 | toolsList, err := ListTools(env, vers.Major) |
579 | if err != nil { |
580 | return nil, err |
581 | } |
582 | - tools := BestTools(toolsList, vers, false) |
583 | + log.Printf("findTools got tools list %v", toolsList) |
584 | + tools := BestTools(toolsList, vers, flags) |
585 | if tools == nil { |
586 | return tools, &NotFoundError{fmt.Errorf("no compatible tools found")} |
587 | } |
588 | |
589 | === modified file 'environs/tools_test.go' |
590 | --- environs/tools_test.go 2012-08-29 16:54:01 +0000 |
591 | +++ environs/tools_test.go 2012-08-31 02:04:18 +0000 |
592 | @@ -384,6 +384,7 @@ |
593 | |
594 | var findToolsTests = []struct { |
595 | version version.Number // version to assume is current for the test. |
596 | + flags environs.ToolsSearchFlags |
597 | contents []string // names in private storage. |
598 | publicContents []string // names in public storage. |
599 | expect string // the name we expect to find (if no error). |
600 | @@ -391,35 +392,34 @@ |
601 | }{{ |
602 | // current version should be satisfied by current tools path. |
603 | version: version.Current.Number, |
604 | + flags: environs.CompatVersion, |
605 | contents: []string{environs.ToolsStoragePath(version.Current)}, |
606 | expect: environs.ToolsStoragePath(version.Current), |
607 | }, { |
608 | - // major versions don't match. |
609 | - version: version.MustParse("1.0.0"), |
610 | + // highest version of tools is chosen. |
611 | + version: version.MustParse("0.0.0"), |
612 | + flags: environs.HighestVersion|environs.DevVersion|environs.CompatVersion, |
613 | contents: []string{ |
614 | toolsStoragePath("0.0.9"), |
615 | - }, |
616 | - err: "no compatible tools found", |
617 | -}, { |
618 | - // major versions don't match. |
619 | - version: version.MustParse("1.0.0"), |
620 | - contents: []string{ |
621 | - toolsStoragePath("2.0.9"), |
622 | - }, |
623 | - err: "no compatible tools found", |
624 | + toolsStoragePath("0.1.9"), |
625 | + }, |
626 | + expect: toolsStoragePath("0.1.9"), |
627 | }, { |
628 | // fall back to public storage when nothing found in private. |
629 | - version: version.MustParse("1.0.0"), |
630 | + version: version.MustParse("1.0.2"), |
631 | + flags: environs.DevVersion|environs.CompatVersion, |
632 | contents: []string{ |
633 | toolsStoragePath("0.0.9"), |
634 | }, |
635 | publicContents: []string{ |
636 | toolsStoragePath("1.0.0"), |
637 | + toolsStoragePath("1.0.1"), |
638 | }, |
639 | - expect: "public-" + toolsStoragePath("1.0.0"), |
640 | + expect: "public-" + toolsStoragePath("1.0.1"), |
641 | }, { |
642 | // always use private storage in preference to public storage. |
643 | version: version.MustParse("1.9.0"), |
644 | + flags: environs.DevVersion|environs.CompatVersion, |
645 | contents: []string{ |
646 | toolsStoragePath("1.0.2"), |
647 | }, |
648 | @@ -428,43 +428,9 @@ |
649 | }, |
650 | expect: toolsStoragePath("1.0.2"), |
651 | }, { |
652 | - // we'll use an earlier version if the major version number matches. |
653 | - version: version.MustParse("1.99.99"), |
654 | - contents: []string{ |
655 | - toolsStoragePath("1.0.0"), |
656 | - }, |
657 | - expect: toolsStoragePath("1.0.0"), |
658 | -}, { |
659 | - // check that version comparing is numeric, not alphabetical. |
660 | - version: version.MustParse("1.0.99"), |
661 | - contents: []string{ |
662 | - toolsStoragePath("1.0.9"), |
663 | - toolsStoragePath("1.0.10"), |
664 | - toolsStoragePath("1.0.11"), |
665 | - }, |
666 | - expect: toolsStoragePath("1.0.11"), |
667 | -}, { |
668 | - // minor version wins over patch version. |
669 | - version: version.MustParse("1.99.99"), |
670 | - contents: []string{ |
671 | - toolsStoragePath("1.9.11"), |
672 | - toolsStoragePath("1.10.10"), |
673 | - toolsStoragePath("1.11.9"), |
674 | - }, |
675 | - expect: toolsStoragePath("1.11.9"), |
676 | -}, { |
677 | - // only earlier versions are chosen. |
678 | - version: version.MustParse("1.10.9"), |
679 | - contents: []string{ |
680 | - toolsStoragePath("1.9.10"), |
681 | - toolsStoragePath("1.9.11"), |
682 | - toolsStoragePath("1.10.10"), |
683 | - toolsStoragePath("1.11.9"), |
684 | - }, |
685 | - expect: toolsStoragePath("1.9.11"), |
686 | -}, { |
687 | // mismatching series or architecture is ignored. |
688 | version: version.MustParse("1.0.0"), |
689 | + flags: environs.CompatVersion, |
690 | contents: []string{ |
691 | environs.ToolsStoragePath(version.Binary{ |
692 | Number: version.MustParse("1.9.9"), |
693 | @@ -508,10 +474,11 @@ |
694 | Series: version.Current.Series, |
695 | Arch: version.Current.Arch, |
696 | } |
697 | - tools, err := environs.FindTools(t.env, vers) |
698 | + tools, err := environs.FindTools(t.env, vers, tt.flags) |
699 | if tt.err != "" { |
700 | c.Assert(err, ErrorMatches, tt.err) |
701 | } else { |
702 | + c.Assert(err, IsNil) |
703 | assertURLContents(c, tools.URL, tt.expect) |
704 | } |
705 | t.env.Destroy(nil) |
706 | @@ -613,15 +580,53 @@ |
707 | var bestToolsTests = []struct { |
708 | list *environs.ToolsList |
709 | vers version.Binary |
710 | - dev bool |
711 | + flags environs.ToolsSearchFlags |
712 | expect *state.Tools |
713 | + expectDev *state.Tools |
714 | + expectHighest *state.Tools |
715 | + expectDevHighest *state.Tools |
716 | }{{ |
717 | - &environs.ToolsList{}, |
718 | - binaryVersion("1.2.3-precise-amd64"), |
719 | - true, |
720 | - nil, |
721 | -}, { |
722 | - &environs.ToolsList{ |
723 | + // 0. Check that we don't get anything from an empty list. |
724 | + list: &environs.ToolsList{}, |
725 | + vers: binaryVersion("1.2.3-precise-amd64"), |
726 | + flags: environs.DevVersion|environs.CompatVersion, |
727 | + expect: nil, |
728 | +}, { |
729 | + // 1. Check that we can choose the same development version. |
730 | + list: &environs.ToolsList{ |
731 | + Private: []*state.Tools{ |
732 | + newTools("1.0.0-precise-amd64", ""), |
733 | + }, |
734 | + }, |
735 | + vers: binaryVersion("1.0.0-precise-amd64"), |
736 | + expect: newTools("1.0.0-precise-amd64", ""), |
737 | + expectDev: newTools("1.0.0-precise-amd64", ""), |
738 | + expectHighest: newTools("1.0.0-precise-amd64", ""), |
739 | + expectDevHighest: newTools("1.0.0-precise-amd64", ""), |
740 | +}, { |
741 | + // 2. Check that major versions need to match. |
742 | + list: &environs.ToolsList{ |
743 | + Private: []*state.Tools{ |
744 | + newTools("2.0.0-precise-amd64", ""), |
745 | + newTools("6.0.0-precise-amd64", ""), |
746 | + }, |
747 | + }, |
748 | + vers: binaryVersion("4.0.0-precise-amd64"), |
749 | +}, { |
750 | + // 3. Check that we can choose the same released version. |
751 | + list: &environs.ToolsList{ |
752 | + Private: []*state.Tools{ |
753 | + newTools("2.0.0-precise-amd64", ""), |
754 | + }, |
755 | + }, |
756 | + vers: binaryVersion("2.0.0-precise-amd64"), |
757 | + expect: newTools("2.0.0-precise-amd64", ""), |
758 | + expectDev: newTools("2.0.0-precise-amd64", ""), |
759 | + expectHighest: newTools("2.0.0-precise-amd64", ""), |
760 | + expectDevHighest: newTools("2.0.0-precise-amd64", ""), |
761 | +}, { |
762 | + // 4. Check that different arch/series are ignored. |
763 | + list: &environs.ToolsList{ |
764 | Private: []*state.Tools{ |
765 | newTools("1.2.3-precise-amd64", ""), |
766 | newTools("1.2.4-precise-amd64", ""), |
767 | @@ -631,29 +636,31 @@ |
768 | newTools("2.2.3-precise-amd64", ""), |
769 | }, |
770 | }, |
771 | - binaryVersion("1.9.4-precise-amd64"), |
772 | - true, |
773 | - newTools("1.3.4-precise-amd64", ""), |
774 | + vers: binaryVersion("1.9.4-precise-amd64"), |
775 | + expect: newTools("1.3.4-precise-amd64", ""), |
776 | + expectDev: newTools("1.3.4-precise-amd64", ""), |
777 | + expectHighest: newTools("1.3.4-precise-amd64", ""), |
778 | + expectDevHighest: newTools("1.3.4-precise-amd64", ""), |
779 | }, { |
780 | - // Check that we can't upgrade to a dev version from |
781 | + // 5. Check that we can't upgrade to a dev version from |
782 | // a release version if dev is false. |
783 | - &environs.ToolsList{ |
784 | + list: &environs.ToolsList{ |
785 | Private: []*state.Tools{ |
786 | newTools("2.2.3-precise-amd64", ""), |
787 | newTools("2.2.4-precise-amd64", ""), |
788 | newTools("2.3.4-precise-amd64", ""), |
789 | - newTools("2.4.4-precise-i386", ""), |
790 | - newTools("2.4.5-quantal-i386", ""), |
791 | newTools("3.2.3-precise-amd64", ""), |
792 | }, |
793 | }, |
794 | - binaryVersion("2.8.8-precise-amd64"), |
795 | - false, |
796 | - newTools("2.2.4-precise-amd64", ""), |
797 | + vers: binaryVersion("2.8.8-precise-amd64"), |
798 | + expect: newTools("2.2.4-precise-amd64", ""), |
799 | + expectDev: newTools("2.3.4-precise-amd64", ""), |
800 | + expectHighest: newTools("2.2.4-precise-amd64", ""), |
801 | + expectDevHighest: newTools("2.3.4-precise-amd64", ""), |
802 | }, { |
803 | - // Check that we can upgrade to a release version from |
804 | + // 6. Check that we can upgrade to a release version from |
805 | // a dev version if dev is false. |
806 | - &environs.ToolsList{ |
807 | + list: &environs.ToolsList{ |
808 | Private: []*state.Tools{ |
809 | newTools("2.2.3-precise-amd64", ""), |
810 | newTools("2.2.4-precise-amd64", ""), |
811 | @@ -662,12 +669,14 @@ |
812 | newTools("3.2.3-precise-amd64", ""), |
813 | }, |
814 | }, |
815 | - binaryVersion("2.8.8-precise-amd64"), |
816 | - false, |
817 | - newTools("2.4.4-precise-amd64", ""), |
818 | + vers: binaryVersion("2.8.8-precise-amd64"), |
819 | + expect: newTools("2.4.4-precise-amd64", ""), |
820 | + expectDev: newTools("2.4.4-precise-amd64", ""), |
821 | + expectHighest: newTools("2.4.4-precise-amd64", ""), |
822 | + expectDevHighest: newTools("2.4.4-precise-amd64", ""), |
823 | }, { |
824 | - // Check that a different major version works ok. |
825 | - &environs.ToolsList{ |
826 | + // 7. Check that a different minor version works ok. |
827 | + list: &environs.ToolsList{ |
828 | Private: []*state.Tools{ |
829 | newTools("1.2.3-precise-amd64", ""), |
830 | newTools("1.2.4-precise-amd64", ""), |
831 | @@ -677,54 +686,96 @@ |
832 | newTools("2.2.3-precise-amd64", ""), |
833 | }, |
834 | }, |
835 | - binaryVersion("2.8.8-precise-amd64"), |
836 | - true, |
837 | - newTools("2.2.3-precise-amd64", ""), |
838 | + vers: binaryVersion("2.8.8-precise-amd64"), |
839 | + expect: nil, |
840 | + expectDev: newTools("2.2.3-precise-amd64", ""), |
841 | + expectHighest: nil, |
842 | + expectDevHighest: newTools("2.2.3-precise-amd64", ""), |
843 | }, { |
844 | - // Check that the private tools are chosen even though |
845 | + // 8. Check that the private tools are chosen even though |
846 | // they have a lower version number. |
847 | - &environs.ToolsList{ |
848 | + list: &environs.ToolsList{ |
849 | Private: []*state.Tools{ |
850 | - newTools("1.2.3-precise-amd64", ""), |
851 | + newTools("1.2.2-precise-amd64", ""), |
852 | }, |
853 | Public: []*state.Tools{ |
854 | newTools("1.2.4-precise-amd64", ""), |
855 | }, |
856 | }, |
857 | - binaryVersion("1.8.8-precise-amd64"), |
858 | - true, |
859 | - newTools("1.2.3-precise-amd64", ""), |
860 | + vers: binaryVersion("1.8.8-precise-amd64"), |
861 | + expect: newTools("1.2.2-precise-amd64", ""), |
862 | + expectDev: newTools("1.2.2-precise-amd64", ""), |
863 | + expectHighest: newTools("1.2.2-precise-amd64", ""), |
864 | + expectDevHighest: newTools("1.2.2-precise-amd64", ""), |
865 | }, { |
866 | - // Check that the public tools can be chosen when |
867 | + // 9. Check that the public tools can be chosen when |
868 | // there are no private tools. |
869 | - &environs.ToolsList{ |
870 | + list: &environs.ToolsList{ |
871 | Public: []*state.Tools{ |
872 | newTools("1.2.4-precise-amd64", ""), |
873 | }, |
874 | }, |
875 | - binaryVersion("1.8.9-precise-amd64"), |
876 | - true, |
877 | - newTools("1.2.4-precise-amd64", ""), |
878 | -}, { |
879 | - // Check that we don't choose a version later |
880 | - // than requested. |
881 | - &environs.ToolsList{ |
882 | - Public: []*state.Tools{ |
883 | - newTools("1.2.2-precise-amd64", ""), |
884 | - newTools("1.2.3-precise-amd64", ""), |
885 | - newTools("1.3.4-precise-amd64", ""), |
886 | - }, |
887 | - }, |
888 | - binaryVersion("1.3.3-precise-amd64"), |
889 | - true, |
890 | - newTools("1.2.3-precise-amd64", ""), |
891 | + vers: binaryVersion("1.8.9-precise-amd64"), |
892 | + expect: newTools("1.2.4-precise-amd64", ""), |
893 | + expectDev: newTools("1.2.4-precise-amd64", ""), |
894 | + expectHighest: newTools("1.2.4-precise-amd64", ""), |
895 | + expectDevHighest: newTools("1.2.4-precise-amd64", ""), |
896 | +}, { |
897 | + // 10. One test giving different values for all flag combinations. |
898 | + list: &environs.ToolsList{ |
899 | + Public: []*state.Tools{ |
900 | + newTools("0.2.0-precise-amd64", ""), |
901 | + newTools("0.2.1-precise-amd64", ""), |
902 | + newTools("0.4.2-precise-amd64", ""), |
903 | + newTools("0.4.3-precise-amd64", ""), |
904 | + }, |
905 | + }, |
906 | + vers: binaryVersion("0.2.2-precise-amd64"), |
907 | + expect: newTools("0.2.0-precise-amd64", ""), |
908 | + expectDev: newTools("0.2.1-precise-amd64", ""), |
909 | + expectHighest: newTools("0.4.2-precise-amd64", ""), |
910 | + expectDevHighest: newTools("0.4.3-precise-amd64", ""), |
911 | +}, { |
912 | + // 11. check that version comparing is numeric, not alphabetical. |
913 | + list: &environs.ToolsList{ |
914 | + Public: []*state.Tools{ |
915 | + newTools("0.0.9-precise-amd64", ""), |
916 | + newTools("0.0.10-precise-amd64", ""), |
917 | + newTools("0.0.11-precise-amd64", ""), |
918 | + }, |
919 | + }, |
920 | + vers: binaryVersion("0.0.98-precise-amd64"), |
921 | + expect: newTools("0.0.10-precise-amd64", ""), |
922 | + expectDev: newTools("0.0.11-precise-amd64", ""), |
923 | + expectHighest: newTools("0.0.10-precise-amd64", ""), |
924 | + expectDevHighest: newTools("0.0.11-precise-amd64", ""), |
925 | +}, { |
926 | + // 12. check that minor version wins over patch version. |
927 | + list: &environs.ToolsList{ |
928 | + Public: []*state.Tools{ |
929 | + newTools("0.9.11-precise-amd64", ""), |
930 | + newTools("0.10.10-precise-amd64", ""), |
931 | + newTools("0.11.9-precise-amd64", ""), |
932 | + }, |
933 | + }, |
934 | + vers: binaryVersion("0.10.10-precise-amd64"), |
935 | + expect: newTools("0.10.10-precise-amd64", ""), |
936 | + expectDev: newTools("0.10.10-precise-amd64", ""), |
937 | + expectHighest: newTools("0.10.10-precise-amd64", ""), |
938 | + expectDevHighest: newTools("0.11.9-precise-amd64", ""), |
939 | }, |
940 | } |
941 | |
942 | func (t *ToolsSuite) TestBestTools(c *C) { |
943 | for i, t := range bestToolsTests { |
944 | c.Logf("test %d", i) |
945 | - tools := environs.BestTools(t.list, t.vers, t.dev) |
946 | + tools := environs.BestTools(t.list, t.vers, environs.CompatVersion) |
947 | c.Assert(tools, DeepEquals, t.expect) |
948 | + tools = environs.BestTools(t.list, t.vers, environs.DevVersion|environs.CompatVersion) |
949 | + c.Assert(tools, DeepEquals, t.expectDev) |
950 | + tools = environs.BestTools(t.list, t.vers, environs.HighestVersion|environs.CompatVersion) |
951 | + c.Assert(tools, DeepEquals, t.expectHighest) |
952 | + tools = environs.BestTools(t.list, t.vers, environs.DevVersion|environs.HighestVersion|environs.CompatVersion) |
953 | + c.Assert(tools, DeepEquals, t.expectDevHighest) |
954 | } |
955 | } |
956 | |
957 | === modified file 'juju/conn.go' |
958 | --- juju/conn.go 2012-08-30 13:21:00 +0000 |
959 | +++ juju/conn.go 2012-08-31 02:04:18 +0000 |
960 | @@ -82,11 +82,31 @@ |
961 | // from the local configuration. |
962 | func (c *Conn) updateSecrets() error { |
963 | cfg := c.Environ.Config() |
964 | +<<<<<<< TREE |
965 | // This is wrong. This will _always_ overwrite the secrets |
966 | // in the state with the local secrets. To fix this properly |
967 | // we need to ensure that the config, minus secrets, is always |
968 | // pushed on bootstrap, then we can fill in the secrets here. |
969 | return c.state.SetEnvironConfig(cfg) |
970 | +======= |
971 | + env, err := c.state.EnvironConfig() |
972 | + if err != nil { |
973 | + return err |
974 | + } |
975 | + for k, v := range cfg.UnknownAttrs() { |
976 | + if _, exists := env.Get(k); !exists { |
977 | + env.Set(k, v) |
978 | + } |
979 | + } |
980 | + n, err := env.Write() |
981 | + if err != nil { |
982 | + return err |
983 | + } |
984 | + if len(n) > 0 { |
985 | + log.Debugf("Updating %d secret(s) in environment %q", len(n), c.Environ.Name()) |
986 | + } |
987 | + return nil |
988 | +>>>>>>> MERGE-SOURCE |
989 | } |
990 | |
991 | // Close terminates the connection to the environment and releases |
992 | |
993 | === modified file 'juju/conn_test.go' |
994 | --- juju/conn_test.go 2012-08-30 13:21:00 +0000 |
995 | +++ juju/conn_test.go 2012-08-31 02:04:18 +0000 |
996 | @@ -92,7 +92,7 @@ |
997 | c.Assert(err, ErrorMatches, "dummy environment not bootstrapped") |
998 | } |
999 | |
1000 | -func (cs *ConnSuite) TestConnStateSecretsSideEffect(c *C) { |
1001 | +func (*ConnSuite) TestConnStateSecretsSideEffect(c *C) { |
1002 | env, err := environs.NewFromAttrs(map[string]interface{}{ |
1003 | "name": "erewhemos", |
1004 | "type": "dummy", |
1005 | @@ -129,6 +129,29 @@ |
1006 | c.Assert(cfg.UnknownAttrs()["secret"], Equals, "pork") |
1007 | } |
1008 | |
1009 | +func (cs *ConnSuite) TestConnStateDoesNotUpdateExistingSecrets(c *C) { |
1010 | + cs.TestConnStateSecretsSideEffect(c) |
1011 | + conn, err := juju.NewConnFromAttrs(map[string]interface{}{ |
1012 | + "name": "erewhemos", |
1013 | + "type": "dummy", |
1014 | + "zookeeper": true, |
1015 | + "authorized-keys": "i-am-a-key", |
1016 | + "secret": "squirrel", |
1017 | + }) |
1018 | + c.Assert(err, IsNil) |
1019 | + defer conn.Close() |
1020 | + st, err := conn.State() |
1021 | + c.Assert(err, IsNil) |
1022 | + cfg, err := st.EnvironConfig() |
1023 | + c.Assert(err, IsNil) |
1024 | + err = cfg.Read() |
1025 | + c.Assert(err, IsNil) |
1026 | + // check that the secret has not changed |
1027 | + secret, ok := cfg.Get("secret") |
1028 | + c.Assert(ok, Equals, true) |
1029 | + c.Assert(secret, Equals, "pork") |
1030 | +} |
1031 | + |
1032 | func (*ConnSuite) TestValidRegexps(c *C) { |
1033 | assertService := func(s string, expect bool) { |
1034 | c.Assert(juju.ValidService.MatchString(s), Equals, expect) |
1035 | |
1036 | === modified file 'state/machine.go' |
1037 | --- state/machine.go 2012-08-17 12:10:32 +0000 |
1038 | +++ state/machine.go 2012-08-31 02:04:18 +0000 |
1039 | @@ -71,7 +71,7 @@ |
1040 | "instance id of machine %v", m.String()) |
1041 | if _, ok := err.(*NotFoundError); ok || (err == nil && instanceId == "") { |
1042 | return "", &NotFoundError{ |
1043 | - fmt.Sprintf("instance id for machine %d is not set", m.Id()), |
1044 | + fmt.Sprintf("instance id for machine %d", m.Id()), |
1045 | } |
1046 | } |
1047 | return instanceId, err |
Please hold off on reviewing this proposal. Tests pass, but an actual deployment fails because the common attributes of the config are not being populated.