func (s *simplestreamsSuite) TestFetch(c *gc.C) { for i, t := range fetchTests { c.Logf("test %d", i) cloudSpec := simplestreams.CloudSpec{t.region, "https://ec2.us-east-1.amazonaws.com"} if t.region == "" { cloudSpec = simplestreams.EmptyCloudSpec } imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: cloudSpec, Series: []string{"precise"}, Arches: t.arches, }) // Add invalid datasource and check later that resolveInfo is correct. invalidSource := simplestreams.NewURLDataSource("invalid", "file://invalid", utils.VerifySSLHostnames) images, resolveInfo, err := imagemetadata.Fetch( []simplestreams.DataSource{invalidSource, s.Source}, simplestreams.DefaultIndexPath, imageConstraint, s.RequireSigned) if !c.Check(err, gc.IsNil) { continue } for _, testImage := range t.images { testImage.Version = t.version } c.Check(images, gc.DeepEquals, t.images) c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{ Source: "test roundtripper", Signed: s.RequireSigned, IndexURL: "test:/streams/v1/index.json", MirrorURL: "", }) } }
func (s *archSuite) TestSupportedArchitecturesMany(c *gc.C) { env, cloudSpec := s.setupMetadata(c, []string{"ppc64", "amd64"}) imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: cloudSpec, }) arches, err := common.SupportedArchitectures(env, imageConstraint) c.Assert(err, gc.IsNil) c.Assert(arches, jc.SameContents, []string{"amd64", "ppc64"}) }
func (s *archSuite) TestSupportedArchitecturesNone(c *gc.C) { env, cloudSpec := s.setupMetadata(c, nil) imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: cloudSpec, }) arches, err := common.SupportedArchitectures(env, imageConstraint) c.Assert(err, gc.IsNil) c.Assert(arches, gc.HasLen, 0) }
func (s *productSpecSuite) TestId(c *gc.C) { imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ Series: []string{"precise"}, Arches: []string{"amd64"}, Stream: "daily", }) ids, err := imageConstraint.Ids() c.Assert(err, gc.IsNil) c.Assert(ids, gc.DeepEquals, []string{"com.ubuntu.cloud.daily:server:12.04:amd64"}) }
func (s *signedSuite) TestSignedImageMetadataInvalidSignature(c *gc.C) { signedSource := simplestreams.NewURLDataSource("test", "signedtest://host/signed", utils.VerifySSLHostnames) imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"}, Series: []string{"precise"}, Arches: []string{"amd64"}, }) imagemetadata.SetSigningPublicKey(s.origKey) _, _, err := imagemetadata.Fetch( []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, imageConstraint, true) c.Assert(err, gc.ErrorMatches, "cannot read index data.*") }
func (s *productSpecSuite) TestIdWithDefaultStream(c *gc.C) { imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ Series: []string{"precise"}, Arches: []string{"amd64"}, }) for _, stream := range []string{"", "released"} { imageConstraint.Stream = stream ids, err := imageConstraint.Ids() c.Assert(err, gc.IsNil) c.Assert(ids, gc.DeepEquals, []string{"com.ubuntu.cloud:server:12.04:amd64"}) } }
func (s *imageSuite) TestFindInstanceSpec(c *gc.C) { for _, t := range findInstanceSpecTests { c.Logf("test: %v", t.desc) t.init() cons := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{t.region, "ep"}, Series: []string{"precise"}, Arches: t.arches, Stream: t.stream, }) imageMeta, err := imagemetadata.GetLatestImageIdMetadata( []byte(jsonImagesContent), simplestreams.NewURLDataSource("test", "some-url", utils.VerifySSLHostnames), cons) c.Assert(err, gc.IsNil) var images []Image for _, imageMetadata := range imageMeta { im := *imageMetadata images = append(images, Image{ Id: im.Id, VirtType: im.VirtType, Arch: im.Arch, }) } imageCons := constraints.MustParse(t.constraints) spec, err := FindInstanceSpec(images, &InstanceConstraint{ Series: "precise", Region: t.region, Arches: t.arches, Constraints: imageCons, }, t.instanceTypes) if t.err != "" { c.Check(err, gc.ErrorMatches, t.err) continue } else { if !c.Check(err, gc.IsNil) { continue } c.Check(spec.Image.Id, gc.Equals, t.imageId) if len(t.instanceTypes) == 1 { c.Check(spec.InstanceType, gc.DeepEquals, t.instanceTypes[0]) } if imageCons.HasInstanceType() { c.Assert(spec.InstanceType.Name, gc.Equals, *imageCons.InstanceType) } } } }
func registerSimpleStreamsTests() { gc.Suite(&simplestreamsSuite{ LocalLiveSimplestreamsSuite: sstesting.LocalLiveSimplestreamsSuite{ Source: simplestreams.NewURLDataSource( "test roundtripper", "test:", utils.VerifySSLHostnames), RequireSigned: false, DataType: imagemetadata.ImageIds, ValidConstraint: imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{ Region: "us-east-1", Endpoint: "https://ec2.us-east-1.amazonaws.com", }, Series: []string{"precise"}, Arches: []string{"amd64", "arm"}, }), }, }) gc.Suite(&signedSuite{}) }
func (s *signedSuite) TestSignedImageMetadata(c *gc.C) { signedSource := simplestreams.NewURLDataSource("test", "signedtest://host/signed", utils.VerifySSLHostnames) imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{"us-east-1", "https://ec2.us-east-1.amazonaws.com"}, Series: []string{"precise"}, Arches: []string{"amd64"}, }) images, resolveInfo, err := imagemetadata.Fetch( []simplestreams.DataSource{signedSource}, simplestreams.DefaultIndexPath, imageConstraint, true) c.Assert(err, gc.IsNil) c.Assert(len(images), gc.Equals, 1) c.Assert(images[0].Id, gc.Equals, "ami-123456") c.Check(resolveInfo, gc.DeepEquals, &simplestreams.ResolveInfo{ Source: "test", Signed: true, IndexURL: "signedtest://host/signed/streams/v1/index.sjson", MirrorURL: "", }) }
// findInstanceSpec returns an image and instance type satisfying the constraint. // The instance type comes from querying the flavors supported by the deployment. func findInstanceSpec(e *environ, ic *instances.InstanceConstraint) (*instances.InstanceSpec, error) { // first construct all available instance types from the supported flavors. nova := e.nova() flavors, err := nova.ListFlavorsDetail() if err != nil { return nil, err } allInstanceTypes := []instances.InstanceType{} for _, flavor := range flavors { instanceType := instances.InstanceType{ Id: flavor.Id, Name: flavor.Name, Arches: ic.Arches, Mem: uint64(flavor.RAM), CpuCores: uint64(flavor.VCPUs), RootDisk: uint64(flavor.Disk * 1024), // tags not currently supported on openstack } allInstanceTypes = append(allInstanceTypes, instanceType) } imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{ic.Region, e.ecfg().authURL()}, Series: []string{ic.Series}, Arches: ic.Arches, Stream: e.Config().ImageStream(), }) sources, err := imagemetadata.GetMetadataSources(e) if err != nil { return nil, err } // TODO (wallyworld): use an env parameter (default true) to mandate use of only signed image metadata. matchingImages, _, err := imagemetadata.Fetch(sources, simplestreams.DefaultIndexPath, imageConstraint, false) if err != nil { return nil, err } images := instances.ImageMetadataToImages(matchingImages) spec, err := instances.FindInstanceSpec(images, ic, allInstanceTypes) if err != nil { return nil, err } return spec, nil }
// findInstanceSpec returns an InstanceSpec satisfying the supplied instanceConstraint. func findInstanceSpec( sources []simplestreams.DataSource, stream string, ic *instances.InstanceConstraint) (*instances.InstanceSpec, error) { if ic.Constraints.CpuPower == nil { ic.Constraints.CpuPower = instances.CpuPower(defaultCpuPower) } ec2Region := allRegions[ic.Region] imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{ic.Region, ec2Region.EC2Endpoint}, Series: []string{ic.Series}, Arches: ic.Arches, Stream: stream, }) matchingImages, _, err := imagemetadata.Fetch( sources, simplestreams.DefaultIndexPath, imageConstraint, signedImageDataOnly) if err != nil { return nil, err } if len(matchingImages) == 0 { logger.Warningf("no matching image meta data for constraints: %v", ic) } suitableImages := filterImages(matchingImages) images := instances.ImageMetadataToImages(suitableImages) // Make a copy of the known EC2 instance types, filling in the cost for the specified region. regionCosts := allRegionCosts[ic.Region] if len(regionCosts) == 0 && len(allRegionCosts) > 0 { return nil, fmt.Errorf("no instance types found in %s", ic.Region) } var itypesWithCosts []instances.InstanceType for _, itype := range allInstanceTypes { cost, ok := regionCosts[itype.Name] if !ok { continue } itWithCost := itype itWithCost.Cost = cost itypesWithCosts = append(itypesWithCosts, itWithCost) } return instances.FindInstanceSpec(images, ic, itypesWithCosts) }
// SupportedArchitectures is specified on the EnvironCapability interface. func (env *joyentEnviron) SupportedArchitectures() ([]string, error) { env.archLock.Lock() defer env.archLock.Unlock() if env.supportedArchitectures != nil { return env.supportedArchitectures, nil } cfg := env.Ecfg() // Create a filter to get all images from our region and for the correct stream. cloudSpec := simplestreams.CloudSpec{ Region: cfg.Region(), Endpoint: cfg.SdcUrl(), } imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: cloudSpec, Stream: cfg.ImageStream(), }) var err error env.supportedArchitectures, err = common.SupportedArchitectures(env, imageConstraint) return env.supportedArchitectures, err }
func Test(t *testing.T) { if *live { if *vendor == "" { t.Fatal("missing vendor") } var ok bool var testData liveTestData if testData, ok = liveUrls[*vendor]; !ok { keys := reflect.ValueOf(liveUrls).MapKeys() t.Fatalf("Unknown vendor %s. Must be one of %s", *vendor, keys) } registerLiveSimpleStreamsTests(testData.baseURL, imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: testData.validCloudSpec, Series: []string{"quantal"}, Arches: []string{"amd64"}, }), testData.requireSigned) } registerSimpleStreamsTests() gc.TestingT(t) }
// findMatchingImages queries simplestreams for OS images that match the given // requirements. // // If it finds no matching images, that's an error. func findMatchingImages(e *azureEnviron, location, series string, arches []string) ([]*imagemetadata.ImageMetadata, error) { endpoint := getEndpoint(location) constraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{ CloudSpec: simplestreams.CloudSpec{location, endpoint}, Series: []string{series}, Arches: arches, Stream: e.Config().ImageStream(), }) sources, err := imagemetadata.GetMetadataSources(e) if err != nil { return nil, err } indexPath := simplestreams.DefaultIndexPath images, _, err := imagemetadata.Fetch(sources, indexPath, constraint, signedImageDataOnly) if len(images) == 0 || errors.IsNotFound(err) { return nil, fmt.Errorf("no OS images found for location %q, series %q, architectures %q (and endpoint: %q)", location, series, arches, endpoint) } else if err != nil { return nil, err } return images, nil }