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