github.com/maheshbr/terraform@v0.3.1-0.20141020033300-deec7194a3ea/terraform/terraform_test.go (about) 1 package terraform 2 3 import ( 4 "bytes" 5 "crypto/sha1" 6 "encoding/gob" 7 "encoding/hex" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "sync" 12 "testing" 13 14 "github.com/hashicorp/terraform/config" 15 "github.com/hashicorp/terraform/config/module" 16 ) 17 18 // This is the directory where our test fixtures are. 19 const fixtureDir = "./test-fixtures" 20 21 func checksumStruct(t *testing.T, i interface{}) string { 22 // TODO(mitchellh): write a library to do this because gob is not 23 // deterministic in order 24 return "foo" 25 26 buf := new(bytes.Buffer) 27 enc := gob.NewEncoder(buf) 28 if err := enc.Encode(i); err != nil { 29 t.Fatalf("err: %s", err) 30 } 31 32 sum := sha1.Sum(buf.Bytes()) 33 return hex.EncodeToString(sum[:]) 34 } 35 36 func tempDir(t *testing.T) string { 37 dir, err := ioutil.TempDir("", "tf") 38 if err != nil { 39 t.Fatalf("err: %s", err) 40 } 41 if err := os.RemoveAll(dir); err != nil { 42 t.Fatalf("err: %s", err) 43 } 44 45 return dir 46 } 47 48 func testConfig(t *testing.T, name string) *config.Config { 49 c, err := config.Load(filepath.Join(fixtureDir, name, "main.tf")) 50 if err != nil { 51 t.Fatalf("err: %s", err) 52 } 53 54 return c 55 } 56 57 func testModule(t *testing.T, name string) *module.Tree { 58 mod, err := module.NewTreeModule("", filepath.Join(fixtureDir, name)) 59 if err != nil { 60 t.Fatalf("err: %s", err) 61 } 62 63 s := &module.FolderStorage{StorageDir: tempDir(t)} 64 if err := mod.Load(s, module.GetModeGet); err != nil { 65 t.Fatalf("err: %s", err) 66 } 67 68 return mod 69 } 70 71 func testProviderFuncFixed(rp ResourceProvider) ResourceProviderFactory { 72 return func() (ResourceProvider, error) { 73 return rp, nil 74 } 75 } 76 77 func testProvisionerFuncFixed(rp ResourceProvisioner) ResourceProvisionerFactory { 78 return func() (ResourceProvisioner, error) { 79 return rp, nil 80 } 81 } 82 83 // HookRecordApplyOrder is a test hook that records the order of applies 84 // by recording the PreApply event. 85 type HookRecordApplyOrder struct { 86 NilHook 87 88 Active bool 89 90 IDs []string 91 States []*InstanceState 92 Diffs []*InstanceDiff 93 94 l sync.Mutex 95 } 96 97 func (h *HookRecordApplyOrder) PreApply( 98 info *InstanceInfo, 99 s *InstanceState, 100 d *InstanceDiff) (HookAction, error) { 101 if h.Active { 102 h.l.Lock() 103 defer h.l.Unlock() 104 105 h.IDs = append(h.IDs, info.Id) 106 h.Diffs = append(h.Diffs, d) 107 h.States = append(h.States, s) 108 } 109 110 return HookActionContinue, nil 111 } 112 113 // Below are all the constant strings that are the expected output for 114 // various tests. 115 116 const testTerraformInputProviderStr = ` 117 aws_instance.bar: 118 ID = foo 119 bar = override 120 foo = us-east-1 121 type = aws_instance 122 aws_instance.foo: 123 ID = foo 124 bar = baz 125 num = 2 126 type = aws_instance 127 ` 128 129 const testTerraformInputProviderOnlyStr = ` 130 aws_instance.foo: 131 ID = foo 132 foo = us-west-2 133 type = aws_instance 134 ` 135 136 const testTerraformInputVarOnlyStr = ` 137 aws_instance.foo: 138 ID = foo 139 foo = us-east-1 140 type = aws_instance 141 ` 142 143 const testTerraformInputVarsStr = ` 144 aws_instance.bar: 145 ID = foo 146 bar = override 147 foo = us-east-1 148 type = aws_instance 149 aws_instance.foo: 150 ID = foo 151 bar = baz 152 num = 2 153 type = aws_instance 154 ` 155 156 const testTerraformApplyStr = ` 157 aws_instance.bar: 158 ID = foo 159 foo = bar 160 type = aws_instance 161 aws_instance.foo: 162 ID = foo 163 num = 2 164 type = aws_instance 165 ` 166 167 const testTerraformApplyDependsCreateBeforeStr = ` 168 aws_instance.lb: 169 ID = foo 170 instance = foo 171 type = aws_instance 172 173 Dependencies: 174 aws_instance.web 175 aws_instance.web: 176 ID = foo 177 require_new = ami-new 178 type = aws_instance 179 ` 180 181 const testTerraformApplyCreateBeforeStr = ` 182 aws_instance.bar: 183 ID = foo 184 require_new = xyz 185 type = aws_instance 186 ` 187 188 const testTerraformApplyCancelStr = ` 189 aws_instance.foo: 190 ID = foo 191 num = 2 192 ` 193 194 const testTerraformApplyComputeStr = ` 195 aws_instance.bar: 196 ID = foo 197 foo = computed_dynamical 198 type = aws_instance 199 200 Dependencies: 201 aws_instance.foo 202 aws_instance.foo: 203 ID = foo 204 dynamical = computed_dynamical 205 num = 2 206 type = aws_instance 207 ` 208 209 const testTerraformApplyCountDecStr = ` 210 aws_instance.foo.0: 211 ID = bar 212 foo = foo 213 type = aws_instance 214 aws_instance.foo.1: 215 ID = bar 216 foo = foo 217 type = aws_instance 218 ` 219 220 const testTerraformApplyCountDecToOneStr = ` 221 aws_instance.foo.0: 222 ID = bar 223 foo = foo 224 type = aws_instance 225 ` 226 227 const testTerraformApplyCountTaintedStr = ` 228 <no state> 229 ` 230 231 const testTerraformApplyCountVariableStr = ` 232 aws_instance.foo.0: 233 ID = foo 234 foo = foo 235 type = aws_instance 236 aws_instance.foo.1: 237 ID = foo 238 foo = foo 239 type = aws_instance 240 ` 241 242 const testTerraformApplyMinimalStr = ` 243 aws_instance.bar: 244 ID = foo 245 aws_instance.foo: 246 ID = foo 247 ` 248 249 const testTerraformApplyModuleStr = ` 250 aws_instance.bar: 251 ID = foo 252 foo = bar 253 type = aws_instance 254 aws_instance.foo: 255 ID = foo 256 num = 2 257 type = aws_instance 258 259 module.child: 260 aws_instance.baz: 261 ID = foo 262 foo = bar 263 type = aws_instance 264 ` 265 266 const testTerraformApplyProvisionerStr = ` 267 aws_instance.bar: 268 ID = foo 269 270 Dependencies: 271 aws_instance.foo 272 aws_instance.foo: 273 ID = foo 274 dynamical = computed_dynamical 275 num = 2 276 type = aws_instance 277 ` 278 279 const testTerraformApplyProvisionerFailStr = ` 280 aws_instance.bar: (1 tainted) 281 ID = <not created> 282 Tainted ID 1 = foo 283 aws_instance.foo: 284 ID = foo 285 num = 2 286 type = aws_instance 287 ` 288 289 const testTerraformApplyProvisionerFailCreateStr = ` 290 aws_instance.bar: (1 tainted) 291 ID = <not created> 292 Tainted ID 1 = foo 293 ` 294 295 const testTerraformApplyProvisionerFailCreateNoIdStr = ` 296 <no state> 297 ` 298 299 const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = ` 300 aws_instance.bar: (1 tainted) 301 ID = bar 302 require_new = abc 303 Tainted ID 1 = foo 304 ` 305 306 const testTerraformApplyProvisionerResourceRefStr = ` 307 aws_instance.bar: 308 ID = foo 309 num = 2 310 type = aws_instance 311 ` 312 313 const testTerraformApplyProvisionerDiffStr = ` 314 aws_instance.bar: 315 ID = foo 316 foo = bar 317 type = aws_instance 318 ` 319 320 const testTerraformApplyDestroyStr = ` 321 <no state> 322 ` 323 324 const testTerraformApplyErrorStr = ` 325 aws_instance.bar: 326 ID = bar 327 328 Dependencies: 329 aws_instance.foo 330 aws_instance.foo: 331 ID = foo 332 num = 2 333 ` 334 335 const testTerraformApplyErrorCreateBeforeDestroyStr = ` 336 aws_instance.bar: 337 ID = bar 338 require_new = abc 339 ` 340 341 const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = ` 342 aws_instance.bar: (1 tainted) 343 ID = foo 344 Tainted ID 1 = bar 345 ` 346 347 const testTerraformApplyErrorPartialStr = ` 348 aws_instance.bar: 349 ID = bar 350 351 Dependencies: 352 aws_instance.foo 353 aws_instance.foo: 354 ID = foo 355 num = 2 356 ` 357 358 const testTerraformApplyTaintStr = ` 359 aws_instance.bar: 360 ID = foo 361 num = 2 362 type = aws_instance 363 ` 364 365 const testTerraformApplyOutputStr = ` 366 aws_instance.bar: 367 ID = foo 368 foo = bar 369 type = aws_instance 370 aws_instance.foo: 371 ID = foo 372 num = 2 373 type = aws_instance 374 375 Outputs: 376 377 foo_num = 2 378 ` 379 380 const testTerraformApplyOutputMultiStr = ` 381 aws_instance.bar.0: 382 ID = foo 383 foo = bar 384 type = aws_instance 385 aws_instance.bar.1: 386 ID = foo 387 foo = bar 388 type = aws_instance 389 aws_instance.bar.2: 390 ID = foo 391 foo = bar 392 type = aws_instance 393 aws_instance.foo: 394 ID = foo 395 num = 2 396 type = aws_instance 397 398 Outputs: 399 400 foo_num = bar,bar,bar 401 ` 402 403 const testTerraformApplyOutputMultiIndexStr = ` 404 aws_instance.bar.0: 405 ID = foo 406 foo = bar 407 type = aws_instance 408 aws_instance.bar.1: 409 ID = foo 410 foo = bar 411 type = aws_instance 412 aws_instance.bar.2: 413 ID = foo 414 foo = bar 415 type = aws_instance 416 aws_instance.foo: 417 ID = foo 418 num = 2 419 type = aws_instance 420 421 Outputs: 422 423 foo_num = bar 424 ` 425 426 const testTerraformApplyUnknownAttrStr = ` 427 aws_instance.foo: 428 ID = foo 429 num = 2 430 type = aws_instance 431 ` 432 433 const testTerraformApplyVarsStr = ` 434 aws_instance.bar: 435 ID = foo 436 bar = foo 437 baz = override 438 foo = us-west-2 439 type = aws_instance 440 aws_instance.foo: 441 ID = foo 442 bar = baz 443 num = 2 444 type = aws_instance 445 ` 446 447 const testTerraformPlanStr = ` 448 DIFF: 449 450 CREATE: aws_instance.bar 451 foo: "" => "2" 452 type: "" => "aws_instance" 453 CREATE: aws_instance.foo 454 num: "" => "2" 455 type: "" => "aws_instance" 456 457 STATE: 458 459 <no state> 460 ` 461 462 const testTerraformPlanComputedStr = ` 463 DIFF: 464 465 CREATE: aws_instance.bar 466 foo: "" => "<computed>" 467 type: "" => "aws_instance" 468 CREATE: aws_instance.foo 469 foo: "" => "<computed>" 470 num: "" => "2" 471 type: "" => "aws_instance" 472 473 STATE: 474 475 <no state> 476 ` 477 478 const testTerraformPlanComputedIdStr = ` 479 DIFF: 480 481 CREATE: aws_instance.bar 482 foo: "" => "<computed>" 483 type: "" => "aws_instance" 484 CREATE: aws_instance.foo 485 foo: "" => "<computed>" 486 num: "" => "2" 487 type: "" => "aws_instance" 488 489 STATE: 490 491 <no state> 492 ` 493 494 const testTerraformPlanComputedListStr = ` 495 DIFF: 496 497 CREATE: aws_instance.bar 498 foo: "" => "<computed>" 499 type: "" => "aws_instance" 500 CREATE: aws_instance.foo 501 list.#: "" => "<computed>" 502 num: "" => "2" 503 type: "" => "aws_instance" 504 505 STATE: 506 507 <no state> 508 ` 509 510 const testTerraformPlanCountStr = ` 511 DIFF: 512 513 CREATE: aws_instance.bar 514 foo: "" => "foo,foo,foo,foo,foo" 515 type: "" => "aws_instance" 516 CREATE: aws_instance.foo.0 517 foo: "" => "foo" 518 type: "" => "aws_instance" 519 CREATE: aws_instance.foo.1 520 foo: "" => "foo" 521 type: "" => "aws_instance" 522 CREATE: aws_instance.foo.2 523 foo: "" => "foo" 524 type: "" => "aws_instance" 525 CREATE: aws_instance.foo.3 526 foo: "" => "foo" 527 type: "" => "aws_instance" 528 CREATE: aws_instance.foo.4 529 foo: "" => "foo" 530 type: "" => "aws_instance" 531 532 STATE: 533 534 <no state> 535 ` 536 537 const testTerraformPlanCountIndexStr = ` 538 DIFF: 539 540 CREATE: aws_instance.foo.0 541 foo: "" => "0" 542 type: "" => "aws_instance" 543 CREATE: aws_instance.foo.1 544 foo: "" => "1" 545 type: "" => "aws_instance" 546 547 STATE: 548 549 <no state> 550 ` 551 552 const testTerraformPlanCountIndexZeroStr = ` 553 DIFF: 554 555 CREATE: aws_instance.foo 556 foo: "" => "0" 557 type: "" => "aws_instance" 558 559 STATE: 560 561 <no state> 562 ` 563 564 const testTerraformPlanCountOneIndexStr = ` 565 DIFF: 566 567 CREATE: aws_instance.bar 568 foo: "" => "foo" 569 type: "" => "aws_instance" 570 CREATE: aws_instance.foo 571 foo: "" => "foo" 572 type: "" => "aws_instance" 573 574 STATE: 575 576 <no state> 577 ` 578 579 const testTerraformPlanCountZeroStr = ` 580 DIFF: 581 582 CREATE: aws_instance.bar 583 foo: "" => "" 584 type: "" => "aws_instance" 585 586 STATE: 587 588 <no state> 589 ` 590 591 const testTerraformPlanCountVarStr = ` 592 DIFF: 593 594 CREATE: aws_instance.bar 595 foo: "" => "foo,foo,foo" 596 type: "" => "aws_instance" 597 CREATE: aws_instance.foo.0 598 foo: "" => "foo" 599 type: "" => "aws_instance" 600 CREATE: aws_instance.foo.1 601 foo: "" => "foo" 602 type: "" => "aws_instance" 603 CREATE: aws_instance.foo.2 604 foo: "" => "foo" 605 type: "" => "aws_instance" 606 607 STATE: 608 609 <no state> 610 ` 611 612 const testTerraformPlanCountDecreaseStr = ` 613 DIFF: 614 615 CREATE: aws_instance.bar 616 foo: "" => "bar" 617 type: "" => "aws_instance" 618 DESTROY: aws_instance.foo.1 619 DESTROY: aws_instance.foo.2 620 621 STATE: 622 623 aws_instance.foo.0: 624 ID = bar 625 foo = foo 626 type = aws_instance 627 aws_instance.foo.1: 628 ID = bar 629 aws_instance.foo.2: 630 ID = bar 631 ` 632 633 const testTerraformPlanCountIncreaseStr = ` 634 DIFF: 635 636 CREATE: aws_instance.bar 637 foo: "" => "bar" 638 type: "" => "aws_instance" 639 CREATE: aws_instance.foo.1 640 foo: "" => "foo" 641 type: "" => "aws_instance" 642 CREATE: aws_instance.foo.2 643 foo: "" => "foo" 644 type: "" => "aws_instance" 645 646 STATE: 647 648 aws_instance.foo: 649 ID = bar 650 foo = foo 651 type = aws_instance 652 ` 653 654 const testTerraformPlanCountIncreaseFromOneStr = ` 655 DIFF: 656 657 CREATE: aws_instance.bar 658 foo: "" => "bar" 659 type: "" => "aws_instance" 660 CREATE: aws_instance.foo.1 661 foo: "" => "foo" 662 type: "" => "aws_instance" 663 CREATE: aws_instance.foo.2 664 foo: "" => "foo" 665 type: "" => "aws_instance" 666 667 STATE: 668 669 aws_instance.foo.0: 670 ID = bar 671 foo = foo 672 type = aws_instance 673 ` 674 675 const testTerraformPlanDestroyStr = ` 676 DIFF: 677 678 DESTROY: aws_instance.one 679 DESTROY: aws_instance.two 680 681 STATE: 682 683 aws_instance.one: 684 ID = bar 685 aws_instance.two: 686 ID = baz 687 ` 688 689 const testTerraformPlanDiffVarStr = ` 690 DIFF: 691 692 CREATE: aws_instance.bar 693 num: "" => "3" 694 type: "" => "aws_instance" 695 UPDATE: aws_instance.foo 696 num: "2" => "3" 697 698 STATE: 699 700 aws_instance.foo: 701 ID = bar 702 num = 2 703 ` 704 705 const testTerraformPlanEmptyStr = ` 706 DIFF: 707 708 CREATE: aws_instance.bar 709 CREATE: aws_instance.foo 710 711 STATE: 712 713 <no state> 714 ` 715 716 const testTerraformPlanModulesStr = ` 717 DIFF: 718 719 CREATE: aws_instance.bar 720 foo: "" => "2" 721 type: "" => "aws_instance" 722 CREATE: aws_instance.foo 723 num: "" => "2" 724 type: "" => "aws_instance" 725 726 module.child: 727 CREATE: aws_instance.foo 728 num: "" => "2" 729 type: "" => "aws_instance" 730 731 STATE: 732 733 <no state> 734 ` 735 736 const testTerraformPlanModuleDestroyStr = ` 737 DIFF: 738 739 DESTROY: aws_instance.foo 740 741 module.child: 742 DESTROY: aws_instance.foo 743 744 STATE: 745 746 aws_instance.foo: 747 ID = bar 748 749 module.child: 750 aws_instance.foo: 751 ID = bar 752 ` 753 754 const testTerraformPlanModuleInputStr = ` 755 DIFF: 756 757 CREATE: aws_instance.bar 758 foo: "" => "2" 759 type: "" => "aws_instance" 760 761 module.child: 762 CREATE: aws_instance.foo 763 foo: "" => "42" 764 type: "" => "aws_instance" 765 766 STATE: 767 768 <no state> 769 ` 770 771 const testTerraformPlanModuleInputComputedStr = ` 772 DIFF: 773 774 CREATE: aws_instance.bar 775 foo: "" => "<computed>" 776 type: "" => "aws_instance" 777 778 module.child: 779 CREATE: aws_instance.foo 780 foo: "" => "<computed>" 781 type: "" => "aws_instance" 782 783 STATE: 784 785 <no state> 786 ` 787 788 const testTerraformPlanModuleInputVarStr = ` 789 DIFF: 790 791 CREATE: aws_instance.bar 792 foo: "" => "2" 793 type: "" => "aws_instance" 794 795 module.child: 796 CREATE: aws_instance.foo 797 foo: "" => "52" 798 type: "" => "aws_instance" 799 800 STATE: 801 802 <no state> 803 ` 804 805 const testTerraformPlanModuleOrphansStr = ` 806 DIFF: 807 808 CREATE: aws_instance.foo 809 num: "" => "2" 810 type: "" => "aws_instance" 811 812 module.child: 813 DESTROY: aws_instance.foo 814 815 STATE: 816 817 module.child: 818 aws_instance.foo: 819 ID = baz 820 ` 821 822 const testTerraformPlanModuleVarStr = ` 823 DIFF: 824 825 CREATE: aws_instance.bar 826 foo: "" => "2" 827 type: "" => "aws_instance" 828 829 module.child: 830 CREATE: aws_instance.foo 831 num: "" => "2" 832 type: "" => "aws_instance" 833 834 STATE: 835 836 <no state> 837 ` 838 839 const testTerraformPlanModuleVarComputedStr = ` 840 DIFF: 841 842 CREATE: aws_instance.bar 843 foo: "" => "<computed>" 844 type: "" => "aws_instance" 845 846 module.child: 847 CREATE: aws_instance.foo 848 foo: "" => "<computed>" 849 type: "" => "aws_instance" 850 851 STATE: 852 853 <no state> 854 ` 855 856 const testTerraformPlanOrphanStr = ` 857 DIFF: 858 859 DESTROY: aws_instance.baz 860 CREATE: aws_instance.foo 861 num: "" => "2" 862 type: "" => "aws_instance" 863 864 STATE: 865 866 aws_instance.baz: 867 ID = bar 868 ` 869 870 const testTerraformPlanStateStr = ` 871 DIFF: 872 873 CREATE: aws_instance.bar 874 foo: "" => "2" 875 type: "" => "aws_instance" 876 UPDATE: aws_instance.foo 877 num: "" => "2" 878 type: "" => "aws_instance" 879 880 STATE: 881 882 aws_instance.foo: 883 ID = bar 884 ` 885 886 const testTerraformPlanTaintStr = ` 887 DIFF: 888 889 DESTROY/CREATE: aws_instance.bar 890 foo: "" => "2" 891 type: "" => "aws_instance" 892 893 STATE: 894 895 aws_instance.bar: (1 tainted) 896 ID = <not created> 897 Tainted ID 1 = baz 898 aws_instance.foo: 899 ID = bar 900 num = 2 901 ` 902 903 const testTerraformPlanMultipleTaintStr = ` 904 DIFF: 905 906 DESTROY/CREATE: aws_instance.bar 907 foo: "" => "2" 908 type: "" => "aws_instance" 909 910 STATE: 911 912 aws_instance.bar: (2 tainted) 913 ID = <not created> 914 Tainted ID 1 = baz 915 Tainted ID 2 = zip 916 aws_instance.foo: 917 ID = bar 918 num = 2 919 ` 920 921 const testTerraformPlanVarMultiCountOneStr = ` 922 DIFF: 923 924 CREATE: aws_instance.bar 925 foo: "" => "2" 926 type: "" => "aws_instance" 927 CREATE: aws_instance.foo 928 num: "" => "2" 929 type: "" => "aws_instance" 930 931 STATE: 932 933 <no state> 934 ` 935 936 const testTerraformPlanPathVarStr = ` 937 DIFF: 938 939 CREATE: aws_instance.foo 940 cwd: "" => "%s/barpath" 941 module: "" => "%s/foopath" 942 root: "" => "%s/barpath" 943 type: "" => "aws_instance" 944 945 STATE: 946 947 <no state> 948 `