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