github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/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_FloppyFiles(t *testing.T) { 228 var b Builder 229 config := testConfig() 230 231 delete(config, "floppy_files") 232 warns, err := b.Prepare(config) 233 if len(warns) > 0 { 234 t.Fatalf("bad: %#v", warns) 235 } 236 if err != nil { 237 t.Fatalf("bad err: %s", err) 238 } 239 240 if len(b.config.FloppyFiles) != 0 { 241 t.Fatalf("bad: %#v", b.config.FloppyFiles) 242 } 243 244 floppies_path := "../../common/test-fixtures/floppies" 245 config["floppy_files"] = []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 246 b = Builder{} 247 warns, err = b.Prepare(config) 248 if len(warns) > 0 { 249 t.Fatalf("bad: %#v", warns) 250 } 251 if err != nil { 252 t.Fatalf("should not have error: %s", err) 253 } 254 255 expected := []string{fmt.Sprintf("%s/bar.bat", floppies_path), fmt.Sprintf("%s/foo.ps1", floppies_path)} 256 if !reflect.DeepEqual(b.config.FloppyFiles, expected) { 257 t.Fatalf("bad: %#v", b.config.FloppyFiles) 258 } 259 } 260 261 func TestBuilderPrepare_InvalidFloppies(t *testing.T) { 262 var b Builder 263 config := testConfig() 264 config["floppy_files"] = []string{"nonexistent.bat", "nonexistent.ps1"} 265 b = Builder{} 266 _, errs := b.Prepare(config) 267 if errs == nil { 268 t.Fatalf("Nonexistent floppies should trigger multierror") 269 } 270 271 if len(errs.(*packer.MultiError).Errors) != 2 { 272 t.Fatalf("Multierror should work and report 2 errors") 273 } 274 } 275 276 func TestBuilderPrepare_InvalidKey(t *testing.T) { 277 var b Builder 278 config := testConfig() 279 280 // Add a random key 281 config["i_should_not_be_valid"] = true 282 warns, err := b.Prepare(config) 283 if len(warns) > 0 { 284 t.Fatalf("bad: %#v", warns) 285 } 286 if err == nil { 287 t.Fatal("should have error") 288 } 289 } 290 291 func TestBuilderPrepare_OutputDir(t *testing.T) { 292 var b Builder 293 config := testConfig() 294 295 // Test with existing dir 296 dir, err := ioutil.TempDir("", "packer") 297 if err != nil { 298 t.Fatalf("err: %s", err) 299 } 300 defer os.RemoveAll(dir) 301 302 config["output_directory"] = dir 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.Fatal("should have error") 310 } 311 312 // Test with a good one 313 config["output_directory"] = "i-hope-i-dont-exist" 314 b = Builder{} 315 warns, err = b.Prepare(config) 316 if len(warns) > 0 { 317 t.Fatalf("bad: %#v", warns) 318 } 319 if err != nil { 320 t.Fatalf("should not have error: %s", err) 321 } 322 } 323 324 func TestBuilderPrepare_ShutdownTimeout(t *testing.T) { 325 var b Builder 326 config := testConfig() 327 328 // Test with a bad value 329 config["shutdown_timeout"] = "this is not good" 330 warns, err := b.Prepare(config) 331 if len(warns) > 0 { 332 t.Fatalf("bad: %#v", warns) 333 } 334 if err == nil { 335 t.Fatal("should have error") 336 } 337 338 // Test with a good one 339 config["shutdown_timeout"] = "5s" 340 b = Builder{} 341 warns, err = b.Prepare(config) 342 if len(warns) > 0 { 343 t.Fatalf("bad: %#v", warns) 344 } 345 if err != nil { 346 t.Fatalf("should not have error: %s", err) 347 } 348 } 349 350 func TestBuilderPrepare_SSHHostPort(t *testing.T) { 351 var b Builder 352 config := testConfig() 353 354 // Bad 355 config["ssh_host_port_min"] = 1000 356 config["ssh_host_port_max"] = 500 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.Fatal("should have error") 364 } 365 366 // Bad 367 config["ssh_host_port_min"] = -500 368 b = Builder{} 369 warns, err = b.Prepare(config) 370 if len(warns) > 0 { 371 t.Fatalf("bad: %#v", warns) 372 } 373 if err == nil { 374 t.Fatal("should have error") 375 } 376 377 // Good 378 config["ssh_host_port_min"] = 500 379 config["ssh_host_port_max"] = 1000 380 b = Builder{} 381 warns, err = b.Prepare(config) 382 if len(warns) > 0 { 383 t.Fatalf("bad: %#v", warns) 384 } 385 if err != nil { 386 t.Fatalf("should not have error: %s", err) 387 } 388 } 389 390 func TestBuilderPrepare_SSHPrivateKey(t *testing.T) { 391 var b Builder 392 config := testConfig() 393 394 config["ssh_private_key_file"] = "" 395 b = Builder{} 396 warns, err := b.Prepare(config) 397 if len(warns) > 0 { 398 t.Fatalf("bad: %#v", warns) 399 } 400 if err != nil { 401 t.Fatalf("should not have error: %s", err) 402 } 403 404 config["ssh_private_key_file"] = "/i/dont/exist" 405 b = Builder{} 406 warns, err = b.Prepare(config) 407 if len(warns) > 0 { 408 t.Fatalf("bad: %#v", warns) 409 } 410 if err == nil { 411 t.Fatal("should have error") 412 } 413 414 // Test bad contents 415 tf, err := ioutil.TempFile("", "packer") 416 if err != nil { 417 t.Fatalf("err: %s", err) 418 } 419 defer os.Remove(tf.Name()) 420 defer tf.Close() 421 422 if _, err := tf.Write([]byte("HELLO!")); err != nil { 423 t.Fatalf("err: %s", err) 424 } 425 426 config["ssh_private_key_file"] = tf.Name() 427 b = Builder{} 428 warns, err = b.Prepare(config) 429 if len(warns) > 0 { 430 t.Fatalf("bad: %#v", warns) 431 } 432 if err == nil { 433 t.Fatal("should have error") 434 } 435 436 // Test good contents 437 tf.Seek(0, 0) 438 tf.Truncate(0) 439 tf.Write([]byte(testPem)) 440 config["ssh_private_key_file"] = tf.Name() 441 b = Builder{} 442 warns, err = b.Prepare(config) 443 if len(warns) > 0 { 444 t.Fatalf("bad: %#v", warns) 445 } 446 if err != nil { 447 t.Fatalf("err: %s", err) 448 } 449 } 450 451 func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { 452 var b Builder 453 config := testConfig() 454 455 // Test a default boot_wait 456 delete(config, "ssh_wait_timeout") 457 warns, err := b.Prepare(config) 458 if len(warns) > 0 { 459 t.Fatalf("bad: %#v", warns) 460 } 461 if err != nil { 462 t.Fatalf("err: %s", err) 463 } 464 465 // Test with a bad value 466 config["ssh_wait_timeout"] = "this is not good" 467 b = Builder{} 468 warns, err = b.Prepare(config) 469 if len(warns) > 0 { 470 t.Fatalf("bad: %#v", warns) 471 } 472 if err == nil { 473 t.Fatal("should have error") 474 } 475 476 // Test with a good one 477 config["ssh_wait_timeout"] = "5s" 478 b = Builder{} 479 warns, err = b.Prepare(config) 480 if len(warns) > 0 { 481 t.Fatalf("bad: %#v", warns) 482 } 483 if err != nil { 484 t.Fatalf("should not have error: %s", err) 485 } 486 } 487 488 func TestBuilderPrepare_QemuArgs(t *testing.T) { 489 var b Builder 490 config := testConfig() 491 492 // Test with empty 493 delete(config, "qemuargs") 494 warns, err := b.Prepare(config) 495 if len(warns) > 0 { 496 t.Fatalf("bad: %#v", warns) 497 } 498 if err != nil { 499 t.Fatalf("err: %s", err) 500 } 501 502 if !reflect.DeepEqual(b.config.QemuArgs, [][]string{}) { 503 t.Fatalf("bad: %#v", b.config.QemuArgs) 504 } 505 506 // Test with a good one 507 config["qemuargs"] = [][]interface{}{ 508 {"foo", "bar", "baz"}, 509 } 510 511 b = Builder{} 512 warns, err = b.Prepare(config) 513 if len(warns) > 0 { 514 t.Fatalf("bad: %#v", warns) 515 } 516 if err != nil { 517 t.Fatalf("should not have error: %s", err) 518 } 519 520 expected := [][]string{ 521 {"foo", "bar", "baz"}, 522 } 523 524 if !reflect.DeepEqual(b.config.QemuArgs, expected) { 525 t.Fatalf("bad: %#v", b.config.QemuArgs) 526 } 527 }