github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/environs/simplestreams/testing/testing.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package testing 5 6 // Provides a TestDataSuite which creates and provides http access to sample simplestreams metadata. 7 8 import ( 9 "fmt" 10 "io" 11 "net/http" 12 "strings" 13 14 jujuhttp "github.com/juju/http/v2" 15 jc "github.com/juju/testing/checkers" 16 gc "gopkg.in/check.v1" 17 18 "github.com/juju/juju/environs/simplestreams" 19 "github.com/juju/juju/testing" 20 ) 21 22 var PrivateKeyPassphrase = "12345" 23 24 var SignedMetadataPrivateKey = ` 25 -----BEGIN PGP PRIVATE KEY BLOCK----- 26 Version: GnuPG v1.4.12 (GNU/Linux) 27 28 lQH+BFJCk2EBBAC4wo3+aJ0PSeE54sv+GYNYckqysjazcZfJSdPK1GCN+Teat7ey 29 9dwlLhUIS34H29V+0/RcXmmRV+dObSkXzCx5ltKPSnuDsxvqiDEP0CgWdyFxhDf0 30 TbQuKK5OXcZ9rOTSFmnMxGaAzaV7T1IyuqA9HqntTIfC2tL4Y+QN41gS+QARAQAB 31 /gMDAjYGIOoxe8CYYGwpat1V7NGuphvvZRpqeP0RrJ6h4vHV3hXu5NK3tn6LZF0n 32 Qp31LfTH4BHF091UTiebexuuF1/ixLVihtv45mEVejFG1U3G298+WkWUP6AYA/5c 33 QRzXGiuTXlsBUuFVTGn1mvxRmG3yVoLkDj0l5rN9Tq3Ir4BACIWyxjBv1n8fqw+x 34 ti4b7YoE35FpIXQqLOdfdcKTOqUJt+5c+bed4Yx82BsLiY2/huqG2dLnbwln80Dz 35 iYudtG8xLJ1AeHBBFB0nVdyO+mPzXgLNEbP3zle2W+rUfz+s6te7y+rlV0gad2VG 36 tBAvUy08T9rDk0DNQl7jMq/3cGfDI1Zi/nzf2BuuBu2ddgIRmsXgKYly+Fq6eIpa 37 nM+P1hd1Fa3rQwUSJc/zrl48tukf8sdPLDk/+nMhLHy86jp+NeXyXPLvsMAlF5kR 38 eFjxEjHOnJlo4uIUxvlUuePyEOEl0XkQfZs+VWAPo+l2tB5UZXN0IFVzZXIgPHRl 39 c3RAc29tZXdoZXJlLmNvbT6IuAQTAQIAIgUCUkKTYQIbAwYLCQgHAwIGFQgCCQoL 40 BBYCAwECHgECF4AACgkQuK3uqWB66vCVugP/eJFir6Qdcvl+y9/HuP4q2iECi8ny 41 z9tC3YC9DcJePyoBnt1LJO3HvaquZh1AIr6hgMFaujjx6cCb7YEgE0pJ4m74dvtS 42 Y03MUPQ+Ok4cYV66zaDZLk6zpYJXZhxP7ZhlBvwQRES/rudBEQMfBcU9PrduFU39 43 iI+2ojHI4lsnMQE= 44 =UUIf 45 -----END PGP PRIVATE KEY BLOCK----- 46 ` 47 48 var SignedMetadataPublicKey = ` 49 -----BEGIN PGP PUBLIC KEY BLOCK----- 50 Version: GnuPG v1.4.12 (GNU/Linux) 51 52 mI0EUkKTYQEEALjCjf5onQ9J4Tniy/4Zg1hySrKyNrNxl8lJ08rUYI35N5q3t7L1 53 3CUuFQhLfgfb1X7T9FxeaZFX505tKRfMLHmW0o9Ke4OzG+qIMQ/QKBZ3IXGEN/RN 54 tC4ork5dxn2s5NIWaczEZoDNpXtPUjK6oD0eqe1Mh8La0vhj5A3jWBL5ABEBAAG0 55 HlRlc3QgVXNlciA8dGVzdEBzb21ld2hlcmUuY29tPoi4BBMBAgAiBQJSQpNhAhsD 56 BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRC4re6pYHrq8JW6A/94kWKvpB1y 57 +X7L38e4/iraIQKLyfLP20LdgL0Nwl4/KgGe3Usk7ce9qq5mHUAivqGAwVq6OPHp 58 wJvtgSATSknibvh2+1JjTcxQ9D46ThxhXrrNoNkuTrOlgldmHE/tmGUG/BBERL+u 59 50ERAx8FxT0+t24VTf2Ij7aiMcjiWycxAQ== 60 =zBYH 61 -----END PGP PUBLIC KEY BLOCK-----` 62 63 var imageData = map[string]string{ 64 "/daily/streams/v1/index.json": ` 65 { 66 "index": { 67 "com.ubuntu.cloud:released:raring": { 68 "updated": "Wed, 01 May 2013 13:31:26 +0000", 69 "clouds": [ 70 { 71 "region": "us-east-1", 72 "endpoint": "https://ec2.us-east-1.amazonaws.com" 73 } 74 ], 75 "cloudname": "aws", 76 "datatype": "image-ids", 77 "format": "products:1.0", 78 "products": [ 79 "com.ubuntu.cloud:server:13.04:amd64" 80 ], 81 "path": "streams/v1/raring_metadata.json" 82 } 83 }, 84 "updated": "Wed, 01 May 2013 13:31:26 +0000", 85 "format": "index:1.0" 86 } 87 `, 88 "/streams/v1/index.json": ` 89 { 90 "index": { 91 "com.ubuntu.cloud:released:precise": { 92 "updated": "Wed, 01 May 2013 13:31:26 +0000", 93 "clouds": [ 94 { 95 "region": "us-east-1", 96 "endpoint": "https://ec2.us-east-1.amazonaws.com" 97 } 98 ], 99 "cloudname": "aws", 100 "datatype": "image-ids", 101 "format": "products:1.0", 102 "products": [ 103 "com.ubuntu.cloud:server:12.04:amd64", 104 "com.ubuntu.cloud:server:12.10:amd64", 105 "com.ubuntu.cloud:server:13.04:amd64", 106 "com.ubuntu.cloud:server:14.04:amd64", 107 "com.ubuntu.cloud:server:14.10:amd64", 108 "com.ubuntu.cloud:server:12.04:arm" 109 ], 110 "path": "streams/v1/image_metadata.json" 111 }, 112 "com.ubuntu.cloud:released:raring": { 113 "updated": "Wed, 01 May 2013 13:31:26 +0000", 114 "clouds": [ 115 { 116 "region": "us-east-1", 117 "endpoint": "https://ec2.us-east-1.amazonaws.com" 118 } 119 ], 120 "cloudname": "aws", 121 "datatype": "image-ids", 122 "format": "products:1.0", 123 "products": [ 124 "com.ubuntu.cloud:server:13.04:amd64" 125 ], 126 "path": "streams/v1/raring_metadata.json" 127 }, 128 "com.ubuntu.cloud:released:download": { 129 "datatype": "content-download", 130 "path": "streams/v1/com.ubuntu.cloud:released:download.json", 131 "updated": "Wed, 01 May 2013 13:30:37 +0000", 132 "products": [ 133 "com.ubuntu.cloud:server:12.10:amd64", 134 "com.ubuntu.cloud:server:13.04:amd64" 135 ], 136 "format": "products:1.0" 137 }, 138 "com.ubuntu.juju:released:agents": { 139 "updated": "Mon, 05 Aug 2013 11:07:04 +0000", 140 "datatype": "content-download", 141 "format": "products:1.0", 142 "products": [ 143 "com.ubuntu.juju:ubuntu:amd64", 144 "com.ubuntu.juju:ubuntu:arm" 145 ], 146 "path": "streams/v1/tools_metadata.json" 147 }, 148 "com.ubuntu.juju:testing:agents": { 149 "updated": "Mon, 05 Aug 2013 11:07:04 +0000", 150 "datatype": "content-download", 151 "format": "products:1.0", 152 "products": [ 153 "com.ubuntu.juju:ubuntu:amd64" 154 ], 155 "path": "streams/v1/testing_tools_metadata.json" 156 } 157 }, 158 "updated": "Wed, 01 May 2013 13:31:26 +0000", 159 "format": "index:1.0" 160 } 161 `, 162 "/streams/v1/mirrors.json": ` 163 { 164 "mirrors": { 165 "com.ubuntu.juju:released:agents": [ 166 { 167 "datatype": "content-download", 168 "path": "streams/v1/tools_metadata:public-mirrors.json", 169 "clouds": [ 170 { 171 "region": "us-east-2", 172 "endpoint": "https://ec2.us-east-2.amazonaws.com" 173 }, 174 { 175 "region": "us-west-2", 176 "endpoint": "https://ec2.us-west-2.amazonaws.com" 177 } 178 ], 179 "updated": "Wed, 14 Aug 2013 13:46:17 +0000", 180 "format": "mirrors:1.0" 181 }, 182 { 183 "datatype": "content-download", 184 "path": "streams/v1/tools_metadata:more-mirrors.json", 185 "updated": "Wed, 14 Aug 2013 13:46:17 +0000", 186 "format": "mirrors:1.0" 187 } 188 ] 189 }, 190 "updated": "Wed, 01 May 2013 13:31:26 +0000", 191 "format": "index:1.0" 192 } 193 `, 194 "/streams/v1/tools_metadata.json": ` 195 { 196 "content_id": "com.ubuntu.juju:agents", 197 "datatype": "content-download", 198 "updated": "Tue, 04 Jun 2013 13:50:31 +0000", 199 "format": "products:1.0", 200 "products": { 201 "com.ubuntu.juju:ubuntu:amd64": { 202 "arch": "amd64", 203 "release": "ubuntu", 204 "versions": { 205 "20130806": { 206 "items": { 207 "1130ubuntuamd64": { 208 "version": "1.13.0", 209 "size": 2973595, 210 "path": "tools/released/20130806/juju-1.13.0-ubuntu-amd64.tgz", 211 "ftype": "tar.gz", 212 "sha256": "447aeb6a934a5eaec4f703eda4ef2dde" 213 } 214 } 215 } 216 } 217 }, 218 "com.ubuntu.juju:ubuntu:arm": { 219 "arch": "arm", 220 "release": "ubuntu", 221 "versions": { 222 "20130806": { 223 "items": { 224 "201ubuntuarm": { 225 "version": "2.0.1", 226 "size": 1951096, 227 "path": "tools/released/20130806/juju-2.0.1-ubuntu-arm.tgz", 228 "ftype": "tar.gz", 229 "sha256": "f65a92b3b41311bdf398663ee1c5cd0c" 230 }, 231 "1114ubuntuarm": { 232 "version": "1.11.4", 233 "size": 1951096, 234 "path": "tools/released/20130806/juju-1.11.4-ubuntu-arm.tgz", 235 "ftype": "tar.gz", 236 "sha256": "f65a92b3b41311bdf398663ee1c5cd0c" 237 } 238 } 239 }, 240 "20130803": { 241 "items": { 242 "1114ubuntuarm": { 243 "version": "1.11.4", 244 "size": 2851541, 245 "path": "tools/released/20130803/juju-1.11.4-ubuntu-arm.tgz", 246 "ftype": "tar.gz", 247 "sha256": "df07ac5e1fb4232d4e9aa2effa57918a" 248 }, 249 "1115ubuntuarm": { 250 "version": "1.11.5", 251 "size": 2031281, 252 "path": "tools/released/20130803/juju-1.11.5-ubuntu-arm.tgz", 253 "ftype": "tar.gz", 254 "sha256": "df07ac5e1fb4232d4e9aa2effa57918a" 255 } 256 } 257 } 258 } 259 } 260 } 261 } 262 `, 263 "/streams/v1/testing_tools_metadata.json": ` 264 { 265 "content_id": "com.ubuntu.juju:agents", 266 "datatype": "content-download", 267 "updated": "Tue, 04 Jun 2013 13:50:31 +0000", 268 "format": "products:1.0", 269 "products": { 270 "com.ubuntu.juju:ubuntu:amd64": { 271 "arch": "amd64", 272 "release": "ubuntu", 273 "versions": { 274 "20130806": { 275 "items": { 276 "1130ubuntuamd64": { 277 "version": "1.16.0", 278 "size": 2973512, 279 "path": "tools/testing/20130806/juju-1.16.0-ubuntu-amd64.tgz", 280 "ftype": "tar.gz", 281 "sha256": "447aeb6a934a5eaec4f703eda4ef2dac" 282 } 283 } 284 } 285 } 286 } 287 } 288 } 289 `, 290 "/streams/v1/mirrored-tools-metadata.json": ` 291 { 292 "content_id": "com.ubuntu.juju:agents", 293 "datatype": "content-download", 294 "updated": "Tue, 04 Jun 2013 13:50:31 +0000", 295 "format": "products:1.0", 296 "products": { 297 "com.ubuntu.juju:ubuntu:amd64": { 298 "arch": "amd64", 299 "release": "ubuntu", 300 "versions": { 301 "20130806": { 302 "items": { 303 "1130ubuntuamd64": { 304 "version": "1.13.0", 305 "size": 2973595, 306 "path": "mirrored-path/juju-1.13.0-ubuntu-amd64.tgz", 307 "ftype": "tar.gz", 308 "sha256": "447aeb6a934a5eaec4f703eda4ef2dde" 309 } 310 } 311 } 312 } 313 } 314 } 315 } 316 `, 317 "/streams/v1/tools_metadata:public-mirrors.json": ` 318 { 319 "mirrors": { 320 "com.ubuntu.juju:released:agents": [ 321 { 322 "mirror": "http://some-mirror/", 323 "path": "com.ubuntu.juju:download.json", 324 "format": "products:1.0", 325 "clouds": [ 326 { 327 "endpoint": "https://ec2.us-east-2.amazonaws.com", 328 "region": "us-east-2" 329 } 330 ] 331 }, 332 { 333 "mirror": "test:/", 334 "path": "streams/v1/mirrored-tools-metadata.json", 335 "format": "products:1.0", 336 "clouds": [ 337 { 338 "endpoint": "https://ec2.us-west-2.amazonaws.com", 339 "region": "us-west-2" 340 } 341 ] 342 }, 343 { 344 "mirror": "http://another-mirror/", 345 "path": "com.ubuntu.juju:download.json", 346 "format": "products:1.0", 347 "clouds": [ 348 { 349 "endpoint": "https://ec2.us-west-1.amazonaws.com", 350 "region": "us-west-1" 351 } 352 ] 353 } 354 ] 355 }, 356 "format": "mirrors:1.0", 357 "updated": "Mon, 05 Aug 2013 11:07:04 +0000" 358 } 359 `, 360 "/streams/v1/tools_metadata:more-mirrors.json": ` 361 { 362 "mirrors": { 363 "com.ubuntu.juju:released:agents": [ 364 { 365 "mirror": "http://big-mirror/", 366 "path": "big:download.json", 367 "clouds": [ 368 { 369 "endpoint": "https://some-endpoint.com", 370 "region": "some-region" 371 } 372 ] 373 } 374 ] 375 }, 376 "format": "mirrors:1.0", 377 "updated": "Mon, 05 Aug 2013 11:07:04 +0000" 378 } 379 `, 380 "/streams/v1/image_metadata.json": ` 381 { 382 "updated": "Wed, 01 May 2013 13:31:26 +0000", 383 "content_id": "com.ubuntu.cloud:released:aws", 384 "region": "nz-east-1", 385 "endpoint": "https://anywhere", 386 "root_store": "ebs", 387 "virt": "pv", 388 "products": { 389 "com.ubuntu.cloud:server:14.04:amd64": { 390 "release": "trusty", 391 "version": "14.04", 392 "arch": "amd64", 393 "versions": { 394 "20140118": { 395 "items": { 396 "nzww1pe": { 397 "root_store": "ssd", 398 "virt": "hvm", 399 "id": "ami-36745463" 400 } 401 }, 402 "pubname": "ubuntu-trusty-14.04-amd64-server-20140118", 403 "label": "release" 404 } 405 } 406 }, 407 "com.ubuntu.cloud:server:13.04:amd64": { 408 "release": "raring", 409 "version": "13.04", 410 "arch": "amd64", 411 "versions": { 412 "20160318": { 413 "items": { 414 "nzww1pe": { 415 "id": "ami-36745463" 416 } 417 }, 418 "pubname": "ubuntu-utopic-13.04-amd64-server-20160318", 419 "label": "release" 420 } 421 } 422 }, 423 "com.ubuntu.cloud:server:14.10:amd64": { 424 "release": "utopic", 425 "version": "14.10", 426 "arch": "amd64", 427 "root_store": "ebs", 428 "virt": "pv", 429 "versions": { 430 "20160218": { 431 "items": { 432 "nzww1pe": { 433 "id": "ami-36745463" 434 } 435 }, 436 "pubname": "ubuntu-utopic-14.10-amd64-server-20160218", 437 "label": "release" 438 } 439 } 440 }, 441 "com.ubuntu.cloud:server:12.10:amd64": { 442 "release": "quantal", 443 "version": "12.10", 444 "arch": "amd64", 445 "versions": { 446 "20160118": { 447 "items": { 448 "nzww1pe": { 449 "id": "ami-36745463" 450 } 451 }, 452 "root_store": "ebs", 453 "virt": "pv", 454 "pubname": "ubuntu-quantal-12.10-amd64-server-20160118", 455 "label": "release" 456 } 457 } 458 }, 459 "com.ubuntu.cloud:server:12.04:amd64": { 460 "release": "precise", 461 "version": "12.04", 462 "arch": "amd64", 463 "region": "au-east-1", 464 "endpoint": "https://somewhere", 465 "versions": { 466 "20121218": { 467 "region": "au-east-2", 468 "endpoint": "https://somewhere-else", 469 "items": { 470 "usww1pe": { 471 "root_store": "ebs", 472 "virt": "pv", 473 "id": "ami-26745463" 474 }, 475 "usww2he": { 476 "root_store": "ebs", 477 "virt": "hvm", 478 "id": "ami-442ea674", 479 "region": "us-east-1", 480 "endpoint": "https://ec2.us-east-1.amazonaws.com" 481 }, 482 "usww3he": { 483 "root_store": "ebs", 484 "virt": "hvm", 485 "crsn": "uswest3", 486 "id": "ami-442ea675" 487 } 488 }, 489 "pubname": "ubuntu-precise-12.04-amd64-server-20121218", 490 "label": "release" 491 }, 492 "20111111": { 493 "items": { 494 "usww3pe": { 495 "root_store": "ebs", 496 "virt": "pv", 497 "id": "ami-26745464" 498 }, 499 "usww2pe": { 500 "root_store": "instance", 501 "virt": "pv", 502 "id": "ami-442ea684", 503 "region": "us-east-1", 504 "endpoint": "https://ec2.us-east-1.amazonaws.com" 505 } 506 }, 507 "pubname": "ubuntu-precise-12.04-amd64-server-20111111", 508 "label": "release" 509 } 510 } 511 }, 512 "com.ubuntu.cloud:server:12.04:arm": { 513 "release": "precise", 514 "version": "12.04", 515 "arch": "arm", 516 "region": "us-east-1", 517 "endpoint": "https://ec2.us-east-1.amazonaws.com", 518 "versions": { 519 "20121219": { 520 "items": { 521 "usww2he": { 522 "root_store": "ebs", 523 "virt": "pv", 524 "id": "ami-442ea699" 525 } 526 }, 527 "pubname": "ubuntu-precise-12.04-arm-server-20121219", 528 "label": "release" 529 } 530 } 531 } 532 }, 533 "_aliases": { 534 "crsn": { 535 "uswest3": { 536 "region": "us-west-3", 537 "endpoint": "https://ec2.us-west-3.amazonaws.com" 538 } 539 } 540 }, 541 "format": "products:1.0" 542 } 543 `, 544 } 545 546 var TestRoundTripper = &testing.ProxyRoundTripper{} 547 548 type TestDataSuite struct{} 549 550 func (s *TestDataSuite) SetUpSuite(c *gc.C) { 551 TestRoundTripper.Sub = testing.NewCannedRoundTripper(imageData, map[string]int{"test://unauth": http.StatusUnauthorized}) 552 } 553 554 func (s *TestDataSuite) TearDownSuite(c *gc.C) { 555 TestRoundTripper.Sub = nil 556 } 557 558 const ( 559 UnsignedJsonSuffix = ".json" 560 SignedJsonSuffix = ".sjson" 561 ) 562 563 func SetRoundTripperFiles(files map[string]string, errorFiles map[string]int) { 564 TestRoundTripper.Sub = testing.NewCannedRoundTripper(files, errorFiles) 565 } 566 567 func AddSignedFiles(c *gc.C, files map[string]string) map[string]string { 568 all := make(map[string]string) 569 for name, content := range files { 570 all[name] = content 571 // Sign file content 572 r := strings.NewReader(content) 573 bytes, err := io.ReadAll(r) 574 c.Assert(err, jc.ErrorIsNil) 575 signedName, signedContent, err := SignMetadata(name, bytes) 576 c.Assert(err, jc.ErrorIsNil) 577 all[signedName] = string(signedContent) 578 } 579 return all 580 } 581 582 func SignMetadata(fileName string, fileData []byte) (string, []byte, error) { 583 signString := func(unsigned string) string { 584 return strings.Replace(unsigned, UnsignedJsonSuffix, SignedJsonSuffix, -1) 585 } 586 587 // Make sure that contents point to signed files too. 588 signedFileData := signString(string(fileData)) 589 signedBytes, err := simplestreams.Encode(strings.NewReader(signedFileData), SignedMetadataPrivateKey, PrivateKeyPassphrase) 590 if err != nil { 591 return "", nil, err 592 } 593 594 return signString(fileName), signedBytes, nil 595 } 596 597 // SourceDetails stored some details that need to be checked about data source. 598 type SourceDetails struct { 599 URL string 600 Key string 601 RequireSigned bool 602 } 603 604 func AssertExpectedSources(c *gc.C, obtained []simplestreams.DataSource, dsDetails []SourceDetails) { 605 // Some data sources do not require to contain signed data. 606 // However, they may still contain it. 607 // Since we will always try to read signed data first, 608 // we want to be able to try to read this signed data 609 // with a public key. Check keys are provided where needed. 610 // Bugs #1542127, #1542131 611 for i, source := range obtained { 612 url, err := source.URL("") 613 c.Assert(err, jc.ErrorIsNil) 614 expected := dsDetails[i] 615 c.Assert(url, gc.DeepEquals, expected.URL) 616 c.Assert(source.PublicSigningKey(), gc.DeepEquals, expected.Key) 617 c.Assert(source.RequireSigned(), gc.Equals, expected.RequireSigned) 618 } 619 c.Assert(obtained, gc.HasLen, len(dsDetails)) 620 } 621 622 type LocalLiveSimplestreamsSuite struct { 623 testing.BaseSuite 624 Source simplestreams.DataSource 625 RequireSigned bool 626 StreamsVersion string 627 DataType string 628 ValidConstraint simplestreams.LookupConstraint 629 } 630 631 const ( 632 Index_v1 = "index:1.0" 633 Product_v1 = "products:1.0" 634 ) 635 636 type testConstraint struct { 637 simplestreams.LookupParams 638 } 639 640 func NewTestConstraint(params simplestreams.LookupParams) *testConstraint { 641 return &testConstraint{LookupParams: params} 642 } 643 644 func (tc *testConstraint) IndexIds() []string { 645 return nil 646 } 647 648 func (tc *testConstraint) ProductIds() ([]string, error) { 649 ids := make([]string, len(tc.Arches)) 650 for i, arch := range tc.Arches { 651 ids[i] = fmt.Sprintf("com.ubuntu.cloud:server:%s:%s", tc.Releases[0], arch) 652 } 653 return ids, nil 654 } 655 656 type testDataSourceFactory struct{} 657 658 func TestDataSourceFactory() simplestreams.DataSourceFactory { 659 return testDataSourceFactory{} 660 } 661 662 func (testDataSourceFactory) NewDataSource(cfg simplestreams.Config) simplestreams.DataSource { 663 return simplestreams.NewDataSourceWithClient(cfg, jujuhttp.NewClient( 664 jujuhttp.WithTransportMiddlewares( 665 jujuhttp.DialContextMiddleware(jujuhttp.NewLocalDialBreaker(false)), 666 jujuhttp.FileProtocolMiddleware, 667 FileProtocolMiddleware, 668 ), 669 )) 670 } 671 672 type testSkipVerifyDataSourceFactory struct{} 673 674 func TestSkipVerifyDataSourceFactory() simplestreams.DataSourceFactory { 675 return testSkipVerifyDataSourceFactory{} 676 } 677 678 func (testSkipVerifyDataSourceFactory) NewDataSource(cfg simplestreams.Config) simplestreams.DataSource { 679 return simplestreams.NewDataSourceWithClient(cfg, jujuhttp.NewClient( 680 jujuhttp.WithSkipHostnameVerification(true), 681 jujuhttp.WithTransportMiddlewares( 682 jujuhttp.DialContextMiddleware(jujuhttp.NewLocalDialBreaker(false)), 683 jujuhttp.FileProtocolMiddleware, 684 FileProtocolMiddleware, 685 ), 686 )) 687 } 688 689 // FileProtocolMiddleware registers support for file:// URLs on the given 690 // transport. 691 func FileProtocolMiddleware(transport *http.Transport) *http.Transport { 692 TestRoundTripper.RegisterForTransportScheme(transport, "test") 693 TestRoundTripper.RegisterForTransportScheme(transport, "signedtest") 694 return transport 695 } 696 697 func init() { 698 // Ensure out test struct can have its tags extracted. 699 simplestreams.RegisterStructTags(TestItem{}) 700 } 701 702 type TestItem struct { 703 Id string `json:"id"` 704 Version string `json:"version"` 705 Storage string `json:"root_store"` 706 VirtType string `json:"virt"` 707 Arch string `json:"arch"` 708 RegionAlias string `json:"crsn"` 709 RegionName string `json:"region"` 710 Endpoint string `json:"endpoint"` 711 } 712 713 func (s *LocalLiveSimplestreamsSuite) IndexPath() string { 714 if s.RequireSigned { 715 return fmt.Sprintf("streams/%s/index.sjson", s.StreamsVersion) 716 } 717 return fmt.Sprintf("streams/%s/index.json", s.StreamsVersion) 718 } 719 720 func (s *LocalLiveSimplestreamsSuite) TestGetIndex(c *gc.C) { 721 indexRef, err := s.GetIndexRef(Index_v1) 722 c.Assert(err, jc.ErrorIsNil) 723 c.Assert(indexRef.Format, gc.Equals, Index_v1) 724 c.Assert(indexRef.Source, gc.Equals, s.Source) 725 c.Assert(len(indexRef.Indexes) > 0, jc.IsTrue) 726 } 727 728 func (s *LocalLiveSimplestreamsSuite) GetIndexRef(format string) (*simplestreams.IndexReference, error) { 729 params := simplestreams.ValueParams{ 730 DataType: s.DataType, 731 ValueTemplate: TestItem{}, 732 } 733 ss := simplestreams.NewSimpleStreams(TestDataSourceFactory()) 734 return ss.GetIndexWithFormat( 735 s.Source, s.IndexPath(), 736 format, 737 simplestreams.MirrorsPath(s.StreamsVersion), 738 s.RequireSigned, 739 s.ValidConstraint.Params().CloudSpec, 740 params, 741 ) 742 } 743 744 func (s *LocalLiveSimplestreamsSuite) TestGetIndexWrongFormat(c *gc.C) { 745 _, err := s.GetIndexRef("bad") 746 c.Assert(err, gc.NotNil) 747 } 748 749 func (s *LocalLiveSimplestreamsSuite) TestGetProductsPathExists(c *gc.C) { 750 indexRef, err := s.GetIndexRef(Index_v1) 751 c.Assert(err, jc.ErrorIsNil) 752 path, err := indexRef.GetProductsPath(s.ValidConstraint) 753 c.Assert(err, jc.ErrorIsNil) 754 c.Assert(path, gc.Not(gc.Equals), "") 755 } 756 757 func (s *LocalLiveSimplestreamsSuite) TestGetProductsPathInvalidCloudSpec(c *gc.C) { 758 indexRef, err := s.GetIndexRef(Index_v1) 759 c.Assert(err, jc.ErrorIsNil) 760 ic := NewTestConstraint(simplestreams.LookupParams{ 761 CloudSpec: simplestreams.CloudSpec{Region: "bad", Endpoint: "spec"}, 762 Releases: []string{"12.04"}, 763 }) 764 _, err = indexRef.GetProductsPath(ic) 765 c.Assert(err, gc.NotNil) 766 } 767 768 func (s *LocalLiveSimplestreamsSuite) TestGetProductsPathInvalidProductSpec(c *gc.C) { 769 indexRef, err := s.GetIndexRef(Index_v1) 770 c.Assert(err, jc.ErrorIsNil) 771 ic := NewTestConstraint(simplestreams.LookupParams{ 772 CloudSpec: s.ValidConstraint.Params().CloudSpec, 773 Releases: []string{"12.04"}, 774 Arches: []string{"bad"}, 775 Stream: "spec", 776 }) 777 _, err = indexRef.GetProductsPath(ic) 778 c.Assert(err, gc.NotNil) 779 } 780 781 func (s *LocalLiveSimplestreamsSuite) AssertGetMetadata(c *gc.C) *simplestreams.CloudMetadata { 782 indexRef, err := s.GetIndexRef(Index_v1) 783 c.Assert(err, jc.ErrorIsNil) 784 metadata, err := indexRef.GetCloudMetadataWithFormat(s.ValidConstraint, Product_v1, s.RequireSigned) 785 c.Assert(err, jc.ErrorIsNil) 786 c.Assert(metadata.Format, gc.Equals, Product_v1) 787 c.Assert(len(metadata.Products) > 0, jc.IsTrue) 788 return metadata 789 } 790 791 func (s *LocalLiveSimplestreamsSuite) TestGetCloudMetadataWithFormat(c *gc.C) { 792 s.AssertGetMetadata(c) 793 } 794 795 func (s *LocalLiveSimplestreamsSuite) AssertGetItemCollections(c *gc.C, version string) *simplestreams.ItemCollection { 796 metadata := s.AssertGetMetadata(c) 797 metadataCatalog := metadata.Products["com.ubuntu.cloud:server:12.04:amd64"] 798 ic := metadataCatalog.Items[version] 799 return ic 800 } 801 802 func InvalidDataSource(requireSigned bool) simplestreams.DataSource { 803 factory := TestDataSourceFactory() 804 return factory.NewDataSource(simplestreams.Config{ 805 Description: "invalid", 806 BaseURL: "file://invalid", 807 HostnameVerification: true, 808 Priority: simplestreams.DEFAULT_CLOUD_DATA, 809 RequireSigned: requireSigned}) 810 } 811 812 func VerifyDefaultCloudDataSource(description, baseURL string) simplestreams.DataSource { 813 factory := TestDataSourceFactory() 814 return factory.NewDataSource(simplestreams.Config{ 815 Description: description, 816 BaseURL: baseURL, 817 HostnameVerification: true, 818 Priority: simplestreams.DEFAULT_CLOUD_DATA}) 819 }