github.com/adamar/terraform@v0.2.2-0.20141016210445-2e703afdad0e/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 testTerraformApplyMinimalStr = ` 232 aws_instance.bar: 233 ID = foo 234 aws_instance.foo: 235 ID = foo 236 ` 237 238 const testTerraformApplyModuleStr = ` 239 aws_instance.bar: 240 ID = foo 241 foo = bar 242 type = aws_instance 243 aws_instance.foo: 244 ID = foo 245 num = 2 246 type = aws_instance 247 248 module.child: 249 aws_instance.baz: 250 ID = foo 251 foo = bar 252 type = aws_instance 253 ` 254 255 const testTerraformApplyProvisionerStr = ` 256 aws_instance.bar: 257 ID = foo 258 259 Dependencies: 260 aws_instance.foo 261 aws_instance.foo: 262 ID = foo 263 dynamical = computed_dynamical 264 num = 2 265 type = aws_instance 266 ` 267 268 const testTerraformApplyProvisionerFailStr = ` 269 aws_instance.bar: (1 tainted) 270 ID = <not created> 271 Tainted ID 1 = foo 272 aws_instance.foo: 273 ID = foo 274 num = 2 275 type = aws_instance 276 ` 277 278 const testTerraformApplyProvisionerFailCreateBeforeDestroyStr = ` 279 aws_instance.bar: (1 tainted) 280 ID = bar 281 require_new = abc 282 Tainted ID 1 = foo 283 ` 284 285 const testTerraformApplyProvisionerResourceRefStr = ` 286 aws_instance.bar: 287 ID = foo 288 num = 2 289 type = aws_instance 290 ` 291 292 const testTerraformApplyProvisionerDiffStr = ` 293 aws_instance.bar: 294 ID = foo 295 foo = bar 296 type = aws_instance 297 ` 298 299 const testTerraformApplyDestroyStr = ` 300 <no state> 301 ` 302 303 const testTerraformApplyErrorStr = ` 304 aws_instance.bar: 305 ID = bar 306 307 Dependencies: 308 aws_instance.foo 309 aws_instance.foo: 310 ID = foo 311 num = 2 312 ` 313 314 const testTerraformApplyErrorCreateBeforeDestroyStr = ` 315 aws_instance.bar: 316 ID = bar 317 require_new = abc 318 ` 319 320 const testTerraformApplyErrorDestroyCreateBeforeDestroyStr = ` 321 aws_instance.bar: (1 tainted) 322 ID = foo 323 Tainted ID 1 = bar 324 ` 325 326 const testTerraformApplyErrorPartialStr = ` 327 aws_instance.bar: 328 ID = bar 329 330 Dependencies: 331 aws_instance.foo 332 aws_instance.foo: 333 ID = foo 334 num = 2 335 ` 336 337 const testTerraformApplyTaintStr = ` 338 aws_instance.bar: 339 ID = foo 340 num = 2 341 type = aws_instance 342 ` 343 344 const testTerraformApplyOutputStr = ` 345 aws_instance.bar: 346 ID = foo 347 foo = bar 348 type = aws_instance 349 aws_instance.foo: 350 ID = foo 351 num = 2 352 type = aws_instance 353 354 Outputs: 355 356 foo_num = 2 357 ` 358 359 const testTerraformApplyOutputMultiStr = ` 360 aws_instance.bar.0: 361 ID = foo 362 foo = bar 363 type = aws_instance 364 aws_instance.bar.1: 365 ID = foo 366 foo = bar 367 type = aws_instance 368 aws_instance.bar.2: 369 ID = foo 370 foo = bar 371 type = aws_instance 372 aws_instance.foo: 373 ID = foo 374 num = 2 375 type = aws_instance 376 377 Outputs: 378 379 foo_num = bar,bar,bar 380 ` 381 382 const testTerraformApplyOutputMultiIndexStr = ` 383 aws_instance.bar.0: 384 ID = foo 385 foo = bar 386 type = aws_instance 387 aws_instance.bar.1: 388 ID = foo 389 foo = bar 390 type = aws_instance 391 aws_instance.bar.2: 392 ID = foo 393 foo = bar 394 type = aws_instance 395 aws_instance.foo: 396 ID = foo 397 num = 2 398 type = aws_instance 399 400 Outputs: 401 402 foo_num = bar 403 ` 404 405 const testTerraformApplyUnknownAttrStr = ` 406 aws_instance.foo: 407 ID = foo 408 num = 2 409 type = aws_instance 410 ` 411 412 const testTerraformApplyVarsStr = ` 413 aws_instance.bar: 414 ID = foo 415 bar = foo 416 baz = override 417 foo = us-west-2 418 type = aws_instance 419 aws_instance.foo: 420 ID = foo 421 bar = baz 422 num = 2 423 type = aws_instance 424 ` 425 426 const testTerraformPlanStr = ` 427 DIFF: 428 429 CREATE: aws_instance.bar 430 foo: "" => "2" 431 type: "" => "aws_instance" 432 CREATE: aws_instance.foo 433 num: "" => "2" 434 type: "" => "aws_instance" 435 436 STATE: 437 438 <no state> 439 ` 440 441 const testTerraformPlanComputedStr = ` 442 DIFF: 443 444 CREATE: aws_instance.bar 445 foo: "" => "<computed>" 446 type: "" => "aws_instance" 447 CREATE: aws_instance.foo 448 foo: "" => "<computed>" 449 num: "" => "2" 450 type: "" => "aws_instance" 451 452 STATE: 453 454 <no state> 455 ` 456 457 const testTerraformPlanComputedIdStr = ` 458 DIFF: 459 460 CREATE: aws_instance.bar 461 foo: "" => "<computed>" 462 type: "" => "aws_instance" 463 CREATE: aws_instance.foo 464 foo: "" => "<computed>" 465 num: "" => "2" 466 type: "" => "aws_instance" 467 468 STATE: 469 470 <no state> 471 ` 472 473 const testTerraformPlanComputedListStr = ` 474 DIFF: 475 476 CREATE: aws_instance.bar 477 foo: "" => "<computed>" 478 type: "" => "aws_instance" 479 CREATE: aws_instance.foo 480 list.#: "" => "<computed>" 481 num: "" => "2" 482 type: "" => "aws_instance" 483 484 STATE: 485 486 <no state> 487 ` 488 489 const testTerraformPlanCountStr = ` 490 DIFF: 491 492 CREATE: aws_instance.bar 493 foo: "" => "foo,foo,foo,foo,foo" 494 type: "" => "aws_instance" 495 CREATE: aws_instance.foo.0 496 foo: "" => "foo" 497 type: "" => "aws_instance" 498 CREATE: aws_instance.foo.1 499 foo: "" => "foo" 500 type: "" => "aws_instance" 501 CREATE: aws_instance.foo.2 502 foo: "" => "foo" 503 type: "" => "aws_instance" 504 CREATE: aws_instance.foo.3 505 foo: "" => "foo" 506 type: "" => "aws_instance" 507 CREATE: aws_instance.foo.4 508 foo: "" => "foo" 509 type: "" => "aws_instance" 510 511 STATE: 512 513 <no state> 514 ` 515 516 const testTerraformPlanCountIndexStr = ` 517 DIFF: 518 519 CREATE: aws_instance.foo.0 520 foo: "" => "0" 521 type: "" => "aws_instance" 522 CREATE: aws_instance.foo.1 523 foo: "" => "1" 524 type: "" => "aws_instance" 525 526 STATE: 527 528 <no state> 529 ` 530 531 const testTerraformPlanCountIndexZeroStr = ` 532 DIFF: 533 534 CREATE: aws_instance.foo 535 foo: "" => "0" 536 type: "" => "aws_instance" 537 538 STATE: 539 540 <no state> 541 ` 542 543 const testTerraformPlanCountOneIndexStr = ` 544 DIFF: 545 546 CREATE: aws_instance.bar 547 foo: "" => "foo" 548 type: "" => "aws_instance" 549 CREATE: aws_instance.foo 550 foo: "" => "foo" 551 type: "" => "aws_instance" 552 553 STATE: 554 555 <no state> 556 ` 557 558 const testTerraformPlanCountZeroStr = ` 559 DIFF: 560 561 CREATE: aws_instance.bar 562 foo: "" => "" 563 type: "" => "aws_instance" 564 565 STATE: 566 567 <no state> 568 ` 569 570 const testTerraformPlanCountVarStr = ` 571 DIFF: 572 573 CREATE: aws_instance.bar 574 foo: "" => "foo,foo,foo" 575 type: "" => "aws_instance" 576 CREATE: aws_instance.foo.0 577 foo: "" => "foo" 578 type: "" => "aws_instance" 579 CREATE: aws_instance.foo.1 580 foo: "" => "foo" 581 type: "" => "aws_instance" 582 CREATE: aws_instance.foo.2 583 foo: "" => "foo" 584 type: "" => "aws_instance" 585 586 STATE: 587 588 <no state> 589 ` 590 591 const testTerraformPlanCountDecreaseStr = ` 592 DIFF: 593 594 CREATE: aws_instance.bar 595 foo: "" => "bar" 596 type: "" => "aws_instance" 597 DESTROY: aws_instance.foo.1 598 DESTROY: aws_instance.foo.2 599 600 STATE: 601 602 aws_instance.foo.0: 603 ID = bar 604 foo = foo 605 type = aws_instance 606 aws_instance.foo.1: 607 ID = bar 608 aws_instance.foo.2: 609 ID = bar 610 ` 611 612 const testTerraformPlanCountIncreaseStr = ` 613 DIFF: 614 615 CREATE: aws_instance.bar 616 foo: "" => "bar" 617 type: "" => "aws_instance" 618 CREATE: aws_instance.foo.1 619 foo: "" => "foo" 620 type: "" => "aws_instance" 621 CREATE: aws_instance.foo.2 622 foo: "" => "foo" 623 type: "" => "aws_instance" 624 625 STATE: 626 627 aws_instance.foo: 628 ID = bar 629 foo = foo 630 type = aws_instance 631 ` 632 633 const testTerraformPlanCountIncreaseFromOneStr = ` 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.0: 649 ID = bar 650 foo = foo 651 type = aws_instance 652 ` 653 654 const testTerraformPlanDestroyStr = ` 655 DIFF: 656 657 DESTROY: aws_instance.one 658 DESTROY: aws_instance.two 659 660 STATE: 661 662 aws_instance.one: 663 ID = bar 664 aws_instance.two: 665 ID = baz 666 ` 667 668 const testTerraformPlanDiffVarStr = ` 669 DIFF: 670 671 CREATE: aws_instance.bar 672 num: "" => "3" 673 type: "" => "aws_instance" 674 UPDATE: aws_instance.foo 675 num: "2" => "3" 676 677 STATE: 678 679 aws_instance.foo: 680 ID = bar 681 num = 2 682 ` 683 684 const testTerraformPlanEmptyStr = ` 685 DIFF: 686 687 CREATE: aws_instance.bar 688 CREATE: aws_instance.foo 689 690 STATE: 691 692 <no state> 693 ` 694 695 const testTerraformPlanModulesStr = ` 696 DIFF: 697 698 CREATE: aws_instance.bar 699 foo: "" => "2" 700 type: "" => "aws_instance" 701 CREATE: aws_instance.foo 702 num: "" => "2" 703 type: "" => "aws_instance" 704 705 module.child: 706 CREATE: aws_instance.foo 707 num: "" => "2" 708 type: "" => "aws_instance" 709 710 STATE: 711 712 <no state> 713 ` 714 715 const testTerraformPlanModuleDestroyStr = ` 716 DIFF: 717 718 DESTROY: aws_instance.foo 719 720 module.child: 721 DESTROY: aws_instance.foo 722 723 STATE: 724 725 aws_instance.foo: 726 ID = bar 727 728 module.child: 729 aws_instance.foo: 730 ID = bar 731 ` 732 733 const testTerraformPlanModuleInputStr = ` 734 DIFF: 735 736 CREATE: aws_instance.bar 737 foo: "" => "2" 738 type: "" => "aws_instance" 739 740 module.child: 741 CREATE: aws_instance.foo 742 foo: "" => "42" 743 type: "" => "aws_instance" 744 745 STATE: 746 747 <no state> 748 ` 749 750 const testTerraformPlanModuleInputComputedStr = ` 751 DIFF: 752 753 CREATE: aws_instance.bar 754 foo: "" => "<computed>" 755 type: "" => "aws_instance" 756 757 module.child: 758 CREATE: aws_instance.foo 759 foo: "" => "<computed>" 760 type: "" => "aws_instance" 761 762 STATE: 763 764 <no state> 765 ` 766 767 const testTerraformPlanModuleInputVarStr = ` 768 DIFF: 769 770 CREATE: aws_instance.bar 771 foo: "" => "2" 772 type: "" => "aws_instance" 773 774 module.child: 775 CREATE: aws_instance.foo 776 foo: "" => "52" 777 type: "" => "aws_instance" 778 779 STATE: 780 781 <no state> 782 ` 783 784 const testTerraformPlanModuleOrphansStr = ` 785 DIFF: 786 787 CREATE: aws_instance.foo 788 num: "" => "2" 789 type: "" => "aws_instance" 790 791 module.child: 792 DESTROY: aws_instance.foo 793 794 STATE: 795 796 module.child: 797 aws_instance.foo: 798 ID = baz 799 ` 800 801 const testTerraformPlanModuleVarStr = ` 802 DIFF: 803 804 CREATE: aws_instance.bar 805 foo: "" => "2" 806 type: "" => "aws_instance" 807 808 module.child: 809 CREATE: aws_instance.foo 810 num: "" => "2" 811 type: "" => "aws_instance" 812 813 STATE: 814 815 <no state> 816 ` 817 818 const testTerraformPlanModuleVarComputedStr = ` 819 DIFF: 820 821 CREATE: aws_instance.bar 822 foo: "" => "<computed>" 823 type: "" => "aws_instance" 824 825 module.child: 826 CREATE: aws_instance.foo 827 foo: "" => "<computed>" 828 type: "" => "aws_instance" 829 830 STATE: 831 832 <no state> 833 ` 834 835 const testTerraformPlanOrphanStr = ` 836 DIFF: 837 838 DESTROY: aws_instance.baz 839 CREATE: aws_instance.foo 840 num: "" => "2" 841 type: "" => "aws_instance" 842 843 STATE: 844 845 aws_instance.baz: 846 ID = bar 847 ` 848 849 const testTerraformPlanStateStr = ` 850 DIFF: 851 852 CREATE: aws_instance.bar 853 foo: "" => "2" 854 type: "" => "aws_instance" 855 UPDATE: aws_instance.foo 856 num: "" => "2" 857 type: "" => "aws_instance" 858 859 STATE: 860 861 aws_instance.foo: 862 ID = bar 863 ` 864 865 const testTerraformPlanTaintStr = ` 866 DIFF: 867 868 DESTROY/CREATE: aws_instance.bar 869 foo: "" => "2" 870 type: "" => "aws_instance" 871 872 STATE: 873 874 aws_instance.bar: (1 tainted) 875 ID = <not created> 876 Tainted ID 1 = baz 877 aws_instance.foo: 878 ID = bar 879 num = 2 880 ` 881 882 const testTerraformPlanMultipleTaintStr = ` 883 DIFF: 884 885 DESTROY/CREATE: aws_instance.bar 886 foo: "" => "2" 887 type: "" => "aws_instance" 888 889 STATE: 890 891 aws_instance.bar: (2 tainted) 892 ID = <not created> 893 Tainted ID 1 = baz 894 Tainted ID 2 = zip 895 aws_instance.foo: 896 ID = bar 897 num = 2 898 ` 899 900 const testTerraformPlanVarMultiCountOneStr = ` 901 DIFF: 902 903 CREATE: aws_instance.bar 904 foo: "" => "2" 905 type: "" => "aws_instance" 906 CREATE: aws_instance.foo 907 num: "" => "2" 908 type: "" => "aws_instance" 909 910 STATE: 911 912 <no state> 913 ` 914 915 const testTerraformPlanPathVarStr = ` 916 DIFF: 917 918 CREATE: aws_instance.foo 919 cwd: "" => "%s/barpath" 920 module: "" => "%s/foopath" 921 root: "" => "%s/barpath" 922 type: "" => "aws_instance" 923 924 STATE: 925 926 <no state> 927 `