github.phpd.cn/hashicorp/packer@v1.3.2/builder/hyperv/iso/builder_test.go (about) 1 // +build !windows 2 3 package iso 4 5 import ( 6 "context" 7 "fmt" 8 "reflect" 9 "strconv" 10 "testing" 11 12 "os" 13 14 hypervcommon "github.com/hashicorp/packer/builder/hyperv/common" 15 "github.com/hashicorp/packer/helper/multistep" 16 "github.com/hashicorp/packer/packer" 17 ) 18 19 func testConfig() map[string]interface{} { 20 return map[string]interface{}{ 21 "iso_checksum": "foo", 22 "iso_checksum_type": "md5", 23 "iso_url": "http://www.packer.io", 24 "shutdown_command": "yes", 25 "ssh_username": "foo", 26 "ram_size": 64, 27 "disk_size": 256, 28 "disk_block_size": 1, 29 "guest_additions_mode": "none", 30 "disk_additional_size": "50000,40000,30000", 31 packer.BuildNameConfigKey: "foo", 32 } 33 } 34 35 func TestBuilder_ImplementsBuilder(t *testing.T) { 36 var raw interface{} 37 raw = &Builder{} 38 if _, ok := raw.(packer.Builder); !ok { 39 t.Error("Builder must implement builder.") 40 } 41 } 42 43 func TestBuilderPrepare_Defaults(t *testing.T) { 44 var b Builder 45 config := testConfig() 46 47 warns, err := b.Prepare(config) 48 if len(warns) > 0 { 49 t.Fatalf("bad: %#v", warns) 50 } 51 if err != nil { 52 t.Fatalf("should not have error: %s", err) 53 } 54 55 if b.config.VMName != "packer-foo" { 56 t.Errorf("bad vm name: %s", b.config.VMName) 57 } 58 } 59 60 func TestBuilderPrepare_DiskSize(t *testing.T) { 61 var b Builder 62 config := testConfig() 63 64 delete(config, "disk_size") 65 warns, err := b.Prepare(config) 66 if len(warns) > 0 { 67 t.Fatalf("bad: %#v", warns) 68 } 69 if err != nil { 70 t.Fatalf("bad err: %s", err) 71 } 72 73 if b.config.DiskSize != 40*1024 { 74 t.Fatalf("bad size: %d", b.config.DiskSize) 75 } 76 77 config["disk_size"] = 256 78 b = Builder{} 79 warns, err = b.Prepare(config) 80 if len(warns) > 0 { 81 t.Fatalf("bad: %#v", warns) 82 } 83 if err != nil { 84 t.Fatalf("should not have error: %s", err) 85 } 86 87 if b.config.DiskSize != 256 { 88 t.Fatalf("bad size: %d", b.config.DiskSize) 89 } 90 } 91 92 func TestBuilderPrepare_DiskBlockSize(t *testing.T) { 93 var b Builder 94 config := testConfig() 95 expected_default_block_size := uint(32) 96 expected_min_block_size := uint(0) 97 expected_max_block_size := uint(256) 98 99 // Test default with empty disk_block_size 100 delete(config, "disk_block_size") 101 warns, err := b.Prepare(config) 102 if len(warns) > 0 { 103 t.Fatalf("bad: %#v", warns) 104 } 105 if err != nil { 106 t.Fatalf("bad err: %s", err) 107 } 108 if b.config.DiskBlockSize != expected_default_block_size { 109 t.Fatalf("bad default block size with empty config: %d. Expected %d", b.config.DiskBlockSize, 110 expected_default_block_size) 111 } 112 113 test_sizes := []uint{0, 1, 32, 256, 512, 1 * 1024, 32 * 1024} 114 for _, test_size := range test_sizes { 115 config["disk_block_size"] = test_size 116 b = Builder{} 117 warns, err = b.Prepare(config) 118 if test_size > expected_max_block_size || test_size < expected_min_block_size { 119 if len(warns) > 0 { 120 t.Fatalf("bad, should have no warns: %#v", warns) 121 } 122 if err == nil { 123 t.Fatalf("bad, should have error. disk_block_size=%d outside expected valid range [%d,%d]", 124 test_size, expected_min_block_size, expected_max_block_size) 125 } 126 } else { 127 if len(warns) > 0 { 128 t.Fatalf("bad: %#v", warns) 129 } 130 if err != nil { 131 t.Fatalf("bad, should not have error: %s", err) 132 } 133 if test_size == 0 { 134 if b.config.DiskBlockSize != expected_default_block_size { 135 t.Fatalf("bad default block size with 0 value config: %d. Expected: %d", 136 b.config.DiskBlockSize, expected_default_block_size) 137 } 138 } else { 139 if b.config.DiskBlockSize != test_size { 140 t.Fatalf("bad block size with 0 value config: %d. Expected: %d", b.config.DiskBlockSize, 141 expected_default_block_size) 142 } 143 } 144 } 145 } 146 } 147 148 func TestBuilderPrepare_FixedVHDFormat(t *testing.T) { 149 var b Builder 150 config := testConfig() 151 config["use_fixed_vhd_format"] = true 152 config["generation"] = 1 153 config["skip_compaction"] = true 154 config["differencing_disk"] = false 155 156 // use_fixed_vhd_format should work with generation = 1, skip_compaction 157 // = true, and differencing_disk = false 158 warns, err := b.Prepare(config) 159 if len(warns) > 0 { 160 t.Fatalf("bad: %#v", warns) 161 } 162 if err != nil { 163 t.Fatalf("bad err: %s", err) 164 } 165 166 //use_fixed_vhd_format should not work with differencing_disk = true 167 config["differencing_disk"] = true 168 b = Builder{} 169 warns, err = b.Prepare(config) 170 if len(warns) > 0 { 171 t.Fatalf("bad: %#v", warns) 172 } 173 if err == nil { 174 t.Fatal("should have error") 175 } 176 config["differencing_disk"] = false 177 178 //use_fixed_vhd_format should not work with skip_compaction = false 179 config["skip_compaction"] = false 180 b = Builder{} 181 warns, err = b.Prepare(config) 182 if len(warns) > 0 { 183 t.Fatalf("bad: %#v", warns) 184 } 185 if err == nil { 186 t.Fatal("should have error") 187 } 188 config["skip_compaction"] = true 189 190 //use_fixed_vhd_format should not work with generation = 2 191 config["generation"] = 2 192 b = Builder{} 193 warns, err = b.Prepare(config) 194 if len(warns) > 0 { 195 t.Fatalf("bad: %#v", warns) 196 } 197 if err == nil { 198 t.Fatal("should have error") 199 } 200 } 201 202 func TestBuilderPrepare_FloppyFiles(t *testing.T) { 203 var b Builder 204 config := testConfig() 205 206 delete(config, "floppy_files") 207 warns, err := b.Prepare(config) 208 if len(warns) > 0 { 209 t.Fatalf("bad: %#v", warns) 210 } 211 if err != nil { 212 t.Fatalf("bad err: %s", err) 213 } 214 215 if len(b.config.FloppyFiles) != 0 { 216 t.Fatalf("bad: %#v", b.config.FloppyFiles) 217 } 218 219 floppiesPath := "../../../common/test-fixtures/floppies" 220 config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)} 221 b = Builder{} 222 warns, err = b.Prepare(config) 223 if len(warns) > 0 { 224 t.Fatalf("bad: %#v", warns) 225 } 226 if err != nil { 227 t.Fatalf("should not have error: %s", err) 228 } 229 230 expected := []string{fmt.Sprintf("%s/bar.bat", floppiesPath), fmt.Sprintf("%s/foo.ps1", floppiesPath)} 231 if !reflect.DeepEqual(b.config.FloppyFiles, expected) { 232 t.Fatalf("bad: %#v", b.config.FloppyFiles) 233 } 234 } 235 236 func TestBuilderPrepare_InvalidFloppies(t *testing.T) { 237 var b Builder 238 config := testConfig() 239 config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} 240 b = Builder{} 241 _, errs := b.Prepare(config) 242 if errs == nil { 243 t.Fatalf("Nonexistent floppies should trigger multierror") 244 } 245 246 if len(errs.(*packer.MultiError).Errors) != 2 { 247 t.Fatalf("Multierror should work and report 2 errors") 248 } 249 } 250 251 func TestBuilderPrepare_InvalidKey(t *testing.T) { 252 var b Builder 253 config := testConfig() 254 255 // Add a random key 256 config["i_should_not_be_valid"] = true 257 warns, err := b.Prepare(config) 258 if len(warns) > 0 { 259 t.Fatalf("bad: %#v", warns) 260 } 261 if err == nil { 262 t.Fatal("should have error") 263 } 264 } 265 266 func TestBuilderPrepare_ISOChecksum(t *testing.T) { 267 var b Builder 268 config := testConfig() 269 270 // Test bad 271 config["iso_checksum"] = "" 272 warns, err := b.Prepare(config) 273 if len(warns) > 0 { 274 t.Fatalf("bad: %#v", warns) 275 } 276 if err == nil { 277 t.Fatal("should have error") 278 } 279 280 // Test good 281 config["iso_checksum"] = "FOo" 282 b = Builder{} 283 warns, err = b.Prepare(config) 284 if len(warns) > 0 { 285 t.Fatalf("bad: %#v", warns) 286 } 287 if err != nil { 288 t.Fatalf("should not have error: %s", err) 289 } 290 291 if b.config.ISOChecksum != "foo" { 292 t.Fatalf("should've lowercased: %s", b.config.ISOChecksum) 293 } 294 } 295 296 func TestBuilderPrepare_ISOChecksumType(t *testing.T) { 297 var b Builder 298 config := testConfig() 299 300 // Test bad 301 config["iso_checksum_type"] = "" 302 warns, err := b.Prepare(config) 303 if len(warns) > 0 { 304 t.Fatalf("bad: %#v", warns) 305 } 306 if err == nil { 307 t.Fatal("should have error") 308 } 309 310 // Test good 311 config["iso_checksum_type"] = "mD5" 312 b = Builder{} 313 warns, err = b.Prepare(config) 314 if len(warns) > 0 { 315 t.Fatalf("bad: %#v", warns) 316 } 317 if err != nil { 318 t.Fatalf("should not have error: %s", err) 319 } 320 321 if b.config.ISOChecksumType != "md5" { 322 t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType) 323 } 324 325 // Test unknown 326 config["iso_checksum_type"] = "fake" 327 b = Builder{} 328 warns, err = b.Prepare(config) 329 if len(warns) > 0 { 330 t.Fatalf("bad: %#v", warns) 331 } 332 if err == nil { 333 t.Fatal("should have error") 334 } 335 336 // Test none 337 config["iso_checksum_type"] = "none" 338 b = Builder{} 339 warns, err = b.Prepare(config) 340 if len(warns) == 0 { 341 t.Fatalf("bad: %#v", warns) 342 } 343 if err != nil { 344 t.Fatalf("should not have error: %s", err) 345 } 346 347 if b.config.ISOChecksumType != "none" { 348 t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType) 349 } 350 } 351 352 func TestBuilderPrepare_ISOUrl(t *testing.T) { 353 var b Builder 354 config := testConfig() 355 delete(config, "iso_url") 356 delete(config, "iso_urls") 357 358 // Test both empty 359 config["iso_url"] = "" 360 b = Builder{} 361 warns, err := b.Prepare(config) 362 if len(warns) > 0 { 363 t.Fatalf("bad: %#v", warns) 364 } 365 if err == nil { 366 t.Fatal("should have error") 367 } 368 369 // Test iso_url set 370 config["iso_url"] = "http://www.packer.io" 371 b = Builder{} 372 warns, err = b.Prepare(config) 373 if len(warns) > 0 { 374 t.Fatalf("bad: %#v", warns) 375 } 376 if err != nil { 377 t.Errorf("should not have error: %s", err) 378 } 379 380 expected := []string{"http://www.packer.io"} 381 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 382 t.Fatalf("bad: %#v", b.config.ISOUrls) 383 } 384 385 // Test both set 386 config["iso_url"] = "http://www.packer.io" 387 config["iso_urls"] = []string{"http://www.packer.io"} 388 b = Builder{} 389 warns, err = b.Prepare(config) 390 if len(warns) > 0 { 391 t.Fatalf("bad: %#v", warns) 392 } 393 if err == nil { 394 t.Fatal("should have error") 395 } 396 397 // Test just iso_urls set 398 delete(config, "iso_url") 399 config["iso_urls"] = []string{ 400 "http://www.packer.io", 401 "http://www.hashicorp.com", 402 } 403 404 b = Builder{} 405 warns, err = b.Prepare(config) 406 if len(warns) > 0 { 407 t.Fatalf("bad: %#v", warns) 408 } 409 if err != nil { 410 t.Errorf("should not have error: %s", err) 411 } 412 413 expected = []string{ 414 "http://www.packer.io", 415 "http://www.hashicorp.com", 416 } 417 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 418 t.Fatalf("bad: %#v", b.config.ISOUrls) 419 } 420 } 421 422 func TestBuilderPrepare_SizeNotRequiredWhenUsingExistingHarddrive(t *testing.T) { 423 var b Builder 424 config := testConfig() 425 delete(config, "iso_url") 426 delete(config, "iso_urls") 427 delete(config, "disk_size") 428 429 config["disk_size"] = 1 430 431 // Test just iso_urls set but with vhdx 432 delete(config, "iso_url") 433 config["iso_urls"] = []string{ 434 "http://www.packer.io/hdd.vhdx", 435 "http://www.hashicorp.com/dvd.iso", 436 } 437 438 b = Builder{} 439 warns, err := b.Prepare(config) 440 if len(warns) > 0 { 441 t.Fatalf("bad: %#v", warns) 442 } 443 if err != nil { 444 t.Errorf("should not have error: %s", err) 445 } 446 447 expected := []string{ 448 "http://www.packer.io/hdd.vhdx", 449 "http://www.hashicorp.com/dvd.iso", 450 } 451 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 452 t.Fatalf("bad: %#v", b.config.ISOUrls) 453 } 454 455 // Test just iso_urls set but with vhd 456 delete(config, "iso_url") 457 config["iso_urls"] = []string{ 458 "http://www.packer.io/hdd.vhd", 459 "http://www.hashicorp.com/dvd.iso", 460 } 461 462 b = Builder{} 463 warns, err = b.Prepare(config) 464 if len(warns) > 0 { 465 t.Fatalf("bad: %#v", warns) 466 } 467 if err != nil { 468 t.Errorf("should not have error: %s", err) 469 } 470 471 expected = []string{ 472 "http://www.packer.io/hdd.vhd", 473 "http://www.hashicorp.com/dvd.iso", 474 } 475 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 476 t.Fatalf("bad: %#v", b.config.ISOUrls) 477 } 478 } 479 480 func TestBuilderPrepare_SizeIsRequiredWhenNotUsingExistingHarddrive(t *testing.T) { 481 var b Builder 482 config := testConfig() 483 delete(config, "iso_url") 484 delete(config, "iso_urls") 485 delete(config, "disk_size") 486 487 config["disk_size"] = 1 488 489 // Test just iso_urls set but with vhdx 490 delete(config, "iso_url") 491 config["iso_urls"] = []string{ 492 "http://www.packer.io/os.iso", 493 "http://www.hashicorp.com/dvd.iso", 494 } 495 496 b = Builder{} 497 warns, err := b.Prepare(config) 498 if len(warns) > 0 { 499 t.Fatalf("bad: %#v", warns) 500 } 501 if err == nil { 502 t.Errorf("should have error") 503 } 504 505 expected := []string{ 506 "http://www.packer.io/os.iso", 507 "http://www.hashicorp.com/dvd.iso", 508 } 509 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 510 t.Fatalf("bad: %#v", b.config.ISOUrls) 511 } 512 } 513 514 func TestBuilderPrepare_MaximumOfSixtyFourAdditionalDisks(t *testing.T) { 515 var b Builder 516 config := testConfig() 517 518 disks := make([]string, 65) 519 for i := range disks { 520 disks[i] = strconv.Itoa(i) 521 } 522 config["disk_additional_size"] = disks 523 524 b = Builder{} 525 warns, err := b.Prepare(config) 526 if len(warns) > 0 { 527 t.Fatalf("bad: %#v", warns) 528 } 529 if err == nil { 530 t.Errorf("should have error") 531 } 532 533 } 534 535 func TestBuilderPrepare_CommConfig(t *testing.T) { 536 // Test Winrm 537 { 538 config := testConfig() 539 config["communicator"] = "winrm" 540 config["winrm_username"] = "username" 541 config["winrm_password"] = "password" 542 config["winrm_host"] = "1.2.3.4" 543 544 var b Builder 545 warns, err := b.Prepare(config) 546 if len(warns) > 0 { 547 t.Fatalf("bad: %#v", warns) 548 } 549 if err != nil { 550 t.Fatalf("should not have error: %s", err) 551 } 552 553 if b.config.Comm.WinRMUser != "username" { 554 t.Errorf("bad winrm_username: %s", b.config.Comm.WinRMUser) 555 } 556 if b.config.Comm.WinRMPassword != "password" { 557 t.Errorf("bad winrm_password: %s", b.config.Comm.WinRMPassword) 558 } 559 if host := b.config.Comm.Host(); host != "1.2.3.4" { 560 t.Errorf("bad host: %s", host) 561 } 562 } 563 564 // Test SSH 565 { 566 config := testConfig() 567 config["communicator"] = "ssh" 568 config["ssh_username"] = "username" 569 config["ssh_password"] = "password" 570 config["ssh_host"] = "1.2.3.4" 571 572 var b Builder 573 warns, err := b.Prepare(config) 574 if len(warns) > 0 { 575 t.Fatalf("bad: %#v", warns) 576 } 577 if err != nil { 578 t.Fatalf("should not have error: %s", err) 579 } 580 581 if b.config.Comm.SSHUsername != "username" { 582 t.Errorf("bad ssh_username: %s", b.config.Comm.SSHUsername) 583 } 584 if b.config.Comm.SSHPassword != "password" { 585 t.Errorf("bad ssh_password: %s", b.config.Comm.SSHPassword) 586 } 587 if host := b.config.Comm.Host(); host != "1.2.3.4" { 588 t.Errorf("bad host: %s", host) 589 } 590 } 591 592 } 593 594 func TestUserVariablesInBootCommand(t *testing.T) { 595 var b Builder 596 config := testConfig() 597 598 config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"} 599 config["boot_command"] = []string{"blah {{user `test-variable`}} blah"} 600 601 warns, err := b.Prepare(config) 602 if len(warns) > 0 { 603 t.Fatalf("bad: %#v", warns) 604 } 605 if err != nil { 606 t.Fatalf("should not have error: %s", err) 607 } 608 609 ui := packer.TestUi(t) 610 cache := &packer.FileCache{CacheDir: os.TempDir()} 611 hook := &packer.MockHook{} 612 driver := &hypervcommon.DriverMock{} 613 614 // Set up the state. 615 state := new(multistep.BasicStateBag) 616 state.Put("cache", cache) 617 state.Put("config", &b.config) 618 state.Put("driver", driver) 619 state.Put("hook", hook) 620 state.Put("http_port", uint(0)) 621 state.Put("ui", ui) 622 state.Put("vmName", "packer-foo") 623 624 step := &hypervcommon.StepTypeBootCommand{ 625 BootCommand: b.config.FlatBootCommand(), 626 SwitchName: b.config.SwitchName, 627 Ctx: b.config.ctx, 628 } 629 630 ret := step.Run(context.Background(), state) 631 if ret != multistep.ActionContinue { 632 t.Fatalf("should not have error: %#v", ret) 633 } 634 }