github.com/raghuse92/packer@v1.3.2/builder/qemu/builder_test.go (about) 1 package qemu 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "reflect" 8 "testing" 9 10 "github.com/hashicorp/packer/packer" 11 ) 12 13 var testPem = ` 14 -----BEGIN RSA PRIVATE KEY----- 15 MIIEpQIBAAKCAQEAxd4iamvrwRJvtNDGQSIbNvvIQN8imXTRWlRY62EvKov60vqu 16 hh+rDzFYAIIzlmrJopvOe0clqmi3mIP9dtkjPFrYflq52a2CF5q+BdwsJXuRHbJW 17 LmStZUwW1khSz93DhvhmK50nIaczW63u4EO/jJb3xj+wxR1Nkk9bxi3DDsYFt8SN 18 AzYx9kjlEYQ/+sI4/ATfmdV9h78SVotjScupd9KFzzi76gWq9gwyCBLRynTUWlyD 19 2UOfJRkOvhN6/jKzvYfVVwjPSfA9IMuooHdScmC4F6KBKJl/zf/zETM0XyzIDNmH 20 uOPbCiljq2WoRM+rY6ET84EO0kVXbfx8uxUsqQIDAQABAoIBAQCkPj9TF0IagbM3 21 5BSs/CKbAWS4dH/D4bPlxx4IRCNirc8GUg+MRb04Xz0tLuajdQDqeWpr6iLZ0RKV 22 BvreLF+TOdV7DNQ4XE4gSdJyCtCaTHeort/aordL3l0WgfI7mVk0L/yfN1PEG4YG 23 E9q1TYcyrB3/8d5JwIkjabxERLglCcP+geOEJp+QijbvFIaZR/n2irlKW4gSy6ko 24 9B0fgUnhkHysSg49ChHQBPQ+o5BbpuLrPDFMiTPTPhdfsvGGcyCGeqfBA56oHcSF 25 K02Fg8OM+Bd1lb48LAN9nWWY4WbwV+9bkN3Ym8hO4c3a/Dxf2N7LtAQqWZzFjvM3 26 /AaDvAgBAoGBAPLD+Xn1IYQPMB2XXCXfOuJewRY7RzoVWvMffJPDfm16O7wOiW5+ 27 2FmvxUDayk4PZy6wQMzGeGKnhcMMZTyaq2g/QtGfrvy7q1Lw2fB1VFlVblvqhoJa 28 nMJojjC4zgjBkXMHsRLeTmgUKyGs+fdFbfI6uejBnnf+eMVUMIdJ+6I9AoGBANCn 29 kWO9640dttyXURxNJ3lBr2H3dJOkmD6XS+u+LWqCSKQe691Y/fZ/ZL0Oc4Mhy7I6 30 hsy3kDQ5k2V0fkaNODQIFJvUqXw2pMewUk8hHc9403f4fe9cPrL12rQ8WlQw4yoC 31 v2B61vNczCCUDtGxlAaw8jzSRaSI5s6ax3K7enbdAoGBAJB1WYDfA2CoAQO6y9Sl 32 b07A/7kQ8SN5DbPaqrDrBdJziBQxukoMJQXJeGFNUFD/DXFU5Fp2R7C86vXT7HIR 33 v6m66zH+CYzOx/YE6EsUJms6UP9VIVF0Rg/RU7teXQwM01ZV32LQ8mswhTH20o/3 34 uqMHmxUMEhZpUMhrfq0isyApAoGAe1UxGTXfj9AqkIVYylPIq2HqGww7+jFmVEj1 35 9Wi6S6Sq72ffnzzFEPkIQL/UA4TsdHMnzsYKFPSbbXLIWUeMGyVTmTDA5c0e5XIR 36 lPhMOKCAzv8w4VUzMnEkTzkFY5JqFCD/ojW57KvDdNZPVB+VEcdxyAW6aKELXMAc 37 eHLc1nkCgYEApm/motCTPN32nINZ+Vvywbv64ZD+gtpeMNP3CLrbe1X9O+H52AXa 38 1jCoOldWR8i2bs2NVPcKZgdo6fFULqE4dBX7Te/uYEIuuZhYLNzRO1IKU/YaqsXG 39 3bfQ8hKYcSnTfE0gPtLDnqCIxTocaGLSHeG3TH9fTw+dA8FvWpUztI4= 40 -----END RSA PRIVATE KEY----- 41 ` 42 43 func testConfig() map[string]interface{} { 44 return map[string]interface{}{ 45 "iso_checksum": "foo", 46 "iso_checksum_type": "md5", 47 "iso_url": "http://www.google.com/", 48 "ssh_username": "foo", 49 packer.BuildNameConfigKey: "foo", 50 } 51 } 52 53 func TestBuilder_ImplementsBuilder(t *testing.T) { 54 var raw interface{} 55 raw = &Builder{} 56 if _, ok := raw.(packer.Builder); !ok { 57 t.Error("Builder must implement builder.") 58 } 59 } 60 61 func TestBuilderPrepare_Defaults(t *testing.T) { 62 var b Builder 63 config := testConfig() 64 warns, err := b.Prepare(config) 65 if len(warns) > 0 { 66 t.Fatalf("bad: %#v", warns) 67 } 68 if err != nil { 69 t.Fatalf("should not have error: %s", err) 70 } 71 72 if b.config.OutputDir != "output-foo" { 73 t.Errorf("bad output dir: %s", b.config.OutputDir) 74 } 75 76 if b.config.SSHHostPortMin != 2222 { 77 t.Errorf("bad min ssh host port: %d", b.config.SSHHostPortMin) 78 } 79 80 if b.config.SSHHostPortMax != 4444 { 81 t.Errorf("bad max ssh host port: %d", b.config.SSHHostPortMax) 82 } 83 84 if b.config.Comm.SSHPort != 22 { 85 t.Errorf("bad ssh port: %d", b.config.Comm.SSHPort) 86 } 87 88 if b.config.VMName != "packer-foo" { 89 t.Errorf("bad vm name: %s", b.config.VMName) 90 } 91 92 if b.config.Format != "qcow2" { 93 t.Errorf("bad format: %s", b.config.Format) 94 } 95 } 96 97 func TestBuilderPrepare_VNCBindAddress(t *testing.T) { 98 var b Builder 99 config := testConfig() 100 101 // Test a default boot_wait 102 delete(config, "vnc_bind_address") 103 warns, err := b.Prepare(config) 104 if len(warns) > 0 { 105 t.Fatalf("bad: %#v", warns) 106 } 107 if err != nil { 108 t.Fatalf("err: %s", err) 109 } 110 111 if b.config.VNCBindAddress != "127.0.0.1" { 112 t.Fatalf("bad value: %s", b.config.VNCBindAddress) 113 } 114 } 115 116 func TestBuilderPrepare_DiskCompaction(t *testing.T) { 117 var b Builder 118 config := testConfig() 119 120 // Bad 121 config["skip_compaction"] = false 122 config["disk_compression"] = true 123 config["format"] = "img" 124 warns, err := b.Prepare(config) 125 if len(warns) > 0 { 126 t.Fatalf("bad: %#v", warns) 127 } 128 if err == nil { 129 t.Fatal("should have error") 130 } 131 if b.config.SkipCompaction != true { 132 t.Fatalf("SkipCompaction should be true") 133 } 134 if b.config.DiskCompression != false { 135 t.Fatalf("DiskCompression should be false") 136 } 137 138 // Good 139 config["skip_compaction"] = false 140 config["disk_compression"] = true 141 config["format"] = "qcow2" 142 b = Builder{} 143 warns, err = b.Prepare(config) 144 if len(warns) > 0 { 145 t.Fatalf("bad: %#v", warns) 146 } 147 if err != nil { 148 t.Fatalf("should not have error: %s", err) 149 } 150 if b.config.SkipCompaction != false { 151 t.Fatalf("SkipCompaction should be false") 152 } 153 if b.config.DiskCompression != true { 154 t.Fatalf("DiskCompression should be true") 155 } 156 } 157 158 func TestBuilderPrepare_DiskSize(t *testing.T) { 159 var b Builder 160 config := testConfig() 161 162 delete(config, "disk_size") 163 warns, err := b.Prepare(config) 164 if len(warns) > 0 { 165 t.Fatalf("bad: %#v", warns) 166 } 167 if err != nil { 168 t.Fatalf("bad err: %s", err) 169 } 170 171 if b.config.DiskSize != 40960 { 172 t.Fatalf("bad size: %d", b.config.DiskSize) 173 } 174 175 config["disk_size"] = 60000 176 b = Builder{} 177 warns, err = b.Prepare(config) 178 if len(warns) > 0 { 179 t.Fatalf("bad: %#v", warns) 180 } 181 if err != nil { 182 t.Fatalf("should not have error: %s", err) 183 } 184 185 if b.config.DiskSize != 60000 { 186 t.Fatalf("bad size: %d", b.config.DiskSize) 187 } 188 } 189 190 func TestBuilderPrepare_Format(t *testing.T) { 191 var b Builder 192 config := testConfig() 193 194 // Bad 195 config["format"] = "illegal value" 196 warns, err := b.Prepare(config) 197 if len(warns) > 0 { 198 t.Fatalf("bad: %#v", warns) 199 } 200 if err == nil { 201 t.Fatal("should have error") 202 } 203 204 // Good 205 config["format"] = "qcow2" 206 b = Builder{} 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("should not have error: %s", err) 213 } 214 215 // Good 216 config["format"] = "raw" 217 b = Builder{} 218 warns, err = b.Prepare(config) 219 if len(warns) > 0 { 220 t.Fatalf("bad: %#v", warns) 221 } 222 if err != nil { 223 t.Fatalf("should not have error: %s", err) 224 } 225 } 226 227 func TestBuilderPrepare_UseBackingFile(t *testing.T) { 228 var b Builder 229 config := testConfig() 230 231 config["use_backing_file"] = true 232 233 // Bad: iso_url is not a disk_image 234 config["disk_image"] = false 235 config["format"] = "qcow2" 236 b = Builder{} 237 warns, err := b.Prepare(config) 238 if len(warns) > 0 { 239 t.Fatalf("bad: %#v", warns) 240 } 241 if err == nil { 242 t.Fatal("should have error") 243 } 244 245 // Bad: format is not 'qcow2' 246 config["disk_image"] = true 247 config["format"] = "raw" 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 // Good: iso_url is a disk image and format is 'qcow2' 258 config["disk_image"] = true 259 config["format"] = "qcow2" 260 b = Builder{} 261 warns, err = b.Prepare(config) 262 if len(warns) > 0 { 263 t.Fatalf("bad: %#v", warns) 264 } 265 if err != nil { 266 t.Fatalf("should not have error: %s", err) 267 } 268 } 269 270 func TestBuilderPrepare_FloppyFiles(t *testing.T) { 271 var b Builder 272 config := testConfig() 273 274 delete(config, "floppy_files") 275 warns, err := b.Prepare(config) 276 if len(warns) > 0 { 277 t.Fatalf("bad: %#v", warns) 278 } 279 if err != nil { 280 t.Fatalf("bad err: %s", err) 281 } 282 283 if len(b.config.FloppyFiles) != 0 { 284 t.Fatalf("bad: %#v", b.config.FloppyFiles) 285 } 286 287 floppies_path := "../../common/test-fixtures/floppies" 288 config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 289 b = Builder{} 290 warns, err = b.Prepare(config) 291 if len(warns) > 0 { 292 t.Fatalf("bad: %#v", warns) 293 } 294 if err != nil { 295 t.Fatalf("should not have error: %s", err) 296 } 297 298 expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 299 if !reflect.DeepEqual(b.config.FloppyFiles, expected) { 300 t.Fatalf("bad: %#v", b.config.FloppyFiles) 301 } 302 } 303 304 func TestBuilderPrepare_InvalidFloppies(t *testing.T) { 305 var b Builder 306 config := testConfig() 307 config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} 308 b = Builder{} 309 _, errs := b.Prepare(config) 310 if errs == nil { 311 t.Fatalf("Nonexistent floppies should trigger multierror") 312 } 313 314 if len(errs.(*packer.MultiError).Errors) != 2 { 315 t.Fatalf("Multierror should work and report 2 errors") 316 } 317 } 318 319 func TestBuilderPrepare_InvalidKey(t *testing.T) { 320 var b Builder 321 config := testConfig() 322 323 // Add a random key 324 config["i_should_not_be_valid"] = true 325 warns, err := b.Prepare(config) 326 if len(warns) > 0 { 327 t.Fatalf("bad: %#v", warns) 328 } 329 if err == nil { 330 t.Fatal("should have error") 331 } 332 } 333 334 func TestBuilderPrepare_OutputDir(t *testing.T) { 335 var b Builder 336 config := testConfig() 337 338 // Test with existing dir 339 dir, err := ioutil.TempDir("", "packer") 340 if err != nil { 341 t.Fatalf("err: %s", err) 342 } 343 defer os.RemoveAll(dir) 344 345 config["output_directory"] = dir 346 b = Builder{} 347 warns, err := b.Prepare(config) 348 if len(warns) > 0 { 349 t.Fatalf("bad: %#v", warns) 350 } 351 if err == nil { 352 t.Fatal("should have error") 353 } 354 355 // Test with a good one 356 config["output_directory"] = "i-hope-i-dont-exist" 357 b = Builder{} 358 warns, err = b.Prepare(config) 359 if len(warns) > 0 { 360 t.Fatalf("bad: %#v", warns) 361 } 362 if err != nil { 363 t.Fatalf("should not have error: %s", err) 364 } 365 } 366 367 func TestBuilderPrepare_ShutdownTimeout(t *testing.T) { 368 var b Builder 369 config := testConfig() 370 371 // Test with a bad value 372 config["shutdown_timeout"] = "this is not good" 373 warns, err := b.Prepare(config) 374 if len(warns) > 0 { 375 t.Fatalf("bad: %#v", warns) 376 } 377 if err == nil { 378 t.Fatal("should have error") 379 } 380 381 // Test with a good one 382 config["shutdown_timeout"] = "5s" 383 b = Builder{} 384 warns, err = b.Prepare(config) 385 if len(warns) > 0 { 386 t.Fatalf("bad: %#v", warns) 387 } 388 if err != nil { 389 t.Fatalf("should not have error: %s", err) 390 } 391 } 392 393 func TestBuilderPrepare_SSHHostPort(t *testing.T) { 394 var b Builder 395 config := testConfig() 396 397 // Bad 398 config["ssh_host_port_min"] = 1000 399 config["ssh_host_port_max"] = 500 400 b = Builder{} 401 warns, err := b.Prepare(config) 402 if len(warns) > 0 { 403 t.Fatalf("bad: %#v", warns) 404 } 405 if err == nil { 406 t.Fatal("should have error") 407 } 408 409 // Bad 410 config["ssh_host_port_min"] = -500 411 b = Builder{} 412 warns, err = b.Prepare(config) 413 if len(warns) > 0 { 414 t.Fatalf("bad: %#v", warns) 415 } 416 if err == nil { 417 t.Fatal("should have error") 418 } 419 420 // Good 421 config["ssh_host_port_min"] = 500 422 config["ssh_host_port_max"] = 1000 423 b = Builder{} 424 warns, err = b.Prepare(config) 425 if len(warns) > 0 { 426 t.Fatalf("bad: %#v", warns) 427 } 428 if err != nil { 429 t.Fatalf("should not have error: %s", err) 430 } 431 } 432 433 func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { 434 var b Builder 435 config := testConfig() 436 437 config["ssh_private_key_file"] = "" 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.Fatalf("should not have error: %s", err) 445 } 446 447 config["ssh_private_key_file"] = "/i/dont/exist" 448 b = Builder{} 449 warns, err = b.Prepare(config) 450 if len(warns) > 0 { 451 t.Fatalf("bad: %#v", warns) 452 } 453 if err == nil { 454 t.Fatal("should have error") 455 } 456 457 // Test bad contents 458 tf, err := ioutil.TempFile("", "packer") 459 if err != nil { 460 t.Fatalf("err: %s", err) 461 } 462 defer os.Remove(tf.Name()) 463 defer tf.Close() 464 465 if _, err := tf.Write([]byte("HELLO!")); err != nil { 466 t.Fatalf("err: %s", err) 467 } 468 469 config["ssh_private_key_file"] = tf.Name() 470 b = Builder{} 471 warns, err = b.Prepare(config) 472 if len(warns) > 0 { 473 t.Fatalf("bad: %#v", warns) 474 } 475 if err == nil { 476 t.Fatal("should have error") 477 } 478 479 // Test good contents 480 tf.Seek(0, 0) 481 tf.Truncate(0) 482 tf.Write([]byte(testPem)) 483 config["ssh_private_key_file"] = tf.Name() 484 b = Builder{} 485 warns, err = b.Prepare(config) 486 if len(warns) > 0 { 487 t.Fatalf("bad: %#v", warns) 488 } 489 if err != nil { 490 t.Fatalf("err: %s", err) 491 } 492 } 493 494 func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { 495 var b Builder 496 config := testConfig() 497 498 // Test a default boot_wait 499 delete(config, "ssh_wait_timeout") 500 warns, err := b.Prepare(config) 501 if len(warns) > 0 { 502 t.Fatalf("bad: %#v", warns) 503 } 504 if err != nil { 505 t.Fatalf("err: %s", err) 506 } 507 508 // Test with a bad value 509 config["ssh_wait_timeout"] = "this is not good" 510 b = Builder{} 511 warns, err = b.Prepare(config) 512 if len(warns) > 0 { 513 t.Fatalf("bad: %#v", warns) 514 } 515 if err == nil { 516 t.Fatal("should have error") 517 } 518 519 // Test with a good one 520 config["ssh_wait_timeout"] = "5s" 521 b = Builder{} 522 warns, err = b.Prepare(config) 523 if len(warns) > 0 { 524 t.Fatalf("bad: %#v", warns) 525 } 526 if err != nil { 527 t.Fatalf("should not have error: %s", err) 528 } 529 } 530 531 func TestBuilderPrepare_QemuArgs(t *testing.T) { 532 var b Builder 533 config := testConfig() 534 535 // Test with empty 536 delete(config, "qemuargs") 537 warns, err := b.Prepare(config) 538 if len(warns) > 0 { 539 t.Fatalf("bad: %#v", warns) 540 } 541 if err != nil { 542 t.Fatalf("err: %s", err) 543 } 544 545 if !reflect.DeepEqual(b.config.QemuArgs, [][]string{}) { 546 t.Fatalf("bad: %#v", b.config.QemuArgs) 547 } 548 549 // Test with a good one 550 config["qemuargs"] = [][]interface{}{ 551 {"foo", "bar", "baz"}, 552 } 553 554 b = Builder{} 555 warns, err = b.Prepare(config) 556 if len(warns) > 0 { 557 t.Fatalf("bad: %#v", warns) 558 } 559 if err != nil { 560 t.Fatalf("should not have error: %s", err) 561 } 562 563 expected := [][]string{ 564 {"foo", "bar", "baz"}, 565 } 566 567 if !reflect.DeepEqual(b.config.QemuArgs, expected) { 568 t.Fatalf("bad: %#v", b.config.QemuArgs) 569 } 570 }