github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/provisioner/imagemetadata_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package provisioner_test 5 6 import ( 7 "github.com/juju/errors" 8 jc "github.com/juju/testing/checkers" 9 gc "gopkg.in/check.v1" 10 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/apiserver/provisioner" 13 "github.com/juju/juju/environs/imagemetadata" 14 imagetesting "github.com/juju/juju/environs/imagemetadata/testing" 15 sstesting "github.com/juju/juju/environs/simplestreams/testing" 16 "github.com/juju/juju/state/cloudimagemetadata" 17 ) 18 19 // useTestImageData causes the given content to be served when published metadata is requested. 20 func useTestImageData(c *gc.C, files map[string]string) { 21 if files != nil { 22 sstesting.SetRoundTripperFiles(sstesting.AddSignedFiles(c, files), nil) 23 } else { 24 sstesting.SetRoundTripperFiles(nil, nil) 25 } 26 } 27 28 type ImageMetadataSuite struct { 29 provisionerSuite 30 } 31 32 var _ = gc.Suite(&ImageMetadataSuite{}) 33 34 func (s *ImageMetadataSuite) SetUpSuite(c *gc.C) { 35 s.provisionerSuite.SetUpSuite(c) 36 37 // Make sure that there is nothing in data sources. 38 // Each individual tests will decide if it needs metadata there. 39 imagetesting.PatchOfficialDataSources(&s.CleanupSuite, "test:/daily") 40 s.PatchValue(&imagemetadata.SimplestreamsImagesPublicKey, sstesting.SignedMetadataPublicKey) 41 useTestImageData(c, nil) 42 } 43 44 func (s *ImageMetadataSuite) TearDownSuite(c *gc.C) { 45 useTestImageData(c, nil) 46 s.provisionerSuite.TearDownSuite(c) 47 } 48 49 func (s *ImageMetadataSuite) SetUpTest(c *gc.C) { 50 s.provisionerSuite.SetUpTest(c) 51 } 52 53 func (s *ImageMetadataSuite) TestMetadataNone(c *gc.C) { 54 api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) 55 c.Assert(err, jc.ErrorIsNil) 56 57 result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) 58 c.Assert(err, jc.ErrorIsNil) 59 60 expected := make([][]params.CloudImageMetadata, len(s.machines)) 61 for i, _ := range result.Results { 62 expected[i] = nil 63 } 64 s.assertImageMetadataResults(c, result, expected...) 65 } 66 67 func (s *ImageMetadataSuite) TestMetadataNotInStateButInDataSources(c *gc.C) { 68 // ensure metadata in data sources and not in state 69 useTestImageData(c, testImagesData) 70 71 criteria := cloudimagemetadata.MetadataFilter{Stream: "daily"} 72 found, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria) 73 c.Assert(errors.IsNotFound(err), jc.IsTrue) 74 c.Assert(found, gc.HasLen, 0) 75 76 api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) 77 c.Assert(err, jc.ErrorIsNil) 78 79 result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) 80 c.Assert(err, jc.ErrorIsNil) 81 82 expected := s.expectedDataSoureImageMetadata() 83 s.assertImageMetadataResults(c, result, expected...) 84 85 // Also make sure that these images metadata has been written to state for re-use 86 saved, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria) 87 c.Assert(err, jc.ErrorIsNil) 88 c.Assert(saved, gc.DeepEquals, map[string][]cloudimagemetadata.Metadata{ 89 "default cloud images": s.convertCloudImageMetadata(expected[0]), 90 }) 91 } 92 93 func (s *ImageMetadataSuite) TestMetadataFromState(c *gc.C) { 94 api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) 95 c.Assert(err, jc.ErrorIsNil) 96 97 expected := s.expectedDataSoureImageMetadata() 98 99 // Write metadata to state. 100 metadata := s.convertCloudImageMetadata(expected[0]) 101 for _, m := range metadata { 102 err := s.State.CloudImageMetadataStorage.SaveMetadata( 103 []cloudimagemetadata.Metadata{m}, 104 ) 105 c.Assert(err, jc.ErrorIsNil) 106 } 107 108 result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) 109 c.Assert(err, jc.ErrorIsNil) 110 111 s.assertImageMetadataResults(c, result, expected...) 112 } 113 114 func (s *ImageMetadataSuite) getTestMachinesTags(c *gc.C) params.Entities { 115 116 testMachines := make([]params.Entity, len(s.machines)) 117 118 for i, m := range s.machines { 119 testMachines[i] = params.Entity{Tag: m.Tag().String()} 120 } 121 return params.Entities{Entities: testMachines} 122 } 123 124 func (s *ImageMetadataSuite) convertCloudImageMetadata(all []params.CloudImageMetadata) []cloudimagemetadata.Metadata { 125 expected := make([]cloudimagemetadata.Metadata, len(all)) 126 for i, one := range all { 127 expected[i] = cloudimagemetadata.Metadata{ 128 cloudimagemetadata.MetadataAttributes{ 129 Region: one.Region, 130 Version: one.Version, 131 Series: one.Series, 132 Arch: one.Arch, 133 VirtType: one.VirtType, 134 RootStorageType: one.RootStorageType, 135 Source: one.Source, 136 Stream: one.Stream, 137 }, 138 one.Priority, 139 one.ImageId, 140 } 141 } 142 return expected 143 } 144 145 func (s *ImageMetadataSuite) expectedDataSoureImageMetadata() [][]params.CloudImageMetadata { 146 expected := make([][]params.CloudImageMetadata, len(s.machines)) 147 for i, _ := range s.machines { 148 expected[i] = []params.CloudImageMetadata{ 149 {ImageId: "ami-1126745463", 150 Region: "another_dummy_region", 151 Version: "12.10", 152 Series: "quantal", 153 Arch: "amd64", 154 VirtType: "pv", 155 RootStorageType: "ebs", 156 Source: "default cloud images", 157 Stream: "daily", 158 Priority: 10, 159 }, 160 {ImageId: "ami-26745463", 161 Region: "dummy_region", 162 Version: "12.10", 163 Series: "quantal", 164 Arch: "amd64", 165 VirtType: "pv", 166 RootStorageType: "ebs", 167 Stream: "daily", 168 Source: "default cloud images", 169 Priority: 10}, 170 } 171 } 172 return expected 173 } 174 175 func (s *ImageMetadataSuite) assertImageMetadataResults(c *gc.C, obtained params.ProvisioningInfoResults, expected ...[]params.CloudImageMetadata) { 176 c.Assert(obtained.Results, gc.HasLen, len(expected)) 177 for i, one := range obtained.Results { 178 // We are only concerned with images here 179 c.Assert(one.Result.ImageMetadata, gc.DeepEquals, expected[i]) 180 } 181 } 182 183 // TODO (anastasiamac 2015-09-04) This metadata is so verbose. 184 // Need to generate the text by creating a struct and marshalling it. 185 var testImagesData = map[string]string{ 186 "/daily/streams/v1/index.json": ` 187 { 188 "index": { 189 "com.ubuntu.cloud:daily:aws": { 190 "updated": "Wed, 01 May 2013 13:31:26 +0000", 191 "clouds": [ 192 { 193 "region": "dummy_region", 194 "endpoint": "https://anywhere" 195 }, 196 { 197 "region": "another_dummy_region", 198 "endpoint": "" 199 } 200 ], 201 "cloudname": "aws", 202 "datatype": "image-ids", 203 "format": "products:1.0", 204 "products": [ 205 "com.ubuntu.cloud.daily:server:12.10:amd64", 206 "com.ubuntu.cloud.daily:server:14.04:amd64" 207 ], 208 "path": "streams/v1/image_metadata.json" 209 } 210 }, 211 "updated": "Wed, 27 May 2015 13:31:26 +0000", 212 "format": "index:1.0" 213 } 214 `, 215 "/daily/streams/v1/image_metadata.json": ` 216 { 217 "updated": "Wed, 27 May 2015 13:31:26 +0000", 218 "content_id": "com.ubuntu.cloud:daily:aws", 219 "products": { 220 "com.ubuntu.cloud.daily:server:14.04:amd64": { 221 "release": "trusty", 222 "version": "14.04", 223 "arch": "amd64", 224 "versions": { 225 "20140118": { 226 "items": { 227 "nzww1pe": { 228 "root_store": "ebs", 229 "virt": "pv", 230 "crsn": "da1", 231 "id": "ami-36745463" 232 }, 233 "nzww1pe2": { 234 "root_store": "ebs", 235 "virt": "pv", 236 "crsn": "da2", 237 "id": "ami-1136745463" 238 } 239 }, 240 "pubname": "ubuntu-trusty-14.04-amd64-server-20140118", 241 "label": "release" 242 } 243 } 244 }, 245 "com.ubuntu.cloud.daily:server:12.10:amd64": { 246 "release": "quantal", 247 "version": "12.10", 248 "arch": "amd64", 249 "versions": { 250 "20121218": { 251 "items": { 252 "usww1pe": { 253 "root_store": "ebs", 254 "virt": "pv", 255 "crsn": "da1", 256 "id": "ami-26745463" 257 }, 258 "usww1pe2": { 259 "root_store": "ebs", 260 "virt": "pv", 261 "crsn": "da2", 262 "id": "ami-1126745463" 263 } 264 }, 265 "pubname": "ubuntu-quantal-12.10-amd64-server-20121218", 266 "label": "release" 267 } 268 } 269 } 270 }, 271 "_aliases": { 272 "crsn": { 273 "da1": { 274 "region": "dummy_region", 275 "endpoint": "https://anywhere" 276 }, 277 "da2": { 278 "region": "another_dummy_region", 279 "endpoint": "" 280 } 281 } 282 }, 283 "format": "products:1.0" 284 } 285 `, 286 }