github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/provider/ec2/image_test.go (about)

     1  // Copyright 2011, 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2
     5  
     6  import (
     7  	"fmt"
     8  
     9  	jc "github.com/juju/testing/checkers"
    10  	"github.com/juju/utils/series"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/constraints"
    14  	"github.com/juju/juju/environs/imagemetadata"
    15  	imagetesting "github.com/juju/juju/environs/imagemetadata/testing"
    16  	"github.com/juju/juju/environs/instances"
    17  	sstesting "github.com/juju/juju/environs/simplestreams/testing"
    18  	"github.com/juju/juju/juju/keys"
    19  	"github.com/juju/juju/testing"
    20  )
    21  
    22  var _ = gc.Suite(&specSuite{})
    23  
    24  type specSuite struct {
    25  	testing.BaseSuite
    26  	sstesting.TestDataSuite
    27  }
    28  
    29  func (s *specSuite) SetUpSuite(c *gc.C) {
    30  	s.BaseSuite.SetUpSuite(c)
    31  	s.TestDataSuite.SetUpSuite(c)
    32  
    33  	imagetesting.PatchOfficialDataSources(&s.CleanupSuite, "test:")
    34  	s.PatchValue(&imagemetadata.SimplestreamsImagesPublicKey, sstesting.SignedMetadataPublicKey)
    35  	s.PatchValue(&keys.JujuPublicKey, sstesting.SignedMetadataPublicKey)
    36  
    37  	UseTestImageData(c, TestImagesData)
    38  	UseTestInstanceTypeData(TestInstanceTypeCosts)
    39  	UseTestRegionData(TestRegions)
    40  }
    41  
    42  func (s *specSuite) TearDownSuite(c *gc.C) {
    43  	UseTestInstanceTypeData(nil)
    44  	UseTestImageData(c, nil)
    45  	UseTestRegionData(nil)
    46  	s.TestDataSuite.TearDownSuite(c)
    47  	s.BaseSuite.TearDownSuite(c)
    48  }
    49  
    50  var findInstanceSpecTests = []struct {
    51  	// LTS-dependent requires new or updated entries upon a new LTS release.
    52  	series  string
    53  	arches  []string
    54  	cons    string
    55  	itype   string
    56  	image   string
    57  	storage []string
    58  }{
    59  	{
    60  		series: "xenial",
    61  		arches: []string{"amd64"},
    62  		itype:  "m3.medium",
    63  		image:  "ami-00000133",
    64  	}, {
    65  		series: "quantal",
    66  		arches: []string{"i386"},
    67  		itype:  "c1.medium",
    68  		image:  "ami-01000034",
    69  	}, {
    70  		series: "xenial",
    71  		arches: []string{"amd64"},
    72  		cons:   "cores=4",
    73  		itype:  "m3.xlarge",
    74  		image:  "ami-00000133",
    75  	}, {
    76  		series: "xenial",
    77  		arches: []string{"amd64"},
    78  		cons:   "mem=10G",
    79  		itype:  "m3.xlarge",
    80  		image:  "ami-00000133",
    81  	}, {
    82  		series: "xenial",
    83  		arches: []string{"amd64"},
    84  		cons:   "mem=",
    85  		itype:  "m3.medium",
    86  		image:  "ami-00000133",
    87  	}, {
    88  		series: "xenial",
    89  		arches: []string{"amd64"},
    90  		cons:   "cpu-power=",
    91  		itype:  "m3.medium",
    92  		image:  "ami-00000133",
    93  	}, {
    94  		series: "xenial",
    95  		arches: []string{"amd64"},
    96  		cons:   "cpu-power=800",
    97  		itype:  "m3.xlarge",
    98  		image:  "ami-00000133",
    99  	}, {
   100  		series: "xenial",
   101  		arches: []string{"amd64"},
   102  		cons:   "instance-type=m1.medium cpu-power=200",
   103  		itype:  "m1.medium",
   104  		image:  "ami-00000133",
   105  	}, {
   106  		series: "xenial",
   107  		arches: []string{"amd64"},
   108  		cons:   "mem=2G root-disk=16384M",
   109  		itype:  "m3.medium",
   110  		image:  "ami-00000133",
   111  	}, {
   112  		series:  "xenial",
   113  		arches:  []string{"amd64"},
   114  		cons:    "mem=4G root-disk=16384M",
   115  		itype:   "m3.large",
   116  		storage: []string{"ssd", "ebs"},
   117  		image:   "ami-00000133",
   118  	}, {
   119  		series:  "xenial",
   120  		arches:  []string{"amd64"},
   121  		cons:    "mem=4G root-disk=16384M",
   122  		itype:   "m3.large",
   123  		storage: []string{"ebs", "ssd"},
   124  		image:   "ami-00000139",
   125  	}, {
   126  		series:  "xenial",
   127  		arches:  []string{"amd64"},
   128  		cons:    "mem=4G root-disk=16384M",
   129  		itype:   "m3.large",
   130  		storage: []string{"ebs"},
   131  		image:   "ami-00000139",
   132  	}, {
   133  		series: "trusty",
   134  		arches: []string{"amd64"},
   135  		itype:  "m3.medium",
   136  		image:  "ami-00000033",
   137  	}, {
   138  		series: "quantal",
   139  		arches: []string{"i386"},
   140  		itype:  "c1.medium",
   141  		image:  "ami-01000034",
   142  	}, {
   143  		series: "quantal",
   144  		arches: both,
   145  		cons:   "arch=amd64",
   146  		itype:  "cc2.8xlarge",
   147  		image:  "ami-01000035",
   148  	}, {
   149  		series: "quantal",
   150  		arches: both,
   151  		cons:   "instance-type=cc2.8xlarge",
   152  		itype:  "cc2.8xlarge",
   153  		image:  "ami-01000035",
   154  	}, {
   155  		series: "trusty",
   156  		arches: []string{"i386"},
   157  		cons:   "instance-type=c1.medium",
   158  		itype:  "c1.medium",
   159  		image:  "ami-00000034",
   160  	},
   161  }
   162  
   163  func (s *specSuite) TestFindInstanceSpec(c *gc.C) {
   164  	for i, test := range findInstanceSpecTests {
   165  		c.Logf("\ntest %d: %q; %q; %q; %v", i, test.series, test.arches, test.cons, test.storage)
   166  		stor := test.storage
   167  		if len(stor) == 0 {
   168  			stor = []string{ssdStorage, ebsStorage}
   169  		}
   170  		// We need to filter the image metadata to the test's
   171  		// arches and series; the provisioner and bootstrap
   172  		// code will do this.
   173  		imageMetadata := filterImageMetadata(
   174  			c, TestImageMetadata, test.series, test.arches,
   175  		)
   176  		spec, err := findInstanceSpec(
   177  			imageMetadata,
   178  			&instances.InstanceConstraint{
   179  				Region:      "test",
   180  				Series:      test.series,
   181  				Arches:      test.arches,
   182  				Constraints: constraints.MustParse(test.cons),
   183  				Storage:     stor,
   184  			})
   185  		c.Assert(err, jc.ErrorIsNil)
   186  		c.Check(spec.InstanceType.Name, gc.Equals, test.itype)
   187  		c.Check(spec.Image.Id, gc.Equals, test.image)
   188  	}
   189  }
   190  
   191  func (s *specSuite) TestFindInstanceSpecNotSetCpuPowerWhenInstanceTypeSet(c *gc.C) {
   192  
   193  	instanceConstraint := &instances.InstanceConstraint{
   194  		Region:      "test",
   195  		Series:      series.LatestLts(),
   196  		Constraints: constraints.MustParse("instance-type=t2.medium"),
   197  	}
   198  
   199  	c.Check(instanceConstraint.Constraints.CpuPower, gc.IsNil)
   200  	findInstanceSpec(TestImageMetadata, instanceConstraint)
   201  
   202  	c.Check(instanceConstraint.Constraints.CpuPower, gc.IsNil)
   203  }
   204  
   205  var findInstanceSpecErrorTests = []struct {
   206  	series string
   207  	arches []string
   208  	cons   string
   209  	err    string
   210  }{
   211  	{
   212  		series: series.LatestLts(),
   213  		arches: []string{"arm"},
   214  		err:    fmt.Sprintf(`no "%s" images in test with arches \[arm\]`, series.LatestLts()),
   215  	}, {
   216  		series: "raring",
   217  		arches: both,
   218  		cons:   "mem=4G",
   219  		err:    `no "raring" images in test matching instance types \[m3.large m3.xlarge c1.xlarge m3.2xlarge cc2.8xlarge\]`,
   220  	}, {
   221  		series: series.LatestLts(),
   222  		arches: []string{"amd64"},
   223  		cons:   "instance-type=m1.small mem=4G",
   224  		err:    `no instance types in test matching constraints "instance-type=m1.small mem=4096M"`,
   225  	},
   226  }
   227  
   228  func (s *specSuite) TestFindInstanceSpecErrors(c *gc.C) {
   229  	for i, t := range findInstanceSpecErrorTests {
   230  		c.Logf("test %d", i)
   231  		// We need to filter the image metadata to the test's
   232  		// arches and series; the provisioner and bootstrap
   233  		// code will do this.
   234  		imageMetadata := filterImageMetadata(
   235  			c, TestImageMetadata, t.series, t.arches,
   236  		)
   237  		_, err := findInstanceSpec(
   238  			imageMetadata,
   239  			&instances.InstanceConstraint{
   240  				Region:      "test",
   241  				Series:      t.series,
   242  				Arches:      t.arches,
   243  				Constraints: constraints.MustParse(t.cons),
   244  			})
   245  		c.Check(err, gc.ErrorMatches, t.err)
   246  	}
   247  }
   248  
   249  func filterImageMetadata(
   250  	c *gc.C,
   251  	in []*imagemetadata.ImageMetadata,
   252  	filterSeries string, filterArches []string,
   253  ) []*imagemetadata.ImageMetadata {
   254  	var imageMetadata []*imagemetadata.ImageMetadata
   255  	for _, im := range in {
   256  		version, err := series.SeriesVersion(filterSeries)
   257  		c.Assert(err, jc.ErrorIsNil)
   258  		if im.Version != version {
   259  			continue
   260  		}
   261  		match := false
   262  		for _, arch := range filterArches {
   263  			match = match || im.Arch == arch
   264  		}
   265  		if match {
   266  			imageMetadata = append(imageMetadata, im)
   267  		}
   268  	}
   269  	return imageMetadata
   270  }
   271  
   272  func (*specSuite) TestFilterImagesAcceptsNil(c *gc.C) {
   273  	c.Check(filterImages(nil, nil), gc.HasLen, 0)
   274  }
   275  
   276  func (*specSuite) TestFilterImagesReturnsSelectively(c *gc.C) {
   277  	good := imagemetadata.ImageMetadata{Id: "good", Storage: "ebs"}
   278  	bad := imagemetadata.ImageMetadata{Id: "bad", Storage: "ftp"}
   279  	input := []*imagemetadata.ImageMetadata{&good, &bad}
   280  	expectation := []*imagemetadata.ImageMetadata{&good}
   281  
   282  	ic := &instances.InstanceConstraint{Storage: []string{"ebs"}}
   283  	c.Check(filterImages(input, ic), gc.DeepEquals, expectation)
   284  }
   285  
   286  func (*specSuite) TestFilterImagesMaintainsOrdering(c *gc.C) {
   287  	input := []*imagemetadata.ImageMetadata{
   288  		{Id: "one", Storage: "ebs"},
   289  		{Id: "two", Storage: "ebs"},
   290  		{Id: "three", Storage: "ebs"},
   291  	}
   292  	ic := &instances.InstanceConstraint{Storage: []string{"ebs"}}
   293  	c.Check(filterImages(input, ic), gc.DeepEquals, input)
   294  }