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