github.com/homburg/packer@v0.6.1-0.20140528012651-1dcaf1716848/packer/template_test.go (about) 1 package packer 2 3 import ( 4 "io/ioutil" 5 "os" 6 "reflect" 7 "sort" 8 "testing" 9 "time" 10 ) 11 12 func testTemplateComponentFinder() *ComponentFinder { 13 builder := new(MockBuilder) 14 pp := new(TestPostProcessor) 15 provisioner := &MockProvisioner{} 16 17 builderMap := map[string]Builder{ 18 "test-builder": builder, 19 } 20 21 ppMap := map[string]PostProcessor{ 22 "test-pp": pp, 23 } 24 25 provisionerMap := map[string]Provisioner{ 26 "test-prov": provisioner, 27 } 28 29 builderFactory := func(n string) (Builder, error) { return builderMap[n], nil } 30 ppFactory := func(n string) (PostProcessor, error) { return ppMap[n], nil } 31 provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil } 32 return &ComponentFinder{ 33 Builder: builderFactory, 34 PostProcessor: ppFactory, 35 Provisioner: provFactory, 36 } 37 } 38 39 func TestParseTemplateFile_basic(t *testing.T) { 40 data := ` 41 { 42 "builders": [{"type": "something"}] 43 } 44 ` 45 46 tf, err := ioutil.TempFile("", "packer") 47 if err != nil { 48 t.Fatalf("err: %s", err) 49 } 50 tf.Write([]byte(data)) 51 tf.Close() 52 53 result, err := ParseTemplateFile(tf.Name(), nil) 54 if err != nil { 55 t.Fatalf("err: %s", err) 56 } 57 58 if len(result.Builders) != 1 { 59 t.Fatalf("bad: %#v", result.Builders) 60 } 61 } 62 63 func TestParseTemplateFile_minPackerVersionBad(t *testing.T) { 64 data := ` 65 { 66 "min_packer_version": "27.0.0", 67 "builders": [{"type": "something"}] 68 } 69 ` 70 71 tf, err := ioutil.TempFile("", "packer") 72 if err != nil { 73 t.Fatalf("err: %s", err) 74 } 75 tf.Write([]byte(data)) 76 tf.Close() 77 78 _, err = ParseTemplateFile(tf.Name(), nil) 79 if err == nil { 80 t.Fatal("expects error") 81 } 82 } 83 84 func TestParseTemplateFile_minPackerVersionFormat(t *testing.T) { 85 data := ` 86 { 87 "min_packer_version": "NOPE NOPE NOPE", 88 "builders": [{"type": "something"}] 89 } 90 ` 91 92 tf, err := ioutil.TempFile("", "packer") 93 if err != nil { 94 t.Fatalf("err: %s", err) 95 } 96 tf.Write([]byte(data)) 97 tf.Close() 98 99 _, err = ParseTemplateFile(tf.Name(), nil) 100 if err == nil { 101 t.Fatal("expects error") 102 } 103 } 104 105 func TestParseTemplateFile_minPackerVersionGood(t *testing.T) { 106 data := ` 107 { 108 "min_packer_version": "0.1", 109 "builders": [{"type": "something"}] 110 } 111 ` 112 113 tf, err := ioutil.TempFile("", "packer") 114 if err != nil { 115 t.Fatalf("err: %s", err) 116 } 117 tf.Write([]byte(data)) 118 tf.Close() 119 120 _, err = ParseTemplateFile(tf.Name(), nil) 121 if err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 } 125 126 func TestParseTemplateFile_stdin(t *testing.T) { 127 data := ` 128 { 129 "builders": [{"type": "something"}] 130 } 131 ` 132 133 tf, err := ioutil.TempFile("", "packer") 134 if err != nil { 135 t.Fatalf("err: %s", err) 136 } 137 defer tf.Close() 138 tf.Write([]byte(data)) 139 140 // Sync and seek to the beginning so that we can re-read the contents 141 tf.Sync() 142 tf.Seek(0, 0) 143 144 // Set stdin to something we control 145 oldStdin := os.Stdin 146 defer func() { os.Stdin = oldStdin }() 147 os.Stdin = tf 148 149 result, err := ParseTemplateFile("-", nil) 150 if err != nil { 151 t.Fatalf("err: %s", err) 152 } 153 154 if len(result.Builders) != 1 { 155 t.Fatalf("bad: %#v", result.Builders) 156 } 157 } 158 159 func TestParseTemplate_Basic(t *testing.T) { 160 data := ` 161 { 162 "builders": [{"type": "something"}] 163 } 164 ` 165 166 result, err := ParseTemplate([]byte(data), nil) 167 if err != nil { 168 t.Fatalf("err: %s", err) 169 } 170 if result == nil { 171 t.Fatal("should have result") 172 } 173 if len(result.Builders) != 1 { 174 t.Fatalf("bad: %#v", result.Builders) 175 } 176 } 177 178 func TestParseTemplate_Description(t *testing.T) { 179 data := ` 180 { 181 "description": "Foo", 182 "builders": [{"type": "something"}] 183 } 184 ` 185 186 result, err := ParseTemplate([]byte(data), nil) 187 if err != nil { 188 t.Fatalf("err: %s", err) 189 } 190 if result == nil { 191 t.Fatal("should have result") 192 } 193 if result.Description != "Foo" { 194 t.Fatalf("bad: %#v", result.Description) 195 } 196 } 197 198 func TestParseTemplate_Invalid(t *testing.T) { 199 // Note there is an extra comma below for a purposeful 200 // syntax error in the JSON. 201 data := ` 202 { 203 "builders": [], 204 } 205 ` 206 207 result, err := ParseTemplate([]byte(data), nil) 208 if err == nil { 209 t.Fatal("shold have error") 210 } 211 if result != nil { 212 t.Fatal("should not have result") 213 } 214 } 215 216 func TestParseTemplate_InvalidKeys(t *testing.T) { 217 // Note there is an extra comma below for a purposeful 218 // syntax error in the JSON. 219 data := ` 220 { 221 "builders": [{"type": "foo"}], 222 "what is this": "" 223 } 224 ` 225 226 result, err := ParseTemplate([]byte(data), nil) 227 if err == nil { 228 t.Fatal("should have error") 229 } 230 if result != nil { 231 t.Fatal("should not have result") 232 } 233 } 234 235 func TestParseTemplate_BuilderWithoutType(t *testing.T) { 236 data := ` 237 { 238 "builders": [{}] 239 } 240 ` 241 242 _, err := ParseTemplate([]byte(data), nil) 243 if err == nil { 244 t.Fatal("should have error") 245 } 246 } 247 248 func TestParseTemplate_BuilderWithNonStringType(t *testing.T) { 249 data := ` 250 { 251 "builders": [{ 252 "type": 42 253 }] 254 } 255 ` 256 257 _, err := ParseTemplate([]byte(data), nil) 258 if err == nil { 259 t.Fatal("should have error") 260 } 261 } 262 263 func TestParseTemplate_BuilderWithoutName(t *testing.T) { 264 data := ` 265 { 266 "builders": [ 267 { 268 "type": "amazon-ebs" 269 } 270 ] 271 } 272 ` 273 274 result, err := ParseTemplate([]byte(data), nil) 275 if err != nil { 276 t.Fatalf("err: %s", err) 277 } 278 if result == nil { 279 t.Fatal("should have result") 280 } 281 if len(result.Builders) != 1 { 282 t.Fatalf("bad: %#v", result.Builders) 283 } 284 285 builder, ok := result.Builders["amazon-ebs"] 286 if !ok { 287 t.Fatal("should be ok") 288 } 289 if builder.Type != "amazon-ebs" { 290 t.Fatalf("bad: %#v", builder.Type) 291 } 292 } 293 294 func TestParseTemplate_BuilderWithName(t *testing.T) { 295 data := ` 296 { 297 "builders": [ 298 { 299 "name": "bob", 300 "type": "amazon-ebs" 301 } 302 ] 303 } 304 ` 305 306 result, err := ParseTemplate([]byte(data), nil) 307 if err != nil { 308 t.Fatalf("err: %s", err) 309 } 310 if result == nil { 311 t.Fatal("should have result") 312 } 313 if len(result.Builders) != 1 { 314 t.Fatalf("bad: %#v", result.Builders) 315 } 316 317 builder, ok := result.Builders["bob"] 318 if !ok { 319 t.Fatal("should be ok") 320 } 321 if builder.Type != "amazon-ebs" { 322 t.Fatalf("bad: %#v", builder.Type) 323 } 324 325 RawConfig := builder.RawConfig 326 if RawConfig == nil { 327 t.Fatal("missing builder raw config") 328 } 329 330 expected := map[string]interface{}{ 331 "type": "amazon-ebs", 332 } 333 334 if !reflect.DeepEqual(RawConfig, expected) { 335 t.Fatalf("bad raw: %#v", RawConfig) 336 } 337 } 338 339 func TestParseTemplate_BuilderWithConflictingName(t *testing.T) { 340 data := ` 341 { 342 "builders": [ 343 { 344 "name": "bob", 345 "type": "amazon-ebs" 346 }, 347 { 348 "name": "bob", 349 "type": "foo", 350 } 351 ] 352 } 353 ` 354 355 _, err := ParseTemplate([]byte(data), nil) 356 if err == nil { 357 t.Fatal("should have error") 358 } 359 } 360 361 func TestParseTemplate_Hooks(t *testing.T) { 362 data := ` 363 { 364 365 "builders": [{"type": "foo"}], 366 367 "hooks": { 368 "event": ["foo", "bar"] 369 } 370 } 371 ` 372 373 result, err := ParseTemplate([]byte(data), nil) 374 if err != nil { 375 t.Fatalf("err: %s", err) 376 } 377 if result == nil { 378 t.Fatal("should have result") 379 } 380 if len(result.Hooks) != 1 { 381 t.Fatalf("bad: %#v", result.Hooks) 382 } 383 384 hooks, ok := result.Hooks["event"] 385 if !ok { 386 t.Fatal("should be okay") 387 } 388 if !reflect.DeepEqual(hooks, []string{"foo", "bar"}) { 389 t.Fatalf("bad: %#v", hooks) 390 } 391 } 392 393 func TestParseTemplate_PostProcessors(t *testing.T) { 394 data := ` 395 { 396 "builders": [{"type": "foo"}], 397 398 "post-processors": [ 399 "simple", 400 401 { "type": "detailed" }, 402 403 [ "foo", { "type": "bar" } ] 404 ] 405 } 406 ` 407 408 tpl, err := ParseTemplate([]byte(data), nil) 409 if err != nil { 410 t.Fatalf("error parsing: %s", err) 411 } 412 413 if len(tpl.PostProcessors) != 3 { 414 t.Fatalf("bad number of post-processors: %d", len(tpl.PostProcessors)) 415 } 416 417 pp := tpl.PostProcessors[0] 418 if len(pp) != 1 { 419 t.Fatalf("wrong number of configs in simple: %d", len(pp)) 420 } 421 422 if pp[0].Type != "simple" { 423 t.Fatalf("wrong type for simple: %s", pp[0].Type) 424 } 425 426 pp = tpl.PostProcessors[1] 427 if len(pp) != 1 { 428 t.Fatalf("wrong number of configs in detailed: %d", len(pp)) 429 } 430 431 if pp[0].Type != "detailed" { 432 t.Fatalf("wrong type for detailed: %s", pp[0].Type) 433 } 434 435 pp = tpl.PostProcessors[2] 436 if len(pp) != 2 { 437 t.Fatalf("wrong number of configs for sequence: %d", len(pp)) 438 } 439 440 if pp[0].Type != "foo" { 441 t.Fatalf("wrong type for sequence 0: %s", pp[0].Type) 442 } 443 444 if pp[1].Type != "bar" { 445 t.Fatalf("wrong type for sequence 1: %s", pp[1].Type) 446 } 447 } 448 449 func TestParseTemplate_ProvisionerWithoutType(t *testing.T) { 450 data := ` 451 { 452 "builders": [{"type": "foo"}], 453 454 "provisioners": [{}] 455 } 456 ` 457 458 _, err := ParseTemplate([]byte(data), nil) 459 if err == nil { 460 t.Fatal("err should not be nil") 461 } 462 } 463 464 func TestParseTemplate_ProvisionerWithNonStringType(t *testing.T) { 465 data := ` 466 { 467 "builders": [{"type": "foo"}], 468 469 "provisioners": [{ 470 "type": 42 471 }] 472 } 473 ` 474 475 _, err := ParseTemplate([]byte(data), nil) 476 if err == nil { 477 t.Fatal("should have error") 478 } 479 } 480 481 func TestParseTemplate_Provisioners(t *testing.T) { 482 data := ` 483 { 484 "builders": [{"type": "foo"}], 485 486 "provisioners": [ 487 { 488 "type": "shell" 489 } 490 ] 491 } 492 ` 493 494 result, err := ParseTemplate([]byte(data), nil) 495 if err != nil { 496 t.Fatal("err: %s", err) 497 } 498 if result == nil { 499 t.Fatal("should have result") 500 } 501 if len(result.Provisioners) != 1 { 502 t.Fatalf("bad: %#v", result.Provisioners) 503 } 504 if result.Provisioners[0].Type != "shell" { 505 t.Fatalf("bad: %#v", result.Provisioners[0].Type) 506 } 507 if result.Provisioners[0].RawConfig == nil { 508 t.Fatal("should have raw config") 509 } 510 } 511 512 func TestParseTemplate_ProvisionerPauseBefore(t *testing.T) { 513 data := ` 514 { 515 "builders": [{"type": "foo"}], 516 517 "provisioners": [ 518 { 519 "type": "shell", 520 "pause_before": "10s" 521 } 522 ] 523 } 524 ` 525 526 result, err := ParseTemplate([]byte(data), nil) 527 if err != nil { 528 t.Fatal("err: %s", err) 529 } 530 if result == nil { 531 t.Fatal("should have result") 532 } 533 if len(result.Provisioners) != 1 { 534 t.Fatalf("bad: %#v", result.Provisioners) 535 } 536 if result.Provisioners[0].Type != "shell" { 537 t.Fatalf("bad: %#v", result.Provisioners[0].Type) 538 } 539 if result.Provisioners[0].pauseBefore != 10*time.Second { 540 t.Fatalf("bad: %s", result.Provisioners[0].pauseBefore) 541 } 542 } 543 544 func TestParseTemplate_Variables(t *testing.T) { 545 data := ` 546 { 547 "variables": { 548 "foo": "bar", 549 "bar": null, 550 "baz": 27 551 }, 552 553 "builders": [{"type": "something"}] 554 } 555 ` 556 557 result, err := ParseTemplate([]byte(data), map[string]string{ 558 "bar": "bar", 559 }) 560 if err != nil { 561 t.Fatalf("err: %s", err) 562 } 563 564 if result.Variables == nil || len(result.Variables) != 3 { 565 t.Fatalf("bad vars: %#v", result.Variables) 566 } 567 568 if result.Variables["foo"].Default != "bar" { 569 t.Fatal("foo default is not right") 570 } 571 if result.Variables["foo"].Required { 572 t.Fatal("foo should not be required") 573 } 574 if result.Variables["foo"].HasValue { 575 t.Fatal("foo should not have value") 576 } 577 578 if result.Variables["bar"].Default != "" { 579 t.Fatal("default should be empty") 580 } 581 if !result.Variables["bar"].Required { 582 t.Fatal("bar should be required") 583 } 584 if !result.Variables["bar"].HasValue { 585 t.Fatal("bar should have value") 586 } 587 if result.Variables["bar"].Value != "bar" { 588 t.Fatal("bad value") 589 } 590 591 if result.Variables["baz"].Default != "27" { 592 t.Fatal("default should be empty") 593 } 594 595 if result.Variables["baz"].Required { 596 t.Fatal("baz should not be required") 597 } 598 } 599 600 func TestParseTemplate_variablesSet(t *testing.T) { 601 data := ` 602 { 603 "variables": { 604 "foo": "bar" 605 }, 606 607 "builders": [ 608 { 609 "name": "test1", 610 "type": "test-builder" 611 } 612 ] 613 } 614 ` 615 616 template, err := ParseTemplate([]byte(data), map[string]string{ 617 "foo": "value", 618 }) 619 if err != nil { 620 t.Fatalf("err: %s", err) 621 } 622 623 if len(template.Variables) != 1 { 624 t.Fatalf("bad vars: %#v", template.Variables) 625 } 626 if template.Variables["foo"].Value != "value" { 627 t.Fatalf("bad: %#v", template.Variables["foo"]) 628 } 629 } 630 631 func TestParseTemplate_variablesSetUnknown(t *testing.T) { 632 data := ` 633 { 634 "variables": { 635 "foo": "bar" 636 }, 637 638 "builders": [ 639 { 640 "name": "test1", 641 "type": "test-builder" 642 } 643 ] 644 } 645 ` 646 647 _, err := ParseTemplate([]byte(data), map[string]string{ 648 "what": "value", 649 }) 650 if err == nil { 651 t.Fatal("should error") 652 } 653 } 654 655 func TestParseTemplate_variablesBadDefault(t *testing.T) { 656 data := ` 657 { 658 "variables": { 659 "foo": 7, 660 }, 661 662 "builders": [{"type": "something"}] 663 } 664 ` 665 666 _, err := ParseTemplate([]byte(data), nil) 667 if err == nil { 668 t.Fatal("should have error") 669 } 670 } 671 672 func TestTemplate_BuildNames(t *testing.T) { 673 data := ` 674 { 675 "builders": [ 676 { 677 "name": "bob", 678 "type": "amazon-ebs" 679 }, 680 { 681 "name": "chris", 682 "type": "another" 683 } 684 ] 685 } 686 ` 687 688 result, err := ParseTemplate([]byte(data), nil) 689 if err != nil { 690 t.Fatalf("err: %s", err) 691 } 692 693 buildNames := result.BuildNames() 694 sort.Strings(buildNames) 695 if !reflect.DeepEqual(buildNames, []string{"bob", "chris"}) { 696 t.Fatalf("bad: %#v", buildNames) 697 } 698 } 699 700 func TestTemplate_BuildUnknown(t *testing.T) { 701 data := ` 702 { 703 "builders": [ 704 { 705 "name": "test1", 706 "type": "test-builder" 707 } 708 ] 709 } 710 ` 711 712 template, err := ParseTemplate([]byte(data), nil) 713 if err != nil { 714 t.Fatalf("bad: %s", err) 715 } 716 717 build, err := template.Build("nope", nil) 718 if build != nil { 719 t.Fatalf("build should be nil: %#v", build) 720 } 721 if err == nil { 722 t.Fatal("should have error") 723 } 724 } 725 726 func TestTemplate_BuildUnknownBuilder(t *testing.T) { 727 data := ` 728 { 729 "builders": [ 730 { 731 "name": "test1", 732 "type": "test-builder" 733 } 734 ] 735 } 736 ` 737 738 template, err := ParseTemplate([]byte(data), nil) 739 if err != nil { 740 t.Fatalf("err: %s", err) 741 } 742 743 builderFactory := func(string) (Builder, error) { return nil, nil } 744 components := &ComponentFinder{Builder: builderFactory} 745 build, err := template.Build("test1", components) 746 if err == nil { 747 t.Fatal("should have error") 748 } 749 if build != nil { 750 t.Fatalf("bad: %#v", build) 751 } 752 } 753 754 func TestTemplateBuild_envInVars(t *testing.T) { 755 data := ` 756 { 757 "variables": { 758 "foo": "{{env \"foo\"}}" 759 }, 760 761 "builders": [ 762 { 763 "name": "test1", 764 "type": "test-builder" 765 } 766 ] 767 } 768 ` 769 770 defer os.Setenv("foo", os.Getenv("foo")) 771 if err := os.Setenv("foo", "bar"); err != nil { 772 t.Fatalf("err: %s", err) 773 } 774 775 template, err := ParseTemplate([]byte(data), map[string]string{}) 776 if err != nil { 777 t.Fatalf("err: %s", err) 778 } 779 780 b, err := template.Build("test1", testComponentFinder()) 781 if err != nil { 782 t.Fatalf("err: %s", err) 783 } 784 785 coreBuild, ok := b.(*coreBuild) 786 if !ok { 787 t.Fatal("should be ok") 788 } 789 790 if coreBuild.variables["foo"] != "bar" { 791 t.Fatalf("bad: %#v", coreBuild.variables) 792 } 793 } 794 795 func TestTemplateBuild_names(t *testing.T) { 796 data := ` 797 { 798 "variables": { 799 "foo": null 800 }, 801 802 "builders": [ 803 { 804 "name": "test1", 805 "type": "test-builder" 806 }, 807 { 808 "name": "test2-{{user \"foo\"}}", 809 "type": "test-builder" 810 } 811 ] 812 } 813 ` 814 815 template, err := ParseTemplate([]byte(data), map[string]string{"foo": "bar"}) 816 if err != nil { 817 t.Fatalf("err: %s", err) 818 } 819 820 b, err := template.Build("test1", testComponentFinder()) 821 if err != nil { 822 t.Fatalf("err: %s", err) 823 } 824 if b.Name() != "test1" { 825 t.Fatalf("bad: %#v", b.Name()) 826 } 827 828 b, err = template.Build("test2-{{user \"foo\"}}", testComponentFinder()) 829 if err != nil { 830 t.Fatalf("err: %s", err) 831 } 832 if b.Name() != "test2-bar" { 833 t.Fatalf("bad: %#v", b.Name()) 834 } 835 } 836 837 func TestTemplate_Build_NilBuilderFunc(t *testing.T) { 838 data := ` 839 { 840 "builders": [ 841 { 842 "name": "test1", 843 "type": "test-builder" 844 } 845 ], 846 847 "provisioners": [ 848 { 849 "type": "test-prov" 850 } 851 ] 852 } 853 ` 854 855 template, err := ParseTemplate([]byte(data), nil) 856 if err != nil { 857 t.Fatalf("err: %s", err) 858 } 859 860 defer func() { 861 p := recover() 862 if p == nil { 863 t.Fatal("should panic") 864 } 865 866 if p.(string) != "no builder function" { 867 t.Fatalf("bad panic: %s", p.(string)) 868 } 869 }() 870 871 template.Build("test1", &ComponentFinder{}) 872 } 873 874 func TestTemplate_Build_NilProvisionerFunc(t *testing.T) { 875 data := ` 876 { 877 "builders": [ 878 { 879 "name": "test1", 880 "type": "test-builder" 881 } 882 ], 883 884 "provisioners": [ 885 { 886 "type": "test-prov" 887 } 888 ] 889 } 890 ` 891 892 template, err := ParseTemplate([]byte(data), nil) 893 if err != nil { 894 t.Fatalf("err: %s", err) 895 } 896 897 defer func() { 898 p := recover() 899 if p == nil { 900 t.Fatal("should panic") 901 } 902 903 if p.(string) != "no provisioner function" { 904 t.Fatalf("bad panic: %s", p.(string)) 905 } 906 }() 907 908 template.Build("test1", &ComponentFinder{ 909 Builder: func(string) (Builder, error) { return nil, nil }, 910 }) 911 } 912 913 func TestTemplate_Build_NilProvisionerFunc_WithNoProvisioners(t *testing.T) { 914 data := ` 915 { 916 "builders": [ 917 { 918 "name": "test1", 919 "type": "test-builder" 920 } 921 ], 922 923 "provisioners": [] 924 } 925 ` 926 927 template, err := ParseTemplate([]byte(data), nil) 928 if err != nil { 929 t.Fatalf("err: %s", err) 930 } 931 932 template.Build("test1", &ComponentFinder{ 933 Builder: func(string) (Builder, error) { return nil, nil }, 934 }) 935 } 936 937 func TestTemplate_Build(t *testing.T) { 938 data := ` 939 { 940 "builders": [ 941 { 942 "name": "test1", 943 "type": "test-builder" 944 } 945 ], 946 947 "provisioners": [ 948 { 949 "type": "test-prov" 950 } 951 ], 952 953 "post-processors": [ 954 "simple", 955 [ 956 "simple", 957 { "type": "simple", "keep_input_artifact": true } 958 ] 959 ] 960 } 961 ` 962 963 expectedConfig := map[string]interface{}{ 964 "type": "test-builder", 965 } 966 967 template, err := ParseTemplate([]byte(data), nil) 968 if err != nil { 969 t.Fatalf("err: %s", err) 970 } 971 972 builder := new(MockBuilder) 973 builderMap := map[string]Builder{ 974 "test-builder": builder, 975 } 976 977 provisioner := &MockProvisioner{} 978 provisionerMap := map[string]Provisioner{ 979 "test-prov": provisioner, 980 } 981 982 pp := new(TestPostProcessor) 983 ppMap := map[string]PostProcessor{ 984 "simple": pp, 985 } 986 987 builderFactory := func(n string) (Builder, error) { return builderMap[n], nil } 988 ppFactory := func(n string) (PostProcessor, error) { return ppMap[n], nil } 989 provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil } 990 components := &ComponentFinder{ 991 Builder: builderFactory, 992 PostProcessor: ppFactory, 993 Provisioner: provFactory, 994 } 995 996 // Get the build, verifying we can get it without issue, but also 997 // that the proper builder was looked up and used for the build. 998 build, err := template.Build("test1", components) 999 if err != nil { 1000 t.Fatalf("err: %s", err) 1001 } 1002 1003 coreBuild, ok := build.(*coreBuild) 1004 if !ok { 1005 t.Fatal("should be ok") 1006 } 1007 if coreBuild.builder != builder { 1008 t.Fatalf("bad: %#v", coreBuild.builder) 1009 } 1010 if !reflect.DeepEqual(coreBuild.builderConfig, expectedConfig) { 1011 t.Fatalf("bad: %#v", coreBuild.builderConfig) 1012 } 1013 if len(coreBuild.provisioners) != 1 { 1014 t.Fatalf("bad: %#v", coreBuild.provisioners) 1015 } 1016 if len(coreBuild.postProcessors) != 2 { 1017 t.Fatalf("bad: %#v", coreBuild.postProcessors) 1018 } 1019 1020 if len(coreBuild.postProcessors[0]) != 1 { 1021 t.Fatalf("bad: %#v", coreBuild.postProcessors[0]) 1022 } 1023 if len(coreBuild.postProcessors[1]) != 2 { 1024 t.Fatalf("bad: %#v", coreBuild.postProcessors[1]) 1025 } 1026 1027 if coreBuild.postProcessors[1][0].keepInputArtifact { 1028 t.Fatal("postProcessors[1][0] should not keep input artifact") 1029 } 1030 if !coreBuild.postProcessors[1][1].keepInputArtifact { 1031 t.Fatal("postProcessors[1][1] should keep input artifact") 1032 } 1033 1034 config := coreBuild.postProcessors[1][1].config 1035 if _, ok := config["keep_input_artifact"]; ok { 1036 t.Fatal("should not have keep_input_artifact") 1037 } 1038 } 1039 1040 func TestTemplateBuild_exceptOnlyPP(t *testing.T) { 1041 data := ` 1042 { 1043 "builders": [ 1044 { 1045 "name": "test1", 1046 "type": "test-builder" 1047 }, 1048 { 1049 "name": "test2", 1050 "type": "test-builder" 1051 } 1052 ], 1053 1054 "post-processors": [ 1055 { 1056 "type": "test-pp", 1057 "except": ["test1"], 1058 "only": ["test1"] 1059 } 1060 ] 1061 } 1062 ` 1063 1064 _, err := ParseTemplate([]byte(data), nil) 1065 if err == nil { 1066 t.Fatal("should have error") 1067 } 1068 } 1069 1070 func TestTemplateBuild_exceptOnlyProv(t *testing.T) { 1071 data := ` 1072 { 1073 "builders": [ 1074 { 1075 "name": "test1", 1076 "type": "test-builder" 1077 }, 1078 { 1079 "name": "test2", 1080 "type": "test-builder" 1081 } 1082 ], 1083 1084 "provisioners": [ 1085 { 1086 "type": "test-prov", 1087 "except": ["test1"], 1088 "only": ["test1"] 1089 } 1090 ] 1091 } 1092 ` 1093 1094 _, err := ParseTemplate([]byte(data), nil) 1095 if err == nil { 1096 t.Fatal("should have error") 1097 } 1098 } 1099 1100 func TestTemplateBuild_exceptPPInvalid(t *testing.T) { 1101 data := ` 1102 { 1103 "builders": [ 1104 { 1105 "name": "test1", 1106 "type": "test-builder" 1107 }, 1108 { 1109 "name": "test2", 1110 "type": "test-builder" 1111 } 1112 ], 1113 1114 "post-processors": [ 1115 { 1116 "type": "test-pp", 1117 "except": ["test5"] 1118 } 1119 ] 1120 } 1121 ` 1122 1123 _, err := ParseTemplate([]byte(data), nil) 1124 if err == nil { 1125 t.Fatal("should have error") 1126 } 1127 } 1128 1129 func TestTemplateBuild_exceptPP(t *testing.T) { 1130 data := ` 1131 { 1132 "builders": [ 1133 { 1134 "name": "test1", 1135 "type": "test-builder" 1136 }, 1137 { 1138 "name": "test2", 1139 "type": "test-builder" 1140 } 1141 ], 1142 1143 "post-processors": [ 1144 { 1145 "type": "test-pp", 1146 "except": ["test1"] 1147 } 1148 ] 1149 } 1150 ` 1151 1152 template, err := ParseTemplate([]byte(data), nil) 1153 if err != nil { 1154 t.Fatalf("err: %s", err) 1155 } 1156 1157 // Verify test1 has no post-processors 1158 build, err := template.Build("test1", testTemplateComponentFinder()) 1159 if err != nil { 1160 t.Fatalf("err: %s", err) 1161 } 1162 1163 cbuild := build.(*coreBuild) 1164 if len(cbuild.postProcessors) > 0 { 1165 t.Fatal("should have no postProcessors") 1166 } 1167 1168 // Verify test2 has no post-processors 1169 build, err = template.Build("test2", testTemplateComponentFinder()) 1170 if err != nil { 1171 t.Fatalf("err: %s", err) 1172 } 1173 1174 cbuild = build.(*coreBuild) 1175 if len(cbuild.postProcessors) != 1 { 1176 t.Fatalf("invalid: %d", len(cbuild.postProcessors)) 1177 } 1178 } 1179 1180 func TestTemplateBuild_exceptProvInvalid(t *testing.T) { 1181 data := ` 1182 { 1183 "builders": [ 1184 { 1185 "name": "test1", 1186 "type": "test-builder" 1187 }, 1188 { 1189 "name": "test2", 1190 "type": "test-builder" 1191 } 1192 ], 1193 1194 "provisioners": [ 1195 { 1196 "type": "test-prov", 1197 "except": ["test5"] 1198 } 1199 ] 1200 } 1201 ` 1202 1203 _, err := ParseTemplate([]byte(data), nil) 1204 if err == nil { 1205 t.Fatal("should have error") 1206 } 1207 } 1208 1209 func TestTemplateBuild_exceptProv(t *testing.T) { 1210 data := ` 1211 { 1212 "builders": [ 1213 { 1214 "name": "test1", 1215 "type": "test-builder" 1216 }, 1217 { 1218 "name": "test2", 1219 "type": "test-builder" 1220 } 1221 ], 1222 1223 "provisioners": [ 1224 { 1225 "type": "test-prov", 1226 "except": ["test1"] 1227 } 1228 ] 1229 } 1230 ` 1231 1232 template, err := ParseTemplate([]byte(data), nil) 1233 if err != nil { 1234 t.Fatalf("err: %s", err) 1235 } 1236 1237 // Verify test1 has no provisioners 1238 build, err := template.Build("test1", testTemplateComponentFinder()) 1239 if err != nil { 1240 t.Fatalf("err: %s", err) 1241 } 1242 1243 cbuild := build.(*coreBuild) 1244 if len(cbuild.provisioners) > 0 { 1245 t.Fatal("should have no provisioners") 1246 } 1247 1248 // Verify test2 has no provisioners 1249 build, err = template.Build("test2", testTemplateComponentFinder()) 1250 if err != nil { 1251 t.Fatalf("err: %s", err) 1252 } 1253 1254 cbuild = build.(*coreBuild) 1255 if len(cbuild.provisioners) != 1 { 1256 t.Fatalf("invalid: %d", len(cbuild.provisioners)) 1257 } 1258 } 1259 1260 func TestTemplateBuild_onlyPPInvalid(t *testing.T) { 1261 data := ` 1262 { 1263 "builders": [ 1264 { 1265 "name": "test1", 1266 "type": "test-builder" 1267 }, 1268 { 1269 "name": "test2", 1270 "type": "test-builder" 1271 } 1272 ], 1273 1274 "post-processors": [ 1275 { 1276 "type": "test-pp", 1277 "only": ["test5"] 1278 } 1279 ] 1280 } 1281 ` 1282 1283 _, err := ParseTemplate([]byte(data), nil) 1284 if err == nil { 1285 t.Fatal("should have error") 1286 } 1287 } 1288 1289 func TestTemplateBuild_onlyPP(t *testing.T) { 1290 data := ` 1291 { 1292 "builders": [ 1293 { 1294 "name": "test1", 1295 "type": "test-builder" 1296 }, 1297 { 1298 "name": "test2", 1299 "type": "test-builder" 1300 } 1301 ], 1302 1303 "post-processors": [ 1304 { 1305 "type": "test-pp", 1306 "only": ["test2"] 1307 } 1308 ] 1309 } 1310 ` 1311 1312 template, err := ParseTemplate([]byte(data), nil) 1313 if err != nil { 1314 t.Fatalf("err: %s", err) 1315 } 1316 1317 // Verify test1 has no post-processors 1318 build, err := template.Build("test1", testTemplateComponentFinder()) 1319 if err != nil { 1320 t.Fatalf("err: %s", err) 1321 } 1322 1323 cbuild := build.(*coreBuild) 1324 if len(cbuild.postProcessors) > 0 { 1325 t.Fatal("should have no postProcessors") 1326 } 1327 1328 // Verify test2 has no post-processors 1329 build, err = template.Build("test2", testTemplateComponentFinder()) 1330 if err != nil { 1331 t.Fatalf("err: %s", err) 1332 } 1333 1334 cbuild = build.(*coreBuild) 1335 if len(cbuild.postProcessors) != 1 { 1336 t.Fatalf("invalid: %d", len(cbuild.postProcessors)) 1337 } 1338 } 1339 1340 func TestTemplateBuild_onlyProvInvalid(t *testing.T) { 1341 data := ` 1342 { 1343 "builders": [ 1344 { 1345 "name": "test1", 1346 "type": "test-builder" 1347 }, 1348 { 1349 "name": "test2", 1350 "type": "test-builder" 1351 } 1352 ], 1353 1354 "provisioners": [ 1355 { 1356 "type": "test-prov", 1357 "only": ["test5"] 1358 } 1359 ] 1360 } 1361 ` 1362 1363 _, err := ParseTemplate([]byte(data), nil) 1364 if err == nil { 1365 t.Fatal("should have error") 1366 } 1367 } 1368 1369 func TestTemplateBuild_onlyProv(t *testing.T) { 1370 data := ` 1371 { 1372 "builders": [ 1373 { 1374 "name": "test1", 1375 "type": "test-builder" 1376 }, 1377 { 1378 "name": "test2", 1379 "type": "test-builder" 1380 } 1381 ], 1382 1383 "provisioners": [ 1384 { 1385 "type": "test-prov", 1386 "only": ["test2"] 1387 } 1388 ] 1389 } 1390 ` 1391 1392 template, err := ParseTemplate([]byte(data), nil) 1393 if err != nil { 1394 t.Fatalf("err: %s", err) 1395 } 1396 1397 // Verify test1 has no provisioners 1398 build, err := template.Build("test1", testTemplateComponentFinder()) 1399 if err != nil { 1400 t.Fatalf("err: %s", err) 1401 } 1402 1403 cbuild := build.(*coreBuild) 1404 if len(cbuild.provisioners) > 0 { 1405 t.Fatal("should have no provisioners") 1406 } 1407 1408 // Verify test2 has no provisioners 1409 build, err = template.Build("test2", testTemplateComponentFinder()) 1410 if err != nil { 1411 t.Fatalf("err: %s", err) 1412 } 1413 1414 cbuild = build.(*coreBuild) 1415 if len(cbuild.provisioners) != 1 { 1416 t.Fatalf("invalid: %d", len(cbuild.provisioners)) 1417 } 1418 } 1419 1420 func TestTemplate_Build_ProvisionerOverride(t *testing.T) { 1421 data := ` 1422 { 1423 "builders": [ 1424 { 1425 "name": "test1", 1426 "type": "test-builder" 1427 } 1428 ], 1429 1430 "provisioners": [ 1431 { 1432 "type": "test-prov", 1433 1434 "override": { 1435 "test1": {} 1436 } 1437 } 1438 ] 1439 } 1440 ` 1441 1442 template, err := ParseTemplate([]byte(data), nil) 1443 if err != nil { 1444 t.Fatalf("err: %s", err) 1445 } 1446 1447 RawConfig := template.Provisioners[0].RawConfig 1448 if RawConfig == nil { 1449 t.Fatal("missing provisioner raw config") 1450 } 1451 1452 expected := map[string]interface{}{ 1453 "type": "test-prov", 1454 } 1455 1456 if !reflect.DeepEqual(RawConfig, expected) { 1457 t.Fatalf("bad raw: %#v", RawConfig) 1458 } 1459 1460 builder := new(MockBuilder) 1461 builderMap := map[string]Builder{ 1462 "test-builder": builder, 1463 } 1464 1465 provisioner := &MockProvisioner{} 1466 provisionerMap := map[string]Provisioner{ 1467 "test-prov": provisioner, 1468 } 1469 1470 builderFactory := func(n string) (Builder, error) { return builderMap[n], nil } 1471 provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil } 1472 components := &ComponentFinder{ 1473 Builder: builderFactory, 1474 Provisioner: provFactory, 1475 } 1476 1477 // Get the build, verifying we can get it without issue, but also 1478 // that the proper builder was looked up and used for the build. 1479 build, err := template.Build("test1", components) 1480 if err != nil { 1481 t.Fatalf("err: %s", err) 1482 } 1483 1484 coreBuild, ok := build.(*coreBuild) 1485 if !ok { 1486 t.Fatal("should be okay") 1487 } 1488 if len(coreBuild.provisioners) != 1 { 1489 t.Fatalf("bad: %#v", coreBuild.provisioners) 1490 } 1491 if len(coreBuild.provisioners[0].config) != 2 { 1492 t.Fatalf("bad: %#v", coreBuild.provisioners[0].config) 1493 } 1494 } 1495 1496 func TestTemplate_Build_ProvisionerOverrideBad(t *testing.T) { 1497 data := ` 1498 { 1499 "builders": [ 1500 { 1501 "name": "test1", 1502 "type": "test-builder" 1503 } 1504 ], 1505 1506 "provisioners": [ 1507 { 1508 "type": "test-prov", 1509 1510 "override": { 1511 "testNope": {} 1512 } 1513 } 1514 ] 1515 } 1516 ` 1517 1518 _, err := ParseTemplate([]byte(data), nil) 1519 if err == nil { 1520 t.Fatal("should have error") 1521 } 1522 } 1523 1524 func TestTemplateBuild_ProvisionerPauseBefore(t *testing.T) { 1525 data := ` 1526 { 1527 "builders": [ 1528 { 1529 "name": "test1", 1530 "type": "test-builder" 1531 } 1532 ], 1533 1534 "provisioners": [ 1535 { 1536 "type": "test-prov", 1537 "pause_before": "5s" 1538 } 1539 ] 1540 } 1541 ` 1542 1543 template, err := ParseTemplate([]byte(data), nil) 1544 if err != nil { 1545 t.Fatalf("err: %s", err) 1546 } 1547 1548 builder := new(MockBuilder) 1549 builderMap := map[string]Builder{ 1550 "test-builder": builder, 1551 } 1552 1553 provisioner := &MockProvisioner{} 1554 provisionerMap := map[string]Provisioner{ 1555 "test-prov": provisioner, 1556 } 1557 1558 builderFactory := func(n string) (Builder, error) { return builderMap[n], nil } 1559 provFactory := func(n string) (Provisioner, error) { return provisionerMap[n], nil } 1560 components := &ComponentFinder{ 1561 Builder: builderFactory, 1562 Provisioner: provFactory, 1563 } 1564 1565 // Get the build, verifying we can get it without issue, but also 1566 // that the proper builder was looked up and used for the build. 1567 build, err := template.Build("test1", components) 1568 if err != nil { 1569 t.Fatalf("err: %s", err) 1570 } 1571 1572 coreBuild, ok := build.(*coreBuild) 1573 if !ok { 1574 t.Fatal("should be okay") 1575 } 1576 if len(coreBuild.provisioners) != 1 { 1577 t.Fatalf("bad: %#v", coreBuild.provisioners) 1578 } 1579 if pp, ok := coreBuild.provisioners[0].provisioner.(*PausedProvisioner); !ok { 1580 t.Fatalf("should be paused provisioner") 1581 } else { 1582 if pp.PauseBefore != 5*time.Second { 1583 t.Fatalf("bad: %#v", pp.PauseBefore) 1584 } 1585 } 1586 1587 config := coreBuild.provisioners[0].config[0].(map[string]interface{}) 1588 if _, ok := config["pause_before"]; ok { 1589 t.Fatal("pause_before should be removed") 1590 } 1591 } 1592 1593 func TestTemplateBuild_variables(t *testing.T) { 1594 data := ` 1595 { 1596 "variables": { 1597 "foo": "bar" 1598 }, 1599 1600 "builders": [ 1601 { 1602 "name": "test1", 1603 "type": "test-builder" 1604 } 1605 ] 1606 } 1607 ` 1608 1609 template, err := ParseTemplate([]byte(data), nil) 1610 if err != nil { 1611 t.Fatalf("err: %s", err) 1612 } 1613 1614 build, err := template.Build("test1", testComponentFinder()) 1615 if err != nil { 1616 t.Fatalf("err: %s", err) 1617 } 1618 1619 coreBuild, ok := build.(*coreBuild) 1620 if !ok { 1621 t.Fatalf("couldn't convert!") 1622 } 1623 1624 expected := map[string]string{"foo": "bar"} 1625 if !reflect.DeepEqual(coreBuild.variables, expected) { 1626 t.Fatalf("bad vars: %#v", coreBuild.variables) 1627 } 1628 } 1629 1630 func TestTemplateBuild_variablesRequiredNotSet(t *testing.T) { 1631 data := ` 1632 { 1633 "variables": { 1634 "foo": null 1635 }, 1636 1637 "builders": [ 1638 { 1639 "name": "test1", 1640 "type": "test-builder" 1641 } 1642 ] 1643 } 1644 ` 1645 1646 template, err := ParseTemplate([]byte(data), map[string]string{}) 1647 if err != nil { 1648 t.Fatalf("err: %s", err) 1649 } 1650 1651 _, err = template.Build("test1", testComponentFinder()) 1652 if err == nil { 1653 t.Fatal("should error") 1654 } 1655 }