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