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 }