Merge lp:~natefinch/juju-core/fix-win-bootstrap into lp:~go-bot/juju-core/trunk
- fix-win-bootstrap
- Merge into trunk
Proposed by
Nate Finch
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Nate Finch | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 1995 | ||||
Proposed branch: | lp:~natefinch/juju-core/fix-win-bootstrap | ||||
Merge into: | lp:~go-bot/juju-core/trunk | ||||
Diff against target: |
624 lines (+366/-52) (has conflicts) 14 files modified
charm/repo.go (+2/-1) cmd/plugins/juju-metadata/validateimagemetadata_test.go (+38/-0) environs/configstore/disk.go (+1/-1) environs/filestorage/filestorage.go (+1/-1) environs/sync/sync.go (+10/-0) environs/sync/sync_test.go (+26/-1) environs/tools/simplestreams_test.go (+113/-0) provider/maas/instance_test.go (+93/-45) utils/file_unix.go (+15/-0) utils/file_windows.go (+35/-0) utils/fslock/fslock.go (+2/-2) utils/trivial.go (+1/-1) utils/zfile_windows.go (+25/-0) version/version.go (+4/-0) Text conflict in cmd/plugins/juju-metadata/validateimagemetadata_test.go Text conflict in environs/sync/sync_test.go Text conflict in environs/tools/simplestreams_test.go Text conflict in provider/maas/instance_test.go Text conflict in version/version.go |
||||
To merge this branch: | bzr merge lp:~natefinch/juju-core/fix-win-bootstrap | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email:
|
Commit message
merge windows fix back to trunk
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'charm/repo.go' |
2 | --- charm/repo.go 2013-07-09 10:32:23 +0000 |
3 | +++ charm/repo.go 2013-10-17 18:24:24 +0000 |
4 | @@ -17,6 +17,7 @@ |
5 | "strings" |
6 | |
7 | "launchpad.net/juju-core/log" |
8 | + "launchpad.net/juju-core/utils" |
9 | ) |
10 | |
11 | // CacheDir stores the charm cache directory path. |
12 | @@ -257,7 +258,7 @@ |
13 | os.Remove(dlPath) |
14 | return nil, err |
15 | } |
16 | - if err := os.Rename(dlPath, path); err != nil { |
17 | + if err := utils.ReplaceFile(dlPath, path); err != nil { |
18 | return nil, err |
19 | } |
20 | } |
21 | |
22 | === modified file 'cmd/plugins/juju-metadata/validateimagemetadata_test.go' |
23 | --- cmd/plugins/juju-metadata/validateimagemetadata_test.go 2013-10-17 05:37:00 +0000 |
24 | +++ cmd/plugins/juju-metadata/validateimagemetadata_test.go 2013-10-17 18:24:24 +0000 |
25 | @@ -19,9 +19,14 @@ |
26 | ) |
27 | |
28 | type ValidateImageMetadataSuite struct { |
29 | +<<<<<<< TREE |
30 | testbase.LoggingSuite |
31 | home *coretesting.FakeHome |
32 | metadataDir string |
33 | +======= |
34 | + testbase.LoggingSuite |
35 | + home *coretesting.FakeHome |
36 | +>>>>>>> MERGE-SOURCE |
37 | } |
38 | |
39 | var _ = gc.Suite(&ValidateImageMetadataSuite{}) |
40 | @@ -89,6 +94,10 @@ |
41 | environments: |
42 | ec2: |
43 | type: ec2 |
44 | +<<<<<<< TREE |
45 | +======= |
46 | + control-bucket: foo |
47 | +>>>>>>> MERGE-SOURCE |
48 | default-series: precise |
49 | region: us-east-1 |
50 | |
51 | @@ -102,11 +111,22 @@ |
52 | ` |
53 | |
54 | func (s *ValidateImageMetadataSuite) SetUpTest(c *gc.C) { |
55 | +<<<<<<< TREE |
56 | s.LoggingSuite.SetUpTest(c) |
57 | s.metadataDir = c.MkDir() |
58 | +======= |
59 | + s.LoggingSuite.SetUpTest(c) |
60 | +>>>>>>> MERGE-SOURCE |
61 | s.home = coretesting.MakeFakeHome(c, metadataTestEnvConfig) |
62 | +<<<<<<< TREE |
63 | s.PatchEnvironment("AWS_ACCESS_KEY_ID", "access") |
64 | s.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "secret") |
65 | +======= |
66 | + restore := testbase.PatchEnvironment("AWS_ACCESS_KEY_ID", "access") |
67 | + s.AddCleanup(func(*gc.C) { restore() }) |
68 | + restore = testbase.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "secret") |
69 | + s.AddCleanup(func(*gc.C) { restore() }) |
70 | +>>>>>>> MERGE-SOURCE |
71 | } |
72 | |
73 | func (s *ValidateImageMetadataSuite) TearDownTest(c *gc.C) { |
74 | @@ -135,6 +155,7 @@ |
75 | c.Check(strippedOut, gc.Matches, `matching image ids for region "us-east-1":.*`) |
76 | } |
77 | |
78 | +<<<<<<< TREE |
79 | func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataUsingIncompleteEnvironment(c *gc.C) { |
80 | testbase.PatchEnvironment("AWS_ACCESS_KEY_ID", "") |
81 | testbase.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "") |
82 | @@ -151,6 +172,23 @@ |
83 | c.Check(strippedOut, gc.Matches, `error: environment has no access-key or secret-key`) |
84 | } |
85 | |
86 | +======= |
87 | +func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataUsingIncompleteEnvironment(c *gc.C) { |
88 | + testbase.PatchEnvironment("AWS_ACCESS_KEY_ID", "") |
89 | + testbase.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "") |
90 | + s.setupEc2LocalMetadata(c, "us-east-1") |
91 | + ctx := coretesting.Context(c) |
92 | + metadataDir := config.JujuHomePath("") |
93 | + code := cmd.Main( |
94 | + &ValidateImageMetadataCommand{}, ctx, []string{"-e", "ec2", "-d", metadataDir}, |
95 | + ) |
96 | + c.Assert(code, gc.Equals, 1) |
97 | + errOut := ctx.Stderr.(*bytes.Buffer).String() |
98 | + strippedOut := strings.Replace(errOut, "\n", "", -1) |
99 | + c.Check(strippedOut, gc.Matches, `error: environment has no access-key or secret-key`) |
100 | +} |
101 | + |
102 | +>>>>>>> MERGE-SOURCE |
103 | func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataWithManualParams(c *gc.C) { |
104 | s.setupEc2LocalMetadata(c, "us-west-1") |
105 | ctx := coretesting.Context(c) |
106 | |
107 | === modified file 'environs/configstore/disk.go' |
108 | --- environs/configstore/disk.go 2013-10-02 15:39:37 +0000 |
109 | +++ environs/configstore/disk.go 2013-10-17 18:24:24 +0000 |
110 | @@ -199,7 +199,7 @@ |
111 | if err != nil { |
112 | return fmt.Errorf("cannot write temporary file: %v", err) |
113 | } |
114 | - if err := os.Rename(tmpFile.Name(), info.path); err != nil { |
115 | + if err := utils.ReplaceFile(tmpFile.Name(), info.path); err != nil { |
116 | os.Remove(tmpFile.Name()) |
117 | return fmt.Errorf("cannot rename new environment info file: %v", err) |
118 | } |
119 | |
120 | === modified file 'environs/filestorage/filestorage.go' |
121 | --- environs/filestorage/filestorage.go 2013-09-20 04:41:12 +0000 |
122 | +++ environs/filestorage/filestorage.go 2013-10-17 18:24:24 +0000 |
123 | @@ -151,7 +151,7 @@ |
124 | os.Remove(file.Name()) |
125 | return err |
126 | } |
127 | - return os.Rename(file.Name(), fullpath) |
128 | + return utils.ReplaceFile(file.Name(), fullpath) |
129 | } |
130 | |
131 | func (f *fileStorageWriter) Remove(name string) error { |
132 | |
133 | === modified file 'environs/imagemetadata/simplestreams.go' |
134 | === modified file 'environs/imagemetadata/simplestreams_test.go' |
135 | === modified file 'environs/simplestreams/simplestreams.go' |
136 | === modified file 'environs/sync/sync.go' |
137 | --- environs/sync/sync.go 2013-10-16 05:26:30 +0000 |
138 | +++ environs/sync/sync.go 2013-10-17 18:24:24 +0000 |
139 | @@ -174,6 +174,16 @@ |
140 | sha256hash.Write(buf.Bytes()) |
141 | tool.SHA256 = fmt.Sprintf("%x", sha256hash.Sum(nil)) |
142 | tool.Size = nBytes |
143 | + |
144 | + // TODO(wallyworld) - 2013-10-09 bug=1237130 |
145 | + // This is a 1.16 only hack to allow upgrades from 1.14 to work. |
146 | + // Remove once 1.16 is released. |
147 | + legacyBuf := bytes.NewBuffer(buf.Bytes()) |
148 | + legacyName := "tools/juju-" + tool.Version.String() + ".tgz" |
149 | + err = dest.Put(legacyName, legacyBuf, nBytes) |
150 | + if err != nil { |
151 | + return fmt.Errorf("writing tools to legacy location: %v", err) |
152 | + } |
153 | return dest.Put(toolsName, buf, nBytes) |
154 | } |
155 | |
156 | |
157 | === modified file 'environs/sync/sync_test.go' |
158 | --- environs/sync/sync_test.go 2013-10-10 11:40:54 +0000 |
159 | +++ environs/sync/sync_test.go 2013-10-17 18:24:24 +0000 |
160 | @@ -182,11 +182,36 @@ |
161 | s.targetEnv, test.ctx.MajorVersion, test.ctx.MinorVersion, coretools.Filter{}, envtools.DoNotAllowRetry) |
162 | c.Assert(err, gc.IsNil) |
163 | assertToolsList(c, targetTools, test.tools) |
164 | - assertNoUnexpectedTools(c, s.targetEnv.Storage()) |
165 | +<<<<<<< TREE |
166 | + assertNoUnexpectedTools(c, s.targetEnv.Storage()) |
167 | +======= |
168 | + |
169 | + // TODO(wallyworld) - 2013-10-09 bug=1237130 |
170 | + // This is a 1.16 only hack to allow upgrades from 1.14 to work. |
171 | + // Remove once 1.16 is released. |
172 | + assertLegacyTools(c, s.targetEnv.Storage(), test.tools) |
173 | + |
174 | + assertNoUnexpectedTools(c, s.targetEnv.Storage()) |
175 | +>>>>>>> MERGE-SOURCE |
176 | }() |
177 | } |
178 | } |
179 | |
180 | +func assertLegacyTools(c *gc.C, stor storage.StorageReader, expected []version.Binary) { |
181 | + files, err := stor.List("tools/juju-") |
182 | + c.Assert(err, gc.IsNil) |
183 | + c.Assert(len(files), gc.Equals, len(expected)) |
184 | + for _, vers := range expected { |
185 | + filename := "tools/juju-" + vers.String() + ".tgz" |
186 | + r, err := stor.Get(filename) |
187 | + c.Check(err, gc.IsNil) |
188 | + defer r.Close() |
189 | + data, err := ioutil.ReadAll(r) |
190 | + c.Check(err, gc.IsNil) |
191 | + c.Check(string(data), gc.Equals, vers.String()) |
192 | + } |
193 | +} |
194 | + |
195 | var ( |
196 | v100p64 = version.MustParseBinary("1.0.0-precise-amd64") |
197 | v100q64 = version.MustParseBinary("1.0.0-quantal-amd64") |
198 | |
199 | === modified file 'environs/tools/simplestreams.go' |
200 | === modified file 'environs/tools/simplestreams_test.go' |
201 | --- environs/tools/simplestreams_test.go 2013-10-16 05:26:30 +0000 |
202 | +++ environs/tools/simplestreams_test.go 2013-10-17 18:24:24 +0000 |
203 | @@ -7,8 +7,13 @@ |
204 | "bytes" |
205 | "flag" |
206 | "fmt" |
207 | +<<<<<<< TREE |
208 | "io" |
209 | "net/http" |
210 | +======= |
211 | + "net/http" |
212 | + "path/filepath" |
213 | +>>>>>>> MERGE-SOURCE |
214 | "reflect" |
215 | "strings" |
216 | "testing" |
217 | @@ -477,6 +482,7 @@ |
218 | c.Assert(item, gc.FitsTypeOf, &tools.ToolsMetadata{}) |
219 | c.Assert(item.(*tools.ToolsMetadata).Size, gc.Equals, int64(9223372036854775807)) |
220 | } |
221 | +<<<<<<< TREE |
222 | |
223 | type metadataHelperSuite struct { |
224 | testbase.LoggingSuite |
225 | @@ -795,3 +801,110 @@ |
226 | "format": "products:1.0" |
227 | } |
228 | ` |
229 | +======= |
230 | + |
231 | +type signedSuite struct { |
232 | + origKey string |
233 | +} |
234 | + |
235 | +var testRoundTripper *jujutest.ProxyRoundTripper |
236 | + |
237 | +func init() { |
238 | + testRoundTripper = &jujutest.ProxyRoundTripper{} |
239 | + simplestreams.RegisterProtocol("signedtest", testRoundTripper) |
240 | +} |
241 | + |
242 | +func (s *signedSuite) SetUpSuite(c *gc.C) { |
243 | + var imageData = map[string]string{ |
244 | + "/unsigned/streams/v1/index.json": unsignedIndex, |
245 | + "/unsigned/streams/v1/tools_metadata.json": unsignedProduct, |
246 | + } |
247 | + |
248 | + // Set up some signed data from the unsigned data. |
249 | + // Overwrite the product path to use the sjson suffix. |
250 | + rawUnsignedIndex := strings.Replace( |
251 | + unsignedIndex, "streams/v1/tools_metadata.json", "streams/v1/tools_metadata.sjson", -1) |
252 | + r := bytes.NewReader([]byte(rawUnsignedIndex)) |
253 | + signedData, err := simplestreams.Encode( |
254 | + r, sstesting.SignedMetadataPrivateKey, sstesting.PrivateKeyPassphrase) |
255 | + c.Assert(err, gc.IsNil) |
256 | + imageData["/signed/streams/v1/index.sjson"] = string(signedData) |
257 | + |
258 | + // Replace the tools path in the unsigned data with a different one so we can test that the right |
259 | + // tools path is used. |
260 | + rawUnsignedProduct := strings.Replace( |
261 | + unsignedProduct, "juju-1.13.0", "juju-1.13.1", -1) |
262 | + r = bytes.NewReader([]byte(rawUnsignedProduct)) |
263 | + signedData, err = simplestreams.Encode( |
264 | + r, sstesting.SignedMetadataPrivateKey, sstesting.PrivateKeyPassphrase) |
265 | + c.Assert(err, gc.IsNil) |
266 | + imageData["/signed/streams/v1/tools_metadata.sjson"] = string(signedData) |
267 | + testRoundTripper.Sub = jujutest.NewCannedRoundTripper( |
268 | + imageData, map[string]int{"signedtest://unauth": http.StatusUnauthorized}) |
269 | + s.origKey = tools.SetSigningPublicKey(sstesting.SignedMetadataPublicKey) |
270 | +} |
271 | + |
272 | +func (s *signedSuite) TearDownSuite(c *gc.C) { |
273 | + testRoundTripper.Sub = nil |
274 | + tools.SetSigningPublicKey(s.origKey) |
275 | +} |
276 | + |
277 | +func (s *signedSuite) TestSignedToolsMetadata(c *gc.C) { |
278 | + signedSource := simplestreams.NewURLDataSource("signedtest://host/signed", simplestreams.VerifySSLHostnames) |
279 | + toolsConstraint := tools.NewVersionedToolsConstraint("1.13.0", simplestreams.LookupParams{ |
280 | + CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"}, |
281 | + Series: []string{"precise"}, |
282 | + Arches: []string{"amd64"}, |
283 | + }) |
284 | + toolsMetadata, err := tools.Fetch( |
285 | + []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, toolsConstraint, true) |
286 | + c.Assert(err, gc.IsNil) |
287 | + c.Assert(len(toolsMetadata), gc.Equals, 1) |
288 | + c.Assert(toolsMetadata[0].Path, gc.Equals, "tools/releases/20130806/juju-1.13.1-precise-amd64.tgz") |
289 | +} |
290 | + |
291 | +var unsignedIndex = ` |
292 | +{ |
293 | + "index": { |
294 | + "com.ubuntu.juju:released:tools": { |
295 | + "updated": "Mon, 05 Aug 2013 11:07:04 +0000", |
296 | + "datatype": "content-download", |
297 | + "format": "products:1.0", |
298 | + "products": [ |
299 | + "com.ubuntu.juju:12.04:amd64" |
300 | + ], |
301 | + "path": "streams/v1/tools_metadata.json" |
302 | + } |
303 | + }, |
304 | + "updated": "Wed, 01 May 2013 13:31:26 +0000", |
305 | + "format": "index:1.0" |
306 | +} |
307 | +` |
308 | +var unsignedProduct = ` |
309 | +{ |
310 | + "updated": "Wed, 01 May 2013 13:31:26 +0000", |
311 | + "content_id": "com.ubuntu.cloud:released:aws", |
312 | + "datatype": "content-download", |
313 | + "products": { |
314 | + "com.ubuntu.juju:12.04:amd64": { |
315 | + "arch": "amd64", |
316 | + "release": "precise", |
317 | + "versions": { |
318 | + "20130806": { |
319 | + "items": { |
320 | + "1130preciseamd64": { |
321 | + "version": "1.13.0", |
322 | + "size": 2973595, |
323 | + "path": "tools/releases/20130806/juju-1.13.0-precise-amd64.tgz", |
324 | + "ftype": "tar.gz", |
325 | + "sha256": "447aeb6a934a5eaec4f703eda4ef2dde" |
326 | + } |
327 | + } |
328 | + } |
329 | + } |
330 | + } |
331 | + }, |
332 | + "format": "products:1.0" |
333 | +} |
334 | +` |
335 | +>>>>>>> MERGE-SOURCE |
336 | |
337 | === modified file 'provider/maas/instance_test.go' |
338 | --- provider/maas/instance_test.go 2013-10-15 16:16:59 +0000 |
339 | +++ provider/maas/instance_test.go 2013-10-17 18:24:24 +0000 |
340 | @@ -95,49 +95,97 @@ |
341 | |
342 | addr, err := inst.Addresses() |
343 | |
344 | - c.Assert(err, gc.IsNil) |
345 | - c.Check(addr, gc.DeepEquals, expected) |
346 | -} |
347 | - |
348 | -func (s *instanceTest) TestAddressesMissing(c *gc.C) { |
349 | - // Older MAAS versions do not have ip_addresses returned, for these |
350 | - // just the DNS name should be returned without error. |
351 | - jsonValue := `{ |
352 | - "hostname": "testing.invalid", |
353 | - "system_id": "system_id" |
354 | - }` |
355 | - obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
356 | - inst := maasInstance{&obj, s.makeEnviron()} |
357 | - |
358 | - addr, err := inst.Addresses() |
359 | - c.Assert(err, gc.IsNil) |
360 | - c.Check(addr, gc.DeepEquals, []instance.Address{ |
361 | - {Value: "testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic}, |
362 | - }) |
363 | -} |
364 | - |
365 | -func (s *instanceTest) TestAddressesInvalid(c *gc.C) { |
366 | - jsonValue := `{ |
367 | - "hostname": "testing.invalid", |
368 | - "system_id": "system_id", |
369 | - "ip_addresses": "incompatible" |
370 | - }` |
371 | - obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
372 | - inst := maasInstance{&obj, s.makeEnviron()} |
373 | - |
374 | - _, err := inst.Addresses() |
375 | - c.Assert(err, gc.NotNil) |
376 | -} |
377 | - |
378 | -func (s *instanceTest) TestAddressesInvalidContents(c *gc.C) { |
379 | - jsonValue := `{ |
380 | - "hostname": "testing.invalid", |
381 | - "system_id": "system_id", |
382 | - "ip_addresses": [42] |
383 | - }` |
384 | - obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
385 | - inst := maasInstance{&obj, s.makeEnviron()} |
386 | - |
387 | - _, err := inst.Addresses() |
388 | - c.Assert(err, gc.NotNil) |
389 | +<<<<<<< TREE |
390 | + c.Assert(err, gc.IsNil) |
391 | + c.Check(addr, gc.DeepEquals, expected) |
392 | +} |
393 | + |
394 | +func (s *instanceTest) TestAddressesMissing(c *gc.C) { |
395 | + // Older MAAS versions do not have ip_addresses returned, for these |
396 | + // just the DNS name should be returned without error. |
397 | + jsonValue := `{ |
398 | + "hostname": "testing.invalid", |
399 | + "system_id": "system_id" |
400 | + }` |
401 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
402 | + inst := maasInstance{&obj, s.makeEnviron()} |
403 | + |
404 | + addr, err := inst.Addresses() |
405 | + c.Assert(err, gc.IsNil) |
406 | + c.Check(addr, gc.DeepEquals, []instance.Address{ |
407 | + {Value: "testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic}, |
408 | + }) |
409 | +} |
410 | + |
411 | +func (s *instanceTest) TestAddressesInvalid(c *gc.C) { |
412 | + jsonValue := `{ |
413 | + "hostname": "testing.invalid", |
414 | + "system_id": "system_id", |
415 | + "ip_addresses": "incompatible" |
416 | + }` |
417 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
418 | + inst := maasInstance{&obj, s.makeEnviron()} |
419 | + |
420 | + _, err := inst.Addresses() |
421 | + c.Assert(err, gc.NotNil) |
422 | +} |
423 | + |
424 | +func (s *instanceTest) TestAddressesInvalidContents(c *gc.C) { |
425 | + jsonValue := `{ |
426 | + "hostname": "testing.invalid", |
427 | + "system_id": "system_id", |
428 | + "ip_addresses": [42] |
429 | + }` |
430 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
431 | + inst := maasInstance{&obj, s.makeEnviron()} |
432 | + |
433 | + _, err := inst.Addresses() |
434 | + c.Assert(err, gc.NotNil) |
435 | +======= |
436 | + c.Assert(err, gc.IsNil) |
437 | + c.Check(addr, gc.DeepEquals, expected) |
438 | +} |
439 | + |
440 | +func (s *instanceTest) TestAddressesMissing(c *gc.C) { |
441 | + // Older MAAS versions do not have ip_addresses returned, for these |
442 | + // just the DNS name should be returned without error. |
443 | + jsonValue := `{ |
444 | + "hostname": "testing.invalid", |
445 | + "system_id": "system_id" |
446 | + }` |
447 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
448 | + inst := maasInstance{&obj, s.environ} |
449 | + |
450 | + addr, err := inst.Addresses() |
451 | + c.Assert(err, gc.IsNil) |
452 | + c.Check(addr, gc.DeepEquals, []instance.Address{ |
453 | + {Value: "testing.invalid", Type: instance.HostName, NetworkScope: instance.NetworkPublic}, |
454 | + }) |
455 | +} |
456 | + |
457 | +func (s *instanceTest) TestAddressesInvalid(c *gc.C) { |
458 | + jsonValue := `{ |
459 | + "hostname": "testing.invalid", |
460 | + "system_id": "system_id", |
461 | + "ip_addresses": "incompatible" |
462 | + }` |
463 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
464 | + inst := maasInstance{&obj, s.environ} |
465 | + |
466 | + _, err := inst.Addresses() |
467 | + c.Assert(err, gc.NotNil) |
468 | +} |
469 | + |
470 | +func (s *instanceTest) TestAddressesInvalidContents(c *gc.C) { |
471 | + jsonValue := `{ |
472 | + "hostname": "testing.invalid", |
473 | + "system_id": "system_id", |
474 | + "ip_addresses": [42] |
475 | + }` |
476 | + obj := s.testMAASObject.TestServer.NewNode(jsonValue) |
477 | + inst := maasInstance{&obj, s.environ} |
478 | + |
479 | + _, err := inst.Addresses() |
480 | + c.Assert(err, gc.NotNil) |
481 | +>>>>>>> MERGE-SOURCE |
482 | } |
483 | |
484 | === modified file 'provider/openstack/provider.go' |
485 | === added file 'utils/file_unix.go' |
486 | --- utils/file_unix.go 1970-01-01 00:00:00 +0000 |
487 | +++ utils/file_unix.go 2013-10-17 18:24:24 +0000 |
488 | @@ -0,0 +1,15 @@ |
489 | +// Copyright 2013 Canonical Ltd. |
490 | +// Licensed under the AGPLv3, see LICENCE file for details. |
491 | +// +build !windows |
492 | + |
493 | +package utils |
494 | + |
495 | +import ( |
496 | + "os" |
497 | +) |
498 | + |
499 | +// Replace atomically replaces the destination file or directory with the source. |
500 | +// The errors that are returned are identical to those returned by os.Rename. |
501 | +func ReplaceFile(source, destination string) error { |
502 | + return os.Rename(source, destination) |
503 | +} |
504 | |
505 | === added file 'utils/file_windows.go' |
506 | --- utils/file_windows.go 1970-01-01 00:00:00 +0000 |
507 | +++ utils/file_windows.go 2013-10-17 18:24:24 +0000 |
508 | @@ -0,0 +1,35 @@ |
509 | +// Copyright 2013 Canonical Ltd. |
510 | +// Licensed under the AGPLv3, see LICENCE file for details. |
511 | + |
512 | +package utils |
513 | + |
514 | +import ( |
515 | + "os" |
516 | + "syscall" |
517 | +) |
518 | + |
519 | +const ( |
520 | + movefile_replace_existing = 0x1 |
521 | + movefile_write_through = 0x8 |
522 | +) |
523 | + |
524 | +//sys moveFileEx(lpExistingFileName *uint16, lpNewFileName *uint16, dwFlags uint32) (err error) = MoveFileExW |
525 | + |
526 | +// ReplaceFile atomically replaces the destination file or directory with the source. |
527 | +// The errors that are returned are identical to those returned by os.Rename. |
528 | +func ReplaceFile(source, destination string) error { |
529 | + src, err := syscall.UTF16PtrFromString(source) |
530 | + if err != nil { |
531 | + return &os.LinkError{"replace", source, destination, err} |
532 | + } |
533 | + dest, err := syscall.UTF16PtrFromString(destination) |
534 | + if err != nil { |
535 | + return &os.LinkError{"replace", source, destination, err} |
536 | + } |
537 | + |
538 | + // see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365240(v=vs.85).aspx |
539 | + if err := moveFileEx(src, dest, movefile_replace_existing|movefile_write_through); err != nil { |
540 | + return &os.LinkError{"replace", source, destination, err} |
541 | + } |
542 | + return nil |
543 | +} |
544 | |
545 | === modified file 'utils/fslock/fslock.go' |
546 | --- utils/fslock/fslock.go 2013-08-02 12:37:43 +0000 |
547 | +++ utils/fslock/fslock.go 2013-10-17 18:24:24 +0000 |
548 | @@ -113,7 +113,7 @@ |
549 | } |
550 | } |
551 | // Now move the temp directory to the lock directory. |
552 | - err = os.Rename(tempDirName, lock.lockDir()) |
553 | + err = utils.ReplaceFile(tempDirName, lock.lockDir()) |
554 | if err != nil { |
555 | // Any error on rename means we failed. |
556 | // Beaten to it, clean up temporary directory. |
557 | @@ -200,7 +200,7 @@ |
558 | tempLockName := fmt.Sprintf(".%s.%x", lock.name, lock.nonce) |
559 | tempDirName := path.Join(lock.parent, tempLockName) |
560 | // Now move the lock directory to the temp directory to release the lock. |
561 | - if err := os.Rename(lock.lockDir(), tempDirName); err != nil { |
562 | + if err := utils.ReplaceFile(lock.lockDir(), tempDirName); err != nil { |
563 | return err |
564 | } |
565 | // And now cleanup. |
566 | |
567 | === modified file 'utils/trivial.go' |
568 | --- utils/trivial.go 2013-07-09 10:32:23 +0000 |
569 | +++ utils/trivial.go 2013-10-17 18:24:24 +0000 |
570 | @@ -32,7 +32,7 @@ |
571 | if _, err = f.Write(data); err != nil { |
572 | return err |
573 | } |
574 | - return os.Rename(prep, path) |
575 | + return ReplaceFile(prep, path) |
576 | } |
577 | |
578 | // ReadYaml unmarshals the yaml contained in the file at path into obj. See |
579 | |
580 | === added file 'utils/zfile_windows.go' |
581 | --- utils/zfile_windows.go 1970-01-01 00:00:00 +0000 |
582 | +++ utils/zfile_windows.go 2013-10-17 18:24:24 +0000 |
583 | @@ -0,0 +1,25 @@ |
584 | +// mksyscall_windows.pl -l32 file_windows.go |
585 | +// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT |
586 | + |
587 | +package utils |
588 | + |
589 | +import "unsafe" |
590 | +import "syscall" |
591 | + |
592 | +var ( |
593 | + modkernel32 = syscall.NewLazyDLL("kernel32.dll") |
594 | + |
595 | + procMoveFileExW = modkernel32.NewProc("MoveFileExW") |
596 | +) |
597 | + |
598 | +func moveFileEx(lpExistingFileName *uint16, lpNewFileName *uint16, dwFlags uint32) (err error) { |
599 | + r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(lpExistingFileName)), uintptr(unsafe.Pointer(lpNewFileName)), uintptr(dwFlags)) |
600 | + if r1 == 0 { |
601 | + if e1 != 0 { |
602 | + err = error(e1) |
603 | + } else { |
604 | + err = syscall.EINVAL |
605 | + } |
606 | + } |
607 | + return |
608 | +} |
609 | |
610 | === modified file 'version/version.go' |
611 | --- version/version.go 2013-10-10 11:40:54 +0000 |
612 | +++ version/version.go 2013-10-17 18:24:24 +0000 |
613 | @@ -22,7 +22,11 @@ |
614 | // The presence and format of this constant is very important. |
615 | // The debian/rules build recipe uses this value for the version |
616 | // number of the release package. |
617 | +<<<<<<< TREE |
618 | const version = "1.17.0" |
619 | +======= |
620 | +const version = "1.16.0" |
621 | +>>>>>>> MERGE-SOURCE |
622 | |
623 | // Current gives the current version of the system. If the file |
624 | // "FORCE-VERSION" is present in the same directory as the running |