github.phpd.cn/hashicorp/packer@v1.3.2/builder/hyperv/vmcx/builder_test.go (about) 1 package vmcx 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "testing" 8 9 "io/ioutil" 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 "switch_name": "switch", // to avoid using builder.detectSwitchName which can lock down in travis-ci 25 "ram_size": 64, 26 "guest_additions_mode": "none", 27 "clone_from_vmcx_path": "generated", 28 packer.BuildNameConfigKey: "foo", 29 } 30 } 31 32 func TestBuilder_ImplementsBuilder(t *testing.T) { 33 var raw interface{} 34 raw = &Builder{} 35 if _, ok := raw.(packer.Builder); !ok { 36 t.Error("Builder must implement builder.") 37 } 38 } 39 40 func TestBuilderPrepare_Defaults(t *testing.T) { 41 var b Builder 42 config := testConfig() 43 44 //Create vmcx folder 45 td, err := ioutil.TempDir("", "packer") 46 if err != nil { 47 t.Fatalf("err: %s", err) 48 } 49 defer os.RemoveAll(td) 50 config["clone_from_vmcx_path"] = td 51 52 warns, err := b.Prepare(config) 53 if len(warns) > 0 { 54 t.Fatalf("bad: %#v", warns) 55 } 56 if err != nil { 57 t.Fatalf("should not have error: %s", err) 58 } 59 60 if b.config.VMName != "packer-foo" { 61 t.Errorf("bad vm name: %s", b.config.VMName) 62 } 63 } 64 65 func TestBuilderPrepare_InvalidKey(t *testing.T) { 66 var b Builder 67 config := testConfig() 68 69 //Create vmcx folder 70 td, err := ioutil.TempDir("", "packer") 71 if err != nil { 72 t.Fatalf("err: %s", err) 73 } 74 defer os.RemoveAll(td) 75 config["clone_from_vmcx_path"] = td 76 77 // Add a random key 78 config["i_should_not_be_valid"] = true 79 warns, err := b.Prepare(config) 80 if len(warns) > 0 { 81 t.Fatalf("bad: %#v", warns) 82 } 83 if err == nil { 84 t.Fatal("should have error") 85 } 86 } 87 88 func TestBuilderPrepare_CloneFromExistingMachineOrImportFromExportedMachineSettingsRequired(t *testing.T) { 89 var b Builder 90 config := testConfig() 91 delete(config, "clone_from_vmcx_path") 92 93 warns, err := b.Prepare(config) 94 if len(warns) > 0 { 95 t.Fatalf("bad: %#v", warns) 96 } 97 if err == nil { 98 t.Fatal("should have error") 99 } 100 } 101 102 func TestBuilderPrepare_ExportedMachinePathDoesNotExist(t *testing.T) { 103 var b Builder 104 config := testConfig() 105 106 //Create vmcx folder 107 td, err := ioutil.TempDir("", "packer") 108 if err != nil { 109 t.Fatalf("err: %s", err) 110 } 111 112 //Delete the folder immediately 113 os.RemoveAll(td) 114 115 config["clone_from_vmcx_path"] = td 116 117 warns, err := b.Prepare(config) 118 if len(warns) > 0 { 119 t.Fatalf("bad: %#v", warns) 120 } 121 if err == nil { 122 t.Fatal("should have error") 123 } 124 } 125 126 func TestBuilderPrepare_ExportedMachinePathExists(t *testing.T) { 127 var b Builder 128 config := testConfig() 129 130 //Create vmcx folder 131 td, err := ioutil.TempDir("", "packer") 132 if err != nil { 133 t.Fatalf("err: %s", err) 134 } 135 136 //Only delete afterwards 137 defer os.RemoveAll(td) 138 139 config["clone_from_vmcx_path"] = td 140 141 warns, err := b.Prepare(config) 142 if len(warns) > 0 { 143 t.Fatalf("bad: %#v", warns) 144 } 145 if err != nil { 146 t.Fatalf("should not have error: %s", err) 147 } 148 } 149 150 func disabled_TestBuilderPrepare_CloneFromVmSettingUsedSoNoCloneFromVmcxPathRequired(t *testing.T) { 151 var b Builder 152 config := testConfig() 153 delete(config, "clone_from_vmcx_path") 154 155 config["clone_from_vm_name"] = "test_machine_name_that_does_not_exist" 156 157 warns, err := b.Prepare(config) 158 if len(warns) > 0 { 159 t.Fatalf("bad: %#v", warns) 160 } 161 162 if err == nil { 163 t.Fatal("should have error") 164 } else { 165 errorMessage := err.Error() 166 if errorMessage != "1 error(s) occurred:\n\n* Virtual machine 'test_machine_name_that_does_not_exist' "+ 167 "to clone from does not exist." { 168 t.Fatalf("should not have error: %s", err) 169 } 170 } 171 } 172 173 func TestBuilderPrepare_ISOChecksum(t *testing.T) { 174 var b Builder 175 config := testConfig() 176 177 //Create vmcx folder 178 td, err := ioutil.TempDir("", "packer") 179 if err != nil { 180 t.Fatalf("err: %s", err) 181 } 182 defer os.RemoveAll(td) 183 config["clone_from_vmcx_path"] = td 184 185 // Test bad 186 config["iso_checksum"] = "" 187 warns, err := b.Prepare(config) 188 if len(warns) > 0 { 189 t.Fatalf("bad: %#v", warns) 190 } 191 if err == nil { 192 t.Fatal("should have error") 193 } 194 195 // Test good 196 config["iso_checksum"] = "FOo" 197 b = Builder{} 198 warns, err = b.Prepare(config) 199 if len(warns) > 0 { 200 t.Fatalf("bad: %#v", warns) 201 } 202 if err != nil { 203 t.Fatalf("should not have error: %s", err) 204 } 205 206 if b.config.ISOChecksum != "foo" { 207 t.Fatalf("should've lowercased: %s", b.config.ISOChecksum) 208 } 209 } 210 211 func TestBuilderPrepare_ISOChecksumType(t *testing.T) { 212 var b Builder 213 config := testConfig() 214 215 //Create vmcx folder 216 td, err := ioutil.TempDir("", "packer") 217 if err != nil { 218 t.Fatalf("err: %s", err) 219 } 220 defer os.RemoveAll(td) 221 config["clone_from_vmcx_path"] = td 222 223 // Test bad 224 config["iso_checksum_type"] = "" 225 warns, err := b.Prepare(config) 226 if len(warns) > 0 { 227 t.Fatalf("bad: %#v", warns) 228 } 229 if err == nil { 230 t.Fatal("should have error") 231 } 232 233 // Test good 234 config["iso_checksum_type"] = "mD5" 235 b = Builder{} 236 warns, err = b.Prepare(config) 237 if len(warns) > 0 { 238 t.Fatalf("bad: %#v", warns) 239 } 240 if err != nil { 241 t.Fatalf("should not have error: %s", err) 242 } 243 244 if b.config.ISOChecksumType != "md5" { 245 t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType) 246 } 247 248 // Test unknown 249 config["iso_checksum_type"] = "fake" 250 b = Builder{} 251 warns, err = b.Prepare(config) 252 if len(warns) > 0 { 253 t.Fatalf("bad: %#v", warns) 254 } 255 if err == nil { 256 t.Fatal("should have error") 257 } 258 259 // Test none 260 config["iso_checksum_type"] = "none" 261 b = Builder{} 262 warns, err = b.Prepare(config) 263 if len(warns) == 0 { 264 t.Fatalf("bad: %#v", warns) 265 } 266 if err != nil { 267 t.Fatalf("should not have error: %s", err) 268 } 269 270 if b.config.ISOChecksumType != "none" { 271 t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType) 272 } 273 } 274 275 func TestBuilderPrepare_ISOUrl(t *testing.T) { 276 var b Builder 277 config := testConfig() 278 279 //Create vmcx folder 280 td, err := ioutil.TempDir("", "packer") 281 if err != nil { 282 t.Fatalf("err: %s", err) 283 } 284 defer os.RemoveAll(td) 285 config["clone_from_vmcx_path"] = td 286 287 delete(config, "iso_url") 288 delete(config, "iso_urls") 289 290 // Test both empty (should be allowed, as we cloning a vm so we probably don't need an ISO file) 291 config["iso_url"] = "" 292 b = Builder{} 293 warns, err := b.Prepare(config) 294 if len(warns) > 0 { 295 t.Fatalf("bad: %#v", warns) 296 } 297 if err != nil { 298 t.Fatal("should not have an error") 299 } 300 301 // Test iso_url set 302 config["iso_url"] = "http://www.packer.io" 303 b = Builder{} 304 warns, err = b.Prepare(config) 305 if len(warns) > 0 { 306 t.Fatalf("bad: %#v", warns) 307 } 308 if err != nil { 309 t.Errorf("should not have error: %s", err) 310 } 311 312 expected := []string{"http://www.packer.io"} 313 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 314 t.Fatalf("bad: %#v", b.config.ISOUrls) 315 } 316 317 // Test both set 318 config["iso_url"] = "http://www.packer.io" 319 config["iso_urls"] = []string{"http://www.packer.io"} 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 just iso_urls set 330 delete(config, "iso_url") 331 config["iso_urls"] = []string{ 332 "http://www.packer.io", 333 "http://www.hashicorp.com", 334 } 335 336 b = Builder{} 337 warns, err = b.Prepare(config) 338 if len(warns) > 0 { 339 t.Fatalf("bad: %#v", warns) 340 } 341 if err != nil { 342 t.Errorf("should not have error: %s", err) 343 } 344 345 expected = []string{ 346 "http://www.packer.io", 347 "http://www.hashicorp.com", 348 } 349 if !reflect.DeepEqual(b.config.ISOUrls, expected) { 350 t.Fatalf("bad: %#v", b.config.ISOUrls) 351 } 352 } 353 354 func TestBuilderPrepare_FloppyFiles(t *testing.T) { 355 var b Builder 356 config := testConfig() 357 358 //Create vmcx folder 359 td, err := ioutil.TempDir("", "packer") 360 if err != nil { 361 t.Fatalf("err: %s", err) 362 } 363 defer os.RemoveAll(td) 364 config["clone_from_vmcx_path"] = td 365 366 delete(config, "floppy_files") 367 warns, err := b.Prepare(config) 368 if len(warns) > 0 { 369 t.Fatalf("bad: %#v", warns) 370 } 371 if err != nil { 372 t.Fatalf("bad err: %s", err) 373 } 374 375 if len(b.config.FloppyFiles) != 0 { 376 t.Fatalf("bad: %#v", b.config.FloppyFiles) 377 } 378 379 floppies_path := "../../../common/test-fixtures/floppies" 380 config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 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.Fatalf("should not have error: %s", err) 388 } 389 390 expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 391 if !reflect.DeepEqual(b.config.FloppyFiles, expected) { 392 t.Fatalf("bad: %#v", b.config.FloppyFiles) 393 } 394 } 395 396 func TestBuilderPrepare_InvalidFloppies(t *testing.T) { 397 var b Builder 398 config := testConfig() 399 400 //Create vmcx folder 401 td, err := ioutil.TempDir("", "packer") 402 if err != nil { 403 t.Fatalf("err: %s", err) 404 } 405 defer os.RemoveAll(td) 406 config["clone_from_vmcx_path"] = td 407 408 config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} 409 b = Builder{} 410 _, errs := b.Prepare(config) 411 if errs == nil { 412 t.Fatalf("Nonexistent floppies should trigger multierror") 413 } 414 415 if len(errs.(*packer.MultiError).Errors) != 2 { 416 t.Fatalf("Multierror should work and report 2 errors") 417 } 418 } 419 420 func TestBuilderPrepare_CommConfig(t *testing.T) { 421 // Test Winrm 422 { 423 config := testConfig() 424 425 //Create vmcx folder 426 td, err := ioutil.TempDir("", "packer") 427 if err != nil { 428 t.Fatalf("err: %s", err) 429 } 430 defer os.RemoveAll(td) 431 config["clone_from_vmcx_path"] = td 432 433 config["communicator"] = "winrm" 434 config["winrm_username"] = "username" 435 config["winrm_password"] = "password" 436 config["winrm_host"] = "1.2.3.4" 437 438 var 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.Fatalf("should not have error: %s", err) 445 } 446 447 if b.config.Comm.WinRMUser != "username" { 448 t.Errorf("bad winrm_username: %s", b.config.Comm.WinRMUser) 449 } 450 if b.config.Comm.WinRMPassword != "password" { 451 t.Errorf("bad winrm_password: %s", b.config.Comm.WinRMPassword) 452 } 453 if host := b.config.Comm.Host(); host != "1.2.3.4" { 454 t.Errorf("bad host: %s", host) 455 } 456 } 457 458 // Test SSH 459 { 460 config := testConfig() 461 462 //Create vmcx folder 463 td, err := ioutil.TempDir("", "packer") 464 if err != nil { 465 t.Fatalf("err: %s", err) 466 } 467 defer os.RemoveAll(td) 468 config["clone_from_vmcx_path"] = td 469 470 config["communicator"] = "ssh" 471 config["ssh_username"] = "username" 472 config["ssh_password"] = "password" 473 config["ssh_host"] = "1.2.3.4" 474 475 var b Builder 476 warns, err := b.Prepare(config) 477 if len(warns) > 0 { 478 t.Fatalf("bad: %#v", warns) 479 } 480 if err != nil { 481 t.Fatalf("should not have error: %s", err) 482 } 483 484 if b.config.Comm.SSHUsername != "username" { 485 t.Errorf("bad ssh_username: %s", b.config.Comm.SSHUsername) 486 } 487 if b.config.Comm.SSHPassword != "password" { 488 t.Errorf("bad ssh_password: %s", b.config.Comm.SSHPassword) 489 } 490 if host := b.config.Comm.Host(); host != "1.2.3.4" { 491 t.Errorf("bad host: %s", host) 492 } 493 } 494 } 495 496 func TestUserVariablesInBootCommand(t *testing.T) { 497 var b Builder 498 config := testConfig() 499 500 //Create vmcx folder 501 td, err := ioutil.TempDir("", "packer") 502 if err != nil { 503 t.Fatalf("err: %s", err) 504 } 505 defer os.RemoveAll(td) 506 config["clone_from_vmcx_path"] = td 507 508 config[packer.UserVariablesConfigKey] = map[string]string{"test-variable": "test"} 509 config["boot_command"] = []string{"blah {{user `test-variable`}} blah"} 510 511 warns, err := b.Prepare(config) 512 if len(warns) > 0 { 513 t.Fatalf("bad: %#v", warns) 514 } 515 if err != nil { 516 t.Fatalf("should not have error: %s", err) 517 } 518 519 ui := packer.TestUi(t) 520 cache := &packer.FileCache{CacheDir: os.TempDir()} 521 hook := &packer.MockHook{} 522 driver := &hypervcommon.DriverMock{} 523 524 // Set up the state. 525 state := new(multistep.BasicStateBag) 526 state.Put("cache", cache) 527 state.Put("config", &b.config) 528 state.Put("driver", driver) 529 state.Put("hook", hook) 530 state.Put("http_port", uint(0)) 531 state.Put("ui", ui) 532 state.Put("vmName", "packer-foo") 533 534 step := &hypervcommon.StepTypeBootCommand{ 535 BootCommand: b.config.FlatBootCommand(), 536 SwitchName: b.config.SwitchName, 537 Ctx: b.config.ctx, 538 } 539 540 ret := step.Run(context.Background(), state) 541 if ret != multistep.ActionContinue { 542 t.Fatalf("should not have error: %#v", ret) 543 } 544 }