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 }