Merge lp:~wallyworld/juju-core/verbose-metadata-validation into lp:~go-bot/juju-core/trunk

Proposed by Ian Booth
Status: Merged
Approved by: Ian Booth
Approved revision: no longer in the source branch.
Merged at revision: 2376
Proposed branch: lp:~wallyworld/juju-core/verbose-metadata-validation
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 2037 lines (+389/-386)
45 files modified
cmd/plugins/juju-metadata/toolsmetadata.go (+5/-15)
cmd/plugins/juju-metadata/validateimagemetadata.go (+27/-8)
cmd/plugins/juju-metadata/validateimagemetadata_test.go (+18/-3)
cmd/plugins/juju-metadata/validatetoolsmetadata.go (+27/-7)
cmd/plugins/juju-metadata/validatetoolsmetadata_test.go (+33/-37)
environs/bootstrap/bootstrap_test.go (+2/-1)
environs/imagemetadata/generate.go (+2/-2)
environs/imagemetadata/generate_test.go (+2/-2)
environs/imagemetadata/simplestreams.go (+6/-4)
environs/imagemetadata/simplestreams_test.go (+24/-7)
environs/imagemetadata/testing/testing.go (+1/-1)
environs/imagemetadata/urls.go (+2/-2)
environs/imagemetadata/validation.go (+10/-10)
environs/imagemetadata/validation_test.go (+11/-4)
environs/instances/image_test.go (+2/-1)
environs/simplestreams/datasource.go (+12/-2)
environs/simplestreams/datasource_test.go (+4/-4)
environs/simplestreams/simplestreams.go (+27/-9)
environs/simplestreams/simplestreams_test.go (+9/-3)
environs/storage/storage.go (+11/-5)
environs/storage/storage_test.go (+6/-6)
environs/sync/sync.go (+1/-1)
environs/tools/boilerplate.go (+0/-153)
environs/tools/simplestreams.go (+12/-9)
environs/tools/simplestreams_test.go (+40/-18)
environs/tools/testing/testing.go (+1/-1)
environs/tools/tools.go (+2/-2)
environs/tools/urls.go (+2/-2)
environs/tools/validation.go (+12/-8)
environs/tools/validation_test.go (+49/-34)
provider/azure/environ.go (+3/-3)
provider/azure/instancetype.go (+1/-1)
provider/azure/instancetype_test.go (+3/-2)
provider/common/mock_test.go (+1/-1)
provider/dummy/environs.go (+2/-2)
provider/ec2/ec2.go (+2/-2)
provider/ec2/image.go (+1/-1)
provider/ec2/image_test.go (+4/-2)
provider/ec2/local_test.go (+1/-1)
provider/local/environ.go (+1/-1)
provider/maas/environ.go (+2/-2)
provider/manual/environ.go (+1/-1)
provider/openstack/image.go (+1/-1)
provider/openstack/local_test.go (+1/-1)
provider/openstack/provider.go (+5/-4)
To merge this branch: bzr merge lp:~wallyworld/juju-core/verbose-metadata-validation
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+209162@code.launchpad.net

Commit message

Add metadata to simplestreams validation

juju metadata validate-[images|tools] now prints
metadata to show how the lookup was performed.
Along the way, drive by fixes were done to delete
old code and improve existing code associated with
simplestreams.

Description of the change

Add metadata to simplestreams validation

juju metadata validate-[images|tools] now prints
metadata to show how the lookup was performed.
Along the way, drive by fixes were done to delete
old code and improve existing code associated with
simplestreams.

A picture is worth 1000 words:

ian@wallyworld:~$ juju metadata validate-images
ImageIds:
- ami-99999af0
- ami-0d9c9f64
- ami-6f969506
- ami-0b9c9f62
- ami-359c9f5c
- ami-a18c8fc8
Region: us-east-1
Resolve Metadata:
  source: default cloud images
  signed: true
  indexURL: http://cloud-images.ubuntu.com/releases/streams/v1/index.sjson
ian@wallyworld:~$ juju metadata validate-tools
Matching Tools Versions:
- 1.17.4-precise-amd64
- 1.17.4-precise-i386
Resolve Metadata:
  source: default simplestreams
  signed: false
  indexURL: https://streams.canonical.com/juju/tools/streams/v1/index.json
  mirrorURL: https://juju-dist.s3.amazonaws.com/tools

https://codereview.appspot.com/70960044/

To post a comment you must log in.
Revision history for this message
Ian Booth (wallyworld) wrote :

Reviewers: mp+209162_code.launchpad.net,

Message:
Please take a look.

Description:
Add metadata to simplestreams validation

juju metadata validate-[images|tools] now prints
metadata to show how the lookup was performed.
Along the way, drive by fixes were done to delete
old code and improve existing code associated with
simplestreams.

A picture is worth 1000 words:

ian@wallyworld:~$ juju metadata validate-images
ImageIds:
- ami-99999af0
- ami-0d9c9f64
- ami-6f969506

- ami-0b9c9f62

- ami-359c9f5c

- ami-a18c8fc8

Region: us-east-1

Resolve Metadata:

   source: default cloud images

   signed: true

   indexURL:
http://cloud-images.ubuntu.com/releases/streams/v1/index.sjson

ian@wallyworld:~$ juju metadata validate-tools
Matching Tools Versions:
- 1.17.4-precise-amd64
- 1.17.4-precise-i386
Resolve Metadata:
   source: default simplestreams
   signed: false
   indexURL:
https://streams.canonical.com/juju/tools/streams/v1/index.json
   mirrorURL: https://juju-dist.s3.amazonaws.com/tools

https://code.launchpad.net/~wallyworld/juju-core/verbose-metadata-validation/+merge/209162

(do not edit description out of merge proposal)

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

Affected files (+330, -361 lines):
   A [revision details]
   M cmd/plugins/juju-metadata/toolsmetadata.go
   M cmd/plugins/juju-metadata/validateimagemetadata.go
   M cmd/plugins/juju-metadata/validateimagemetadata_test.go
   M cmd/plugins/juju-metadata/validatetoolsmetadata.go
   M cmd/plugins/juju-metadata/validatetoolsmetadata_test.go
   M environs/bootstrap/bootstrap_test.go
   M environs/imagemetadata/generate.go
   M environs/imagemetadata/generate_test.go
   M environs/imagemetadata/simplestreams.go
   M environs/imagemetadata/simplestreams_test.go
   M environs/imagemetadata/testing/testing.go
   M environs/imagemetadata/urls.go
   M environs/imagemetadata/validation.go
   M environs/imagemetadata/validation_test.go
   M environs/instances/image_test.go
   M environs/simplestreams/datasource.go
   M environs/simplestreams/datasource_test.go
   M environs/simplestreams/simplestreams.go
   M environs/simplestreams/simplestreams_test.go
   M environs/storage/storage.go
   M environs/storage/storage_test.go
   M environs/sync/sync.go
   D environs/tools/boilerplate.go
   M environs/tools/simplestreams.go
   M environs/tools/simplestreams_test.go
   M environs/tools/testing/testing.go
   M environs/tools/tools.go
   M environs/tools/urls.go
   M environs/tools/validation.go
   M environs/tools/validation_test.go
   M provider/azure/environ.go
   M provider/azure/instancetype.go
   M provider/azure/instancetype_test.go
   M provider/common/mock_test.go
   M provider/dummy/environs.go
   M provider/ec2/ec2.go
   M provider/ec2/image.go
   M provider/ec2/image_test.go
   M provider/ec2/local_test.go
   M provider/local/environ.go
   M provider/maas/environ.go
   M provider/manual/environ.go
   M provider/openstack/image.go
   M provider/openstack/local_test.go
   M provider/openstack/provider.go

Revision history for this message
Ian Booth (wallyworld) wrote :
Revision history for this message
Tim Penhey (thumper) wrote :

On 2014/03/04 05:51:30, wallyworld wrote:
> Please take a look.

LGTM - although was wondering why the resolve information wasn't
encapsulated in the error rather than a separate parameter.

https://codereview.appspot.com/70960044/

Revision history for this message
Tim Penhey (thumper) wrote :

On 2014/03/05 01:54:16, thumper wrote:
> On 2014/03/04 05:51:30, wallyworld wrote:
> > Please take a look.

> LGTM - although was wondering why the resolve information wasn't
encapsulated in
> the error rather than a separate parameter.

Ah, we show the resolution info on success as well. nm.

https://codereview.appspot.com/70960044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmd/plugins/juju-metadata/toolsmetadata.go'
2--- cmd/plugins/juju-metadata/toolsmetadata.go 2014-01-31 00:14:11 +0000
3+++ cmd/plugins/juju-metadata/toolsmetadata.go 2014-03-04 05:51:00 +0000
4@@ -5,9 +5,6 @@
5
6 import (
7 "fmt"
8- "net/url"
9- "path"
10- "strings"
11
12 "github.com/loggo/loggo"
13 "launchpad.net/gnuflag"
14@@ -60,19 +57,12 @@
15 const minorVersion = -1
16 toolsList, err := envtools.ReadList(sourceStorage, version.Current.Major, minorVersion)
17 if err == envtools.ErrNoTools {
18- source := envtools.DefaultBaseURL
19- var u *url.URL
20- u, err = url.Parse(source)
21+ var source string
22+ source, err = envtools.ToolsURL(envtools.DefaultBaseURL)
23 if err != nil {
24- return fmt.Errorf("invalid tools source %s: %v", source, err)
25- }
26- if u.Scheme == "" {
27- source = "file://" + source
28- if !strings.HasSuffix(source, "/"+storage.BaseToolsPath) {
29- source = path.Join(source, storage.BaseToolsPath)
30- }
31- }
32- sourceDataSource := simplestreams.NewURLDataSource(source, simplestreams.VerifySSLHostnames)
33+ return err
34+ }
35+ sourceDataSource := simplestreams.NewURLDataSource("local source", source, simplestreams.VerifySSLHostnames)
36 toolsList, err = envtools.FindToolsForCloud(
37 []simplestreams.DataSource{sourceDataSource}, simplestreams.CloudSpec{},
38 version.Current.Major, minorVersion, coretools.Filter{})
39
40=== modified file 'cmd/plugins/juju-metadata/validateimagemetadata.go'
41--- cmd/plugins/juju-metadata/validateimagemetadata.go 2014-02-13 02:46:58 +0000
42+++ cmd/plugins/juju-metadata/validateimagemetadata.go 2014-03-04 05:51:00 +0000
43@@ -22,6 +22,7 @@
44 // ValidateImageMetadataCommand
45 type ValidateImageMetadataCommand struct {
46 cmd.EnvCommandBase
47+ out cmd.Output
48 providerType string
49 metadataDir string
50 series string
51@@ -79,6 +80,7 @@
52
53 func (c *ValidateImageMetadataCommand) SetFlags(f *gnuflag.FlagSet) {
54 c.EnvCommandBase.SetFlags(f)
55+ c.out.AddFlags(f, "smart", cmd.DefaultFormatters)
56 f.StringVar(&c.providerType, "p", "", "the provider type eg ec2, openstack")
57 f.StringVar(&c.metadataDir, "d", "", "directory where metadata files are found")
58 f.StringVar(&c.series, "s", "", "the series for which to validate (overrides env config series)")
59@@ -180,26 +182,43 @@
60 if _, err := os.Stat(dir); err != nil {
61 return err
62 }
63- params.Sources = []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+dir, simplestreams.VerifySSLHostnames)}
64+ params.Sources = []simplestreams.DataSource{
65+ simplestreams.NewURLDataSource(
66+ "local metadata directory", "file://"+dir, simplestreams.VerifySSLHostnames),
67+ }
68 }
69 params.Stream = c.stream
70
71- image_ids, err := imagemetadata.ValidateImageMetadata(params)
72+ image_ids, resolveInfo, err := imagemetadata.ValidateImageMetadata(params)
73 if err != nil {
74+ if resolveInfo != nil {
75+ metadata := map[string]interface{}{
76+ "Resolve Metadata": *resolveInfo,
77+ }
78+ if metadataYaml, yamlErr := cmd.FormatYaml(metadata); yamlErr == nil {
79+ err = fmt.Errorf("%v\n%v", err, string(metadataYaml))
80+ }
81+ }
82 return err
83 }
84-
85 if len(image_ids) > 0 {
86- fmt.Fprintf(context.Stdout, "matching image ids for region %q:\n%s\n", params.Region, strings.Join(image_ids, "\n"))
87+ metadata := map[string]interface{}{
88+ "ImageIds": image_ids,
89+ "Region": params.Region,
90+ "Resolve Metadata": *resolveInfo,
91+ }
92+ c.out.Write(context, metadata)
93 } else {
94- var urls []string
95+ var sources []string
96 for _, s := range params.Sources {
97 url, err := s.URL("")
98- if err != nil {
99- urls = append(urls, url)
100+ if err == nil {
101+ sources = append(sources, fmt.Sprintf("- %s (%s)", s.Description(), url))
102 }
103 }
104- return fmt.Errorf("no matching image ids for region %s using URLs:\n%s", params.Region, strings.Join(urls, "\n"))
105+ return fmt.Errorf(
106+ "no matching image ids for region %s using sources:\n%s",
107+ params.Region, strings.Join(sources, "\n"))
108 }
109 return nil
110 }
111
112=== modified file 'cmd/plugins/juju-metadata/validateimagemetadata_test.go'
113--- cmd/plugins/juju-metadata/validateimagemetadata_test.go 2014-01-29 02:09:39 +0000
114+++ cmd/plugins/juju-metadata/validateimagemetadata_test.go 2014-03-04 05:51:00 +0000
115@@ -133,7 +133,9 @@
116 c.Assert(code, gc.Equals, 0)
117 errOut := ctx.Stdout.(*bytes.Buffer).String()
118 strippedOut := strings.Replace(errOut, "\n", "", -1)
119- c.Check(strippedOut, gc.Matches, `matching image ids for region "us-east-1":.*`)
120+ c.Check(
121+ strippedOut, gc.Matches,
122+ `ImageIds:.*"1234".*Region:.*us-east-1.*Resolve Metadata:.*source: local metadata directory.*`)
123 }
124
125 func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataUsingEnvironment(c *gc.C) {
126@@ -169,7 +171,9 @@
127 c.Assert(code, gc.Equals, 0)
128 errOut := ctx.Stdout.(*bytes.Buffer).String()
129 strippedOut := strings.Replace(errOut, "\n", "", -1)
130- c.Check(strippedOut, gc.Matches, `matching image ids for region "us-west-1":.*`)
131+ c.Check(
132+ strippedOut, gc.Matches,
133+ `ImageIds:.*"1234".*Region:.*us-west-1.*Resolve Metadata:.*source: local metadata directory.*`)
134 }
135
136 func (s *ValidateImageMetadataSuite) TestEc2LocalMetadataNoMatch(c *gc.C) {
137@@ -187,6 +191,9 @@
138 "-u", "https://ec2.region.amazonaws.com", "-d", s.metadataDir},
139 )
140 c.Assert(code, gc.Equals, 1)
141+ errOut := ctx.Stderr.(*bytes.Buffer).String()
142+ strippedOut := strings.Replace(errOut, "\n", "", -1)
143+ c.Check(strippedOut, gc.Matches, `.*Resolve Metadata:.*`)
144 }
145
146 func (s *ValidateImageMetadataSuite) TestOpenstackLocalMetadataWithManualParams(c *gc.C) {
147@@ -200,7 +207,9 @@
148 c.Assert(code, gc.Equals, 0)
149 errOut := ctx.Stdout.(*bytes.Buffer).String()
150 strippedOut := strings.Replace(errOut, "\n", "", -1)
151- c.Check(strippedOut, gc.Matches, `matching image ids for region "region-2":.*`)
152+ c.Check(
153+ strippedOut, gc.Matches,
154+ `ImageIds:.*"1234".*Region:.*region-2.*Resolve Metadata:.*source: local metadata directory.*`)
155 }
156
157 func (s *ValidateImageMetadataSuite) TestOpenstackLocalMetadataNoMatch(c *gc.C) {
158@@ -212,10 +221,16 @@
159 "-u", "some-auth-url", "-d", s.metadataDir},
160 )
161 c.Assert(code, gc.Equals, 1)
162+ errOut := ctx.Stderr.(*bytes.Buffer).String()
163+ strippedOut := strings.Replace(errOut, "\n", "", -1)
164+ c.Check(strippedOut, gc.Matches, `.*Resolve Metadata:.*`)
165 code = cmd.Main(
166 &ValidateImageMetadataCommand{}, ctx, []string{
167 "-p", "openstack", "-s", "raring", "-r", "region-3",
168 "-u", "some-auth-url", "-d", s.metadataDir},
169 )
170 c.Assert(code, gc.Equals, 1)
171+ errOut = ctx.Stderr.(*bytes.Buffer).String()
172+ strippedOut = strings.Replace(errOut, "\n", "", -1)
173+ c.Check(strippedOut, gc.Matches, `.*Resolve Metadata:.*`)
174 }
175
176=== modified file 'cmd/plugins/juju-metadata/validatetoolsmetadata.go'
177--- cmd/plugins/juju-metadata/validatetoolsmetadata.go 2014-02-28 03:05:47 +0000
178+++ cmd/plugins/juju-metadata/validatetoolsmetadata.go 2014-03-04 05:51:00 +0000
179@@ -21,6 +21,7 @@
180 // ValidateToolsMetadataCommand
181 type ValidateToolsMetadataCommand struct {
182 cmd.EnvCommandBase
183+ out cmd.Output
184 providerType string
185 metadataDir string
186 series string
187@@ -100,6 +101,7 @@
188
189 func (c *ValidateToolsMetadataCommand) SetFlags(f *gnuflag.FlagSet) {
190 c.EnvCommandBase.SetFlags(f)
191+ c.out.AddFlags(f, "smart", cmd.DefaultFormatters)
192 f.StringVar(&c.providerType, "p", "", "the provider type eg ec2, openstack")
193 f.StringVar(&c.metadataDir, "d", "", "directory where metadata files are found")
194 f.StringVar(&c.series, "s", "", "the series for which to validate (overrides env config series)")
195@@ -191,30 +193,48 @@
196 if _, err := os.Stat(c.metadataDir); err != nil {
197 return err
198 }
199- params.Sources = []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+c.metadataDir, simplestreams.VerifySSLHostnames)}
200+ toolsURL, err := tools.ToolsURL(c.metadataDir)
201+ if err != nil {
202+ return err
203+ }
204+ params.Sources = []simplestreams.DataSource{simplestreams.NewURLDataSource(
205+ "local metadata directory", toolsURL, simplestreams.VerifySSLHostnames),
206+ }
207 }
208
209- versions, err := tools.ValidateToolsMetadata(&tools.ToolsMetadataLookupParams{
210+ versions, resolveInfo, err := tools.ValidateToolsMetadata(&tools.ToolsMetadataLookupParams{
211 MetadataLookupParams: *params,
212 Version: c.exactVersion,
213 Major: c.major,
214 Minor: c.minor,
215 })
216 if err != nil {
217+ if resolveInfo != nil {
218+ metadata := map[string]interface{}{
219+ "Resolve Metadata": *resolveInfo,
220+ }
221+ if metadataYaml, yamlErr := cmd.FormatYaml(metadata); yamlErr == nil {
222+ err = fmt.Errorf("%v\n%v", err, string(metadataYaml))
223+ }
224+ }
225 return err
226 }
227
228 if len(versions) > 0 {
229- fmt.Fprintf(context.Stdout, "matching tools versions:\n%s\n", strings.Join(versions, "\n"))
230+ metadata := map[string]interface{}{
231+ "Matching Tools Versions": versions,
232+ "Resolve Metadata": *resolveInfo,
233+ }
234+ c.out.Write(context, metadata)
235 } else {
236- var urls []string
237+ var sources []string
238 for _, s := range params.Sources {
239 url, err := s.URL("")
240- if err != nil {
241- urls = append(urls, url)
242+ if err == nil {
243+ sources = append(sources, fmt.Sprintf("- %s (%s)", s.Description(), url))
244 }
245 }
246- return fmt.Errorf("no matching tools using URLs:\n%s", strings.Join(urls, "\n"))
247+ return fmt.Errorf("no matching tools using sources:\n%s", strings.Join(sources, "\n"))
248 }
249 return nil
250 }
251
252=== modified file 'cmd/plugins/juju-metadata/validatetoolsmetadata_test.go'
253--- cmd/plugins/juju-metadata/validatetoolsmetadata_test.go 2014-01-22 22:48:54 +0000
254+++ cmd/plugins/juju-metadata/validatetoolsmetadata_test.go 2014-03-04 05:51:00 +0000
255@@ -11,9 +11,8 @@
256 gc "launchpad.net/gocheck"
257
258 "launchpad.net/juju-core/cmd"
259- "launchpad.net/juju-core/environs/simplestreams"
260+ "launchpad.net/juju-core/environs/filestorage"
261 "launchpad.net/juju-core/environs/tools"
262- "launchpad.net/juju-core/juju/osenv"
263 coretesting "launchpad.net/juju-core/testing"
264 "launchpad.net/juju-core/testing/testbase"
265 "launchpad.net/juju-core/version"
266@@ -21,7 +20,8 @@
267
268 type ValidateToolsMetadataSuite struct {
269 testbase.LoggingSuite
270- home *coretesting.FakeHome
271+ home *coretesting.FakeHome
272+ metadataDir string
273 }
274
275 var _ = gc.Suite(&ValidateToolsMetadataSuite{})
276@@ -72,16 +72,14 @@
277 }
278
279 func (s *ValidateToolsMetadataSuite) makeLocalMetadata(c *gc.C, version, region, series, endpoint string) error {
280- tm := tools.ToolsMetadata{
281+ tm := []*tools.ToolsMetadata{{
282 Version: version,
283 Arch: "amd64",
284 Release: series,
285- }
286- cloudSpec := simplestreams.CloudSpec{
287- Region: region,
288- Endpoint: endpoint,
289- }
290- _, err := tools.MakeBoilerplate(&tm, &cloudSpec, false)
291+ }}
292+ targetStorage, err := filestorage.NewFileStorageWriter(s.metadataDir, filestorage.UseDefaultTmpDir)
293+ c.Assert(err, gc.IsNil)
294+ err = tools.WriteMetadata(targetStorage, tm, false)
295 if err != nil {
296 return err
297 }
298@@ -91,6 +89,7 @@
299 func (s *ValidateToolsMetadataSuite) SetUpTest(c *gc.C) {
300 s.LoggingSuite.SetUpTest(c)
301 s.home = coretesting.MakeFakeHome(c, metadataTestEnvConfig)
302+ s.metadataDir = c.MkDir()
303 restore := testbase.PatchEnvironment("AWS_ACCESS_KEY_ID", "access")
304 s.AddCleanup(func(*gc.C) { restore() })
305 restore = testbase.PatchEnvironment("AWS_SECRET_ACCESS_KEY", "secret")
306@@ -114,14 +113,13 @@
307 func (s *ValidateToolsMetadataSuite) TestEc2LocalMetadataUsingEnvironment(c *gc.C) {
308 s.setupEc2LocalMetadata(c, "us-east-1")
309 ctx := coretesting.Context(c)
310- metadataDir := osenv.JujuHomePath("")
311 code := cmd.Main(
312- &ValidateToolsMetadataCommand{}, ctx, []string{"-e", "ec2", "-j", "1.11.4", "-d", metadataDir},
313+ &ValidateToolsMetadataCommand{}, ctx, []string{"-e", "ec2", "-j", "1.11.4", "-d", s.metadataDir},
314 )
315 c.Assert(code, gc.Equals, 0)
316 errOut := ctx.Stdout.(*bytes.Buffer).String()
317 strippedOut := strings.Replace(errOut, "\n", "", -1)
318- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
319+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
320 }
321
322 func (s *ValidateToolsMetadataSuite) TestEc2LocalMetadataUsingIncompleteEnvironment(c *gc.C) {
323@@ -141,123 +139,121 @@
324 func (s *ValidateToolsMetadataSuite) TestEc2LocalMetadataWithManualParams(c *gc.C) {
325 s.setupEc2LocalMetadata(c, "us-west-1")
326 ctx := coretesting.Context(c)
327- metadataDir := osenv.JujuHomePath("")
328 code := cmd.Main(
329 &ValidateToolsMetadataCommand{}, ctx, []string{
330 "-p", "ec2", "-s", "precise", "-r", "us-west-1", "-j", "1.11.4",
331- "-u", "https://ec2.us-west-1.amazonaws.com", "-d", metadataDir},
332+ "-u", "https://ec2.us-west-1.amazonaws.com", "-d", s.metadataDir},
333 )
334 c.Assert(code, gc.Equals, 0)
335 errOut := ctx.Stdout.(*bytes.Buffer).String()
336 strippedOut := strings.Replace(errOut, "\n", "", -1)
337- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
338+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
339 }
340
341 func (s *ValidateToolsMetadataSuite) TestEc2LocalMetadataNoMatch(c *gc.C) {
342 s.setupEc2LocalMetadata(c, "us-east-1")
343 ctx := coretesting.Context(c)
344- metadataDir := osenv.JujuHomePath("")
345 code := cmd.Main(
346 &ValidateToolsMetadataCommand{}, ctx, []string{
347 "-p", "ec2", "-s", "raring", "-r", "us-west-1",
348- "-u", "https://ec2.us-west-1.amazonaws.com", "-d", metadataDir},
349+ "-u", "https://ec2.us-west-1.amazonaws.com", "-d", s.metadataDir},
350 )
351 c.Assert(code, gc.Equals, 1)
352 code = cmd.Main(
353 &ValidateToolsMetadataCommand{}, ctx, []string{
354 "-p", "ec2", "-s", "precise", "-r", "region",
355- "-u", "https://ec2.region.amazonaws.com", "-d", metadataDir},
356+ "-u", "https://ec2.region.amazonaws.com", "-d", s.metadataDir},
357 )
358 c.Assert(code, gc.Equals, 1)
359+ errOut := ctx.Stderr.(*bytes.Buffer).String()
360+ strippedOut := strings.Replace(errOut, "\n", "", -1)
361+ c.Check(strippedOut, gc.Matches, `.*Resolve Metadata:.*`)
362 }
363
364 func (s *ValidateToolsMetadataSuite) TestOpenstackLocalMetadataWithManualParams(c *gc.C) {
365 s.makeLocalMetadata(c, "1.11.4", "region-2", "raring", "some-auth-url")
366 ctx := coretesting.Context(c)
367- metadataDir := osenv.JujuHomePath("")
368 code := cmd.Main(
369 &ValidateToolsMetadataCommand{}, ctx, []string{
370 "-p", "openstack", "-s", "raring", "-r", "region-2", "-j", "1.11.4",
371- "-u", "some-auth-url", "-d", metadataDir},
372+ "-u", "some-auth-url", "-d", s.metadataDir},
373 )
374 c.Assert(code, gc.Equals, 0)
375 errOut := ctx.Stdout.(*bytes.Buffer).String()
376 strippedOut := strings.Replace(errOut, "\n", "", -1)
377- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
378+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
379 }
380
381 func (s *ValidateToolsMetadataSuite) TestOpenstackLocalMetadataNoMatch(c *gc.C) {
382 s.makeLocalMetadata(c, "1.11.4", "region-2", "raring", "some-auth-url")
383 ctx := coretesting.Context(c)
384- metadataDir := osenv.JujuHomePath("")
385 code := cmd.Main(
386 &ValidateToolsMetadataCommand{}, ctx, []string{
387 "-p", "openstack", "-s", "precise", "-r", "region-2",
388- "-u", "some-auth-url", "-d", metadataDir},
389+ "-u", "some-auth-url", "-d", s.metadataDir},
390 )
391 c.Assert(code, gc.Equals, 1)
392 code = cmd.Main(
393 &ValidateToolsMetadataCommand{}, ctx, []string{
394 "-p", "openstack", "-s", "raring", "-r", "region-3",
395- "-u", "some-auth-url", "-d", metadataDir},
396+ "-u", "some-auth-url", "-d", s.metadataDir},
397 )
398 c.Assert(code, gc.Equals, 1)
399+ errOut := ctx.Stderr.(*bytes.Buffer).String()
400+ strippedOut := strings.Replace(errOut, "\n", "", -1)
401+ c.Check(strippedOut, gc.Matches, `.*Resolve Metadata:.*`)
402 }
403
404 func (s *ValidateToolsMetadataSuite) TestDefaultVersion(c *gc.C) {
405 s.makeLocalMetadata(c, version.Current.Number.String(), "region-2", "raring", "some-auth-url")
406 ctx := coretesting.Context(c)
407- metadataDir := osenv.JujuHomePath("")
408 code := cmd.Main(
409 &ValidateToolsMetadataCommand{}, ctx, []string{
410 "-p", "openstack", "-s", "raring", "-r", "region-2",
411- "-u", "some-auth-url", "-d", metadataDir},
412+ "-u", "some-auth-url", "-d", s.metadataDir},
413 )
414 c.Assert(code, gc.Equals, 0)
415 errOut := ctx.Stdout.(*bytes.Buffer).String()
416 strippedOut := strings.Replace(errOut, "\n", "", -1)
417- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
418+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
419 }
420
421 func (s *ValidateToolsMetadataSuite) TestMajorVersionMatch(c *gc.C) {
422 s.makeLocalMetadata(c, "1.11.4", "region-2", "raring", "some-auth-url")
423 ctx := coretesting.Context(c)
424- metadataDir := osenv.JujuHomePath("")
425 code := cmd.Main(
426 &ValidateToolsMetadataCommand{}, ctx, []string{
427 "-p", "openstack", "-s", "raring", "-r", "region-2",
428- "-u", "some-auth-url", "-d", metadataDir, "-m", "1"},
429+ "-u", "some-auth-url", "-d", s.metadataDir, "-m", "1"},
430 )
431 c.Assert(code, gc.Equals, 0)
432 errOut := ctx.Stdout.(*bytes.Buffer).String()
433 strippedOut := strings.Replace(errOut, "\n", "", -1)
434- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
435+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
436 }
437
438 func (s *ValidateToolsMetadataSuite) TestMajorMinorVersionMatch(c *gc.C) {
439 s.makeLocalMetadata(c, "1.12.1", "region-2", "raring", "some-auth-url")
440 ctx := coretesting.Context(c)
441- metadataDir := osenv.JujuHomePath("")
442 code := cmd.Main(
443 &ValidateToolsMetadataCommand{}, ctx, []string{
444 "-p", "openstack", "-s", "raring", "-r", "region-2",
445- "-u", "some-auth-url", "-d", metadataDir, "-m", "1.12"},
446+ "-u", "some-auth-url", "-d", s.metadataDir, "-m", "1.12"},
447 )
448 c.Assert(code, gc.Equals, 0)
449 errOut := ctx.Stdout.(*bytes.Buffer).String()
450 strippedOut := strings.Replace(errOut, "\n", "", -1)
451- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
452+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
453 }
454
455 func (s *ValidateToolsMetadataSuite) TestJustDirectory(c *gc.C) {
456 s.makeLocalMetadata(c, version.Current.Number.String(), "region-2", "raring", "some-auth-url")
457 ctx := coretesting.Context(c)
458- metadataDir := osenv.JujuHomePath("")
459 code := cmd.Main(
460- &ValidateToolsMetadataCommand{}, ctx, []string{"-s", "raring", "-d", metadataDir},
461+ &ValidateToolsMetadataCommand{}, ctx, []string{"-s", "raring", "-d", s.metadataDir},
462 )
463 c.Assert(code, gc.Equals, 0)
464 errOut := ctx.Stdout.(*bytes.Buffer).String()
465 strippedOut := strings.Replace(errOut, "\n", "", -1)
466- c.Check(strippedOut, gc.Matches, `matching tools versions:.*`)
467+ c.Check(strippedOut, gc.Matches, `Matching Tools Versions:.*Resolve Metadata.*`)
468 }
469
470=== modified file 'environs/bootstrap/bootstrap_test.go'
471--- environs/bootstrap/bootstrap_test.go 2014-02-13 02:46:58 +0000
472+++ environs/bootstrap/bootstrap_test.go 2014-03-04 05:51:00 +0000
473@@ -218,7 +218,8 @@
474 // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata.
475 func (e *bootstrapEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
476 // Add the simplestreams source off the control bucket.
477- return []simplestreams.DataSource{storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath)}, nil
478+ return []simplestreams.DataSource{
479+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath)}, nil
480 }
481
482 func newEnviron(name string, defaultKeys bool) *bootstrapEnviron {
483
484=== modified file 'environs/imagemetadata/generate.go'
485--- environs/imagemetadata/generate.go 2014-01-21 22:26:08 +0000
486+++ environs/imagemetadata/generate.go 2014-03-04 05:51:00 +0000
487@@ -34,9 +34,9 @@
488 // readMetadata reads the image metadata from metadataStore.
489 func readMetadata(metadataStore storage.Storage) ([]*ImageMetadata, error) {
490 // Read any existing metadata so we can merge the new tools metadata with what's there.
491- dataSource := storage.NewStorageSimpleStreamsDataSource(metadataStore, storage.BaseImagesPath)
492+ dataSource := storage.NewStorageSimpleStreamsDataSource("existing metadata", metadataStore, storage.BaseImagesPath)
493 imageConstraint := NewImageConstraint(simplestreams.LookupParams{})
494- existingMetadata, err := Fetch(
495+ existingMetadata, _, err := Fetch(
496 []simplestreams.DataSource{dataSource}, simplestreams.DefaultIndexPath, imageConstraint, false)
497 if err != nil && !errors.IsNotFoundError(err) {
498 return nil, err
499
500=== modified file 'environs/imagemetadata/generate_test.go'
501--- environs/imagemetadata/generate_test.go 2014-01-21 22:26:08 +0000
502+++ environs/imagemetadata/generate_test.go 2014-03-04 05:51:00 +0000
503@@ -28,8 +28,8 @@
504 Series: []string{series},
505 Arches: []string{arch},
506 })
507- dataSource := storage.NewStorageSimpleStreamsDataSource(stor, "images")
508- metadata, err := imagemetadata.Fetch(
509+ dataSource := storage.NewStorageSimpleStreamsDataSource("test datasource", stor, "images")
510+ metadata, _, err := imagemetadata.Fetch(
511 []simplestreams.DataSource{dataSource}, simplestreams.DefaultIndexPath, cons, false)
512 c.Assert(err, gc.IsNil)
513 c.Assert(metadata, gc.HasLen, 1)
514
515=== modified file 'environs/imagemetadata/simplestreams.go'
516--- environs/imagemetadata/simplestreams.go 2014-02-28 03:05:47 +0000
517+++ environs/imagemetadata/simplestreams.go 2014-03-04 05:51:00 +0000
518@@ -164,22 +164,24 @@
519 // The base URL locations are as specified - the first location which has a file is the one used.
520 // Signed data is preferred, but if there is no signed data available and onlySigned is false,
521 // then unsigned data is used.
522-func Fetch(sources []simplestreams.DataSource, indexPath string, cons *ImageConstraint, onlySigned bool) ([]*ImageMetadata, error) {
523+func Fetch(
524+ sources []simplestreams.DataSource, indexPath string, cons *ImageConstraint,
525+ onlySigned bool) ([]*ImageMetadata, *simplestreams.ResolveInfo, error) {
526 params := simplestreams.ValueParams{
527 DataType: ImageIds,
528 FilterFunc: appendMatchingImages,
529 ValueTemplate: ImageMetadata{},
530 PublicKey: simplestreamsImagesPublicKey,
531 }
532- items, err := simplestreams.GetMetadata(sources, indexPath, cons, onlySigned, params)
533+ items, resolveInfo, err := simplestreams.GetMetadata(sources, indexPath, cons, onlySigned, params)
534 if err != nil {
535- return nil, err
536+ return nil, resolveInfo, err
537 }
538 metadata := make([]*ImageMetadata, len(items))
539 for i, md := range items {
540 metadata[i] = md.(*ImageMetadata)
541 }
542- return metadata, nil
543+ return metadata, resolveInfo, nil
544 }
545
546 type imageKey struct {
547
548=== modified file 'environs/imagemetadata/simplestreams_test.go'
549--- environs/imagemetadata/simplestreams_test.go 2014-01-29 00:14:51 +0000
550+++ environs/imagemetadata/simplestreams_test.go 2014-03-04 05:51:00 +0000
551@@ -66,7 +66,8 @@
552 func registerSimpleStreamsTests() {
553 gc.Suite(&simplestreamsSuite{
554 LocalLiveSimplestreamsSuite: sstesting.LocalLiveSimplestreamsSuite{
555- Source: simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames),
556+ Source: simplestreams.NewURLDataSource(
557+ "test roundtripper", "test:", simplestreams.VerifySSLHostnames),
558 RequireSigned: false,
559 DataType: imagemetadata.ImageIds,
560 ValidConstraint: imagemetadata.NewImageConstraint(simplestreams.LookupParams{
561@@ -84,7 +85,7 @@
562
563 func registerLiveSimpleStreamsTests(baseURL string, validImageConstraint simplestreams.LookupConstraint, requireSigned bool) {
564 gc.Suite(&sstesting.LocalLiveSimplestreamsSuite{
565- Source: simplestreams.NewURLDataSource(baseURL, simplestreams.VerifySSLHostnames),
566+ Source: simplestreams.NewURLDataSource("test", baseURL, simplestreams.VerifySSLHostnames),
567 RequireSigned: requireSigned,
568 DataType: imagemetadata.ImageIds,
569 ValidConstraint: validImageConstraint,
570@@ -265,7 +266,11 @@
571 Series: []string{"precise"},
572 Arches: t.arches,
573 })
574- images, err := imagemetadata.Fetch([]simplestreams.DataSource{s.Source}, simplestreams.DefaultIndexPath, imageConstraint, s.RequireSigned)
575+ // Add invalid datasource and check later that resolveInfo is correct.
576+ invalidSource := simplestreams.NewURLDataSource("invalid", "file://invalid", simplestreams.VerifySSLHostnames)
577+ images, resolveInfo, err := imagemetadata.Fetch(
578+ []simplestreams.DataSource{invalidSource, s.Source}, simplestreams.DefaultIndexPath,
579+ imageConstraint, s.RequireSigned)
580 if !c.Check(err, gc.IsNil) {
581 continue
582 }
583@@ -273,6 +278,12 @@
584 testImage.Version = t.version
585 }
586 c.Check(images, gc.DeepEquals, t.images)
587+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
588+ Source: "test roundtripper",
589+ Signed: s.RequireSigned,
590+ IndexURL: "test:/streams/v1/index.json",
591+ MirrorURL: "",
592+ })
593 }
594 }
595
596@@ -364,28 +375,34 @@
597 }
598
599 func (s *signedSuite) TestSignedImageMetadata(c *gc.C) {
600- signedSource := simplestreams.NewURLDataSource("signedtest://host/signed", simplestreams.VerifySSLHostnames)
601+ signedSource := simplestreams.NewURLDataSource("test", "signedtest://host/signed", simplestreams.VerifySSLHostnames)
602 imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
603 CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"},
604 Series: []string{"precise"},
605 Arches: []string{"amd64"},
606 })
607- images, err := imagemetadata.Fetch(
608+ images, resolveInfo, err := imagemetadata.Fetch(
609 []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, imageConstraint, true)
610 c.Assert(err, gc.IsNil)
611 c.Assert(len(images), gc.Equals, 1)
612 c.Assert(images[0].Id, gc.Equals, "ami-123456")
613+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
614+ Source: "test",
615+ Signed: true,
616+ IndexURL: "signedtest://host/signed/streams/v1/index.sjson",
617+ MirrorURL: "",
618+ })
619 }
620
621 func (s *signedSuite) TestSignedImageMetadataInvalidSignature(c *gc.C) {
622- signedSource := simplestreams.NewURLDataSource("signedtest://host/signed", simplestreams.VerifySSLHostnames)
623+ signedSource := simplestreams.NewURLDataSource("test", "signedtest://host/signed", simplestreams.VerifySSLHostnames)
624 imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
625 CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"},
626 Series: []string{"precise"},
627 Arches: []string{"amd64"},
628 })
629 imagemetadata.SetSigningPublicKey(s.origKey)
630- _, err := imagemetadata.Fetch(
631+ _, _, err := imagemetadata.Fetch(
632 []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, imageConstraint, true)
633 c.Assert(err, gc.ErrorMatches, "cannot read index data.*")
634 }
635
636=== modified file 'environs/imagemetadata/testing/testing.go'
637--- environs/imagemetadata/testing/testing.go 2014-01-21 22:26:08 +0000
638+++ environs/imagemetadata/testing/testing.go 2014-03-04 05:51:00 +0000
639@@ -27,7 +27,7 @@
640
641 // ParseMetadataFromStorage loads ImageMetadata from the specified storage reader.
642 func ParseMetadataFromStorage(c *gc.C, stor storage.StorageReader) []*imagemetadata.ImageMetadata {
643- source := storage.NewStorageSimpleStreamsDataSource(stor, "images")
644+ source := storage.NewStorageSimpleStreamsDataSource("test storage reader", stor, "images")
645
646 // Find the simplestreams index file.
647 params := simplestreams.ValueParams{
648
649=== modified file 'environs/imagemetadata/urls.go'
650--- environs/imagemetadata/urls.go 2014-01-29 06:45:16 +0000
651+++ environs/imagemetadata/urls.go 2014-03-04 05:51:00 +0000
652@@ -31,7 +31,7 @@
653 if !config.SSLHostnameVerification() {
654 verify = simplestreams.NoVerifySSLHostnames
655 }
656- sources = append(sources, simplestreams.NewURLDataSource(userURL, verify))
657+ sources = append(sources, simplestreams.NewURLDataSource("image-metadata-url", userURL, verify))
658 }
659 if custom, ok := env.(SupportsCustomSources); ok {
660 customSources, err := custom.GetImageSources()
661@@ -46,7 +46,7 @@
662 return nil, err
663 }
664 if defaultURL != "" {
665- sources = append(sources, simplestreams.NewURLDataSource(defaultURL, simplestreams.VerifySSLHostnames))
666+ sources = append(sources, simplestreams.NewURLDataSource("default cloud images", defaultURL, simplestreams.VerifySSLHostnames))
667 }
668 return sources, nil
669 }
670
671=== modified file 'environs/imagemetadata/validation.go'
672--- environs/imagemetadata/validation.go 2014-01-29 06:45:16 +0000
673+++ environs/imagemetadata/validation.go 2014-03-04 05:51:00 +0000
674@@ -11,21 +11,21 @@
675
676 // ValidateImageMetadata attempts to load image metadata for the specified cloud attributes and stream
677 // and returns any image ids found, or an error if the metadata could not be loaded.
678-func ValidateImageMetadata(params *simplestreams.MetadataLookupParams) ([]string, error) {
679+func ValidateImageMetadata(params *simplestreams.MetadataLookupParams) ([]string, *simplestreams.ResolveInfo, error) {
680 if params.Series == "" {
681- return nil, fmt.Errorf("required parameter series not specified")
682+ return nil, nil, fmt.Errorf("required parameter series not specified")
683 }
684 if params.Region == "" {
685- return nil, fmt.Errorf("required parameter region not specified")
686+ return nil, nil, fmt.Errorf("required parameter region not specified")
687 }
688 if params.Endpoint == "" {
689- return nil, fmt.Errorf("required parameter endpoint not specified")
690+ return nil, nil, fmt.Errorf("required parameter endpoint not specified")
691 }
692 if len(params.Architectures) == 0 {
693- return nil, fmt.Errorf("required parameter arches not specified")
694+ return nil, nil, fmt.Errorf("required parameter arches not specified")
695 }
696 if len(params.Sources) == 0 {
697- return nil, fmt.Errorf("required parameter sources not specified")
698+ return nil, nil, fmt.Errorf("required parameter sources not specified")
699 }
700 imageConstraint := NewImageConstraint(simplestreams.LookupParams{
701 CloudSpec: simplestreams.CloudSpec{params.Region, params.Endpoint},
702@@ -33,16 +33,16 @@
703 Arches: params.Architectures,
704 Stream: params.Stream,
705 })
706- matchingImages, err := Fetch(params.Sources, simplestreams.DefaultIndexPath, imageConstraint, false)
707+ matchingImages, resolveInfo, err := Fetch(params.Sources, simplestreams.DefaultIndexPath, imageConstraint, false)
708 if err != nil {
709- return nil, err
710+ return nil, resolveInfo, err
711 }
712 if len(matchingImages) == 0 {
713- return nil, fmt.Errorf("no matching images found for constraint %+v", imageConstraint)
714+ return nil, resolveInfo, fmt.Errorf("no matching images found for constraint %+v", imageConstraint)
715 }
716 image_ids := make([]string, len(matchingImages))
717 for i, im := range matchingImages {
718 image_ids[i] = im.Id
719 }
720- return image_ids, nil
721+ return image_ids, resolveInfo, nil
722 }
723
724=== modified file 'environs/imagemetadata/validation_test.go'
725--- environs/imagemetadata/validation_test.go 2014-01-29 06:45:16 +0000
726+++ environs/imagemetadata/validation_test.go 2014-03-04 05:51:00 +0000
727@@ -4,6 +4,7 @@
728 package imagemetadata_test
729
730 import (
731+ "path"
732 "path/filepath"
733
734 gc "launchpad.net/gocheck"
735@@ -57,11 +58,17 @@
736 Endpoint: "some-auth-url",
737 Stream: stream,
738 Sources: []simplestreams.DataSource{
739- simplestreams.NewURLDataSource("file://"+metadataPath, simplestreams.VerifySSLHostnames)},
740+ simplestreams.NewURLDataSource("test", "file://"+metadataPath, simplestreams.VerifySSLHostnames)},
741 }
742- imageIds, err := imagemetadata.ValidateImageMetadata(params)
743+ imageIds, resolveInfo, err := imagemetadata.ValidateImageMetadata(params)
744 c.Assert(err, gc.IsNil)
745 c.Assert(imageIds, gc.DeepEquals, []string{"1234"})
746+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
747+ Source: "test",
748+ Signed: false,
749+ IndexURL: "file://" + path.Join(metadataPath, "streams/v1/index.json"),
750+ MirrorURL: "",
751+ })
752 }
753
754 func (s *ValidateSuite) TestMatch(c *gc.C) {
755@@ -79,9 +86,9 @@
756 Endpoint: "some-auth-url",
757 Stream: stream,
758 Sources: []simplestreams.DataSource{
759- simplestreams.NewURLDataSource("file://"+s.metadataDir, simplestreams.VerifySSLHostnames)},
760+ simplestreams.NewURLDataSource("test", "file://"+s.metadataDir, simplestreams.VerifySSLHostnames)},
761 }
762- _, err := imagemetadata.ValidateImageMetadata(params)
763+ _, _, err := imagemetadata.ValidateImageMetadata(params)
764 c.Assert(err, gc.Not(gc.IsNil))
765 }
766
767
768=== modified file 'environs/instances/image_test.go'
769--- environs/instances/image_test.go 2014-01-29 00:14:51 +0000
770+++ environs/instances/image_test.go 2014-03-04 05:51:00 +0000
771@@ -240,7 +240,8 @@
772 Stream: t.stream,
773 })
774 imageMeta, err := imagemetadata.GetLatestImageIdMetadata(
775- []byte(jsonImagesContent), simplestreams.NewURLDataSource("some-url", simplestreams.VerifySSLHostnames), cons)
776+ []byte(jsonImagesContent),
777+ simplestreams.NewURLDataSource("test", "some-url", simplestreams.VerifySSLHostnames), cons)
778 c.Assert(err, gc.IsNil)
779 var images []Image
780 for _, imageMetadata := range imageMeta {
781
782=== modified file 'environs/simplestreams/datasource.go'
783--- environs/simplestreams/datasource.go 2013-10-17 22:48:19 +0000
784+++ environs/simplestreams/datasource.go 2014-03-04 05:51:00 +0000
785@@ -15,6 +15,9 @@
786
787 // A DataSource retrieves simplestreams metadata.
788 type DataSource interface {
789+ // Description describes the origin of this datasource.
790+ // eg tools-metadata-url, cloud storage, keystone catalog etc.
791+ Description() string
792 // Fetch loads the data at the specified relative path. It returns a reader from which
793 // the data can be retrieved as well as the full URL of the file. The full URL is typically
794 // used in log messages to help diagnose issues accessing the data.
795@@ -43,20 +46,27 @@
796
797 // A urlDataSource retrieves data from an HTTP URL.
798 type urlDataSource struct {
799+ description string
800 baseURL string
801 hostnameVerification SSLHostnameVerification
802 }
803
804 // NewURLDataSource returns a new datasource reading from the specified baseURL.
805-func NewURLDataSource(baseURL string, verify SSLHostnameVerification) DataSource {
806+func NewURLDataSource(description, baseURL string, verify SSLHostnameVerification) DataSource {
807 return &urlDataSource{
808+ description: description,
809 baseURL: baseURL,
810 hostnameVerification: verify,
811 }
812 }
813
814+// Description is defined in simplestreams.DataSource.
815+func (u *urlDataSource) Description() string {
816+ return u.description
817+}
818+
819 func (u *urlDataSource) GoString() string {
820- return fmt.Sprintf("urlDataSource(%q)", u.baseURL)
821+ return fmt.Sprintf("%v: urlDataSource(%q)", u.description, u.baseURL)
822 }
823
824 // urlJoin returns baseURL + relpath making sure to have a '/' inbetween them
825
826=== modified file 'environs/simplestreams/datasource_test.go'
827--- environs/simplestreams/datasource_test.go 2013-09-17 09:18:36 +0000
828+++ environs/simplestreams/datasource_test.go 2014-03-04 05:51:00 +0000
829@@ -24,7 +24,7 @@
830 }
831
832 func (s *datasourceSuite) TestFetch(c *gc.C) {
833- ds := simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames)
834+ ds := simplestreams.NewURLDataSource("test", "test:", simplestreams.VerifySSLHostnames)
835 rc, url, err := ds.Fetch("streams/v1/tools_metadata.json")
836 c.Assert(err, gc.IsNil)
837 defer rc.Close()
838@@ -36,7 +36,7 @@
839 }
840
841 func (s *datasourceSuite) TestURL(c *gc.C) {
842- ds := simplestreams.NewURLDataSource("foo", simplestreams.VerifySSLHostnames)
843+ ds := simplestreams.NewURLDataSource("test", "foo", simplestreams.VerifySSLHostnames)
844 url, err := ds.URL("bar")
845 c.Assert(err, gc.IsNil)
846 c.Assert(url, gc.Equals, "foo/bar")
847@@ -64,7 +64,7 @@
848 }
849
850 func (s *datasourceHTTPSSuite) TestNormalClientFails(c *gc.C) {
851- ds := simplestreams.NewURLDataSource(s.Server.URL, simplestreams.VerifySSLHostnames)
852+ ds := simplestreams.NewURLDataSource("test", s.Server.URL, simplestreams.VerifySSLHostnames)
853 url, err := ds.URL("bar")
854 c.Assert(err, gc.IsNil)
855 c.Check(url, gc.Equals, s.Server.URL+"/bar")
856@@ -76,7 +76,7 @@
857 }
858
859 func (s *datasourceHTTPSSuite) TestNonVerifyingClientSucceeds(c *gc.C) {
860- ds := simplestreams.NewURLDataSource(s.Server.URL, simplestreams.NoVerifySSLHostnames)
861+ ds := simplestreams.NewURLDataSource("test", s.Server.URL, simplestreams.NoVerifySSLHostnames)
862 url, err := ds.URL("bar")
863 c.Assert(err, gc.IsNil)
864 c.Check(url, gc.Equals, s.Server.URL+"/bar")
865
866=== modified file 'environs/simplestreams/simplestreams.go'
867--- environs/simplestreams/simplestreams.go 2014-02-25 04:47:53 +0000
868+++ environs/simplestreams/simplestreams.go 2014-03-04 05:51:00 +0000
869@@ -30,6 +30,13 @@
870
871 var logger = loggo.GetLogger("juju.environs.simplestreams")
872
873+type ResolveInfo struct {
874+ Source string `yaml:"source" json:"source"`
875+ Signed bool `yaml:"signed" json:"signed"`
876+ IndexURL string `yaml:"indexURL" json:"indexURL"`
877+ MirrorURL string `yaml:"mirrorURL,omitempty" json:"mirrorURL,omitempty"`
878+}
879+
880 // CloudSpec uniquely defines a specific cloud deployment.
881 type CloudSpec struct {
882 Region string `json:"region"`
883@@ -422,12 +429,14 @@
884 // GetMetadata returns metadata records matching the specified constraint,looking in each source for signed metadata.
885 // If onlySigned is false and no signed metadata is found in a source, the source is used to look for unsigned metadata.
886 // Each source is tried in turn until at least one signed (or unsigned) match is found.
887-func GetMetadata(sources []DataSource, baseIndexPath string, cons LookupConstraint, onlySigned bool, params ValueParams) (items []interface{}, err error) {
888+func GetMetadata(
889+ sources []DataSource, baseIndexPath string, cons LookupConstraint, onlySigned bool,
890+ params ValueParams) (items []interface{}, resolveInfo *ResolveInfo, err error) {
891 for _, source := range sources {
892- items, err = getMaybeSignedMetadata(source, baseIndexPath, cons, true, params)
893+ items, resolveInfo, err = getMaybeSignedMetadata(source, baseIndexPath, cons, true, params)
894 // If no items are found using signed metadata, check unsigned.
895 if err != nil && len(items) == 0 && !onlySigned {
896- items, err = getMaybeSignedMetadata(source, baseIndexPath, cons, false, params)
897+ items, resolveInfo, err = getMaybeSignedMetadata(source, baseIndexPath, cons, false, params)
898 }
899 if err == nil {
900 break
901@@ -437,11 +446,14 @@
902 // no matching products is an internal error only
903 err = nil
904 }
905- return items, err
906+ return items, resolveInfo, err
907 }
908
909 // getMaybeSignedMetadata returns metadata records matching the specified constraint.
910-func getMaybeSignedMetadata(source DataSource, baseIndexPath string, cons LookupConstraint, signed bool, params ValueParams) ([]interface{}, error) {
911+func getMaybeSignedMetadata(source DataSource, baseIndexPath string, cons LookupConstraint,
912+ signed bool, params ValueParams) ([]interface{}, *ResolveInfo, error) {
913+
914+ resolveInfo := &ResolveInfo{}
915 indexPath := baseIndexPath + UnsignedSuffix
916 if signed {
917 indexPath = baseIndexPath + signedSuffix
918@@ -453,25 +465,31 @@
919 // So the best we can do is use the relative path for the URL when logging messages.
920 indexURL = indexPath
921 }
922+ resolveInfo.Source = source.Description()
923+ resolveInfo.Signed = signed
924+ resolveInfo.IndexURL = indexURL
925 indexRef, err := GetIndexWithFormat(source, indexPath, "index:1.0", signed, cons.Params().CloudSpec, params)
926 if err != nil {
927 if errors.IsNotFoundError(err) || errors.IsUnauthorizedError(err) {
928 logger.Debugf("cannot load index %q: %v", indexURL, err)
929 }
930- return nil, err
931+ return nil, resolveInfo, err
932 }
933 logger.Debugf("read metadata index at %q", indexURL)
934 items, err = indexRef.getLatestMetadataWithFormat(cons, "products:1.0", signed)
935 if err != nil {
936 if errors.IsNotFoundError(err) {
937 logger.Debugf("skipping index because of error getting latest metadata %q: %v", indexURL, err)
938- return nil, err
939+ return nil, resolveInfo, err
940 }
941 if _, ok := err.(*noMatchingProductsError); ok {
942 logger.Debugf("%v", err)
943 }
944 }
945- return items, err
946+ if indexRef.Source.Description() == "mirror" {
947+ resolveInfo.MirrorURL = indexRef.Source.(*urlDataSource).baseURL
948+ }
949+ return items, resolveInfo, err
950 }
951
952 // fetchData gets all the data from the given source located at the specified path.
953@@ -534,7 +552,7 @@
954 source, mirrors, params.DataType, params.MirrorContentId, cloudSpec, requireSigned, params.PublicKey)
955 if err == nil {
956 logger.Debugf("using mirrored products path: %s", path.Join(mirrorInfo.MirrorURL, mirrorInfo.Path))
957- indexRef.Source = NewURLDataSource(mirrorInfo.MirrorURL, VerifySSLHostnames)
958+ indexRef.Source = NewURLDataSource("mirror", mirrorInfo.MirrorURL, VerifySSLHostnames)
959 indexRef.MirroredProductsPath = mirrorInfo.Path
960 } else {
961 logger.Debugf("no mirror information available for %s: %v", cloudSpec, err)
962
963=== modified file 'environs/simplestreams/simplestreams_test.go'
964--- environs/simplestreams/simplestreams_test.go 2014-02-11 03:40:13 +0000
965+++ environs/simplestreams/simplestreams_test.go 2014-03-04 05:51:00 +0000
966@@ -27,7 +27,7 @@
967 func registerSimpleStreamsTests() {
968 gc.Suite(&simplestreamsSuite{
969 LocalLiveSimplestreamsSuite: sstesting.LocalLiveSimplestreamsSuite{
970- Source: simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames),
971+ Source: simplestreams.NewURLDataSource("test", "test:", simplestreams.VerifySSLHostnames),
972 RequireSigned: false,
973 DataType: "image-ids",
974 ValidConstraint: sstesting.NewTestConstraint(simplestreams.LookupParams{
975@@ -316,7 +316,7 @@
976 func (s *simplestreamsSuite) TestGetMetadataNoMatching(c *gc.C) {
977 source := &countingSource{
978 DataSource: simplestreams.NewURLDataSource(
979- "test:/daily", simplestreams.VerifySSLHostnames,
980+ "test", "test:/daily", simplestreams.VerifySSLHostnames,
981 ),
982 }
983 sources := []simplestreams.DataSource{source, source, source}
984@@ -330,7 +330,7 @@
985 Arches: []string{"not-a-real-arch"}, // never matches
986 })
987
988- items, err := simplestreams.GetMetadata(
989+ items, resolveInfo, err := simplestreams.GetMetadata(
990 sources,
991 simplestreams.DefaultIndexPath,
992 constraint,
993@@ -339,6 +339,12 @@
994 )
995 c.Assert(err, gc.IsNil)
996 c.Assert(items, gc.HasLen, 0)
997+ c.Assert(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
998+ Source: "test",
999+ Signed: false,
1000+ IndexURL: "test:/daily/streams/v1/index.json",
1001+ MirrorURL: "",
1002+ })
1003
1004 // There should be 2 calls to each data-source:
1005 // one for .sjson, one for .json.
1006
1007=== modified file 'environs/storage/storage.go'
1008--- environs/storage/storage.go 2014-01-09 05:27:24 +0000
1009+++ environs/storage/storage.go 2014-03-04 05:51:00 +0000
1010@@ -72,9 +72,10 @@
1011
1012 // A storageSimpleStreamsDataSource retrieves data from a StorageReader.
1013 type storageSimpleStreamsDataSource struct {
1014- basePath string
1015- storage StorageReader
1016- allowRetry bool
1017+ description string
1018+ basePath string
1019+ storage StorageReader
1020+ allowRetry bool
1021 }
1022
1023 // TestingGetAllowRetry is used in tests which need to see if allowRetry has been
1024@@ -87,8 +88,8 @@
1025 }
1026
1027 // NewStorageSimpleStreamsDataSource returns a new datasource reading from the specified storage.
1028-func NewStorageSimpleStreamsDataSource(storage StorageReader, basePath string) simplestreams.DataSource {
1029- return &storageSimpleStreamsDataSource{basePath, storage, false}
1030+func NewStorageSimpleStreamsDataSource(description string, storage StorageReader, basePath string) simplestreams.DataSource {
1031+ return &storageSimpleStreamsDataSource{description, basePath, storage, false}
1032 }
1033
1034 func (s *storageSimpleStreamsDataSource) relpath(storagePath string) string {
1035@@ -99,6 +100,11 @@
1036 return relpath
1037 }
1038
1039+// Description is defined in simplestreams.DataSource.
1040+func (s *storageSimpleStreamsDataSource) Description() string {
1041+ return s.description
1042+}
1043+
1044 // Fetch is defined in simplestreams.DataSource.
1045 func (s *storageSimpleStreamsDataSource) Fetch(path string) (io.ReadCloser, string, error) {
1046 relpath := s.relpath(path)
1047
1048=== modified file 'environs/storage/storage_test.go'
1049--- environs/storage/storage_test.go 2014-02-13 02:46:58 +0000
1050+++ environs/storage/storage_test.go 2014-03-04 05:51:00 +0000
1051@@ -57,7 +57,7 @@
1052 func (s *datasourceSuite) TestFetch(c *gc.C) {
1053 sampleData := "hello world"
1054 s.stor.Put("foo/bar/data.txt", bytes.NewReader([]byte(sampleData)), int64(len(sampleData)))
1055- ds := storage.NewStorageSimpleStreamsDataSource(s.stor, "")
1056+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", s.stor, "")
1057 rc, url, err := ds.Fetch("foo/bar/data.txt")
1058 c.Assert(err, gc.IsNil)
1059 defer rc.Close()
1060@@ -69,7 +69,7 @@
1061 func (s *datasourceSuite) TestFetchWithBasePath(c *gc.C) {
1062 sampleData := "hello world"
1063 s.stor.Put("base/foo/bar/data.txt", bytes.NewReader([]byte(sampleData)), int64(len(sampleData)))
1064- ds := storage.NewStorageSimpleStreamsDataSource(s.stor, "base")
1065+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", s.stor, "base")
1066 rc, url, err := ds.Fetch("foo/bar/data.txt")
1067 c.Assert(err, gc.IsNil)
1068 defer rc.Close()
1069@@ -80,7 +80,7 @@
1070
1071 func (s *datasourceSuite) TestFetchWithRetry(c *gc.C) {
1072 stor := &fakeStorage{shouldRetry: true}
1073- ds := storage.NewStorageSimpleStreamsDataSource(stor, "base")
1074+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", stor, "base")
1075 ds.SetAllowRetry(true)
1076 _, _, err := ds.Fetch("foo/bar/data.txt")
1077 c.Assert(err, gc.ErrorMatches, "an error")
1078@@ -92,7 +92,7 @@
1079 // NB shouldRetry below is true indicating the fake storage is capable of
1080 // retrying, not that it will retry.
1081 stor := &fakeStorage{shouldRetry: true}
1082- ds := storage.NewStorageSimpleStreamsDataSource(stor, "base")
1083+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", stor, "base")
1084 _, _, err := ds.Fetch("foo/bar/data.txt")
1085 c.Assert(err, gc.ErrorMatches, "an error")
1086 c.Assert(stor.getName, gc.Equals, "base/foo/bar/data.txt")
1087@@ -102,7 +102,7 @@
1088 func (s *datasourceSuite) TestURL(c *gc.C) {
1089 sampleData := "hello world"
1090 s.stor.Put("bar/data.txt", bytes.NewReader([]byte(sampleData)), int64(len(sampleData)))
1091- ds := storage.NewStorageSimpleStreamsDataSource(s.stor, "")
1092+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", s.stor, "")
1093 url, err := ds.URL("bar")
1094 c.Assert(err, gc.IsNil)
1095 expectedURL, _ := s.stor.URL("bar")
1096@@ -112,7 +112,7 @@
1097 func (s *datasourceSuite) TestURLWithBasePath(c *gc.C) {
1098 sampleData := "hello world"
1099 s.stor.Put("base/bar/data.txt", bytes.NewReader([]byte(sampleData)), int64(len(sampleData)))
1100- ds := storage.NewStorageSimpleStreamsDataSource(s.stor, "base")
1101+ ds := storage.NewStorageSimpleStreamsDataSource("test datasource", s.stor, "base")
1102 url, err := ds.URL("bar")
1103 c.Assert(err, gc.IsNil)
1104 expectedURL, _ := s.stor.URL("base/bar")
1105
1106=== modified file 'environs/sync/sync.go'
1107--- environs/sync/sync.go 2014-01-30 14:11:27 +0000
1108+++ environs/sync/sync.go 2014-03-04 05:51:00 +0000
1109@@ -140,7 +140,7 @@
1110 return nil, err
1111 }
1112 logger.Infof("using sync tools source: %v", sourceURL)
1113- return simplestreams.NewURLDataSource(sourceURL, simplestreams.VerifySSLHostnames), nil
1114+ return simplestreams.NewURLDataSource("sync tools source", sourceURL, simplestreams.VerifySSLHostnames), nil
1115 }
1116
1117 // copyTools copies a set of tools from the source to the target.
1118
1119=== removed file 'environs/tools/boilerplate.go'
1120--- environs/tools/boilerplate.go 2014-01-22 22:48:54 +0000
1121+++ environs/tools/boilerplate.go 1970-01-01 00:00:00 +0000
1122@@ -1,153 +0,0 @@
1123-// Copyright 2013 Canonical Ltd.
1124-// Licensed under the AGPLv3, see LICENCE file for details.
1125-
1126-package tools
1127-
1128-import (
1129- "bytes"
1130- "fmt"
1131- "io/ioutil"
1132- "os"
1133- "path/filepath"
1134- "text/template"
1135- "time"
1136-
1137- "launchpad.net/juju-core/environs/simplestreams"
1138- "launchpad.net/juju-core/juju/osenv"
1139-)
1140-
1141-const (
1142- defaultIndexFileName = "index.json"
1143- defaultToolsFileName = "toolsmetadata.json"
1144- streamsDir = "streams/v1"
1145-)
1146-
1147-// Boilerplate generates some basic simplestreams metadata using the specified cloud and tools details.
1148-func Boilerplate(tm *ToolsMetadata, cloudSpec *simplestreams.CloudSpec) ([]string, error) {
1149- return MakeBoilerplate(tm, cloudSpec, true)
1150-}
1151-
1152-// MakeBoilerplate exists so it can be called by tests. See Boilerplate above. It provides an option to retain
1153-// the streams directories when writing the generated metadata files.
1154-func MakeBoilerplate(tm *ToolsMetadata, cloudSpec *simplestreams.CloudSpec, flattenPath bool) ([]string, error) {
1155- indexFileName := defaultIndexFileName
1156- toolsFileName := defaultToolsFileName
1157- now := time.Now()
1158- imparams := toolsMetadataParams{
1159- ToolsBinarySize: tm.Size,
1160- ToolsBinaryPath: tm.Path,
1161- ToolsBinarySHA256: tm.SHA256,
1162- Version: tm.Version,
1163- Arch: tm.Arch,
1164- Series: tm.Release,
1165- Region: cloudSpec.Region,
1166- URL: cloudSpec.Endpoint,
1167- Path: streamsDir,
1168- ToolsFileName: toolsFileName,
1169- Updated: now.Format(time.RFC1123Z),
1170- VersionKey: now.Format("20060102"),
1171- }
1172-
1173- var err error
1174- imparams.SeriesVersion, err = simplestreams.SeriesVersion(tm.Release)
1175- if err != nil {
1176- return nil, fmt.Errorf("invalid series %q", tm.Release)
1177- }
1178-
1179- if !flattenPath {
1180- streamsPath := osenv.JujuHomePath(streamsDir)
1181- if err := os.MkdirAll(streamsPath, 0755); err != nil {
1182- return nil, err
1183- }
1184- indexFileName = filepath.Join(streamsDir, indexFileName)
1185- toolsFileName = filepath.Join(streamsDir, toolsFileName)
1186- }
1187- err = writeJsonFile(imparams, indexFileName, indexBoilerplate)
1188- if err != nil {
1189- return nil, err
1190- }
1191- err = writeJsonFile(imparams, toolsFileName, productBoilerplate)
1192- if err != nil {
1193- return nil, err
1194- }
1195- return []string{indexFileName, toolsFileName}, nil
1196-}
1197-
1198-type toolsMetadataParams struct {
1199- ToolsBinaryPath string
1200- ToolsBinarySize int64
1201- ToolsBinarySHA256 string
1202- Region string
1203- URL string
1204- Updated string
1205- Arch string
1206- Path string
1207- Series string
1208- SeriesVersion string
1209- Version string
1210- VersionKey string
1211- ToolsFileName string
1212-}
1213-
1214-func writeJsonFile(imparams toolsMetadataParams, filename, boilerplate string) error {
1215- t := template.Must(template.New("").Parse(boilerplate))
1216- var metadata bytes.Buffer
1217- if err := t.Execute(&metadata, imparams); err != nil {
1218- panic(fmt.Errorf("cannot generate %s metdata: %v", filename, err))
1219- }
1220- data := metadata.Bytes()
1221- path := osenv.JujuHomePath(filename)
1222- if err := ioutil.WriteFile(path, data, 0666); err != nil {
1223- return err
1224- }
1225- return nil
1226-}
1227-
1228-var indexBoilerplate = `
1229-{
1230- "index": {
1231- "com.ubuntu.juju:custom": {
1232- "updated": "{{.Updated}}",
1233- "cloudname": "custom",
1234- "datatype": "content-download",
1235- "format": "products:1.0",
1236- "products": [
1237- "com.ubuntu.juju:{{.SeriesVersion}}:{{.Arch}}"
1238- ],
1239- "path": "{{.Path}}/{{.ToolsFileName}}"
1240- }
1241- },
1242- "updated": "{{.Updated}}",
1243- "format": "index:1.0"
1244-}
1245-`
1246-
1247-var productBoilerplate = `
1248-{
1249- "content_id": "com.ubuntu.juju:custom",
1250- "format": "products:1.0",
1251- "updated": "{{.Updated}}",
1252- "datatype": "content-download",
1253- "products": {
1254- "com.ubuntu.juju:{{.SeriesVersion}}:{{.Arch}}": {
1255- "release": "{{.Series}}",
1256- "arch": "{{.Arch}}",
1257- "versions": {
1258- "{{.VersionKey}}": {
1259- "items": {
1260- "{{.Series}}{{.Version}}": {
1261- "version": "{{.Version}}",
1262- "size": {{.ToolsBinarySize}},
1263- "path": "{{.ToolsBinaryPath}}",
1264- "ftype": "tar.gz",
1265- "sha256": "{{.ToolsBinarySHA256}}"
1266- }
1267- },
1268- "pubname": "juju-{{.Series}}-{{.Arch}}-{{.VersionKey}}",
1269- "label": "custom"
1270- }
1271- }
1272- }
1273- }
1274-}
1275-`
1276
1277=== modified file 'environs/tools/simplestreams.go'
1278--- environs/tools/simplestreams.go 2014-01-30 06:21:03 +0000
1279+++ environs/tools/simplestreams.go 2014-03-04 05:51:00 +0000
1280@@ -102,9 +102,8 @@
1281 }
1282
1283 // NewVersionedToolsConstraint returns a ToolsConstraint for a tools with a specific version.
1284-func NewVersionedToolsConstraint(vers string, params simplestreams.LookupParams) *ToolsConstraint {
1285- versNum := version.MustParse(vers)
1286- return &ToolsConstraint{LookupParams: params, Version: versNum}
1287+func NewVersionedToolsConstraint(vers version.Number, params simplestreams.LookupParams) *ToolsConstraint {
1288+ return &ToolsConstraint{LookupParams: params, Version: vers}
1289 }
1290
1291 // NewGeneralToolsConstraint returns a ToolsConstraint for tools with matching major/minor version numbers.
1292@@ -168,7 +167,10 @@
1293 // The base URL locations are as specified - the first location which has a file is the one used.
1294 // Signed data is preferred, but if there is no signed data available and onlySigned is false,
1295 // then unsigned data is used.
1296-func Fetch(sources []simplestreams.DataSource, indexPath string, cons *ToolsConstraint, onlySigned bool) ([]*ToolsMetadata, error) {
1297+func Fetch(
1298+ sources []simplestreams.DataSource, indexPath string, cons *ToolsConstraint,
1299+ onlySigned bool) ([]*ToolsMetadata, *simplestreams.ResolveInfo, error) {
1300+
1301 params := simplestreams.ValueParams{
1302 DataType: ContentDownload,
1303 FilterFunc: appendMatchingTools,
1304@@ -176,15 +178,15 @@
1305 ValueTemplate: ToolsMetadata{},
1306 PublicKey: simplestreamsToolsPublicKey,
1307 }
1308- items, err := simplestreams.GetMetadata(sources, indexPath, cons, onlySigned, params)
1309+ items, resolveInfo, err := simplestreams.GetMetadata(sources, indexPath, cons, onlySigned, params)
1310 if err != nil {
1311- return nil, err
1312+ return nil, nil, err
1313 }
1314 metadata := make([]*ToolsMetadata, len(items))
1315 for i, md := range items {
1316 metadata[i] = md.(*ToolsMetadata)
1317 }
1318- return metadata, nil
1319+ return metadata, resolveInfo, nil
1320 }
1321
1322 // appendMatchingTools updates matchingTools with tools metadata records from tools which belong to the
1323@@ -311,12 +313,13 @@
1324
1325 // ReadMetadata returns the tools metadata from the given storage.
1326 func ReadMetadata(store storage.StorageReader) ([]*ToolsMetadata, error) {
1327- dataSource := storage.NewStorageSimpleStreamsDataSource(store, storage.BaseToolsPath)
1328+ dataSource := storage.NewStorageSimpleStreamsDataSource("existing metadata", store, storage.BaseToolsPath)
1329 toolsConstraint, err := makeToolsConstraint(simplestreams.CloudSpec{}, -1, -1, coretools.Filter{})
1330 if err != nil {
1331 return nil, err
1332 }
1333- metadata, err := Fetch([]simplestreams.DataSource{dataSource}, simplestreams.DefaultIndexPath, toolsConstraint, false)
1334+ metadata, _, err := Fetch(
1335+ []simplestreams.DataSource{dataSource}, simplestreams.DefaultIndexPath, toolsConstraint, false)
1336 if err != nil && !errors.IsNotFoundError(err) {
1337 return nil, err
1338 }
1339
1340=== modified file 'environs/tools/simplestreams_test.go'
1341--- environs/tools/simplestreams_test.go 2014-01-30 06:21:03 +0000
1342+++ environs/tools/simplestreams_test.go 2014-03-04 05:51:00 +0000
1343@@ -62,7 +62,7 @@
1344 t.Fatalf("Unknown vendor %s. Must be one of %s", *vendor, keys)
1345 }
1346 registerLiveSimpleStreamsTests(testData.baseURL,
1347- tools.NewVersionedToolsConstraint("1.13.0", simplestreams.LookupParams{
1348+ tools.NewVersionedToolsConstraint(version.MustParse("1.13.0"), simplestreams.LookupParams{
1349 CloudSpec: testData.validCloudSpec,
1350 Series: []string{version.Current.Series},
1351 Arches: []string{"amd64"},
1352@@ -74,10 +74,10 @@
1353 func registerSimpleStreamsTests() {
1354 gc.Suite(&simplestreamsSuite{
1355 LocalLiveSimplestreamsSuite: sstesting.LocalLiveSimplestreamsSuite{
1356- Source: simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames),
1357+ Source: simplestreams.NewURLDataSource("test", "test:", simplestreams.VerifySSLHostnames),
1358 RequireSigned: false,
1359 DataType: tools.ContentDownload,
1360- ValidConstraint: tools.NewVersionedToolsConstraint("1.13.0", simplestreams.LookupParams{
1361+ ValidConstraint: tools.NewVersionedToolsConstraint(version.MustParse("1.13.0"), simplestreams.LookupParams{
1362 CloudSpec: simplestreams.CloudSpec{
1363 Region: "us-east-1",
1364 Endpoint: "https://ec2.us-east-1.amazonaws.com",
1365@@ -92,7 +92,7 @@
1366
1367 func registerLiveSimpleStreamsTests(baseURL string, validToolsConstraint simplestreams.LookupConstraint, requireSigned bool) {
1368 gc.Suite(&sstesting.LocalLiveSimplestreamsSuite{
1369- Source: simplestreams.NewURLDataSource(baseURL, simplestreams.VerifySSLHostnames),
1370+ Source: simplestreams.NewURLDataSource("test", baseURL, simplestreams.VerifySSLHostnames),
1371 RequireSigned: requireSigned,
1372 DataType: tools.ContentDownload,
1373 ValidConstraint: validToolsConstraint,
1374@@ -238,14 +238,18 @@
1375 Arches: t.arches,
1376 })
1377 } else {
1378- toolsConstraint = tools.NewVersionedToolsConstraint(t.version, simplestreams.LookupParams{
1379- CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"},
1380- Series: []string{t.series},
1381- Arches: t.arches,
1382- })
1383+ toolsConstraint = tools.NewVersionedToolsConstraint(version.MustParse(t.version),
1384+ simplestreams.LookupParams{
1385+ CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"},
1386+ Series: []string{t.series},
1387+ Arches: t.arches,
1388+ })
1389 }
1390- tools, err := tools.Fetch(
1391- []simplestreams.DataSource{s.Source}, simplestreams.DefaultIndexPath, toolsConstraint, s.RequireSigned)
1392+ // Add invalid datasource and check later that resolveInfo is correct.
1393+ invalidSource := simplestreams.NewURLDataSource("invalid", "file://invalid", simplestreams.VerifySSLHostnames)
1394+ tools, resolveInfo, err := tools.Fetch(
1395+ []simplestreams.DataSource{invalidSource, s.Source},
1396+ simplestreams.DefaultIndexPath, toolsConstraint, s.RequireSigned)
1397 if !c.Check(err, gc.IsNil) {
1398 continue
1399 }
1400@@ -254,6 +258,12 @@
1401 c.Assert(err, gc.IsNil)
1402 }
1403 c.Check(tools, gc.DeepEquals, t.tools)
1404+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1405+ Source: "test",
1406+ Signed: s.RequireSigned,
1407+ IndexURL: "test:/streams/v1/index.json",
1408+ MirrorURL: "",
1409+ })
1410 }
1411 }
1412
1413@@ -263,7 +273,7 @@
1414 Series: []string{"precise"},
1415 Arches: []string{"amd64"},
1416 })
1417- toolsMetadata, err := tools.Fetch(
1418+ toolsMetadata, resolveInfo, err := tools.Fetch(
1419 []simplestreams.DataSource{s.Source}, simplestreams.DefaultIndexPath, toolsConstraint, s.RequireSigned)
1420 c.Assert(err, gc.IsNil)
1421 c.Assert(len(toolsMetadata), gc.Equals, 1)
1422@@ -280,6 +290,12 @@
1423 }
1424 c.Assert(err, gc.IsNil)
1425 c.Assert(toolsMetadata[0], gc.DeepEquals, expectedMetadata)
1426+ c.Assert(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1427+ Source: "test",
1428+ Signed: s.RequireSigned,
1429+ IndexURL: "test:/streams/v1/index.json",
1430+ MirrorURL: "test:/",
1431+ })
1432 }
1433
1434 func assertMetadataMatches(c *gc.C, storageDir string, toolList coretools.List, metadata []*tools.ToolsMetadata) {
1435@@ -396,7 +412,7 @@
1436 var _ = gc.Suite(&productSpecSuite{})
1437
1438 func (s *productSpecSuite) TestId(c *gc.C) {
1439- toolsConstraint := tools.NewVersionedToolsConstraint("1.13.0", simplestreams.LookupParams{
1440+ toolsConstraint := tools.NewVersionedToolsConstraint(version.MustParse("1.13.0"), simplestreams.LookupParams{
1441 Series: []string{"precise"},
1442 Arches: []string{"amd64"},
1443 })
1444@@ -406,7 +422,7 @@
1445 }
1446
1447 func (s *productSpecSuite) TestIdMultiArch(c *gc.C) {
1448- toolsConstraint := tools.NewVersionedToolsConstraint("1.11.3", simplestreams.LookupParams{
1449+ toolsConstraint := tools.NewVersionedToolsConstraint(version.MustParse("1.11.3"), simplestreams.LookupParams{
1450 Series: []string{"precise"},
1451 Arches: []string{"amd64", "arm"},
1452 })
1453@@ -418,7 +434,7 @@
1454 }
1455
1456 func (s *productSpecSuite) TestIdMultiSeries(c *gc.C) {
1457- toolsConstraint := tools.NewVersionedToolsConstraint("1.11.3", simplestreams.LookupParams{
1458+ toolsConstraint := tools.NewVersionedToolsConstraint(version.MustParse("1.11.3"), simplestreams.LookupParams{
1459 Series: []string{"precise", "raring"},
1460 Arches: []string{"amd64"},
1461 })
1462@@ -752,17 +768,23 @@
1463 }
1464
1465 func (s *signedSuite) TestSignedToolsMetadata(c *gc.C) {
1466- signedSource := simplestreams.NewURLDataSource("signedtest://host/signed", simplestreams.VerifySSLHostnames)
1467- toolsConstraint := tools.NewVersionedToolsConstraint("1.13.0", simplestreams.LookupParams{
1468+ signedSource := simplestreams.NewURLDataSource("test", "signedtest://host/signed", simplestreams.VerifySSLHostnames)
1469+ toolsConstraint := tools.NewVersionedToolsConstraint(version.MustParse("1.13.0"), simplestreams.LookupParams{
1470 CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"},
1471 Series: []string{"precise"},
1472 Arches: []string{"amd64"},
1473 })
1474- toolsMetadata, err := tools.Fetch(
1475+ toolsMetadata, resolveInfo, err := tools.Fetch(
1476 []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, toolsConstraint, true)
1477 c.Assert(err, gc.IsNil)
1478 c.Assert(len(toolsMetadata), gc.Equals, 1)
1479 c.Assert(toolsMetadata[0].Path, gc.Equals, "tools/releases/20130806/juju-1.13.1-precise-amd64.tgz")
1480+ c.Assert(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1481+ Source: "test",
1482+ Signed: true,
1483+ IndexURL: "signedtest://host/signed/streams/v1/index.sjson",
1484+ MirrorURL: "",
1485+ })
1486 }
1487
1488 var unsignedIndex = `
1489
1490=== modified file 'environs/tools/testing/testing.go'
1491--- environs/tools/testing/testing.go 2014-01-30 14:11:27 +0000
1492+++ environs/tools/testing/testing.go 2014-03-04 05:51:00 +0000
1493@@ -83,7 +83,7 @@
1494
1495 // ParseMetadataFromStorage loads ToolsMetadata from the specified storage reader.
1496 func ParseMetadataFromStorage(c *gc.C, stor storage.StorageReader, expectMirrors bool) []*tools.ToolsMetadata {
1497- source := storage.NewStorageSimpleStreamsDataSource(stor, "tools")
1498+ source := storage.NewStorageSimpleStreamsDataSource("test storage reader", stor, "tools")
1499 params := simplestreams.ValueParams{
1500 DataType: tools.ContentDownload,
1501 ValueTemplate: tools.ToolsMetadata{},
1502
1503=== modified file 'environs/tools/tools.go'
1504--- environs/tools/tools.go 2014-02-28 03:05:47 +0000
1505+++ environs/tools/tools.go 2014-03-04 05:51:00 +0000
1506@@ -32,7 +32,7 @@
1507 if majorMismatch || minorMismacth {
1508 return nil, coretools.ErrNoMatches
1509 }
1510- toolsConstraint = NewVersionedToolsConstraint(filter.Number.String(),
1511+ toolsConstraint = NewVersionedToolsConstraint(filter.Number,
1512 simplestreams.LookupParams{CloudSpec: cloudSpec})
1513 } else {
1514 toolsConstraint = NewGeneralToolsConstraint(majorVersion, minorVersion, filter.Released,
1515@@ -117,7 +117,7 @@
1516 if err != nil {
1517 return nil, err
1518 }
1519- toolsMetadata, err := Fetch(sources, simplestreams.DefaultIndexPath, toolsConstraint, false)
1520+ toolsMetadata, _, err := Fetch(sources, simplestreams.DefaultIndexPath, toolsConstraint, false)
1521 if err != nil {
1522 if errors.IsNotFoundError(err) {
1523 err = ErrNoTools
1524
1525=== modified file 'environs/tools/urls.go'
1526--- environs/tools/urls.go 2014-01-20 23:32:00 +0000
1527+++ environs/tools/urls.go 2014-03-04 05:51:00 +0000
1528@@ -39,7 +39,7 @@
1529 if !config.SSLHostnameVerification() {
1530 verify = simplestreams.NoVerifySSLHostnames
1531 }
1532- sources = append(sources, simplestreams.NewURLDataSource(userURL, verify))
1533+ sources = append(sources, simplestreams.NewURLDataSource("tools-metadata-url", userURL, verify))
1534 }
1535 if custom, ok := env.(SupportsCustomSources); ok {
1536 customSources, err := custom.GetToolsSources()
1537@@ -54,7 +54,7 @@
1538 return nil, err
1539 }
1540 if defaultURL != "" {
1541- sources = append(sources, simplestreams.NewURLDataSource(defaultURL, simplestreams.VerifySSLHostnames))
1542+ sources = append(sources, simplestreams.NewURLDataSource("default simplestreams", defaultURL, simplestreams.VerifySSLHostnames))
1543 }
1544 for _, source := range sources {
1545 source.SetAllowRetry(allowRetry)
1546
1547=== modified file 'environs/tools/validation.go'
1548--- environs/tools/validation.go 2013-09-20 18:46:47 +0000
1549+++ environs/tools/validation.go 2014-03-04 05:51:00 +0000
1550@@ -20,12 +20,12 @@
1551
1552 // ValidateToolsMetadata attempts to load tools metadata for the specified cloud attributes and returns
1553 // any tools versions found, or an error if the metadata could not be loaded.
1554-func ValidateToolsMetadata(params *ToolsMetadataLookupParams) ([]string, error) {
1555+func ValidateToolsMetadata(params *ToolsMetadataLookupParams) ([]string, *simplestreams.ResolveInfo, error) {
1556 if len(params.Architectures) == 0 {
1557- return nil, fmt.Errorf("required parameter arches not specified")
1558+ return nil, nil, fmt.Errorf("required parameter arches not specified")
1559 }
1560 if len(params.Sources) == 0 {
1561- return nil, fmt.Errorf("required parameter sources not specified")
1562+ return nil, nil, fmt.Errorf("required parameter sources not specified")
1563 }
1564 if params.Version == "" && params.Major == 0 {
1565 params.Version = version.Current.Number.String()
1566@@ -38,23 +38,27 @@
1567 Arches: params.Architectures,
1568 })
1569 } else {
1570- toolsConstraint = NewVersionedToolsConstraint(params.Version, simplestreams.LookupParams{
1571+ versNum, err := version.Parse(params.Version)
1572+ if err != nil {
1573+ return nil, nil, err
1574+ }
1575+ toolsConstraint = NewVersionedToolsConstraint(versNum, simplestreams.LookupParams{
1576 CloudSpec: simplestreams.CloudSpec{params.Region, params.Endpoint},
1577 Series: []string{params.Series},
1578 Arches: params.Architectures,
1579 })
1580 }
1581- matchingTools, err := Fetch(params.Sources, simplestreams.DefaultIndexPath, toolsConstraint, false)
1582+ matchingTools, resolveInfo, err := Fetch(params.Sources, simplestreams.DefaultIndexPath, toolsConstraint, false)
1583 if err != nil {
1584- return nil, err
1585+ return nil, resolveInfo, err
1586 }
1587 if len(matchingTools) == 0 {
1588- return nil, fmt.Errorf("no matching tools found for constraint %+v", toolsConstraint)
1589+ return nil, resolveInfo, fmt.Errorf("no matching tools found for constraint %+v", toolsConstraint)
1590 }
1591 versions := make([]string, len(matchingTools))
1592 for i, tm := range matchingTools {
1593 vers := version.Binary{version.MustParse(tm.Version), tm.Release, tm.Arch}
1594 versions[i] = vers.String()
1595 }
1596- return versions, nil
1597+ return versions, resolveInfo, nil
1598 }
1599
1600=== modified file 'environs/tools/validation_test.go'
1601--- environs/tools/validation_test.go 2014-01-22 22:48:54 +0000
1602+++ environs/tools/validation_test.go 2014-03-04 05:51:00 +0000
1603@@ -4,23 +4,24 @@
1604 package tools
1605
1606 import (
1607+ "path"
1608+
1609 gc "launchpad.net/gocheck"
1610
1611+ "launchpad.net/juju-core/environs/filestorage"
1612 "launchpad.net/juju-core/environs/simplestreams"
1613- "launchpad.net/juju-core/juju/osenv"
1614- coretesting "launchpad.net/juju-core/testing"
1615 "launchpad.net/juju-core/testing/testbase"
1616 )
1617
1618 type ValidateSuite struct {
1619 testbase.LoggingSuite
1620- home *coretesting.FakeHome
1621+ metadataDir string
1622 }
1623
1624 var _ = gc.Suite(&ValidateSuite{})
1625
1626-func (s *ValidateSuite) makeLocalMetadata(c *gc.C, version, region, series, endpoint string) error {
1627- tm := ToolsMetadata{
1628+func (s *ValidateSuite) makeLocalMetadata(c *gc.C, version, series string) error {
1629+ tm := []*ToolsMetadata{{
1630 Version: version,
1631 Release: series,
1632 Arch: "amd64",
1633@@ -28,31 +29,26 @@
1634 Size: 1234,
1635 FileType: "tar.gz",
1636 SHA256: "f65a92b3b41311bdf398663ee1c5cd0c",
1637- }
1638- cloudSpec := simplestreams.CloudSpec{
1639- Region: region,
1640- Endpoint: endpoint,
1641- }
1642- _, err := MakeBoilerplate(&tm, &cloudSpec, false)
1643- if err != nil {
1644- return err
1645- }
1646+ }}
1647+
1648+ stor, err := filestorage.NewFileStorageWriter(s.metadataDir, filestorage.UseDefaultTmpDir)
1649+ c.Assert(err, gc.IsNil)
1650+ err = WriteMetadata(stor, tm, false)
1651+ c.Assert(err, gc.IsNil)
1652 return nil
1653 }
1654
1655 func (s *ValidateSuite) SetUpTest(c *gc.C) {
1656 s.LoggingSuite.SetUpTest(c)
1657- s.home = coretesting.MakeEmptyFakeHome(c)
1658+ s.metadataDir = c.MkDir()
1659 }
1660
1661-func (s *ValidateSuite) TearDownTest(c *gc.C) {
1662- s.home.Restore()
1663- s.LoggingSuite.TearDownTest(c)
1664+func (s *ValidateSuite) toolsURL() string {
1665+ return "file://" + path.Join(s.metadataDir, "tools")
1666 }
1667
1668 func (s *ValidateSuite) TestExactVersionMatch(c *gc.C) {
1669- s.makeLocalMetadata(c, "1.11.2", "region-2", "raring", "some-auth-url")
1670- metadataDir := osenv.JujuHomePath("")
1671+ s.makeLocalMetadata(c, "1.11.2", "raring")
1672 params := &ToolsMetadataLookupParams{
1673 Version: "1.11.2",
1674 MetadataLookupParams: simplestreams.MetadataLookupParams{
1675@@ -60,17 +56,23 @@
1676 Series: "raring",
1677 Architectures: []string{"amd64"},
1678 Endpoint: "some-auth-url",
1679- Sources: []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+metadataDir, simplestreams.VerifySSLHostnames)},
1680+ Sources: []simplestreams.DataSource{
1681+ simplestreams.NewURLDataSource("test", s.toolsURL(), simplestreams.VerifySSLHostnames)},
1682 },
1683 }
1684- versions, err := ValidateToolsMetadata(params)
1685+ versions, resolveInfo, err := ValidateToolsMetadata(params)
1686 c.Assert(err, gc.IsNil)
1687 c.Assert(versions, gc.DeepEquals, []string{"1.11.2-raring-amd64"})
1688+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1689+ Source: "test",
1690+ Signed: false,
1691+ IndexURL: "file://" + path.Join(s.metadataDir, "tools/streams/v1/index.json"),
1692+ MirrorURL: "",
1693+ })
1694 }
1695
1696 func (s *ValidateSuite) TestMajorVersionMatch(c *gc.C) {
1697- s.makeLocalMetadata(c, "1.11.2", "region-2", "raring", "some-auth-url")
1698- metadataDir := osenv.JujuHomePath("")
1699+ s.makeLocalMetadata(c, "1.11.2", "raring")
1700 params := &ToolsMetadataLookupParams{
1701 Major: 1,
1702 Minor: -1,
1703@@ -79,17 +81,23 @@
1704 Series: "raring",
1705 Architectures: []string{"amd64"},
1706 Endpoint: "some-auth-url",
1707- Sources: []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+metadataDir, simplestreams.VerifySSLHostnames)},
1708+ Sources: []simplestreams.DataSource{
1709+ simplestreams.NewURLDataSource("test", s.toolsURL(), simplestreams.VerifySSLHostnames)},
1710 },
1711 }
1712- versions, err := ValidateToolsMetadata(params)
1713+ versions, resolveInfo, err := ValidateToolsMetadata(params)
1714 c.Assert(err, gc.IsNil)
1715 c.Assert(versions, gc.DeepEquals, []string{"1.11.2-raring-amd64"})
1716+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1717+ Source: "test",
1718+ Signed: false,
1719+ IndexURL: "file://" + path.Join(s.metadataDir, "tools/streams/v1/index.json"),
1720+ MirrorURL: "",
1721+ })
1722 }
1723
1724 func (s *ValidateSuite) TestMajorMinorVersionMatch(c *gc.C) {
1725- s.makeLocalMetadata(c, "1.11.2", "region-2", "raring", "some-auth-url")
1726- metadataDir := osenv.JujuHomePath("")
1727+ s.makeLocalMetadata(c, "1.11.2", "raring")
1728 params := &ToolsMetadataLookupParams{
1729 Major: 1,
1730 Minor: 11,
1731@@ -98,17 +106,23 @@
1732 Series: "raring",
1733 Architectures: []string{"amd64"},
1734 Endpoint: "some-auth-url",
1735- Sources: []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+metadataDir, simplestreams.VerifySSLHostnames)},
1736+ Sources: []simplestreams.DataSource{
1737+ simplestreams.NewURLDataSource("test", s.toolsURL(), simplestreams.VerifySSLHostnames)},
1738 },
1739 }
1740- versions, err := ValidateToolsMetadata(params)
1741+ versions, resolveInfo, err := ValidateToolsMetadata(params)
1742 c.Assert(err, gc.IsNil)
1743 c.Assert(versions, gc.DeepEquals, []string{"1.11.2-raring-amd64"})
1744+ c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{
1745+ Source: "test",
1746+ Signed: false,
1747+ IndexURL: "file://" + path.Join(s.metadataDir, "tools/streams/v1/index.json"),
1748+ MirrorURL: "",
1749+ })
1750 }
1751
1752 func (s *ValidateSuite) TestNoMatch(c *gc.C) {
1753- s.makeLocalMetadata(c, "1.11.2", "region-2", "raring", "some-auth-url")
1754- metadataDir := osenv.JujuHomePath("")
1755+ s.makeLocalMetadata(c, "1.11.2", "raring")
1756 params := &ToolsMetadataLookupParams{
1757 Version: "1.11.2",
1758 MetadataLookupParams: simplestreams.MetadataLookupParams{
1759@@ -116,9 +130,10 @@
1760 Series: "precise",
1761 Architectures: []string{"amd64"},
1762 Endpoint: "some-auth-url",
1763- Sources: []simplestreams.DataSource{simplestreams.NewURLDataSource("file://"+metadataDir, simplestreams.VerifySSLHostnames)},
1764+ Sources: []simplestreams.DataSource{
1765+ simplestreams.NewURLDataSource("test", s.toolsURL(), simplestreams.VerifySSLHostnames)},
1766 },
1767 }
1768- _, err := ValidateToolsMetadata(params)
1769+ _, _, err := ValidateToolsMetadata(params)
1770 c.Assert(err, gc.Not(gc.IsNil))
1771 }
1772
1773=== modified file 'provider/azure/environ.go'
1774--- provider/azure/environ.go 2014-02-18 03:18:16 +0000
1775+++ provider/azure/environ.go 2014-03-04 05:51:00 +0000
1776@@ -860,9 +860,9 @@
1777 // GetImageSources returns a list of sources which are used to search for simplestreams image metadata.
1778 func (env *azureEnviron) GetImageSources() ([]simplestreams.DataSource, error) {
1779 sources := make([]simplestreams.DataSource, 1+len(baseURLs))
1780- sources[0] = storage.NewStorageSimpleStreamsDataSource(env.Storage(), storage.BaseImagesPath)
1781+ sources[0] = storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseImagesPath)
1782 for i, url := range baseURLs {
1783- sources[i+1] = simplestreams.NewURLDataSource(url, simplestreams.VerifySSLHostnames)
1784+ sources[i+1] = simplestreams.NewURLDataSource("Azure base URL", url, simplestreams.VerifySSLHostnames)
1785 }
1786 return sources, nil
1787 }
1788@@ -871,7 +871,7 @@
1789 func (env *azureEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
1790 // Add the simplestreams source off the control bucket.
1791 sources := []simplestreams.DataSource{
1792- storage.NewStorageSimpleStreamsDataSource(env.Storage(), storage.BaseToolsPath)}
1793+ storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseToolsPath)}
1794 return sources, nil
1795 }
1796
1797
1798=== modified file 'provider/azure/instancetype.go'
1799--- provider/azure/instancetype.go 2014-01-29 06:45:16 +0000
1800+++ provider/azure/instancetype.go 2014-03-04 05:51:00 +0000
1801@@ -142,7 +142,7 @@
1802 return nil, err
1803 }
1804 indexPath := simplestreams.DefaultIndexPath
1805- images, err := fetchImageMetadata(sources, indexPath, constraint, signedImageDataOnly)
1806+ images, _, err := fetchImageMetadata(sources, indexPath, constraint, signedImageDataOnly)
1807 if len(images) == 0 || errors.IsNotFoundError(err) {
1808 return nil, fmt.Errorf("no OS images found for location %q, series %q, architectures %q (and endpoint: %q)", location, series, arches, endpoint)
1809 } else if err != nil {
1810
1811=== modified file 'provider/azure/instancetype_test.go'
1812--- provider/azure/instancetype_test.go 2014-01-29 06:45:16 +0000
1813+++ provider/azure/instancetype_test.go 2014-03-04 05:51:00 +0000
1814@@ -482,8 +482,9 @@
1815 // It returns a cleanup function, which you must call when done.
1816 func patchFetchImageMetadata(cannedResponse []*imagemetadata.ImageMetadata, cannedError error) func() {
1817 original := fetchImageMetadata
1818- fetchImageMetadata = func([]simplestreams.DataSource, string, *imagemetadata.ImageConstraint, bool) ([]*imagemetadata.ImageMetadata, error) {
1819- return cannedResponse, cannedError
1820+ fetchImageMetadata = func([]simplestreams.DataSource, string, *imagemetadata.ImageConstraint, bool) (
1821+ []*imagemetadata.ImageMetadata, *simplestreams.ResolveInfo, error) {
1822+ return cannedResponse, nil, cannedError
1823 }
1824 return func() { fetchImageMetadata = original }
1825 }
1826
1827=== modified file 'provider/common/mock_test.go'
1828--- provider/common/mock_test.go 2013-10-15 04:38:40 +0000
1829+++ provider/common/mock_test.go 2014-03-04 05:51:00 +0000
1830@@ -72,7 +72,7 @@
1831 if env.getToolsSources != nil {
1832 return env.getToolsSources()
1833 }
1834- datasource := storage.NewStorageSimpleStreamsDataSource(env.Storage(), storage.BaseToolsPath)
1835+ datasource := storage.NewStorageSimpleStreamsDataSource("test cloud storage", env.Storage(), storage.BaseToolsPath)
1836 return []simplestreams.DataSource{datasource}, nil
1837 }
1838
1839
1840=== modified file 'provider/dummy/environs.go'
1841--- provider/dummy/environs.go 2014-02-20 08:23:40 +0000
1842+++ provider/dummy/environs.go 2014-03-04 05:51:00 +0000
1843@@ -529,13 +529,13 @@
1844 // GetImageSources returns a list of sources which are used to search for simplestreams image metadata.
1845 func (e *environ) GetImageSources() ([]simplestreams.DataSource, error) {
1846 return []simplestreams.DataSource{
1847- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseImagesPath)}, nil
1848+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseImagesPath)}, nil
1849 }
1850
1851 // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata.
1852 func (e *environ) GetToolsSources() ([]simplestreams.DataSource, error) {
1853 return []simplestreams.DataSource{
1854- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath)}, nil
1855+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath)}, nil
1856 }
1857
1858 func (e *environ) Bootstrap(ctx environs.BootstrapContext, cons constraints.Value) error {
1859
1860=== modified file 'provider/ec2/ec2.go'
1861--- provider/ec2/ec2.go 2014-02-28 03:05:47 +0000
1862+++ provider/ec2/ec2.go 2014-03-04 05:51:00 +0000
1863@@ -1057,7 +1057,7 @@
1864 func (e *environ) GetImageSources() ([]simplestreams.DataSource, error) {
1865 // Add the simplestreams source off the control bucket.
1866 sources := []simplestreams.DataSource{
1867- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseImagesPath)}
1868+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseImagesPath)}
1869 return sources, nil
1870 }
1871
1872@@ -1065,6 +1065,6 @@
1873 func (e *environ) GetToolsSources() ([]simplestreams.DataSource, error) {
1874 // Add the simplestreams source off the control bucket.
1875 sources := []simplestreams.DataSource{
1876- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath)}
1877+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath)}
1878 return sources, nil
1879 }
1880
1881=== modified file 'provider/ec2/image.go'
1882--- provider/ec2/image.go 2014-01-29 00:14:51 +0000
1883+++ provider/ec2/image.go 2014-03-04 05:51:00 +0000
1884@@ -48,7 +48,7 @@
1885 Arches: ic.Arches,
1886 Stream: stream,
1887 })
1888- matchingImages, err := imagemetadata.Fetch(
1889+ matchingImages, _, err := imagemetadata.Fetch(
1890 sources, simplestreams.DefaultIndexPath, imageConstraint, signedImageDataOnly)
1891 if err != nil {
1892 return nil, err
1893
1894=== modified file 'provider/ec2/image_test.go'
1895--- provider/ec2/image_test.go 2014-02-14 01:03:03 +0000
1896+++ provider/ec2/image_test.go 2014-03-04 05:51:00 +0000
1897@@ -128,7 +128,8 @@
1898 c.Logf("test %d", i)
1899 stor := ebsStorage
1900 spec, err := findInstanceSpec(
1901- []simplestreams.DataSource{simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames)},
1902+ []simplestreams.DataSource{
1903+ simplestreams.NewURLDataSource("test", "test:", simplestreams.VerifySSLHostnames)},
1904 "released",
1905 &instances.InstanceConstraint{
1906 Region: "test",
1907@@ -169,7 +170,8 @@
1908 for i, t := range findInstanceSpecErrorTests {
1909 c.Logf("test %d", i)
1910 _, err := findInstanceSpec(
1911- []simplestreams.DataSource{simplestreams.NewURLDataSource("test:", simplestreams.VerifySSLHostnames)},
1912+ []simplestreams.DataSource{
1913+ simplestreams.NewURLDataSource("test", "test:", simplestreams.VerifySSLHostnames)},
1914 "released",
1915 &instances.InstanceConstraint{
1916 Region: "test",
1917
1918=== modified file 'provider/ec2/local_test.go'
1919--- provider/ec2/local_test.go 2014-02-20 08:23:40 +0000
1920+++ provider/ec2/local_test.go 2014-03-04 05:51:00 +0000
1921@@ -383,7 +383,7 @@
1922 params.Endpoint = "https://ec2.endpoint.com"
1923 params.Sources, err = imagemetadata.GetMetadataSources(env)
1924 c.Assert(err, gc.IsNil)
1925- image_ids, err := imagemetadata.ValidateImageMetadata(params)
1926+ image_ids, _, err := imagemetadata.ValidateImageMetadata(params)
1927 c.Assert(err, gc.IsNil)
1928 sort.Strings(image_ids)
1929 c.Assert(image_ids, gc.DeepEquals, []string{"ami-00000033", "ami-00000034", "ami-00000035"})
1930
1931=== modified file 'provider/local/environ.go'
1932--- provider/local/environ.go 2014-02-28 09:13:21 +0000
1933+++ provider/local/environ.go 2014-03-04 05:51:00 +0000
1934@@ -65,7 +65,7 @@
1935 func (e *localEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
1936 // Add the simplestreams source off the control bucket.
1937 return []simplestreams.DataSource{
1938- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath)}, nil
1939+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath)}, nil
1940 }
1941
1942 // Name is specified in the Environ interface.
1943
1944=== modified file 'provider/maas/environ.go'
1945--- provider/maas/environ.go 2013-12-19 09:15:40 +0000
1946+++ provider/maas/environ.go 2014-03-04 05:51:00 +0000
1947@@ -421,12 +421,12 @@
1948 func (e *maasEnviron) GetImageSources() ([]simplestreams.DataSource, error) {
1949 // Add the simplestreams source off the control bucket.
1950 return []simplestreams.DataSource{
1951- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseImagesPath)}, nil
1952+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseImagesPath)}, nil
1953 }
1954
1955 // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata.
1956 func (e *maasEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
1957 // Add the simplestreams source off the control bucket.
1958 return []simplestreams.DataSource{
1959- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath)}, nil
1960+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath)}, nil
1961 }
1962
1963=== modified file 'provider/manual/environ.go'
1964--- provider/manual/environ.go 2014-02-20 08:23:40 +0000
1965+++ provider/manual/environ.go 2014-03-04 05:51:00 +0000
1966@@ -200,7 +200,7 @@
1967 func (e *manualEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
1968 // Add the simplestreams source off private storage.
1969 return []simplestreams.DataSource{
1970- storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath),
1971+ storage.NewStorageSimpleStreamsDataSource("cloud storage", e.Storage(), storage.BaseToolsPath),
1972 }, nil
1973 }
1974
1975
1976=== modified file 'provider/openstack/image.go'
1977--- provider/openstack/image.go 2014-01-29 06:45:16 +0000
1978+++ provider/openstack/image.go 2014-03-04 05:51:00 +0000
1979@@ -43,7 +43,7 @@
1980 return nil, err
1981 }
1982 // TODO (wallyworld): use an env parameter (default true) to mandate use of only signed image metadata.
1983- matchingImages, err := imagemetadata.Fetch(sources, simplestreams.DefaultIndexPath, imageConstraint, false)
1984+ matchingImages, _, err := imagemetadata.Fetch(sources, simplestreams.DefaultIndexPath, imageConstraint, false)
1985 if err != nil {
1986 return nil, err
1987 }
1988
1989=== modified file 'provider/openstack/local_test.go'
1990--- provider/openstack/local_test.go 2014-02-20 08:23:40 +0000
1991+++ provider/openstack/local_test.go 2014-03-04 05:51:00 +0000
1992@@ -605,7 +605,7 @@
1993 params.Sources, err = imagemetadata.GetMetadataSources(env)
1994 c.Assert(err, gc.IsNil)
1995 params.Series = "raring"
1996- image_ids, err := imagemetadata.ValidateImageMetadata(params)
1997+ image_ids, _, err := imagemetadata.ValidateImageMetadata(params)
1998 c.Assert(err, gc.IsNil)
1999 c.Assert(image_ids, gc.DeepEquals, []string{"id-y"})
2000 }
2001
2002=== modified file 'provider/openstack/provider.go'
2003--- provider/openstack/provider.go 2014-02-28 03:05:47 +0000
2004+++ provider/openstack/provider.go 2014-03-04 05:51:00 +0000
2005@@ -585,7 +585,7 @@
2006 }
2007 // Add the simplestreams source off the control bucket.
2008 e.imageSources = append(e.imageSources, storage.NewStorageSimpleStreamsDataSource(
2009- e.Storage(), storage.BaseImagesPath))
2010+ "cloud storage", e.Storage(), storage.BaseImagesPath))
2011 // Add the simplestreams base URL from keystone if it is defined.
2012 productStreamsURL, err := e.client.MakeServiceURL("product-streams", nil)
2013 if err == nil {
2014@@ -593,7 +593,7 @@
2015 if !e.Config().SSLHostnameVerification() {
2016 verify = simplestreams.NoVerifySSLHostnames
2017 }
2018- source := simplestreams.NewURLDataSource(productStreamsURL, verify)
2019+ source := simplestreams.NewURLDataSource("keystone catalog", productStreamsURL, verify)
2020 e.imageSources = append(e.imageSources, source)
2021 }
2022 return e.imageSources, nil
2023@@ -618,11 +618,12 @@
2024 verify = simplestreams.NoVerifySSLHostnames
2025 }
2026 // Add the simplestreams source off the control bucket.
2027- e.toolsSources = append(e.toolsSources, storage.NewStorageSimpleStreamsDataSource(e.Storage(), storage.BaseToolsPath))
2028+ e.toolsSources = append(e.toolsSources, storage.NewStorageSimpleStreamsDataSource(
2029+ "cloud storage", e.Storage(), storage.BaseToolsPath))
2030 // Add the simplestreams base URL from keystone if it is defined.
2031 toolsURL, err := e.client.MakeServiceURL("juju-tools", nil)
2032 if err == nil {
2033- source := simplestreams.NewURLDataSource(toolsURL, verify)
2034+ source := simplestreams.NewURLDataSource("keystone catalog", toolsURL, verify)
2035 e.toolsSources = append(e.toolsSources, source)
2036 }
2037 return e.toolsSources, nil

Subscribers

People subscribed via source and target branches

to status/vote changes: