github.com/hobbeswalsh/terraform@v0.3.7-0.20150619183303-ad17cf55a0fa/terraform/context_test.go (about) 1 package terraform 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "reflect" 8 "sort" 9 "strings" 10 "sync" 11 "sync/atomic" 12 "testing" 13 "time" 14 ) 15 16 func TestContext2Plan(t *testing.T) { 17 m := testModule(t, "plan-good") 18 p := testProvider("aws") 19 p.DiffFn = testDiffFn 20 ctx := testContext2(t, &ContextOpts{ 21 Module: m, 22 Providers: map[string]ResourceProviderFactory{ 23 "aws": testProviderFuncFixed(p), 24 }, 25 }) 26 27 plan, err := ctx.Plan() 28 if err != nil { 29 t.Fatalf("err: %s", err) 30 } 31 32 if len(plan.Diff.RootModule().Resources) < 2 { 33 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 34 } 35 36 actual := strings.TrimSpace(plan.String()) 37 expected := strings.TrimSpace(testTerraformPlanStr) 38 if actual != expected { 39 t.Fatalf("bad:\n%s", actual) 40 } 41 } 42 43 func TestContext2Plan_createBefore_maintainRoot(t *testing.T) { 44 m := testModule(t, "plan-cbd-maintain-root") 45 p := testProvider("aws") 46 p.DiffFn = testDiffFn 47 ctx := testContext2(t, &ContextOpts{ 48 Module: m, 49 Providers: map[string]ResourceProviderFactory{ 50 "aws": testProviderFuncFixed(p), 51 }, 52 Variables: map[string]string{ 53 "in": "a,b,c", 54 }, 55 }) 56 57 plan, err := ctx.Plan() 58 if err != nil { 59 t.Fatalf("err: %s", err) 60 } 61 62 actual := strings.TrimSpace(plan.String()) 63 expected := strings.TrimSpace(` 64 DIFF: 65 66 CREATE: aws_instance.bar.0 67 CREATE: aws_instance.bar.1 68 CREATE: aws_instance.foo.0 69 CREATE: aws_instance.foo.1 70 71 STATE: 72 73 <no state> 74 `) 75 if actual != expected { 76 t.Fatalf("expected:\n%s, got:\n%s", expected, actual) 77 } 78 } 79 80 func TestContext2Plan_emptyDiff(t *testing.T) { 81 m := testModule(t, "plan-empty") 82 p := testProvider("aws") 83 p.DiffFn = func( 84 info *InstanceInfo, 85 s *InstanceState, 86 c *ResourceConfig) (*InstanceDiff, error) { 87 return nil, nil 88 } 89 90 ctx := testContext2(t, &ContextOpts{ 91 Module: m, 92 Providers: map[string]ResourceProviderFactory{ 93 "aws": testProviderFuncFixed(p), 94 }, 95 }) 96 97 plan, err := ctx.Plan() 98 if err != nil { 99 t.Fatalf("err: %s", err) 100 } 101 102 actual := strings.TrimSpace(plan.String()) 103 expected := strings.TrimSpace(testTerraformPlanEmptyStr) 104 if actual != expected { 105 t.Fatalf("bad:\n%s", actual) 106 } 107 } 108 109 func TestContext2Plan_minimal(t *testing.T) { 110 m := testModule(t, "plan-empty") 111 p := testProvider("aws") 112 p.DiffFn = testDiffFn 113 ctx := testContext2(t, &ContextOpts{ 114 Module: m, 115 Providers: map[string]ResourceProviderFactory{ 116 "aws": testProviderFuncFixed(p), 117 }, 118 }) 119 120 plan, err := ctx.Plan() 121 if err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 125 actual := strings.TrimSpace(plan.String()) 126 expected := strings.TrimSpace(testTerraformPlanEmptyStr) 127 if actual != expected { 128 t.Fatalf("bad:\n%s", actual) 129 } 130 } 131 132 func TestContext2Plan_modules(t *testing.T) { 133 m := testModule(t, "plan-modules") 134 p := testProvider("aws") 135 p.DiffFn = testDiffFn 136 ctx := testContext2(t, &ContextOpts{ 137 Module: m, 138 Providers: map[string]ResourceProviderFactory{ 139 "aws": testProviderFuncFixed(p), 140 }, 141 }) 142 143 plan, err := ctx.Plan() 144 if err != nil { 145 t.Fatalf("err: %s", err) 146 } 147 148 actual := strings.TrimSpace(plan.String()) 149 expected := strings.TrimSpace(testTerraformPlanModulesStr) 150 if actual != expected { 151 t.Fatalf("bad:\n%s", actual) 152 } 153 } 154 155 // GH-1475 156 func TestContext2Plan_moduleCycle(t *testing.T) { 157 m := testModule(t, "plan-module-cycle") 158 p := testProvider("aws") 159 p.DiffFn = testDiffFn 160 ctx := testContext2(t, &ContextOpts{ 161 Module: m, 162 Providers: map[string]ResourceProviderFactory{ 163 "aws": testProviderFuncFixed(p), 164 }, 165 }) 166 167 plan, err := ctx.Plan() 168 if err != nil { 169 t.Fatalf("err: %s", err) 170 } 171 172 actual := strings.TrimSpace(plan.String()) 173 expected := strings.TrimSpace(testTerraformPlanModuleCycleStr) 174 if actual != expected { 175 t.Fatalf("bad:\n%s", actual) 176 } 177 } 178 179 func TestContext2Plan_moduleDeadlock(t *testing.T) { 180 m := testModule(t, "plan-module-deadlock") 181 p := testProvider("aws") 182 p.DiffFn = testDiffFn 183 timeout := make(chan bool, 1) 184 done := make(chan bool, 1) 185 go func() { 186 time.Sleep(3 * time.Second) 187 timeout <- true 188 }() 189 go func() { 190 ctx := testContext2(t, &ContextOpts{ 191 Module: m, 192 Providers: map[string]ResourceProviderFactory{ 193 "aws": testProviderFuncFixed(p), 194 }, 195 }) 196 197 plan, err := ctx.Plan() 198 done <- true 199 if err != nil { 200 t.Fatalf("err: %s", err) 201 } 202 203 actual := strings.TrimSpace(plan.String()) 204 expected := strings.TrimSpace(` 205 DIFF: 206 207 module.child: 208 CREATE: aws_instance.foo.0 209 CREATE: aws_instance.foo.1 210 CREATE: aws_instance.foo.2 211 212 STATE: 213 214 <no state> 215 `) 216 if actual != expected { 217 t.Fatalf("expected:\n%sgot:\n%s", expected, actual) 218 } 219 }() 220 221 select { 222 case <-timeout: 223 t.Fatalf("timed out! probably deadlock") 224 case <-done: 225 // ok 226 } 227 } 228 229 func TestContext2Plan_moduleInput(t *testing.T) { 230 m := testModule(t, "plan-module-input") 231 p := testProvider("aws") 232 p.DiffFn = testDiffFn 233 ctx := testContext2(t, &ContextOpts{ 234 Module: m, 235 Providers: map[string]ResourceProviderFactory{ 236 "aws": testProviderFuncFixed(p), 237 }, 238 }) 239 240 plan, err := ctx.Plan() 241 if err != nil { 242 t.Fatalf("err: %s", err) 243 } 244 245 actual := strings.TrimSpace(plan.String()) 246 expected := strings.TrimSpace(testTerraformPlanModuleInputStr) 247 if actual != expected { 248 t.Fatalf("bad:\n%s", actual) 249 } 250 } 251 252 func TestContext2Plan_moduleInputComputed(t *testing.T) { 253 m := testModule(t, "plan-module-input-computed") 254 p := testProvider("aws") 255 p.DiffFn = testDiffFn 256 ctx := testContext2(t, &ContextOpts{ 257 Module: m, 258 Providers: map[string]ResourceProviderFactory{ 259 "aws": testProviderFuncFixed(p), 260 }, 261 }) 262 263 plan, err := ctx.Plan() 264 if err != nil { 265 t.Fatalf("err: %s", err) 266 } 267 268 actual := strings.TrimSpace(plan.String()) 269 expected := strings.TrimSpace(testTerraformPlanModuleInputComputedStr) 270 if actual != expected { 271 t.Fatalf("bad:\n%s", actual) 272 } 273 } 274 275 func TestContext2Plan_moduleInputFromVar(t *testing.T) { 276 m := testModule(t, "plan-module-input-var") 277 p := testProvider("aws") 278 p.DiffFn = testDiffFn 279 ctx := testContext2(t, &ContextOpts{ 280 Module: m, 281 Providers: map[string]ResourceProviderFactory{ 282 "aws": testProviderFuncFixed(p), 283 }, 284 Variables: map[string]string{ 285 "foo": "52", 286 }, 287 }) 288 289 plan, err := ctx.Plan() 290 if err != nil { 291 t.Fatalf("err: %s", err) 292 } 293 294 actual := strings.TrimSpace(plan.String()) 295 expected := strings.TrimSpace(testTerraformPlanModuleInputVarStr) 296 if actual != expected { 297 t.Fatalf("bad:\n%s", actual) 298 } 299 } 300 301 func TestContext2Plan_moduleMultiVar(t *testing.T) { 302 m := testModule(t, "plan-module-multi-var") 303 p := testProvider("aws") 304 p.DiffFn = testDiffFn 305 ctx := testContext2(t, &ContextOpts{ 306 Module: m, 307 Providers: map[string]ResourceProviderFactory{ 308 "aws": testProviderFuncFixed(p), 309 }, 310 }) 311 312 plan, err := ctx.Plan() 313 if err != nil { 314 t.Fatalf("err: %s", err) 315 } 316 317 actual := strings.TrimSpace(plan.String()) 318 expected := strings.TrimSpace(testTerraformPlanModuleMultiVarStr) 319 if actual != expected { 320 t.Fatalf("bad:\n%s", actual) 321 } 322 } 323 324 func TestContext2Plan_moduleOrphans(t *testing.T) { 325 m := testModule(t, "plan-modules-remove") 326 p := testProvider("aws") 327 p.DiffFn = testDiffFn 328 s := &State{ 329 Modules: []*ModuleState{ 330 &ModuleState{ 331 Path: []string{"root", "child"}, 332 Resources: map[string]*ResourceState{ 333 "aws_instance.foo": &ResourceState{ 334 Type: "aws_instance", 335 Primary: &InstanceState{ 336 ID: "baz", 337 }, 338 }, 339 }, 340 }, 341 }, 342 } 343 ctx := testContext2(t, &ContextOpts{ 344 Module: m, 345 Providers: map[string]ResourceProviderFactory{ 346 "aws": testProviderFuncFixed(p), 347 }, 348 State: s, 349 }) 350 351 plan, err := ctx.Plan() 352 if err != nil { 353 t.Fatalf("err: %s", err) 354 } 355 356 actual := strings.TrimSpace(plan.String()) 357 expected := strings.TrimSpace(testTerraformPlanModuleOrphansStr) 358 if actual != expected { 359 t.Fatalf("bad:\n%s", actual) 360 } 361 } 362 363 func TestContext2Plan_moduleProviderInherit(t *testing.T) { 364 var l sync.Mutex 365 var calls []string 366 367 m := testModule(t, "plan-module-provider-inherit") 368 ctx := testContext2(t, &ContextOpts{ 369 Module: m, 370 Providers: map[string]ResourceProviderFactory{ 371 "aws": func() (ResourceProvider, error) { 372 l.Lock() 373 defer l.Unlock() 374 375 p := testProvider("aws") 376 p.ConfigureFn = func(c *ResourceConfig) error { 377 if v, ok := c.Get("from"); !ok || v.(string) != "root" { 378 return fmt.Errorf("bad") 379 } 380 381 return nil 382 } 383 p.DiffFn = func( 384 info *InstanceInfo, 385 state *InstanceState, 386 c *ResourceConfig) (*InstanceDiff, error) { 387 v, _ := c.Get("from") 388 calls = append(calls, v.(string)) 389 return testDiffFn(info, state, c) 390 } 391 return p, nil 392 }, 393 }, 394 }) 395 396 _, err := ctx.Plan() 397 if err != nil { 398 t.Fatalf("err: %s", err) 399 } 400 401 actual := calls 402 sort.Strings(actual) 403 expected := []string{"child", "root"} 404 if !reflect.DeepEqual(actual, expected) { 405 t.Fatalf("bad: %#v", actual) 406 } 407 } 408 409 func TestContext2Plan_moduleProviderDefaults(t *testing.T) { 410 var l sync.Mutex 411 var calls []string 412 toCount := 0 413 414 m := testModule(t, "plan-module-provider-defaults") 415 ctx := testContext2(t, &ContextOpts{ 416 Module: m, 417 Providers: map[string]ResourceProviderFactory{ 418 "aws": func() (ResourceProvider, error) { 419 l.Lock() 420 defer l.Unlock() 421 422 p := testProvider("aws") 423 p.ConfigureFn = func(c *ResourceConfig) error { 424 if v, ok := c.Get("from"); !ok || v.(string) != "root" { 425 return fmt.Errorf("bad") 426 } 427 if v, ok := c.Get("to"); ok && v.(string) == "child" { 428 toCount++ 429 } 430 431 return nil 432 } 433 p.DiffFn = func( 434 info *InstanceInfo, 435 state *InstanceState, 436 c *ResourceConfig) (*InstanceDiff, error) { 437 v, _ := c.Get("from") 438 calls = append(calls, v.(string)) 439 return testDiffFn(info, state, c) 440 } 441 return p, nil 442 }, 443 }, 444 }) 445 446 _, err := ctx.Plan() 447 if err != nil { 448 t.Fatalf("err: %s", err) 449 } 450 451 if toCount != 1 { 452 t.Fatalf( 453 "provider in child didn't set proper config\n\n"+ 454 "toCount: %d", toCount) 455 } 456 457 actual := calls 458 sort.Strings(actual) 459 expected := []string{"child", "root"} 460 if !reflect.DeepEqual(actual, expected) { 461 t.Fatalf("bad: %#v", actual) 462 } 463 } 464 465 func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) { 466 var l sync.Mutex 467 var calls []string 468 469 m := testModule(t, "plan-module-provider-defaults-var") 470 ctx := testContext2(t, &ContextOpts{ 471 Module: m, 472 Providers: map[string]ResourceProviderFactory{ 473 "aws": func() (ResourceProvider, error) { 474 l.Lock() 475 defer l.Unlock() 476 477 p := testProvider("aws") 478 p.ConfigureFn = func(c *ResourceConfig) error { 479 var buf bytes.Buffer 480 if v, ok := c.Get("from"); ok { 481 buf.WriteString(v.(string) + "\n") 482 } 483 if v, ok := c.Get("to"); ok { 484 buf.WriteString(v.(string) + "\n") 485 } 486 487 calls = append(calls, buf.String()) 488 return nil 489 } 490 p.DiffFn = testDiffFn 491 return p, nil 492 }, 493 }, 494 Variables: map[string]string{ 495 "foo": "root", 496 }, 497 }) 498 499 _, err := ctx.Plan() 500 if err != nil { 501 t.Fatalf("err: %s", err) 502 } 503 504 expected := []string{ 505 "root\n", 506 "root\nchild\n", 507 } 508 if !reflect.DeepEqual(calls, expected) { 509 t.Fatalf("BAD: %#v", calls) 510 } 511 } 512 513 func TestContext2Plan_moduleVar(t *testing.T) { 514 m := testModule(t, "plan-module-var") 515 p := testProvider("aws") 516 p.DiffFn = testDiffFn 517 ctx := testContext2(t, &ContextOpts{ 518 Module: m, 519 Providers: map[string]ResourceProviderFactory{ 520 "aws": testProviderFuncFixed(p), 521 }, 522 }) 523 524 plan, err := ctx.Plan() 525 if err != nil { 526 t.Fatalf("err: %s", err) 527 } 528 529 actual := strings.TrimSpace(plan.String()) 530 expected := strings.TrimSpace(testTerraformPlanModuleVarStr) 531 if actual != expected { 532 t.Fatalf("bad:\n%s", actual) 533 } 534 } 535 536 func TestContext2Plan_moduleVarComputed(t *testing.T) { 537 m := testModule(t, "plan-module-var-computed") 538 p := testProvider("aws") 539 p.DiffFn = testDiffFn 540 ctx := testContext2(t, &ContextOpts{ 541 Module: m, 542 Providers: map[string]ResourceProviderFactory{ 543 "aws": testProviderFuncFixed(p), 544 }, 545 }) 546 547 plan, err := ctx.Plan() 548 if err != nil { 549 t.Fatalf("err: %s", err) 550 } 551 552 actual := strings.TrimSpace(plan.String()) 553 expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr) 554 if actual != expected { 555 t.Fatalf("bad:\n%s", actual) 556 } 557 } 558 559 func TestContext2Plan_nil(t *testing.T) { 560 m := testModule(t, "plan-nil") 561 p := testProvider("aws") 562 p.DiffFn = testDiffFn 563 ctx := testContext2(t, &ContextOpts{ 564 Module: m, 565 Providers: map[string]ResourceProviderFactory{ 566 "aws": testProviderFuncFixed(p), 567 }, 568 State: &State{ 569 Modules: []*ModuleState{ 570 &ModuleState{ 571 Path: rootModulePath, 572 Resources: map[string]*ResourceState{ 573 "aws_instance.foo": &ResourceState{ 574 Type: "aws_instance", 575 Primary: &InstanceState{ 576 ID: "bar", 577 }, 578 }, 579 }, 580 }, 581 }, 582 }, 583 }) 584 585 plan, err := ctx.Plan() 586 if err != nil { 587 t.Fatalf("err: %s", err) 588 } 589 if len(plan.Diff.RootModule().Resources) != 0 { 590 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 591 } 592 } 593 594 func TestContext2Plan_preventDestroy_bad(t *testing.T) { 595 m := testModule(t, "plan-prevent-destroy-bad") 596 p := testProvider("aws") 597 p.DiffFn = testDiffFn 598 ctx := testContext2(t, &ContextOpts{ 599 Module: m, 600 Providers: map[string]ResourceProviderFactory{ 601 "aws": testProviderFuncFixed(p), 602 }, 603 State: &State{ 604 Modules: []*ModuleState{ 605 &ModuleState{ 606 Path: rootModulePath, 607 Resources: map[string]*ResourceState{ 608 "aws_instance.foo": &ResourceState{ 609 Type: "aws_instance", 610 Primary: &InstanceState{ 611 ID: "i-abc123", 612 }, 613 }, 614 }, 615 }, 616 }, 617 }, 618 }) 619 620 plan, err := ctx.Plan() 621 622 expectedErr := "aws_instance.foo: plan would destroy" 623 if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) { 624 t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s", 625 expectedErr, err, plan) 626 } 627 } 628 629 func TestContext2Plan_preventDestroy_good(t *testing.T) { 630 m := testModule(t, "plan-prevent-destroy-good") 631 p := testProvider("aws") 632 p.DiffFn = testDiffFn 633 ctx := testContext2(t, &ContextOpts{ 634 Module: m, 635 Providers: map[string]ResourceProviderFactory{ 636 "aws": testProviderFuncFixed(p), 637 }, 638 State: &State{ 639 Modules: []*ModuleState{ 640 &ModuleState{ 641 Path: rootModulePath, 642 Resources: map[string]*ResourceState{ 643 "aws_instance.foo": &ResourceState{ 644 Type: "aws_instance", 645 Primary: &InstanceState{ 646 ID: "i-abc123", 647 }, 648 }, 649 }, 650 }, 651 }, 652 }, 653 }) 654 655 plan, err := ctx.Plan() 656 if err != nil { 657 t.Fatalf("err: %s", err) 658 } 659 if !plan.Diff.Empty() { 660 t.Fatalf("Expected empty plan, got %s", plan.String()) 661 } 662 } 663 664 func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) { 665 m := testModule(t, "plan-prevent-destroy-good") 666 p := testProvider("aws") 667 p.DiffFn = testDiffFn 668 ctx := testContext2(t, &ContextOpts{ 669 Module: m, 670 Providers: map[string]ResourceProviderFactory{ 671 "aws": testProviderFuncFixed(p), 672 }, 673 State: &State{ 674 Modules: []*ModuleState{ 675 &ModuleState{ 676 Path: rootModulePath, 677 Resources: map[string]*ResourceState{ 678 "aws_instance.foo": &ResourceState{ 679 Type: "aws_instance", 680 Primary: &InstanceState{ 681 ID: "i-abc123", 682 }, 683 }, 684 }, 685 }, 686 }, 687 }, 688 Destroy: true, 689 }) 690 691 plan, err := ctx.Plan() 692 693 expectedErr := "aws_instance.foo: plan would destroy" 694 if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) { 695 t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s", 696 expectedErr, err, plan) 697 } 698 } 699 700 func TestContext2Plan_providerAliasMissing(t *testing.T) { 701 m := testModule(t, "apply-provider-alias-missing") 702 p := testProvider("aws") 703 p.ApplyFn = testApplyFn 704 p.DiffFn = testDiffFn 705 state := &State{ 706 Modules: []*ModuleState{ 707 &ModuleState{ 708 Path: rootModulePath, 709 Resources: map[string]*ResourceState{ 710 "aws_instance.foo": &ResourceState{ 711 Type: "aws_instance", 712 Provider: "aws.foo", 713 Primary: &InstanceState{ 714 ID: "bar", 715 Attributes: map[string]string{ 716 "require_new": "abc", 717 }, 718 }, 719 }, 720 }, 721 }, 722 }, 723 } 724 ctx := testContext2(t, &ContextOpts{ 725 Module: m, 726 Providers: map[string]ResourceProviderFactory{ 727 "aws": testProviderFuncFixed(p), 728 }, 729 State: state, 730 }) 731 732 if _, err := ctx.Plan(); err == nil { 733 t.Fatal("should err") 734 } 735 } 736 737 func TestContext2Plan_computed(t *testing.T) { 738 m := testModule(t, "plan-computed") 739 p := testProvider("aws") 740 p.DiffFn = testDiffFn 741 ctx := testContext2(t, &ContextOpts{ 742 Module: m, 743 Providers: map[string]ResourceProviderFactory{ 744 "aws": testProviderFuncFixed(p), 745 }, 746 }) 747 748 plan, err := ctx.Plan() 749 if err != nil { 750 t.Fatalf("err: %s", err) 751 } 752 753 actual := strings.TrimSpace(plan.String()) 754 expected := strings.TrimSpace(testTerraformPlanComputedStr) 755 if actual != expected { 756 t.Fatalf("bad:\n%s", actual) 757 } 758 } 759 760 func TestContext2Plan_computedList(t *testing.T) { 761 m := testModule(t, "plan-computed-list") 762 p := testProvider("aws") 763 p.DiffFn = testDiffFn 764 ctx := testContext2(t, &ContextOpts{ 765 Module: m, 766 Providers: map[string]ResourceProviderFactory{ 767 "aws": testProviderFuncFixed(p), 768 }, 769 }) 770 771 plan, err := ctx.Plan() 772 if err != nil { 773 t.Fatalf("err: %s", err) 774 } 775 776 actual := strings.TrimSpace(plan.String()) 777 expected := strings.TrimSpace(testTerraformPlanComputedListStr) 778 if actual != expected { 779 t.Fatalf("bad:\n%s", actual) 780 } 781 } 782 783 func TestContext2Plan_count(t *testing.T) { 784 m := testModule(t, "plan-count") 785 p := testProvider("aws") 786 p.DiffFn = testDiffFn 787 ctx := testContext2(t, &ContextOpts{ 788 Module: m, 789 Providers: map[string]ResourceProviderFactory{ 790 "aws": testProviderFuncFixed(p), 791 }, 792 }) 793 794 plan, err := ctx.Plan() 795 if err != nil { 796 t.Fatalf("err: %s", err) 797 } 798 799 if len(plan.Diff.RootModule().Resources) < 6 { 800 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 801 } 802 803 actual := strings.TrimSpace(plan.String()) 804 expected := strings.TrimSpace(testTerraformPlanCountStr) 805 if actual != expected { 806 t.Fatalf("bad:\n%s", actual) 807 } 808 } 809 810 func TestContext2Plan_countComputed(t *testing.T) { 811 m := testModule(t, "plan-count-computed") 812 p := testProvider("aws") 813 p.DiffFn = testDiffFn 814 ctx := testContext2(t, &ContextOpts{ 815 Module: m, 816 Providers: map[string]ResourceProviderFactory{ 817 "aws": testProviderFuncFixed(p), 818 }, 819 }) 820 821 _, err := ctx.Plan() 822 if err == nil { 823 t.Fatal("should error") 824 } 825 } 826 827 func TestContext2Plan_countIndex(t *testing.T) { 828 m := testModule(t, "plan-count-index") 829 p := testProvider("aws") 830 p.DiffFn = testDiffFn 831 ctx := testContext2(t, &ContextOpts{ 832 Module: m, 833 Providers: map[string]ResourceProviderFactory{ 834 "aws": testProviderFuncFixed(p), 835 }, 836 }) 837 838 plan, err := ctx.Plan() 839 if err != nil { 840 t.Fatalf("err: %s", err) 841 } 842 843 actual := strings.TrimSpace(plan.String()) 844 expected := strings.TrimSpace(testTerraformPlanCountIndexStr) 845 if actual != expected { 846 t.Fatalf("bad:\n%s", actual) 847 } 848 } 849 850 func TestContext2Plan_countIndexZero(t *testing.T) { 851 m := testModule(t, "plan-count-index-zero") 852 p := testProvider("aws") 853 p.DiffFn = testDiffFn 854 ctx := testContext2(t, &ContextOpts{ 855 Module: m, 856 Providers: map[string]ResourceProviderFactory{ 857 "aws": testProviderFuncFixed(p), 858 }, 859 }) 860 861 plan, err := ctx.Plan() 862 if err != nil { 863 t.Fatalf("err: %s", err) 864 } 865 866 actual := strings.TrimSpace(plan.String()) 867 expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr) 868 if actual != expected { 869 t.Fatalf("bad:\n%s", actual) 870 } 871 } 872 873 func TestContext2Plan_countVar(t *testing.T) { 874 m := testModule(t, "plan-count-var") 875 p := testProvider("aws") 876 p.DiffFn = testDiffFn 877 ctx := testContext2(t, &ContextOpts{ 878 Module: m, 879 Providers: map[string]ResourceProviderFactory{ 880 "aws": testProviderFuncFixed(p), 881 }, 882 Variables: map[string]string{ 883 "count": "3", 884 }, 885 }) 886 887 plan, err := ctx.Plan() 888 if err != nil { 889 t.Fatalf("err: %s", err) 890 } 891 892 actual := strings.TrimSpace(plan.String()) 893 expected := strings.TrimSpace(testTerraformPlanCountVarStr) 894 if actual != expected { 895 t.Fatalf("bad:\n%s", actual) 896 } 897 } 898 899 func TestContext2Plan_countZero(t *testing.T) { 900 m := testModule(t, "plan-count-zero") 901 p := testProvider("aws") 902 p.DiffFn = testDiffFn 903 ctx := testContext2(t, &ContextOpts{ 904 Module: m, 905 Providers: map[string]ResourceProviderFactory{ 906 "aws": testProviderFuncFixed(p), 907 }, 908 }) 909 910 plan, err := ctx.Plan() 911 if err != nil { 912 t.Fatalf("err: %s", err) 913 } 914 915 actual := strings.TrimSpace(plan.String()) 916 expected := strings.TrimSpace(testTerraformPlanCountZeroStr) 917 if actual != expected { 918 t.Fatalf("bad:\n%s", actual) 919 } 920 } 921 922 func TestContext2Plan_countOneIndex(t *testing.T) { 923 m := testModule(t, "plan-count-one-index") 924 p := testProvider("aws") 925 p.DiffFn = testDiffFn 926 ctx := testContext2(t, &ContextOpts{ 927 Module: m, 928 Providers: map[string]ResourceProviderFactory{ 929 "aws": testProviderFuncFixed(p), 930 }, 931 }) 932 933 plan, err := ctx.Plan() 934 if err != nil { 935 t.Fatalf("err: %s", err) 936 } 937 938 actual := strings.TrimSpace(plan.String()) 939 expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr) 940 if actual != expected { 941 t.Fatalf("bad:\n%s", actual) 942 } 943 } 944 945 func TestContext2Plan_countDecreaseToOne(t *testing.T) { 946 m := testModule(t, "plan-count-dec") 947 p := testProvider("aws") 948 p.DiffFn = testDiffFn 949 s := &State{ 950 Modules: []*ModuleState{ 951 &ModuleState{ 952 Path: rootModulePath, 953 Resources: map[string]*ResourceState{ 954 "aws_instance.foo.0": &ResourceState{ 955 Type: "aws_instance", 956 Primary: &InstanceState{ 957 ID: "bar", 958 Attributes: map[string]string{ 959 "foo": "foo", 960 "type": "aws_instance", 961 }, 962 }, 963 }, 964 "aws_instance.foo.1": &ResourceState{ 965 Type: "aws_instance", 966 Primary: &InstanceState{ 967 ID: "bar", 968 }, 969 }, 970 "aws_instance.foo.2": &ResourceState{ 971 Type: "aws_instance", 972 Primary: &InstanceState{ 973 ID: "bar", 974 }, 975 }, 976 }, 977 }, 978 }, 979 } 980 ctx := testContext2(t, &ContextOpts{ 981 Module: m, 982 Providers: map[string]ResourceProviderFactory{ 983 "aws": testProviderFuncFixed(p), 984 }, 985 State: s, 986 }) 987 988 plan, err := ctx.Plan() 989 if err != nil { 990 t.Fatalf("err: %s", err) 991 } 992 993 actual := strings.TrimSpace(plan.String()) 994 expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr) 995 if actual != expected { 996 t.Fatalf("bad:\n%s", actual) 997 } 998 } 999 1000 func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) { 1001 m := testModule(t, "plan-count-inc") 1002 p := testProvider("aws") 1003 p.DiffFn = testDiffFn 1004 s := &State{ 1005 Modules: []*ModuleState{ 1006 &ModuleState{ 1007 Path: rootModulePath, 1008 Resources: map[string]*ResourceState{ 1009 "aws_instance.foo": &ResourceState{ 1010 Type: "aws_instance", 1011 Primary: &InstanceState{ 1012 ID: "bar", 1013 Attributes: map[string]string{ 1014 "foo": "foo", 1015 "type": "aws_instance", 1016 }, 1017 }, 1018 }, 1019 }, 1020 }, 1021 }, 1022 } 1023 ctx := testContext2(t, &ContextOpts{ 1024 Module: m, 1025 Providers: map[string]ResourceProviderFactory{ 1026 "aws": testProviderFuncFixed(p), 1027 }, 1028 State: s, 1029 }) 1030 1031 plan, err := ctx.Plan() 1032 if err != nil { 1033 t.Fatalf("err: %s", err) 1034 } 1035 1036 actual := strings.TrimSpace(plan.String()) 1037 expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr) 1038 if actual != expected { 1039 t.Fatalf("bad:\n%s", actual) 1040 } 1041 } 1042 1043 func TestContext2Plan_countIncreaseFromOne(t *testing.T) { 1044 m := testModule(t, "plan-count-inc") 1045 p := testProvider("aws") 1046 p.DiffFn = testDiffFn 1047 s := &State{ 1048 Modules: []*ModuleState{ 1049 &ModuleState{ 1050 Path: rootModulePath, 1051 Resources: map[string]*ResourceState{ 1052 "aws_instance.foo.0": &ResourceState{ 1053 Type: "aws_instance", 1054 Primary: &InstanceState{ 1055 ID: "bar", 1056 Attributes: map[string]string{ 1057 "foo": "foo", 1058 "type": "aws_instance", 1059 }, 1060 }, 1061 }, 1062 }, 1063 }, 1064 }, 1065 } 1066 ctx := testContext2(t, &ContextOpts{ 1067 Module: m, 1068 Providers: map[string]ResourceProviderFactory{ 1069 "aws": testProviderFuncFixed(p), 1070 }, 1071 State: s, 1072 }) 1073 1074 plan, err := ctx.Plan() 1075 if err != nil { 1076 t.Fatalf("err: %s", err) 1077 } 1078 1079 actual := strings.TrimSpace(plan.String()) 1080 expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr) 1081 if actual != expected { 1082 t.Fatalf("bad:\n%s", actual) 1083 } 1084 } 1085 1086 // https://github.com/PeoplePerHour/terraform/pull/11 1087 // 1088 // This tests a case where both a "resource" and "resource.0" are in 1089 // the state file, which apparently is a reasonable backwards compatibility 1090 // concern found in the above 3rd party repo. 1091 func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) { 1092 m := testModule(t, "plan-count-inc") 1093 p := testProvider("aws") 1094 p.DiffFn = testDiffFn 1095 s := &State{ 1096 Modules: []*ModuleState{ 1097 &ModuleState{ 1098 Path: rootModulePath, 1099 Resources: map[string]*ResourceState{ 1100 "aws_instance.foo": &ResourceState{ 1101 Type: "aws_instance", 1102 Primary: &InstanceState{ 1103 ID: "bar", 1104 Attributes: map[string]string{ 1105 "foo": "foo", 1106 "type": "aws_instance", 1107 }, 1108 }, 1109 }, 1110 "aws_instance.foo.0": &ResourceState{ 1111 Type: "aws_instance", 1112 Primary: &InstanceState{ 1113 ID: "bar", 1114 Attributes: map[string]string{ 1115 "foo": "foo", 1116 "type": "aws_instance", 1117 }, 1118 }, 1119 }, 1120 }, 1121 }, 1122 }, 1123 } 1124 ctx := testContext2(t, &ContextOpts{ 1125 Module: m, 1126 Providers: map[string]ResourceProviderFactory{ 1127 "aws": testProviderFuncFixed(p), 1128 }, 1129 State: s, 1130 }) 1131 1132 plan, err := ctx.Plan() 1133 if err != nil { 1134 t.Fatalf("err: %s", err) 1135 } 1136 1137 actual := strings.TrimSpace(plan.String()) 1138 expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr) 1139 if actual != expected { 1140 t.Fatalf("bad:\n%s", actual) 1141 } 1142 } 1143 1144 func TestContext2Plan_destroy(t *testing.T) { 1145 m := testModule(t, "plan-destroy") 1146 p := testProvider("aws") 1147 p.DiffFn = testDiffFn 1148 s := &State{ 1149 Modules: []*ModuleState{ 1150 &ModuleState{ 1151 Path: rootModulePath, 1152 Resources: map[string]*ResourceState{ 1153 "aws_instance.one": &ResourceState{ 1154 Type: "aws_instance", 1155 Primary: &InstanceState{ 1156 ID: "bar", 1157 }, 1158 }, 1159 "aws_instance.two": &ResourceState{ 1160 Type: "aws_instance", 1161 Primary: &InstanceState{ 1162 ID: "baz", 1163 }, 1164 }, 1165 }, 1166 }, 1167 }, 1168 } 1169 ctx := testContext2(t, &ContextOpts{ 1170 Module: m, 1171 Providers: map[string]ResourceProviderFactory{ 1172 "aws": testProviderFuncFixed(p), 1173 }, 1174 State: s, 1175 Destroy: true, 1176 }) 1177 1178 plan, err := ctx.Plan() 1179 if err != nil { 1180 t.Fatalf("err: %s", err) 1181 } 1182 1183 if len(plan.Diff.RootModule().Resources) != 2 { 1184 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 1185 } 1186 1187 actual := strings.TrimSpace(plan.String()) 1188 expected := strings.TrimSpace(testTerraformPlanDestroyStr) 1189 if actual != expected { 1190 t.Fatalf("bad:\n%s", actual) 1191 } 1192 } 1193 1194 func TestContext2Plan_moduleDestroy(t *testing.T) { 1195 m := testModule(t, "plan-module-destroy") 1196 p := testProvider("aws") 1197 p.DiffFn = testDiffFn 1198 s := &State{ 1199 Modules: []*ModuleState{ 1200 &ModuleState{ 1201 Path: rootModulePath, 1202 Resources: map[string]*ResourceState{ 1203 "aws_instance.foo": &ResourceState{ 1204 Type: "aws_instance", 1205 Primary: &InstanceState{ 1206 ID: "bar", 1207 }, 1208 }, 1209 }, 1210 }, 1211 &ModuleState{ 1212 Path: []string{"root", "child"}, 1213 Resources: map[string]*ResourceState{ 1214 "aws_instance.foo": &ResourceState{ 1215 Type: "aws_instance", 1216 Primary: &InstanceState{ 1217 ID: "bar", 1218 }, 1219 }, 1220 }, 1221 }, 1222 }, 1223 } 1224 ctx := testContext2(t, &ContextOpts{ 1225 Module: m, 1226 Providers: map[string]ResourceProviderFactory{ 1227 "aws": testProviderFuncFixed(p), 1228 }, 1229 State: s, 1230 Destroy: true, 1231 }) 1232 1233 plan, err := ctx.Plan() 1234 if err != nil { 1235 t.Fatalf("err: %s", err) 1236 } 1237 1238 actual := strings.TrimSpace(plan.String()) 1239 expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr) 1240 if actual != expected { 1241 t.Fatalf("bad:\n%s", actual) 1242 } 1243 } 1244 1245 // GH-1835 1246 func TestContext2Plan_moduleDestroyCycle(t *testing.T) { 1247 m := testModule(t, "plan-module-destroy-gh-1835") 1248 p := testProvider("aws") 1249 p.DiffFn = testDiffFn 1250 s := &State{ 1251 Modules: []*ModuleState{ 1252 &ModuleState{ 1253 Path: []string{"root", "a_module"}, 1254 Resources: map[string]*ResourceState{ 1255 "aws_instance.a": &ResourceState{ 1256 Type: "aws_instance", 1257 Primary: &InstanceState{ 1258 ID: "a", 1259 }, 1260 }, 1261 }, 1262 }, 1263 &ModuleState{ 1264 Path: []string{"root", "b_module"}, 1265 Resources: map[string]*ResourceState{ 1266 "aws_instance.b": &ResourceState{ 1267 Type: "aws_instance", 1268 Primary: &InstanceState{ 1269 ID: "b", 1270 }, 1271 }, 1272 }, 1273 }, 1274 }, 1275 } 1276 ctx := testContext2(t, &ContextOpts{ 1277 Module: m, 1278 Providers: map[string]ResourceProviderFactory{ 1279 "aws": testProviderFuncFixed(p), 1280 }, 1281 State: s, 1282 Destroy: true, 1283 }) 1284 1285 plan, err := ctx.Plan() 1286 if err != nil { 1287 t.Fatalf("err: %s", err) 1288 } 1289 1290 actual := strings.TrimSpace(plan.String()) 1291 expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr) 1292 if actual != expected { 1293 t.Fatalf("bad:\n%s", actual) 1294 } 1295 } 1296 1297 func TestContext2Plan_moduleDestroyMultivar(t *testing.T) { 1298 m := testModule(t, "plan-module-destroy-multivar") 1299 p := testProvider("aws") 1300 p.DiffFn = testDiffFn 1301 s := &State{ 1302 Modules: []*ModuleState{ 1303 &ModuleState{ 1304 Path: rootModulePath, 1305 Resources: map[string]*ResourceState{}, 1306 }, 1307 &ModuleState{ 1308 Path: []string{"root", "child"}, 1309 Resources: map[string]*ResourceState{ 1310 "aws_instance.foo.0": &ResourceState{ 1311 Type: "aws_instance", 1312 Primary: &InstanceState{ 1313 ID: "bar0", 1314 }, 1315 }, 1316 "aws_instance.foo.1": &ResourceState{ 1317 Type: "aws_instance", 1318 Primary: &InstanceState{ 1319 ID: "bar1", 1320 }, 1321 }, 1322 }, 1323 }, 1324 }, 1325 } 1326 ctx := testContext2(t, &ContextOpts{ 1327 Module: m, 1328 Providers: map[string]ResourceProviderFactory{ 1329 "aws": testProviderFuncFixed(p), 1330 }, 1331 State: s, 1332 Destroy: true, 1333 }) 1334 1335 plan, err := ctx.Plan() 1336 if err != nil { 1337 t.Fatalf("err: %s", err) 1338 } 1339 1340 actual := strings.TrimSpace(plan.String()) 1341 expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr) 1342 if actual != expected { 1343 t.Fatalf("bad:\n%s", actual) 1344 } 1345 } 1346 1347 func TestContext2Plan_pathVar(t *testing.T) { 1348 cwd, err := os.Getwd() 1349 if err != nil { 1350 t.Fatalf("err: %s", err) 1351 } 1352 1353 m := testModule(t, "plan-path-var") 1354 p := testProvider("aws") 1355 p.DiffFn = testDiffFn 1356 ctx := testContext2(t, &ContextOpts{ 1357 Module: m, 1358 Providers: map[string]ResourceProviderFactory{ 1359 "aws": testProviderFuncFixed(p), 1360 }, 1361 }) 1362 1363 plan, err := ctx.Plan() 1364 if err != nil { 1365 t.Fatalf("err: %s", err) 1366 } 1367 1368 actual := strings.TrimSpace(plan.String()) 1369 expected := strings.TrimSpace(testTerraformPlanPathVarStr) 1370 1371 // Warning: this ordering REALLY matters for this test. The 1372 // order is: cwd, module, root. 1373 expected = fmt.Sprintf( 1374 expected, 1375 cwd, 1376 m.Config().Dir, 1377 m.Config().Dir) 1378 1379 if actual != expected { 1380 t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected) 1381 } 1382 } 1383 1384 func TestContext2Plan_diffVar(t *testing.T) { 1385 m := testModule(t, "plan-diffvar") 1386 p := testProvider("aws") 1387 s := &State{ 1388 Modules: []*ModuleState{ 1389 &ModuleState{ 1390 Path: rootModulePath, 1391 Resources: map[string]*ResourceState{ 1392 "aws_instance.foo": &ResourceState{ 1393 Primary: &InstanceState{ 1394 ID: "bar", 1395 Attributes: map[string]string{ 1396 "num": "2", 1397 }, 1398 }, 1399 }, 1400 }, 1401 }, 1402 }, 1403 } 1404 ctx := testContext2(t, &ContextOpts{ 1405 Module: m, 1406 Providers: map[string]ResourceProviderFactory{ 1407 "aws": testProviderFuncFixed(p), 1408 }, 1409 State: s, 1410 }) 1411 1412 p.DiffFn = func( 1413 info *InstanceInfo, 1414 s *InstanceState, 1415 c *ResourceConfig) (*InstanceDiff, error) { 1416 if s.ID != "bar" { 1417 return testDiffFn(info, s, c) 1418 } 1419 1420 return &InstanceDiff{ 1421 Attributes: map[string]*ResourceAttrDiff{ 1422 "num": &ResourceAttrDiff{ 1423 Old: "2", 1424 New: "3", 1425 }, 1426 }, 1427 }, nil 1428 } 1429 1430 plan, err := ctx.Plan() 1431 if err != nil { 1432 t.Fatalf("err: %s", err) 1433 } 1434 1435 actual := strings.TrimSpace(plan.String()) 1436 expected := strings.TrimSpace(testTerraformPlanDiffVarStr) 1437 if actual != expected { 1438 t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected) 1439 } 1440 } 1441 1442 func TestContext2Plan_hook(t *testing.T) { 1443 m := testModule(t, "plan-good") 1444 h := new(MockHook) 1445 p := testProvider("aws") 1446 p.DiffFn = testDiffFn 1447 ctx := testContext2(t, &ContextOpts{ 1448 Module: m, 1449 Hooks: []Hook{h}, 1450 Providers: map[string]ResourceProviderFactory{ 1451 "aws": testProviderFuncFixed(p), 1452 }, 1453 }) 1454 1455 _, err := ctx.Plan() 1456 if err != nil { 1457 t.Fatalf("err: %s", err) 1458 } 1459 1460 if !h.PreDiffCalled { 1461 t.Fatal("should be called") 1462 } 1463 if !h.PostDiffCalled { 1464 t.Fatal("should be called") 1465 } 1466 } 1467 1468 func TestContext2Plan_orphan(t *testing.T) { 1469 m := testModule(t, "plan-orphan") 1470 p := testProvider("aws") 1471 p.DiffFn = testDiffFn 1472 s := &State{ 1473 Modules: []*ModuleState{ 1474 &ModuleState{ 1475 Path: rootModulePath, 1476 Resources: map[string]*ResourceState{ 1477 "aws_instance.baz": &ResourceState{ 1478 Type: "aws_instance", 1479 Primary: &InstanceState{ 1480 ID: "bar", 1481 }, 1482 }, 1483 }, 1484 }, 1485 }, 1486 } 1487 ctx := testContext2(t, &ContextOpts{ 1488 Module: m, 1489 Providers: map[string]ResourceProviderFactory{ 1490 "aws": testProviderFuncFixed(p), 1491 }, 1492 State: s, 1493 }) 1494 1495 plan, err := ctx.Plan() 1496 if err != nil { 1497 t.Fatalf("err: %s", err) 1498 } 1499 1500 actual := strings.TrimSpace(plan.String()) 1501 expected := strings.TrimSpace(testTerraformPlanOrphanStr) 1502 if actual != expected { 1503 t.Fatalf("bad:\n%s", actual) 1504 } 1505 } 1506 1507 func TestContext2Plan_state(t *testing.T) { 1508 m := testModule(t, "plan-good") 1509 p := testProvider("aws") 1510 p.DiffFn = testDiffFn 1511 s := &State{ 1512 Modules: []*ModuleState{ 1513 &ModuleState{ 1514 Path: rootModulePath, 1515 Resources: map[string]*ResourceState{ 1516 "aws_instance.foo": &ResourceState{ 1517 Primary: &InstanceState{ 1518 ID: "bar", 1519 }, 1520 }, 1521 }, 1522 }, 1523 }, 1524 } 1525 ctx := testContext2(t, &ContextOpts{ 1526 Module: m, 1527 Providers: map[string]ResourceProviderFactory{ 1528 "aws": testProviderFuncFixed(p), 1529 }, 1530 State: s, 1531 }) 1532 1533 plan, err := ctx.Plan() 1534 if err != nil { 1535 t.Fatalf("err: %s", err) 1536 } 1537 1538 if len(plan.Diff.RootModule().Resources) < 2 { 1539 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 1540 } 1541 1542 actual := strings.TrimSpace(plan.String()) 1543 expected := strings.TrimSpace(testTerraformPlanStateStr) 1544 if actual != expected { 1545 t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected) 1546 } 1547 } 1548 1549 func TestContext2Plan_taint(t *testing.T) { 1550 m := testModule(t, "plan-taint") 1551 p := testProvider("aws") 1552 p.DiffFn = testDiffFn 1553 s := &State{ 1554 Modules: []*ModuleState{ 1555 &ModuleState{ 1556 Path: rootModulePath, 1557 Resources: map[string]*ResourceState{ 1558 "aws_instance.foo": &ResourceState{ 1559 Type: "aws_instance", 1560 Primary: &InstanceState{ 1561 ID: "bar", 1562 Attributes: map[string]string{"num": "2"}, 1563 }, 1564 }, 1565 "aws_instance.bar": &ResourceState{ 1566 Type: "aws_instance", 1567 Tainted: []*InstanceState{ 1568 &InstanceState{ 1569 ID: "baz", 1570 }, 1571 }, 1572 }, 1573 }, 1574 }, 1575 }, 1576 } 1577 ctx := testContext2(t, &ContextOpts{ 1578 Module: m, 1579 Providers: map[string]ResourceProviderFactory{ 1580 "aws": testProviderFuncFixed(p), 1581 }, 1582 State: s, 1583 }) 1584 1585 plan, err := ctx.Plan() 1586 if err != nil { 1587 t.Fatalf("err: %s", err) 1588 } 1589 1590 actual := strings.TrimSpace(plan.String()) 1591 expected := strings.TrimSpace(testTerraformPlanTaintStr) 1592 if actual != expected { 1593 t.Fatalf("bad:\n%s", actual) 1594 } 1595 } 1596 1597 func TestContext2Plan_multiple_taint(t *testing.T) { 1598 m := testModule(t, "plan-taint") 1599 p := testProvider("aws") 1600 p.DiffFn = testDiffFn 1601 s := &State{ 1602 Modules: []*ModuleState{ 1603 &ModuleState{ 1604 Path: rootModulePath, 1605 Resources: map[string]*ResourceState{ 1606 "aws_instance.foo": &ResourceState{ 1607 Type: "aws_instance", 1608 Primary: &InstanceState{ 1609 ID: "bar", 1610 Attributes: map[string]string{"num": "2"}, 1611 }, 1612 }, 1613 "aws_instance.bar": &ResourceState{ 1614 Type: "aws_instance", 1615 Tainted: []*InstanceState{ 1616 &InstanceState{ 1617 ID: "baz", 1618 }, 1619 &InstanceState{ 1620 ID: "zip", 1621 }, 1622 }, 1623 }, 1624 }, 1625 }, 1626 }, 1627 } 1628 ctx := testContext2(t, &ContextOpts{ 1629 Module: m, 1630 Providers: map[string]ResourceProviderFactory{ 1631 "aws": testProviderFuncFixed(p), 1632 }, 1633 State: s, 1634 }) 1635 1636 plan, err := ctx.Plan() 1637 if err != nil { 1638 t.Fatalf("err: %s", err) 1639 } 1640 1641 actual := strings.TrimSpace(plan.String()) 1642 expected := strings.TrimSpace(testTerraformPlanMultipleTaintStr) 1643 if actual != expected { 1644 t.Fatalf("bad:\n%s", actual) 1645 } 1646 } 1647 1648 func TestContext2Plan_targeted(t *testing.T) { 1649 m := testModule(t, "plan-targeted") 1650 p := testProvider("aws") 1651 p.DiffFn = testDiffFn 1652 ctx := testContext2(t, &ContextOpts{ 1653 Module: m, 1654 Providers: map[string]ResourceProviderFactory{ 1655 "aws": testProviderFuncFixed(p), 1656 }, 1657 Targets: []string{"aws_instance.foo"}, 1658 }) 1659 1660 plan, err := ctx.Plan() 1661 if err != nil { 1662 t.Fatalf("err: %s", err) 1663 } 1664 1665 actual := strings.TrimSpace(plan.String()) 1666 expected := strings.TrimSpace(` 1667 DIFF: 1668 1669 CREATE: aws_instance.foo 1670 num: "" => "2" 1671 type: "" => "aws_instance" 1672 1673 STATE: 1674 1675 <no state> 1676 `) 1677 if actual != expected { 1678 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 1679 } 1680 } 1681 1682 func TestContext2Plan_provider(t *testing.T) { 1683 m := testModule(t, "plan-provider") 1684 p := testProvider("aws") 1685 p.DiffFn = testDiffFn 1686 1687 var value interface{} 1688 p.ConfigureFn = func(c *ResourceConfig) error { 1689 value, _ = c.Get("foo") 1690 return nil 1691 } 1692 1693 ctx := testContext2(t, &ContextOpts{ 1694 Module: m, 1695 Providers: map[string]ResourceProviderFactory{ 1696 "aws": testProviderFuncFixed(p), 1697 }, 1698 Variables: map[string]string{ 1699 "foo": "bar", 1700 }, 1701 }) 1702 1703 if _, err := ctx.Plan(); err != nil { 1704 t.Fatalf("err: %s", err) 1705 } 1706 1707 if value != "bar" { 1708 t.Fatalf("bad: %#v", value) 1709 } 1710 } 1711 1712 func TestContext2Plan_varMultiCountOne(t *testing.T) { 1713 m := testModule(t, "plan-var-multi-count-one") 1714 p := testProvider("aws") 1715 p.DiffFn = testDiffFn 1716 ctx := testContext2(t, &ContextOpts{ 1717 Module: m, 1718 Providers: map[string]ResourceProviderFactory{ 1719 "aws": testProviderFuncFixed(p), 1720 }, 1721 }) 1722 1723 plan, err := ctx.Plan() 1724 if err != nil { 1725 t.Fatalf("err: %s", err) 1726 } 1727 1728 actual := strings.TrimSpace(plan.String()) 1729 expected := strings.TrimSpace(testTerraformPlanVarMultiCountOneStr) 1730 if actual != expected { 1731 t.Fatalf("bad:\n%s", actual) 1732 } 1733 } 1734 1735 func TestContext2Plan_varListErr(t *testing.T) { 1736 m := testModule(t, "plan-var-list-err") 1737 p := testProvider("aws") 1738 ctx := testContext2(t, &ContextOpts{ 1739 Module: m, 1740 Providers: map[string]ResourceProviderFactory{ 1741 "aws": testProviderFuncFixed(p), 1742 }, 1743 }) 1744 1745 _, err := ctx.Plan() 1746 if err == nil { 1747 t.Fatal("should error") 1748 } 1749 } 1750 1751 func TestContext2Refresh(t *testing.T) { 1752 p := testProvider("aws") 1753 m := testModule(t, "refresh-basic") 1754 ctx := testContext2(t, &ContextOpts{ 1755 Module: m, 1756 Providers: map[string]ResourceProviderFactory{ 1757 "aws": testProviderFuncFixed(p), 1758 }, 1759 State: &State{ 1760 Modules: []*ModuleState{ 1761 &ModuleState{ 1762 Path: rootModulePath, 1763 Resources: map[string]*ResourceState{ 1764 "aws_instance.web": &ResourceState{ 1765 Type: "aws_instance", 1766 Primary: &InstanceState{ 1767 ID: "foo", 1768 }, 1769 }, 1770 }, 1771 }, 1772 }, 1773 }, 1774 }) 1775 1776 p.RefreshFn = nil 1777 p.RefreshReturn = &InstanceState{ 1778 ID: "foo", 1779 } 1780 1781 s, err := ctx.Refresh() 1782 mod := s.RootModule() 1783 if err != nil { 1784 t.Fatalf("err: %s", err) 1785 } 1786 if !p.RefreshCalled { 1787 t.Fatal("refresh should be called") 1788 } 1789 if p.RefreshState.ID != "foo" { 1790 t.Fatalf("bad: %#v", p.RefreshState) 1791 } 1792 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 1793 t.Fatalf("bad: %#v %#v", mod.Resources["aws_instance.web"], p.RefreshReturn) 1794 } 1795 1796 for _, r := range mod.Resources { 1797 if r.Type == "" { 1798 t.Fatalf("no type: %#v", r) 1799 } 1800 } 1801 } 1802 1803 func TestContext2Refresh_targeted(t *testing.T) { 1804 p := testProvider("aws") 1805 m := testModule(t, "refresh-targeted") 1806 ctx := testContext2(t, &ContextOpts{ 1807 Module: m, 1808 Providers: map[string]ResourceProviderFactory{ 1809 "aws": testProviderFuncFixed(p), 1810 }, 1811 State: &State{ 1812 Modules: []*ModuleState{ 1813 &ModuleState{ 1814 Path: rootModulePath, 1815 Resources: map[string]*ResourceState{ 1816 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 1817 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 1818 "aws_instance.me": resourceState("aws_instance", "i-abc123"), 1819 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 1820 }, 1821 }, 1822 }, 1823 }, 1824 Targets: []string{"aws_instance.me"}, 1825 }) 1826 1827 refreshedResources := make([]string, 0, 2) 1828 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 1829 refreshedResources = append(refreshedResources, i.Id) 1830 return is, nil 1831 } 1832 1833 _, err := ctx.Refresh() 1834 if err != nil { 1835 t.Fatalf("err: %s", err) 1836 } 1837 1838 expected := []string{"aws_vpc.metoo", "aws_instance.me"} 1839 if !reflect.DeepEqual(refreshedResources, expected) { 1840 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 1841 } 1842 } 1843 1844 func TestContext2Refresh_targetedCount(t *testing.T) { 1845 p := testProvider("aws") 1846 m := testModule(t, "refresh-targeted-count") 1847 ctx := testContext2(t, &ContextOpts{ 1848 Module: m, 1849 Providers: map[string]ResourceProviderFactory{ 1850 "aws": testProviderFuncFixed(p), 1851 }, 1852 State: &State{ 1853 Modules: []*ModuleState{ 1854 &ModuleState{ 1855 Path: rootModulePath, 1856 Resources: map[string]*ResourceState{ 1857 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 1858 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 1859 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 1860 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 1861 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 1862 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 1863 }, 1864 }, 1865 }, 1866 }, 1867 Targets: []string{"aws_instance.me"}, 1868 }) 1869 1870 refreshedResources := make([]string, 0, 2) 1871 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 1872 refreshedResources = append(refreshedResources, i.Id) 1873 return is, nil 1874 } 1875 1876 _, err := ctx.Refresh() 1877 if err != nil { 1878 t.Fatalf("err: %s", err) 1879 } 1880 1881 // Target didn't specify index, so we should get all our instances 1882 expected := []string{ 1883 "aws_vpc.metoo", 1884 "aws_instance.me.0", 1885 "aws_instance.me.1", 1886 "aws_instance.me.2", 1887 } 1888 sort.Strings(expected) 1889 sort.Strings(refreshedResources) 1890 if !reflect.DeepEqual(refreshedResources, expected) { 1891 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 1892 } 1893 } 1894 1895 func TestContext2Refresh_targetedCountIndex(t *testing.T) { 1896 p := testProvider("aws") 1897 m := testModule(t, "refresh-targeted-count") 1898 ctx := testContext2(t, &ContextOpts{ 1899 Module: m, 1900 Providers: map[string]ResourceProviderFactory{ 1901 "aws": testProviderFuncFixed(p), 1902 }, 1903 State: &State{ 1904 Modules: []*ModuleState{ 1905 &ModuleState{ 1906 Path: rootModulePath, 1907 Resources: map[string]*ResourceState{ 1908 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 1909 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 1910 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 1911 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 1912 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 1913 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 1914 }, 1915 }, 1916 }, 1917 }, 1918 Targets: []string{"aws_instance.me[0]"}, 1919 }) 1920 1921 refreshedResources := make([]string, 0, 2) 1922 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 1923 refreshedResources = append(refreshedResources, i.Id) 1924 return is, nil 1925 } 1926 1927 _, err := ctx.Refresh() 1928 if err != nil { 1929 t.Fatalf("err: %s", err) 1930 } 1931 1932 expected := []string{"aws_vpc.metoo", "aws_instance.me.0"} 1933 if !reflect.DeepEqual(refreshedResources, expected) { 1934 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 1935 } 1936 } 1937 1938 func TestContext2Refresh_delete(t *testing.T) { 1939 p := testProvider("aws") 1940 m := testModule(t, "refresh-basic") 1941 ctx := testContext2(t, &ContextOpts{ 1942 Module: m, 1943 Providers: map[string]ResourceProviderFactory{ 1944 "aws": testProviderFuncFixed(p), 1945 }, 1946 State: &State{ 1947 Modules: []*ModuleState{ 1948 &ModuleState{ 1949 Path: rootModulePath, 1950 Resources: map[string]*ResourceState{ 1951 "aws_instance.web": &ResourceState{ 1952 Type: "aws_instance", 1953 Primary: &InstanceState{ 1954 ID: "foo", 1955 }, 1956 }, 1957 }, 1958 }, 1959 }, 1960 }, 1961 }) 1962 1963 p.RefreshFn = nil 1964 p.RefreshReturn = nil 1965 1966 s, err := ctx.Refresh() 1967 if err != nil { 1968 t.Fatalf("err: %s", err) 1969 } 1970 1971 mod := s.RootModule() 1972 if len(mod.Resources) > 0 { 1973 t.Fatal("resources should be empty") 1974 } 1975 } 1976 1977 func TestContext2Refresh_ignoreUncreated(t *testing.T) { 1978 p := testProvider("aws") 1979 m := testModule(t, "refresh-basic") 1980 ctx := testContext2(t, &ContextOpts{ 1981 Module: m, 1982 Providers: map[string]ResourceProviderFactory{ 1983 "aws": testProviderFuncFixed(p), 1984 }, 1985 State: nil, 1986 }) 1987 1988 p.RefreshFn = nil 1989 p.RefreshReturn = &InstanceState{ 1990 ID: "foo", 1991 } 1992 1993 _, err := ctx.Refresh() 1994 if err != nil { 1995 t.Fatalf("err: %s", err) 1996 } 1997 if p.RefreshCalled { 1998 t.Fatal("refresh should not be called") 1999 } 2000 } 2001 2002 func TestContext2Refresh_hook(t *testing.T) { 2003 h := new(MockHook) 2004 p := testProvider("aws") 2005 m := testModule(t, "refresh-basic") 2006 ctx := testContext2(t, &ContextOpts{ 2007 Module: m, 2008 Hooks: []Hook{h}, 2009 Providers: map[string]ResourceProviderFactory{ 2010 "aws": testProviderFuncFixed(p), 2011 }, 2012 State: &State{ 2013 Modules: []*ModuleState{ 2014 &ModuleState{ 2015 Path: rootModulePath, 2016 Resources: map[string]*ResourceState{ 2017 "aws_instance.web": &ResourceState{ 2018 Type: "aws_instance", 2019 Primary: &InstanceState{ 2020 ID: "foo", 2021 }, 2022 }, 2023 }, 2024 }, 2025 }, 2026 }, 2027 }) 2028 2029 if _, err := ctx.Refresh(); err != nil { 2030 t.Fatalf("err: %s", err) 2031 } 2032 if !h.PreRefreshCalled { 2033 t.Fatal("should be called") 2034 } 2035 if !h.PostRefreshCalled { 2036 t.Fatal("should be called") 2037 } 2038 } 2039 2040 func TestContext2Refresh_modules(t *testing.T) { 2041 p := testProvider("aws") 2042 m := testModule(t, "refresh-modules") 2043 state := &State{ 2044 Modules: []*ModuleState{ 2045 &ModuleState{ 2046 Path: rootModulePath, 2047 Resources: map[string]*ResourceState{ 2048 "aws_instance.web": &ResourceState{ 2049 Type: "aws_instance", 2050 Tainted: []*InstanceState{ 2051 &InstanceState{ 2052 ID: "bar", 2053 }, 2054 }, 2055 }, 2056 }, 2057 }, 2058 2059 &ModuleState{ 2060 Path: []string{"root", "child"}, 2061 Resources: map[string]*ResourceState{ 2062 "aws_instance.web": &ResourceState{ 2063 Type: "aws_instance", 2064 Primary: &InstanceState{ 2065 ID: "baz", 2066 }, 2067 }, 2068 }, 2069 }, 2070 }, 2071 } 2072 ctx := testContext2(t, &ContextOpts{ 2073 Module: m, 2074 Providers: map[string]ResourceProviderFactory{ 2075 "aws": testProviderFuncFixed(p), 2076 }, 2077 State: state, 2078 }) 2079 2080 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 2081 if s.ID != "baz" { 2082 return s, nil 2083 } 2084 2085 s.ID = "new" 2086 return s, nil 2087 } 2088 2089 s, err := ctx.Refresh() 2090 if err != nil { 2091 t.Fatalf("err: %s", err) 2092 } 2093 2094 actual := strings.TrimSpace(s.String()) 2095 expected := strings.TrimSpace(testContextRefreshModuleStr) 2096 if actual != expected { 2097 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 2098 } 2099 } 2100 2101 func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) { 2102 m := testModule(t, "refresh-module-input-computed-output") 2103 p := testProvider("aws") 2104 p.DiffFn = testDiffFn 2105 ctx := testContext2(t, &ContextOpts{ 2106 Module: m, 2107 Providers: map[string]ResourceProviderFactory{ 2108 "aws": testProviderFuncFixed(p), 2109 }, 2110 }) 2111 2112 if _, err := ctx.Refresh(); err != nil { 2113 t.Fatalf("err: %s", err) 2114 } 2115 } 2116 2117 func TestContext2Refresh_moduleVarModule(t *testing.T) { 2118 m := testModule(t, "refresh-module-var-module") 2119 p := testProvider("aws") 2120 p.DiffFn = testDiffFn 2121 ctx := testContext2(t, &ContextOpts{ 2122 Module: m, 2123 Providers: map[string]ResourceProviderFactory{ 2124 "aws": testProviderFuncFixed(p), 2125 }, 2126 }) 2127 2128 if _, err := ctx.Refresh(); err != nil { 2129 t.Fatalf("err: %s", err) 2130 } 2131 } 2132 2133 // GH-70 2134 func TestContext2Refresh_noState(t *testing.T) { 2135 p := testProvider("aws") 2136 m := testModule(t, "refresh-no-state") 2137 ctx := testContext2(t, &ContextOpts{ 2138 Module: m, 2139 Providers: map[string]ResourceProviderFactory{ 2140 "aws": testProviderFuncFixed(p), 2141 }, 2142 }) 2143 2144 p.RefreshFn = nil 2145 p.RefreshReturn = &InstanceState{ 2146 ID: "foo", 2147 } 2148 2149 if _, err := ctx.Refresh(); err != nil { 2150 t.Fatalf("err: %s", err) 2151 } 2152 } 2153 2154 func TestContext2Refresh_output(t *testing.T) { 2155 p := testProvider("aws") 2156 m := testModule(t, "refresh-output") 2157 ctx := testContext2(t, &ContextOpts{ 2158 Module: m, 2159 Providers: map[string]ResourceProviderFactory{ 2160 "aws": testProviderFuncFixed(p), 2161 }, 2162 State: &State{ 2163 Modules: []*ModuleState{ 2164 &ModuleState{ 2165 Path: rootModulePath, 2166 Resources: map[string]*ResourceState{ 2167 "aws_instance.web": &ResourceState{ 2168 Type: "aws_instance", 2169 Primary: &InstanceState{ 2170 ID: "foo", 2171 Attributes: map[string]string{ 2172 "foo": "bar", 2173 }, 2174 }, 2175 }, 2176 }, 2177 2178 Outputs: map[string]string{ 2179 "foo": "foo", 2180 }, 2181 }, 2182 }, 2183 }, 2184 }) 2185 2186 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 2187 return s, nil 2188 } 2189 2190 s, err := ctx.Refresh() 2191 if err != nil { 2192 t.Fatalf("err: %s", err) 2193 } 2194 2195 actual := strings.TrimSpace(s.String()) 2196 expected := strings.TrimSpace(testContextRefreshOutputStr) 2197 if actual != expected { 2198 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 2199 } 2200 } 2201 2202 func TestContext2Refresh_outputPartial(t *testing.T) { 2203 p := testProvider("aws") 2204 m := testModule(t, "refresh-output-partial") 2205 ctx := testContext2(t, &ContextOpts{ 2206 Module: m, 2207 Providers: map[string]ResourceProviderFactory{ 2208 "aws": testProviderFuncFixed(p), 2209 }, 2210 State: &State{ 2211 Modules: []*ModuleState{ 2212 &ModuleState{ 2213 Path: rootModulePath, 2214 Resources: map[string]*ResourceState{ 2215 "aws_instance.foo": &ResourceState{ 2216 Type: "aws_instance", 2217 Primary: &InstanceState{ 2218 ID: "foo", 2219 }, 2220 }, 2221 }, 2222 }, 2223 }, 2224 }, 2225 }) 2226 2227 p.RefreshFn = nil 2228 p.RefreshReturn = nil 2229 2230 s, err := ctx.Refresh() 2231 if err != nil { 2232 t.Fatalf("err: %s", err) 2233 } 2234 2235 actual := strings.TrimSpace(s.String()) 2236 expected := strings.TrimSpace(testContextRefreshOutputPartialStr) 2237 if actual != expected { 2238 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 2239 } 2240 } 2241 2242 func TestContext2Refresh_state(t *testing.T) { 2243 p := testProvider("aws") 2244 m := testModule(t, "refresh-basic") 2245 state := &State{ 2246 Modules: []*ModuleState{ 2247 &ModuleState{ 2248 Path: rootModulePath, 2249 Resources: map[string]*ResourceState{ 2250 "aws_instance.web": &ResourceState{ 2251 Primary: &InstanceState{ 2252 ID: "bar", 2253 }, 2254 }, 2255 }, 2256 }, 2257 }, 2258 } 2259 ctx := testContext2(t, &ContextOpts{ 2260 Module: m, 2261 Providers: map[string]ResourceProviderFactory{ 2262 "aws": testProviderFuncFixed(p), 2263 }, 2264 State: state, 2265 }) 2266 2267 p.RefreshFn = nil 2268 p.RefreshReturn = &InstanceState{ 2269 ID: "foo", 2270 } 2271 2272 s, err := ctx.Refresh() 2273 if err != nil { 2274 t.Fatalf("err: %s", err) 2275 } 2276 originalMod := state.RootModule() 2277 mod := s.RootModule() 2278 if !p.RefreshCalled { 2279 t.Fatal("refresh should be called") 2280 } 2281 if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Primary) { 2282 t.Fatalf( 2283 "bad:\n\n%#v\n\n%#v", 2284 p.RefreshState, 2285 originalMod.Resources["aws_instance.web"].Primary) 2286 } 2287 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 2288 t.Fatalf("bad: %#v", mod.Resources) 2289 } 2290 } 2291 2292 func TestContext2Refresh_tainted(t *testing.T) { 2293 p := testProvider("aws") 2294 m := testModule(t, "refresh-basic") 2295 state := &State{ 2296 Modules: []*ModuleState{ 2297 &ModuleState{ 2298 Path: rootModulePath, 2299 Resources: map[string]*ResourceState{ 2300 "aws_instance.web": &ResourceState{ 2301 Type: "aws_instance", 2302 Tainted: []*InstanceState{ 2303 &InstanceState{ 2304 ID: "bar", 2305 }, 2306 }, 2307 }, 2308 }, 2309 }, 2310 }, 2311 } 2312 ctx := testContext2(t, &ContextOpts{ 2313 Module: m, 2314 Providers: map[string]ResourceProviderFactory{ 2315 "aws": testProviderFuncFixed(p), 2316 }, 2317 State: state, 2318 }) 2319 2320 p.RefreshFn = nil 2321 p.RefreshReturn = &InstanceState{ 2322 ID: "foo", 2323 } 2324 2325 s, err := ctx.Refresh() 2326 if err != nil { 2327 t.Fatalf("err: %s", err) 2328 } 2329 if !p.RefreshCalled { 2330 t.Fatal("refresh should be called") 2331 } 2332 2333 actual := strings.TrimSpace(s.String()) 2334 expected := strings.TrimSpace(testContextRefreshTaintedStr) 2335 if actual != expected { 2336 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 2337 } 2338 } 2339 2340 // Doing a Refresh (or any operation really, but Refresh usually 2341 // happens first) with a config with an unknown provider should result in 2342 // an error. The key bug this found was that this wasn't happening if 2343 // Providers was _empty_. 2344 func TestContext2Refresh_unknownProvider(t *testing.T) { 2345 m := testModule(t, "refresh-unknown-provider") 2346 p := testProvider("aws") 2347 p.ApplyFn = testApplyFn 2348 p.DiffFn = testDiffFn 2349 ctx := testContext2(t, &ContextOpts{ 2350 Module: m, 2351 Providers: map[string]ResourceProviderFactory{}, 2352 }) 2353 2354 if _, err := ctx.Refresh(); err == nil { 2355 t.Fatal("should error") 2356 } 2357 } 2358 2359 func TestContext2Refresh_vars(t *testing.T) { 2360 p := testProvider("aws") 2361 m := testModule(t, "refresh-vars") 2362 ctx := testContext2(t, &ContextOpts{ 2363 Module: m, 2364 Providers: map[string]ResourceProviderFactory{ 2365 "aws": testProviderFuncFixed(p), 2366 }, 2367 State: &State{ 2368 2369 Modules: []*ModuleState{ 2370 &ModuleState{ 2371 Path: rootModulePath, 2372 Resources: map[string]*ResourceState{ 2373 "aws_instance.web": &ResourceState{ 2374 Type: "aws_instance", 2375 Primary: &InstanceState{ 2376 ID: "foo", 2377 }, 2378 }, 2379 }, 2380 }, 2381 }, 2382 }, 2383 }) 2384 2385 p.RefreshFn = nil 2386 p.RefreshReturn = &InstanceState{ 2387 ID: "foo", 2388 } 2389 2390 s, err := ctx.Refresh() 2391 if err != nil { 2392 t.Fatalf("err: %s", err) 2393 } 2394 mod := s.RootModule() 2395 if !p.RefreshCalled { 2396 t.Fatal("refresh should be called") 2397 } 2398 if p.RefreshState.ID != "foo" { 2399 t.Fatalf("bad: %#v", p.RefreshState) 2400 } 2401 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 2402 t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"]) 2403 } 2404 2405 for _, r := range mod.Resources { 2406 if r.Type == "" { 2407 t.Fatalf("no type: %#v", r) 2408 } 2409 } 2410 } 2411 2412 func TestContext2Validate(t *testing.T) { 2413 p := testProvider("aws") 2414 m := testModule(t, "validate-good") 2415 c := testContext2(t, &ContextOpts{ 2416 Module: m, 2417 Providers: map[string]ResourceProviderFactory{ 2418 "aws": testProviderFuncFixed(p), 2419 }, 2420 }) 2421 2422 w, e := c.Validate() 2423 if len(w) > 0 { 2424 t.Fatalf("bad: %#v", w) 2425 } 2426 if len(e) > 0 { 2427 t.Fatalf("bad: %s", e) 2428 } 2429 } 2430 2431 func TestContext2Validate_badVar(t *testing.T) { 2432 p := testProvider("aws") 2433 m := testModule(t, "validate-bad-var") 2434 c := testContext2(t, &ContextOpts{ 2435 Module: m, 2436 Providers: map[string]ResourceProviderFactory{ 2437 "aws": testProviderFuncFixed(p), 2438 }, 2439 }) 2440 2441 w, e := c.Validate() 2442 if len(w) > 0 { 2443 t.Fatalf("bad: %#v", w) 2444 } 2445 if len(e) == 0 { 2446 t.Fatalf("bad: %#v", e) 2447 } 2448 } 2449 2450 func TestContext2Validate_countNegative(t *testing.T) { 2451 p := testProvider("aws") 2452 m := testModule(t, "validate-count-negative") 2453 c := testContext2(t, &ContextOpts{ 2454 Module: m, 2455 Providers: map[string]ResourceProviderFactory{ 2456 "aws": testProviderFuncFixed(p), 2457 }, 2458 }) 2459 2460 w, e := c.Validate() 2461 if len(w) > 0 { 2462 t.Fatalf("bad: %#v", w) 2463 } 2464 if len(e) == 0 { 2465 t.Fatalf("bad: %#v", e) 2466 } 2467 } 2468 2469 func TestContext2Validate_countVariable(t *testing.T) { 2470 p := testProvider("aws") 2471 m := testModule(t, "apply-count-variable") 2472 c := testContext2(t, &ContextOpts{ 2473 Module: m, 2474 Providers: map[string]ResourceProviderFactory{ 2475 "aws": testProviderFuncFixed(p), 2476 }, 2477 }) 2478 2479 w, e := c.Validate() 2480 if len(w) > 0 { 2481 t.Fatalf("bad: %#v", w) 2482 } 2483 if len(e) > 0 { 2484 t.Fatalf("bad: %s", e) 2485 } 2486 } 2487 2488 func TestContext2Validate_countVariableNoDefault(t *testing.T) { 2489 p := testProvider("aws") 2490 m := testModule(t, "validate-count-variable") 2491 c := testContext2(t, &ContextOpts{ 2492 Module: m, 2493 Providers: map[string]ResourceProviderFactory{ 2494 "aws": testProviderFuncFixed(p), 2495 }, 2496 }) 2497 2498 w, e := c.Validate() 2499 if len(w) > 0 { 2500 t.Fatalf("bad: %#v", w) 2501 } 2502 if len(e) != 1 { 2503 t.Fatalf("bad: %s", e) 2504 } 2505 } 2506 2507 /* 2508 TODO: What should we do here? 2509 func TestContext2Validate_cycle(t *testing.T) { 2510 p := testProvider("aws") 2511 m := testModule(t, "validate-cycle") 2512 c := testContext2(t, &ContextOpts{ 2513 Module: m, 2514 Providers: map[string]ResourceProviderFactory{ 2515 "aws": testProviderFuncFixed(p), 2516 }, 2517 }) 2518 2519 w, e := c.Validate() 2520 if len(w) > 0 { 2521 t.Fatalf("expected no warns, got: %#v", w) 2522 } 2523 if len(e) != 1 { 2524 t.Fatalf("expected 1 err, got: %s", e) 2525 } 2526 } 2527 */ 2528 2529 func TestContext2Validate_moduleBadOutput(t *testing.T) { 2530 p := testProvider("aws") 2531 m := testModule(t, "validate-bad-module-output") 2532 c := testContext2(t, &ContextOpts{ 2533 Module: m, 2534 Providers: map[string]ResourceProviderFactory{ 2535 "aws": testProviderFuncFixed(p), 2536 }, 2537 }) 2538 2539 w, e := c.Validate() 2540 if len(w) > 0 { 2541 t.Fatalf("bad: %#v", w) 2542 } 2543 if len(e) == 0 { 2544 t.Fatalf("bad: %s", e) 2545 } 2546 } 2547 2548 func TestContext2Validate_moduleGood(t *testing.T) { 2549 p := testProvider("aws") 2550 m := testModule(t, "validate-good-module") 2551 c := testContext2(t, &ContextOpts{ 2552 Module: m, 2553 Providers: map[string]ResourceProviderFactory{ 2554 "aws": testProviderFuncFixed(p), 2555 }, 2556 }) 2557 2558 w, e := c.Validate() 2559 if len(w) > 0 { 2560 t.Fatalf("bad: %#v", w) 2561 } 2562 if len(e) > 0 { 2563 t.Fatalf("bad: %#v", e) 2564 } 2565 } 2566 2567 func TestContext2Validate_moduleBadResource(t *testing.T) { 2568 m := testModule(t, "validate-module-bad-rc") 2569 p := testProvider("aws") 2570 c := testContext2(t, &ContextOpts{ 2571 Module: m, 2572 Providers: map[string]ResourceProviderFactory{ 2573 "aws": testProviderFuncFixed(p), 2574 }, 2575 }) 2576 2577 p.ValidateResourceReturnErrors = []error{fmt.Errorf("bad")} 2578 2579 w, e := c.Validate() 2580 if len(w) > 0 { 2581 t.Fatalf("bad: %#v", w) 2582 } 2583 if len(e) == 0 { 2584 t.Fatalf("bad: %#v", e) 2585 } 2586 } 2587 2588 func TestContext2Validate_moduleDepsShouldNotCycle(t *testing.T) { 2589 m := testModule(t, "validate-module-deps-cycle") 2590 p := testProvider("aws") 2591 ctx := testContext2(t, &ContextOpts{ 2592 Module: m, 2593 Providers: map[string]ResourceProviderFactory{ 2594 "aws": testProviderFuncFixed(p), 2595 }, 2596 }) 2597 2598 w, e := ctx.Validate() 2599 2600 if len(w) > 0 { 2601 t.Fatalf("expected no warnings, got: %s", w) 2602 } 2603 if len(e) > 0 { 2604 t.Fatalf("expected no errors, got: %s", e) 2605 } 2606 } 2607 2608 func TestContext2Validate_moduleProviderInherit(t *testing.T) { 2609 m := testModule(t, "validate-module-pc-inherit") 2610 p := testProvider("aws") 2611 c := testContext2(t, &ContextOpts{ 2612 Module: m, 2613 Providers: map[string]ResourceProviderFactory{ 2614 "aws": testProviderFuncFixed(p), 2615 }, 2616 }) 2617 2618 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 2619 return nil, c.CheckSet([]string{"set"}) 2620 } 2621 2622 w, e := c.Validate() 2623 if len(w) > 0 { 2624 t.Fatalf("bad: %#v", w) 2625 } 2626 if len(e) > 0 { 2627 t.Fatalf("bad: %s", e) 2628 } 2629 } 2630 2631 func TestContext2Validate_moduleProviderInheritOrphan(t *testing.T) { 2632 m := testModule(t, "validate-module-pc-inherit-orphan") 2633 p := testProvider("aws") 2634 c := testContext2(t, &ContextOpts{ 2635 Module: m, 2636 Providers: map[string]ResourceProviderFactory{ 2637 "aws": testProviderFuncFixed(p), 2638 }, 2639 State: &State{ 2640 Modules: []*ModuleState{ 2641 &ModuleState{ 2642 Path: []string{"root", "child"}, 2643 Resources: map[string]*ResourceState{ 2644 "aws_instance.bar": &ResourceState{ 2645 Type: "aws_instance", 2646 Primary: &InstanceState{ 2647 ID: "bar", 2648 }, 2649 }, 2650 }, 2651 }, 2652 }, 2653 }, 2654 }) 2655 2656 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 2657 v, ok := c.Get("set") 2658 if !ok { 2659 return nil, []error{fmt.Errorf("not set")} 2660 } 2661 if v != "bar" { 2662 return nil, []error{fmt.Errorf("bad: %#v", v)} 2663 } 2664 2665 return nil, nil 2666 } 2667 2668 w, e := c.Validate() 2669 if len(w) > 0 { 2670 t.Fatalf("bad: %#v", w) 2671 } 2672 if len(e) > 0 { 2673 t.Fatalf("bad: %s", e) 2674 } 2675 } 2676 2677 func TestContext2Validate_moduleProviderVar(t *testing.T) { 2678 m := testModule(t, "validate-module-pc-vars") 2679 p := testProvider("aws") 2680 c := testContext2(t, &ContextOpts{ 2681 Module: m, 2682 Providers: map[string]ResourceProviderFactory{ 2683 "aws": testProviderFuncFixed(p), 2684 }, 2685 Variables: map[string]string{ 2686 "provider_var": "bar", 2687 }, 2688 }) 2689 2690 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 2691 return nil, c.CheckSet([]string{"foo"}) 2692 } 2693 2694 w, e := c.Validate() 2695 if len(w) > 0 { 2696 t.Fatalf("bad: %#v", w) 2697 } 2698 if len(e) > 0 { 2699 t.Fatalf("bad: %s", e) 2700 } 2701 } 2702 2703 func TestContext2Validate_moduleProviderInheritUnused(t *testing.T) { 2704 m := testModule(t, "validate-module-pc-inherit-unused") 2705 p := testProvider("aws") 2706 c := testContext2(t, &ContextOpts{ 2707 Module: m, 2708 Providers: map[string]ResourceProviderFactory{ 2709 "aws": testProviderFuncFixed(p), 2710 }, 2711 }) 2712 2713 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 2714 return nil, c.CheckSet([]string{"foo"}) 2715 } 2716 2717 w, e := c.Validate() 2718 if len(w) > 0 { 2719 t.Fatalf("bad: %#v", w) 2720 } 2721 if len(e) > 0 { 2722 t.Fatalf("bad: %s", e) 2723 } 2724 } 2725 2726 func TestContext2Validate_orphans(t *testing.T) { 2727 p := testProvider("aws") 2728 m := testModule(t, "validate-good") 2729 state := &State{ 2730 Modules: []*ModuleState{ 2731 &ModuleState{ 2732 Path: rootModulePath, 2733 Resources: map[string]*ResourceState{ 2734 "aws_instance.web": &ResourceState{ 2735 Type: "aws_instance", 2736 Primary: &InstanceState{ 2737 ID: "bar", 2738 }, 2739 }, 2740 }, 2741 }, 2742 }, 2743 } 2744 c := testContext2(t, &ContextOpts{ 2745 Module: m, 2746 Providers: map[string]ResourceProviderFactory{ 2747 "aws": testProviderFuncFixed(p), 2748 }, 2749 State: state, 2750 }) 2751 2752 p.ValidateResourceFn = func( 2753 t string, c *ResourceConfig) ([]string, []error) { 2754 return nil, c.CheckSet([]string{"foo"}) 2755 } 2756 2757 w, e := c.Validate() 2758 if len(w) > 0 { 2759 t.Fatalf("bad: %#v", w) 2760 } 2761 if len(e) > 0 { 2762 t.Fatalf("bad: %s", e) 2763 } 2764 } 2765 2766 func TestContext2Validate_providerConfig_bad(t *testing.T) { 2767 m := testModule(t, "validate-bad-pc") 2768 p := testProvider("aws") 2769 c := testContext2(t, &ContextOpts{ 2770 Module: m, 2771 Providers: map[string]ResourceProviderFactory{ 2772 "aws": testProviderFuncFixed(p), 2773 }, 2774 }) 2775 2776 p.ValidateReturnErrors = []error{fmt.Errorf("bad")} 2777 2778 w, e := c.Validate() 2779 if len(w) > 0 { 2780 t.Fatalf("bad: %#v", w) 2781 } 2782 if len(e) == 0 { 2783 t.Fatalf("bad: %s", e) 2784 } 2785 if !strings.Contains(fmt.Sprintf("%s", e), "bad") { 2786 t.Fatalf("bad: %s", e) 2787 } 2788 } 2789 2790 func TestContext2Validate_providerConfig_badEmpty(t *testing.T) { 2791 m := testModule(t, "validate-bad-pc-empty") 2792 p := testProvider("aws") 2793 c := testContext2(t, &ContextOpts{ 2794 Module: m, 2795 Providers: map[string]ResourceProviderFactory{ 2796 "aws": testProviderFuncFixed(p), 2797 }, 2798 }) 2799 2800 p.ValidateReturnErrors = []error{fmt.Errorf("bad")} 2801 2802 w, e := c.Validate() 2803 if len(w) > 0 { 2804 t.Fatalf("bad: %#v", w) 2805 } 2806 if len(e) == 0 { 2807 t.Fatalf("bad: %#v", e) 2808 } 2809 } 2810 2811 func TestContext2Validate_providerConfig_good(t *testing.T) { 2812 m := testModule(t, "validate-bad-pc") 2813 p := testProvider("aws") 2814 c := testContext2(t, &ContextOpts{ 2815 Module: m, 2816 Providers: map[string]ResourceProviderFactory{ 2817 "aws": testProviderFuncFixed(p), 2818 }, 2819 }) 2820 2821 w, e := c.Validate() 2822 if len(w) > 0 { 2823 t.Fatalf("bad: %#v", w) 2824 } 2825 if len(e) > 0 { 2826 t.Fatalf("bad: %#v", e) 2827 } 2828 } 2829 2830 func TestContext2Validate_provisionerConfig_bad(t *testing.T) { 2831 m := testModule(t, "validate-bad-prov-conf") 2832 p := testProvider("aws") 2833 pr := testProvisioner() 2834 c := testContext2(t, &ContextOpts{ 2835 Module: m, 2836 Providers: map[string]ResourceProviderFactory{ 2837 "aws": testProviderFuncFixed(p), 2838 }, 2839 Provisioners: map[string]ResourceProvisionerFactory{ 2840 "shell": testProvisionerFuncFixed(pr), 2841 }, 2842 }) 2843 2844 pr.ValidateReturnErrors = []error{fmt.Errorf("bad")} 2845 2846 w, e := c.Validate() 2847 if len(w) > 0 { 2848 t.Fatalf("bad: %#v", w) 2849 } 2850 if len(e) == 0 { 2851 t.Fatalf("bad: %#v", e) 2852 } 2853 } 2854 2855 func TestContext2Validate_provisionerConfig_good(t *testing.T) { 2856 m := testModule(t, "validate-bad-prov-conf") 2857 p := testProvider("aws") 2858 pr := testProvisioner() 2859 pr.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 2860 if c == nil { 2861 t.Fatalf("missing resource config for provisioner") 2862 } 2863 return nil, c.CheckSet([]string{"command"}) 2864 } 2865 c := testContext2(t, &ContextOpts{ 2866 Module: m, 2867 Providers: map[string]ResourceProviderFactory{ 2868 "aws": testProviderFuncFixed(p), 2869 }, 2870 Provisioners: map[string]ResourceProvisionerFactory{ 2871 "shell": testProvisionerFuncFixed(pr), 2872 }, 2873 }) 2874 2875 w, e := c.Validate() 2876 if len(w) > 0 { 2877 t.Fatalf("bad: %#v", w) 2878 } 2879 if len(e) > 0 { 2880 t.Fatalf("bad: %#v", e) 2881 } 2882 } 2883 2884 func TestContext2Validate_requiredVar(t *testing.T) { 2885 m := testModule(t, "validate-required-var") 2886 p := testProvider("aws") 2887 c := testContext2(t, &ContextOpts{ 2888 Module: m, 2889 Providers: map[string]ResourceProviderFactory{ 2890 "aws": testProviderFuncFixed(p), 2891 }, 2892 }) 2893 2894 w, e := c.Validate() 2895 if len(w) > 0 { 2896 t.Fatalf("bad: %#v", w) 2897 } 2898 if len(e) == 0 { 2899 t.Fatalf("bad: %s", e) 2900 } 2901 } 2902 2903 func TestContext2Validate_resourceConfig_bad(t *testing.T) { 2904 m := testModule(t, "validate-bad-rc") 2905 p := testProvider("aws") 2906 c := testContext2(t, &ContextOpts{ 2907 Module: m, 2908 Providers: map[string]ResourceProviderFactory{ 2909 "aws": testProviderFuncFixed(p), 2910 }, 2911 }) 2912 2913 p.ValidateResourceReturnErrors = []error{fmt.Errorf("bad")} 2914 2915 w, e := c.Validate() 2916 if len(w) > 0 { 2917 t.Fatalf("bad: %#v", w) 2918 } 2919 if len(e) == 0 { 2920 t.Fatalf("bad: %s", e) 2921 } 2922 } 2923 2924 func TestContext2Validate_resourceConfig_good(t *testing.T) { 2925 m := testModule(t, "validate-bad-rc") 2926 p := testProvider("aws") 2927 c := testContext2(t, &ContextOpts{ 2928 Module: m, 2929 Providers: map[string]ResourceProviderFactory{ 2930 "aws": testProviderFuncFixed(p), 2931 }, 2932 }) 2933 2934 w, e := c.Validate() 2935 if len(w) > 0 { 2936 t.Fatalf("bad: %#v", w) 2937 } 2938 if len(e) > 0 { 2939 t.Fatalf("bad: %#v", e) 2940 } 2941 } 2942 2943 func TestContext2Validate_resourceNameSymbol(t *testing.T) { 2944 p := testProvider("aws") 2945 m := testModule(t, "validate-resource-name-symbol") 2946 c := testContext2(t, &ContextOpts{ 2947 Module: m, 2948 Providers: map[string]ResourceProviderFactory{ 2949 "aws": testProviderFuncFixed(p), 2950 }, 2951 }) 2952 2953 w, e := c.Validate() 2954 if len(w) == 0 { 2955 t.Fatalf("bad: %#v", w) 2956 } 2957 if len(e) > 0 { 2958 t.Fatalf("bad: %s", e) 2959 } 2960 } 2961 2962 func TestContext2Validate_selfRef(t *testing.T) { 2963 p := testProvider("aws") 2964 m := testModule(t, "validate-self-ref") 2965 c := testContext2(t, &ContextOpts{ 2966 Module: m, 2967 Providers: map[string]ResourceProviderFactory{ 2968 "aws": testProviderFuncFixed(p), 2969 }, 2970 }) 2971 2972 w, e := c.Validate() 2973 if len(w) > 0 { 2974 t.Fatalf("bad: %#v", w) 2975 } 2976 if len(e) == 0 { 2977 t.Fatalf("bad: %s", e) 2978 } 2979 } 2980 2981 func TestContext2Validate_selfRefMulti(t *testing.T) { 2982 p := testProvider("aws") 2983 m := testModule(t, "validate-self-ref-multi") 2984 c := testContext2(t, &ContextOpts{ 2985 Module: m, 2986 Providers: map[string]ResourceProviderFactory{ 2987 "aws": testProviderFuncFixed(p), 2988 }, 2989 }) 2990 2991 w, e := c.Validate() 2992 if len(w) > 0 { 2993 t.Fatalf("bad: %#v", w) 2994 } 2995 if len(e) == 0 { 2996 t.Fatalf("bad: %#v", e) 2997 } 2998 } 2999 3000 func TestContext2Validate_selfRefMultiAll(t *testing.T) { 3001 p := testProvider("aws") 3002 m := testModule(t, "validate-self-ref-multi-all") 3003 c := testContext2(t, &ContextOpts{ 3004 Module: m, 3005 Providers: map[string]ResourceProviderFactory{ 3006 "aws": testProviderFuncFixed(p), 3007 }, 3008 }) 3009 3010 w, e := c.Validate() 3011 if len(w) > 0 { 3012 t.Fatalf("bad: %#v", w) 3013 } 3014 if len(e) == 0 { 3015 t.Fatalf("bad: %#v", e) 3016 } 3017 } 3018 3019 func TestContext2Validate_tainted(t *testing.T) { 3020 p := testProvider("aws") 3021 m := testModule(t, "validate-good") 3022 state := &State{ 3023 Modules: []*ModuleState{ 3024 &ModuleState{ 3025 Path: rootModulePath, 3026 Resources: map[string]*ResourceState{ 3027 "aws_instance.foo": &ResourceState{ 3028 Type: "aws_instance", 3029 Tainted: []*InstanceState{ 3030 &InstanceState{ 3031 ID: "bar", 3032 }, 3033 }, 3034 }, 3035 }, 3036 }, 3037 }, 3038 } 3039 c := testContext2(t, &ContextOpts{ 3040 Module: m, 3041 Providers: map[string]ResourceProviderFactory{ 3042 "aws": testProviderFuncFixed(p), 3043 }, 3044 State: state, 3045 }) 3046 3047 p.ValidateResourceFn = func( 3048 t string, c *ResourceConfig) ([]string, []error) { 3049 return nil, c.CheckSet([]string{"foo"}) 3050 } 3051 3052 w, e := c.Validate() 3053 if len(w) > 0 { 3054 t.Fatalf("bad: %#v", w) 3055 } 3056 if len(e) > 0 { 3057 t.Fatalf("bad: %#v", e) 3058 } 3059 } 3060 3061 func TestContext2Validate_targetedDestroy(t *testing.T) { 3062 m := testModule(t, "validate-targeted") 3063 p := testProvider("aws") 3064 pr := testProvisioner() 3065 p.ApplyFn = testApplyFn 3066 p.DiffFn = testDiffFn 3067 ctx := testContext2(t, &ContextOpts{ 3068 Module: m, 3069 Providers: map[string]ResourceProviderFactory{ 3070 "aws": testProviderFuncFixed(p), 3071 }, 3072 Provisioners: map[string]ResourceProvisionerFactory{ 3073 "shell": testProvisionerFuncFixed(pr), 3074 }, 3075 State: &State{ 3076 Modules: []*ModuleState{ 3077 &ModuleState{ 3078 Path: rootModulePath, 3079 Resources: map[string]*ResourceState{ 3080 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 3081 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 3082 }, 3083 }, 3084 }, 3085 }, 3086 Targets: []string{"aws_instance.foo"}, 3087 Destroy: true, 3088 }) 3089 3090 w, e := ctx.Validate() 3091 if len(w) > 0 { 3092 warnStr := "" 3093 for _, v := range w { 3094 warnStr = warnStr + " " + v 3095 } 3096 t.Fatalf("bad: %s", warnStr) 3097 } 3098 if len(e) > 0 { 3099 t.Fatalf("bad: %s", e) 3100 } 3101 } 3102 3103 func TestContext2Validate_varRef(t *testing.T) { 3104 m := testModule(t, "validate-variable-ref") 3105 p := testProvider("aws") 3106 c := testContext2(t, &ContextOpts{ 3107 Module: m, 3108 Providers: map[string]ResourceProviderFactory{ 3109 "aws": testProviderFuncFixed(p), 3110 }, 3111 }) 3112 3113 computed := false 3114 p.ValidateResourceFn = func(t string, c *ResourceConfig) ([]string, []error) { 3115 computed = c.IsComputed("foo") 3116 return nil, nil 3117 } 3118 3119 c.Validate() 3120 if !computed { 3121 t.Fatal("should be computed") 3122 } 3123 } 3124 3125 func TestContext2Validate_varRefFilled(t *testing.T) { 3126 m := testModule(t, "validate-variable-ref") 3127 p := testProvider("aws") 3128 c := testContext2(t, &ContextOpts{ 3129 Module: m, 3130 Providers: map[string]ResourceProviderFactory{ 3131 "aws": testProviderFuncFixed(p), 3132 }, 3133 Variables: map[string]string{ 3134 "foo": "bar", 3135 }, 3136 }) 3137 3138 var value interface{} 3139 p.ValidateResourceFn = func(t string, c *ResourceConfig) ([]string, []error) { 3140 value, _ = c.Get("foo") 3141 return nil, nil 3142 } 3143 3144 c.Validate() 3145 if value != "bar" { 3146 t.Fatalf("bad: %#v", value) 3147 } 3148 } 3149 3150 func TestContext2Input(t *testing.T) { 3151 input := new(MockUIInput) 3152 m := testModule(t, "input-vars") 3153 p := testProvider("aws") 3154 p.ApplyFn = testApplyFn 3155 p.DiffFn = testDiffFn 3156 ctx := testContext2(t, &ContextOpts{ 3157 Module: m, 3158 Providers: map[string]ResourceProviderFactory{ 3159 "aws": testProviderFuncFixed(p), 3160 }, 3161 Variables: map[string]string{ 3162 "foo": "us-west-2", 3163 "amis.us-east-1": "override", 3164 }, 3165 UIInput: input, 3166 }) 3167 3168 input.InputReturnMap = map[string]string{ 3169 "var.foo": "us-east-1", 3170 } 3171 3172 if err := ctx.Input(InputModeStd); err != nil { 3173 t.Fatalf("err: %s", err) 3174 } 3175 3176 if _, err := ctx.Plan(); err != nil { 3177 t.Fatalf("err: %s", err) 3178 } 3179 3180 state, err := ctx.Apply() 3181 if err != nil { 3182 t.Fatalf("err: %s", err) 3183 } 3184 3185 actual := strings.TrimSpace(state.String()) 3186 expected := strings.TrimSpace(testTerraformInputVarsStr) 3187 if actual != expected { 3188 t.Fatalf("bad: \n%s", actual) 3189 } 3190 } 3191 3192 func TestContext2Input_badVarDefault(t *testing.T) { 3193 m := testModule(t, "input-bad-var-default") 3194 p := testProvider("aws") 3195 p.ApplyFn = testApplyFn 3196 p.DiffFn = testDiffFn 3197 ctx := testContext2(t, &ContextOpts{ 3198 Module: m, 3199 Providers: map[string]ResourceProviderFactory{ 3200 "aws": testProviderFuncFixed(p), 3201 }, 3202 }) 3203 3204 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3205 c.Config["foo"] = "bar" 3206 return c, nil 3207 } 3208 3209 if err := ctx.Input(InputModeStd); err != nil { 3210 t.Fatalf("err: %s", err) 3211 } 3212 } 3213 3214 func TestContext2Input_provider(t *testing.T) { 3215 m := testModule(t, "input-provider") 3216 p := testProvider("aws") 3217 p.ApplyFn = testApplyFn 3218 p.DiffFn = testDiffFn 3219 ctx := testContext2(t, &ContextOpts{ 3220 Module: m, 3221 Providers: map[string]ResourceProviderFactory{ 3222 "aws": testProviderFuncFixed(p), 3223 }, 3224 }) 3225 3226 var actual interface{} 3227 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3228 c.Config["foo"] = "bar" 3229 return c, nil 3230 } 3231 p.ConfigureFn = func(c *ResourceConfig) error { 3232 actual = c.Config["foo"] 3233 return nil 3234 } 3235 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 3236 return nil, c.CheckSet([]string{"foo"}) 3237 } 3238 3239 if err := ctx.Input(InputModeStd); err != nil { 3240 t.Fatalf("err: %s", err) 3241 } 3242 3243 if _, err := ctx.Plan(); err != nil { 3244 t.Fatalf("err: %s", err) 3245 } 3246 3247 if _, err := ctx.Apply(); err != nil { 3248 t.Fatalf("err: %s", err) 3249 } 3250 3251 if !reflect.DeepEqual(actual, "bar") { 3252 t.Fatalf("bad: %#v", actual) 3253 } 3254 } 3255 3256 func TestContext2Input_providerMulti(t *testing.T) { 3257 m := testModule(t, "input-provider-multi") 3258 p := testProvider("aws") 3259 p.ApplyFn = testApplyFn 3260 p.DiffFn = testDiffFn 3261 ctx := testContext2(t, &ContextOpts{ 3262 Module: m, 3263 Providers: map[string]ResourceProviderFactory{ 3264 "aws": testProviderFuncFixed(p), 3265 }, 3266 }) 3267 3268 var actual []interface{} 3269 var lock sync.Mutex 3270 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3271 c.Config["foo"] = "bar" 3272 return c, nil 3273 } 3274 p.ConfigureFn = func(c *ResourceConfig) error { 3275 lock.Lock() 3276 defer lock.Unlock() 3277 actual = append(actual, c.Config["foo"]) 3278 return nil 3279 } 3280 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 3281 return nil, c.CheckSet([]string{"foo"}) 3282 } 3283 3284 if err := ctx.Input(InputModeStd); err != nil { 3285 t.Fatalf("err: %s", err) 3286 } 3287 3288 if _, err := ctx.Plan(); err != nil { 3289 t.Fatalf("err: %s", err) 3290 } 3291 3292 if _, err := ctx.Apply(); err != nil { 3293 t.Fatalf("err: %s", err) 3294 } 3295 3296 expected := []interface{}{"bar", "bar"} 3297 if !reflect.DeepEqual(actual, expected) { 3298 t.Fatalf("bad: %#v", actual) 3299 } 3300 } 3301 3302 func TestContext2Input_providerOnce(t *testing.T) { 3303 m := testModule(t, "input-provider-once") 3304 p := testProvider("aws") 3305 p.ApplyFn = testApplyFn 3306 p.DiffFn = testDiffFn 3307 ctx := testContext2(t, &ContextOpts{ 3308 Module: m, 3309 Providers: map[string]ResourceProviderFactory{ 3310 "aws": testProviderFuncFixed(p), 3311 }, 3312 }) 3313 3314 count := 0 3315 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3316 count++ 3317 return nil, nil 3318 } 3319 3320 if err := ctx.Input(InputModeStd); err != nil { 3321 t.Fatalf("err: %s", err) 3322 } 3323 3324 if count != 1 { 3325 t.Fatalf("should only be called once: %d", count) 3326 } 3327 } 3328 3329 func TestContext2Input_providerId(t *testing.T) { 3330 input := new(MockUIInput) 3331 m := testModule(t, "input-provider") 3332 p := testProvider("aws") 3333 p.ApplyFn = testApplyFn 3334 p.DiffFn = testDiffFn 3335 ctx := testContext2(t, &ContextOpts{ 3336 Module: m, 3337 Providers: map[string]ResourceProviderFactory{ 3338 "aws": testProviderFuncFixed(p), 3339 }, 3340 UIInput: input, 3341 }) 3342 3343 var actual interface{} 3344 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3345 v, err := i.Input(&InputOpts{Id: "foo"}) 3346 if err != nil { 3347 return nil, err 3348 } 3349 3350 c.Config["foo"] = v 3351 return c, nil 3352 } 3353 p.ConfigureFn = func(c *ResourceConfig) error { 3354 actual = c.Config["foo"] 3355 return nil 3356 } 3357 3358 input.InputReturnMap = map[string]string{ 3359 "provider.aws.foo": "bar", 3360 } 3361 3362 if err := ctx.Input(InputModeStd); err != nil { 3363 t.Fatalf("err: %s", err) 3364 } 3365 3366 if _, err := ctx.Plan(); err != nil { 3367 t.Fatalf("err: %s", err) 3368 } 3369 3370 if _, err := ctx.Apply(); err != nil { 3371 t.Fatalf("err: %s", err) 3372 } 3373 3374 if !reflect.DeepEqual(actual, "bar") { 3375 t.Fatalf("bad: %#v", actual) 3376 } 3377 } 3378 3379 func TestContext2Input_providerOnly(t *testing.T) { 3380 input := new(MockUIInput) 3381 m := testModule(t, "input-provider-vars") 3382 p := testProvider("aws") 3383 p.ApplyFn = testApplyFn 3384 p.DiffFn = testDiffFn 3385 ctx := testContext2(t, &ContextOpts{ 3386 Module: m, 3387 Providers: map[string]ResourceProviderFactory{ 3388 "aws": testProviderFuncFixed(p), 3389 }, 3390 Variables: map[string]string{ 3391 "foo": "us-west-2", 3392 }, 3393 UIInput: input, 3394 }) 3395 3396 input.InputReturnMap = map[string]string{ 3397 "var.foo": "us-east-1", 3398 } 3399 3400 var actual interface{} 3401 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3402 c.Config["foo"] = "bar" 3403 return c, nil 3404 } 3405 p.ConfigureFn = func(c *ResourceConfig) error { 3406 actual = c.Config["foo"] 3407 return nil 3408 } 3409 3410 if err := ctx.Input(InputModeProvider); err != nil { 3411 t.Fatalf("err: %s", err) 3412 } 3413 3414 if _, err := ctx.Plan(); err != nil { 3415 t.Fatalf("err: %s", err) 3416 } 3417 3418 state, err := ctx.Apply() 3419 if err != nil { 3420 t.Fatalf("err: %s", err) 3421 } 3422 3423 if !reflect.DeepEqual(actual, "bar") { 3424 t.Fatalf("bad: %#v", actual) 3425 } 3426 3427 actualStr := strings.TrimSpace(state.String()) 3428 expectedStr := strings.TrimSpace(testTerraformInputProviderOnlyStr) 3429 if actualStr != expectedStr { 3430 t.Fatalf("bad: \n%s", actualStr) 3431 } 3432 } 3433 3434 func TestContext2Input_providerVars(t *testing.T) { 3435 input := new(MockUIInput) 3436 m := testModule(t, "input-provider-with-vars") 3437 p := testProvider("aws") 3438 p.ApplyFn = testApplyFn 3439 p.DiffFn = testDiffFn 3440 ctx := testContext2(t, &ContextOpts{ 3441 Module: m, 3442 Providers: map[string]ResourceProviderFactory{ 3443 "aws": testProviderFuncFixed(p), 3444 }, 3445 Variables: map[string]string{ 3446 "foo": "bar", 3447 }, 3448 UIInput: input, 3449 }) 3450 3451 input.InputReturnMap = map[string]string{ 3452 "var.foo": "bar", 3453 } 3454 3455 var actual interface{} 3456 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3457 c.Config["bar"] = "baz" 3458 return c, nil 3459 } 3460 p.ConfigureFn = func(c *ResourceConfig) error { 3461 actual, _ = c.Get("foo") 3462 return nil 3463 } 3464 3465 if err := ctx.Input(InputModeStd); err != nil { 3466 t.Fatalf("err: %s", err) 3467 } 3468 3469 if _, err := ctx.Plan(); err != nil { 3470 t.Fatalf("err: %s", err) 3471 } 3472 3473 if _, err := ctx.Apply(); err != nil { 3474 t.Fatalf("err: %s", err) 3475 } 3476 3477 if !reflect.DeepEqual(actual, "bar") { 3478 t.Fatalf("bad: %#v", actual) 3479 } 3480 } 3481 3482 func TestContext2Input_providerVarsModuleInherit(t *testing.T) { 3483 input := new(MockUIInput) 3484 m := testModule(t, "input-provider-with-vars-and-module") 3485 p := testProvider("aws") 3486 p.ApplyFn = testApplyFn 3487 p.DiffFn = testDiffFn 3488 ctx := testContext2(t, &ContextOpts{ 3489 Module: m, 3490 Providers: map[string]ResourceProviderFactory{ 3491 "aws": testProviderFuncFixed(p), 3492 }, 3493 UIInput: input, 3494 }) 3495 3496 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3497 if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 { 3498 return c, errs[0] 3499 } 3500 return c, nil 3501 } 3502 p.ConfigureFn = func(c *ResourceConfig) error { 3503 return nil 3504 } 3505 3506 if err := ctx.Input(InputModeStd); err != nil { 3507 t.Fatalf("err: %s", err) 3508 } 3509 } 3510 3511 func TestContext2Input_varOnly(t *testing.T) { 3512 input := new(MockUIInput) 3513 m := testModule(t, "input-provider-vars") 3514 p := testProvider("aws") 3515 p.ApplyFn = testApplyFn 3516 p.DiffFn = testDiffFn 3517 ctx := testContext2(t, &ContextOpts{ 3518 Module: m, 3519 Providers: map[string]ResourceProviderFactory{ 3520 "aws": testProviderFuncFixed(p), 3521 }, 3522 Variables: map[string]string{ 3523 "foo": "us-west-2", 3524 }, 3525 UIInput: input, 3526 }) 3527 3528 input.InputReturnMap = map[string]string{ 3529 "var.foo": "us-east-1", 3530 } 3531 3532 var actual interface{} 3533 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 3534 c.Raw["foo"] = "bar" 3535 return c, nil 3536 } 3537 p.ConfigureFn = func(c *ResourceConfig) error { 3538 actual = c.Raw["foo"] 3539 return nil 3540 } 3541 3542 if err := ctx.Input(InputModeVar); err != nil { 3543 t.Fatalf("err: %s", err) 3544 } 3545 3546 if _, err := ctx.Plan(); err != nil { 3547 t.Fatalf("err: %s", err) 3548 } 3549 3550 state, err := ctx.Apply() 3551 if err != nil { 3552 t.Fatalf("err: %s", err) 3553 } 3554 3555 if reflect.DeepEqual(actual, "bar") { 3556 t.Fatalf("bad: %#v", actual) 3557 } 3558 3559 actualStr := strings.TrimSpace(state.String()) 3560 expectedStr := strings.TrimSpace(testTerraformInputVarOnlyStr) 3561 if actualStr != expectedStr { 3562 t.Fatalf("bad: \n%s", actualStr) 3563 } 3564 } 3565 3566 func TestContext2Input_varOnlyUnset(t *testing.T) { 3567 input := new(MockUIInput) 3568 m := testModule(t, "input-vars-unset") 3569 p := testProvider("aws") 3570 p.ApplyFn = testApplyFn 3571 p.DiffFn = testDiffFn 3572 ctx := testContext2(t, &ContextOpts{ 3573 Module: m, 3574 Providers: map[string]ResourceProviderFactory{ 3575 "aws": testProviderFuncFixed(p), 3576 }, 3577 Variables: map[string]string{ 3578 "foo": "foovalue", 3579 }, 3580 UIInput: input, 3581 }) 3582 3583 input.InputReturnMap = map[string]string{ 3584 "var.foo": "nope", 3585 "var.bar": "baz", 3586 } 3587 3588 if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil { 3589 t.Fatalf("err: %s", err) 3590 } 3591 3592 if _, err := ctx.Plan(); err != nil { 3593 t.Fatalf("err: %s", err) 3594 } 3595 3596 state, err := ctx.Apply() 3597 if err != nil { 3598 t.Fatalf("err: %s", err) 3599 } 3600 3601 actualStr := strings.TrimSpace(state.String()) 3602 expectedStr := strings.TrimSpace(testTerraformInputVarOnlyUnsetStr) 3603 if actualStr != expectedStr { 3604 t.Fatalf("bad: \n%s", actualStr) 3605 } 3606 } 3607 3608 func TestContext2Apply(t *testing.T) { 3609 m := testModule(t, "apply-good") 3610 p := testProvider("aws") 3611 p.ApplyFn = testApplyFn 3612 p.DiffFn = testDiffFn 3613 ctx := testContext2(t, &ContextOpts{ 3614 Module: m, 3615 Providers: map[string]ResourceProviderFactory{ 3616 "aws": testProviderFuncFixed(p), 3617 }, 3618 }) 3619 3620 if _, err := ctx.Plan(); err != nil { 3621 t.Fatalf("err: %s", err) 3622 } 3623 3624 state, err := ctx.Apply() 3625 if err != nil { 3626 t.Fatalf("err: %s", err) 3627 } 3628 3629 mod := state.RootModule() 3630 if len(mod.Resources) < 2 { 3631 t.Fatalf("bad: %#v", mod.Resources) 3632 } 3633 3634 actual := strings.TrimSpace(state.String()) 3635 expected := strings.TrimSpace(testTerraformApplyStr) 3636 if actual != expected { 3637 t.Fatalf("bad: \n%s", actual) 3638 } 3639 } 3640 3641 func TestContext2Apply_providerAlias(t *testing.T) { 3642 m := testModule(t, "apply-provider-alias") 3643 p := testProvider("aws") 3644 p.ApplyFn = testApplyFn 3645 p.DiffFn = testDiffFn 3646 ctx := testContext2(t, &ContextOpts{ 3647 Module: m, 3648 Providers: map[string]ResourceProviderFactory{ 3649 "aws": testProviderFuncFixed(p), 3650 }, 3651 }) 3652 3653 if _, err := ctx.Plan(); err != nil { 3654 t.Fatalf("err: %s", err) 3655 } 3656 3657 state, err := ctx.Apply() 3658 if err != nil { 3659 t.Fatalf("err: %s", err) 3660 } 3661 3662 mod := state.RootModule() 3663 if len(mod.Resources) < 2 { 3664 t.Fatalf("bad: %#v", mod.Resources) 3665 } 3666 3667 actual := strings.TrimSpace(state.String()) 3668 expected := strings.TrimSpace(testTerraformApplyProviderAliasStr) 3669 if actual != expected { 3670 t.Fatalf("bad: \n%s", actual) 3671 } 3672 } 3673 3674 func TestContext2Apply_emptyModule(t *testing.T) { 3675 m := testModule(t, "apply-empty-module") 3676 p := testProvider("aws") 3677 p.ApplyFn = testApplyFn 3678 p.DiffFn = testDiffFn 3679 ctx := testContext2(t, &ContextOpts{ 3680 Module: m, 3681 Providers: map[string]ResourceProviderFactory{ 3682 "aws": testProviderFuncFixed(p), 3683 }, 3684 }) 3685 3686 if _, err := ctx.Plan(); err != nil { 3687 t.Fatalf("err: %s", err) 3688 } 3689 3690 state, err := ctx.Apply() 3691 if err != nil { 3692 t.Fatalf("err: %s", err) 3693 } 3694 3695 actual := strings.TrimSpace(state.String()) 3696 actual = strings.Replace(actual, " ", "", -1) 3697 expected := strings.TrimSpace(testTerraformApplyEmptyModuleStr) 3698 if actual != expected { 3699 t.Fatalf("bad: \n%s\nexpect:\n%s", actual, expected) 3700 } 3701 } 3702 3703 func TestContext2Apply_createBeforeDestroy(t *testing.T) { 3704 m := testModule(t, "apply-good-create-before") 3705 p := testProvider("aws") 3706 p.ApplyFn = testApplyFn 3707 p.DiffFn = testDiffFn 3708 state := &State{ 3709 Modules: []*ModuleState{ 3710 &ModuleState{ 3711 Path: rootModulePath, 3712 Resources: map[string]*ResourceState{ 3713 "aws_instance.bar": &ResourceState{ 3714 Type: "aws_instance", 3715 Primary: &InstanceState{ 3716 ID: "bar", 3717 Attributes: map[string]string{ 3718 "require_new": "abc", 3719 }, 3720 }, 3721 }, 3722 }, 3723 }, 3724 }, 3725 } 3726 ctx := testContext2(t, &ContextOpts{ 3727 Module: m, 3728 Providers: map[string]ResourceProviderFactory{ 3729 "aws": testProviderFuncFixed(p), 3730 }, 3731 State: state, 3732 }) 3733 3734 if p, err := ctx.Plan(); err != nil { 3735 t.Fatalf("err: %s", err) 3736 } else { 3737 t.Logf(p.String()) 3738 } 3739 3740 state, err := ctx.Apply() 3741 if err != nil { 3742 t.Fatalf("err: %s", err) 3743 } 3744 3745 mod := state.RootModule() 3746 if len(mod.Resources) != 1 { 3747 t.Fatalf("bad: %s", state) 3748 } 3749 3750 actual := strings.TrimSpace(state.String()) 3751 expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr) 3752 if actual != expected { 3753 t.Fatalf("bad: \n%s", actual) 3754 } 3755 } 3756 3757 func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) { 3758 m := testModule(t, "apply-good-create-before-update") 3759 p := testProvider("aws") 3760 p.ApplyFn = testApplyFn 3761 p.DiffFn = testDiffFn 3762 state := &State{ 3763 Modules: []*ModuleState{ 3764 &ModuleState{ 3765 Path: rootModulePath, 3766 Resources: map[string]*ResourceState{ 3767 "aws_instance.bar": &ResourceState{ 3768 Type: "aws_instance", 3769 Primary: &InstanceState{ 3770 ID: "bar", 3771 Attributes: map[string]string{ 3772 "foo": "bar", 3773 }, 3774 }, 3775 }, 3776 }, 3777 }, 3778 }, 3779 } 3780 ctx := testContext2(t, &ContextOpts{ 3781 Module: m, 3782 Providers: map[string]ResourceProviderFactory{ 3783 "aws": testProviderFuncFixed(p), 3784 }, 3785 State: state, 3786 }) 3787 3788 if p, err := ctx.Plan(); err != nil { 3789 t.Fatalf("err: %s", err) 3790 } else { 3791 t.Logf(p.String()) 3792 } 3793 3794 state, err := ctx.Apply() 3795 if err != nil { 3796 t.Fatalf("err: %s", err) 3797 } 3798 3799 mod := state.RootModule() 3800 if len(mod.Resources) != 1 { 3801 t.Fatalf("bad: %s", state) 3802 } 3803 3804 actual := strings.TrimSpace(state.String()) 3805 expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr) 3806 if actual != expected { 3807 t.Fatalf("bad: \n%s", actual) 3808 } 3809 } 3810 3811 func TestContext2Apply_minimal(t *testing.T) { 3812 m := testModule(t, "apply-minimal") 3813 p := testProvider("aws") 3814 p.ApplyFn = testApplyFn 3815 p.DiffFn = testDiffFn 3816 ctx := testContext2(t, &ContextOpts{ 3817 Module: m, 3818 Providers: map[string]ResourceProviderFactory{ 3819 "aws": testProviderFuncFixed(p), 3820 }, 3821 }) 3822 3823 if _, err := ctx.Plan(); err != nil { 3824 t.Fatalf("err: %s", err) 3825 } 3826 3827 state, err := ctx.Apply() 3828 if err != nil { 3829 t.Fatalf("err: %s", err) 3830 } 3831 3832 actual := strings.TrimSpace(state.String()) 3833 expected := strings.TrimSpace(testTerraformApplyMinimalStr) 3834 if actual != expected { 3835 t.Fatalf("bad: \n%s", actual) 3836 } 3837 } 3838 3839 func TestContext2Apply_badDiff(t *testing.T) { 3840 m := testModule(t, "apply-good") 3841 p := testProvider("aws") 3842 p.ApplyFn = testApplyFn 3843 p.DiffFn = testDiffFn 3844 ctx := testContext2(t, &ContextOpts{ 3845 Module: m, 3846 Providers: map[string]ResourceProviderFactory{ 3847 "aws": testProviderFuncFixed(p), 3848 }, 3849 }) 3850 3851 if _, err := ctx.Plan(); err != nil { 3852 t.Fatalf("err: %s", err) 3853 } 3854 3855 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3856 return &InstanceDiff{ 3857 Attributes: map[string]*ResourceAttrDiff{ 3858 "newp": nil, 3859 }, 3860 }, nil 3861 } 3862 3863 if _, err := ctx.Apply(); err == nil { 3864 t.Fatal("should error") 3865 } 3866 } 3867 3868 func TestContext2Apply_cancel(t *testing.T) { 3869 stopped := false 3870 3871 m := testModule(t, "apply-cancel") 3872 p := testProvider("aws") 3873 ctx := testContext2(t, &ContextOpts{ 3874 Module: m, 3875 Providers: map[string]ResourceProviderFactory{ 3876 "aws": testProviderFuncFixed(p), 3877 }, 3878 }) 3879 3880 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 3881 if !stopped { 3882 stopped = true 3883 go ctx.Stop() 3884 3885 for { 3886 if ctx.sh.Stopped() { 3887 break 3888 } 3889 } 3890 } 3891 3892 return &InstanceState{ 3893 ID: "foo", 3894 Attributes: map[string]string{ 3895 "num": "2", 3896 }, 3897 }, nil 3898 } 3899 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3900 return &InstanceDiff{ 3901 Attributes: map[string]*ResourceAttrDiff{ 3902 "num": &ResourceAttrDiff{ 3903 New: "bar", 3904 }, 3905 }, 3906 }, nil 3907 } 3908 3909 if _, err := ctx.Plan(); err != nil { 3910 t.Fatalf("err: %s", err) 3911 } 3912 3913 // Start the Apply in a goroutine 3914 stateCh := make(chan *State) 3915 go func() { 3916 state, err := ctx.Apply() 3917 if err != nil { 3918 panic(err) 3919 } 3920 3921 stateCh <- state 3922 }() 3923 3924 state := <-stateCh 3925 3926 mod := state.RootModule() 3927 if len(mod.Resources) != 1 { 3928 t.Fatalf("bad: %s", state.String()) 3929 } 3930 3931 actual := strings.TrimSpace(state.String()) 3932 expected := strings.TrimSpace(testTerraformApplyCancelStr) 3933 if actual != expected { 3934 t.Fatalf("bad: \n%s", actual) 3935 } 3936 } 3937 3938 func TestContext2Apply_compute(t *testing.T) { 3939 m := testModule(t, "apply-compute") 3940 p := testProvider("aws") 3941 p.ApplyFn = testApplyFn 3942 p.DiffFn = testDiffFn 3943 ctx := testContext2(t, &ContextOpts{ 3944 Module: m, 3945 Providers: map[string]ResourceProviderFactory{ 3946 "aws": testProviderFuncFixed(p), 3947 }, 3948 }) 3949 3950 if _, err := ctx.Plan(); err != nil { 3951 t.Fatalf("err: %s", err) 3952 } 3953 3954 ctx.variables = map[string]string{"value": "1"} 3955 3956 state, err := ctx.Apply() 3957 if err != nil { 3958 t.Fatalf("err: %s", err) 3959 } 3960 3961 actual := strings.TrimSpace(state.String()) 3962 expected := strings.TrimSpace(testTerraformApplyComputeStr) 3963 if actual != expected { 3964 t.Fatalf("bad: \n%s", actual) 3965 } 3966 } 3967 3968 func TestContext2Apply_countDecrease(t *testing.T) { 3969 m := testModule(t, "apply-count-dec") 3970 p := testProvider("aws") 3971 p.DiffFn = testDiffFn 3972 s := &State{ 3973 Modules: []*ModuleState{ 3974 &ModuleState{ 3975 Path: rootModulePath, 3976 Resources: map[string]*ResourceState{ 3977 "aws_instance.foo.0": &ResourceState{ 3978 Type: "aws_instance", 3979 Primary: &InstanceState{ 3980 ID: "bar", 3981 Attributes: map[string]string{ 3982 "foo": "foo", 3983 "type": "aws_instance", 3984 }, 3985 }, 3986 }, 3987 "aws_instance.foo.1": &ResourceState{ 3988 Type: "aws_instance", 3989 Primary: &InstanceState{ 3990 ID: "bar", 3991 Attributes: map[string]string{ 3992 "foo": "foo", 3993 "type": "aws_instance", 3994 }, 3995 }, 3996 }, 3997 "aws_instance.foo.2": &ResourceState{ 3998 Type: "aws_instance", 3999 Primary: &InstanceState{ 4000 ID: "bar", 4001 Attributes: map[string]string{ 4002 "foo": "foo", 4003 "type": "aws_instance", 4004 }, 4005 }, 4006 }, 4007 }, 4008 }, 4009 }, 4010 } 4011 ctx := testContext2(t, &ContextOpts{ 4012 Module: m, 4013 Providers: map[string]ResourceProviderFactory{ 4014 "aws": testProviderFuncFixed(p), 4015 }, 4016 State: s, 4017 }) 4018 4019 if _, err := ctx.Plan(); err != nil { 4020 t.Fatalf("err: %s", err) 4021 } 4022 4023 state, err := ctx.Apply() 4024 if err != nil { 4025 t.Fatalf("err: %s", err) 4026 } 4027 4028 actual := strings.TrimSpace(state.String()) 4029 expected := strings.TrimSpace(testTerraformApplyCountDecStr) 4030 if actual != expected { 4031 t.Fatalf("bad: \n%s", actual) 4032 } 4033 } 4034 4035 func TestContext2Apply_countDecreaseToOne(t *testing.T) { 4036 m := testModule(t, "apply-count-dec-one") 4037 p := testProvider("aws") 4038 p.ApplyFn = testApplyFn 4039 p.DiffFn = testDiffFn 4040 s := &State{ 4041 Modules: []*ModuleState{ 4042 &ModuleState{ 4043 Path: rootModulePath, 4044 Resources: map[string]*ResourceState{ 4045 "aws_instance.foo.0": &ResourceState{ 4046 Type: "aws_instance", 4047 Primary: &InstanceState{ 4048 ID: "bar", 4049 Attributes: map[string]string{ 4050 "foo": "foo", 4051 "type": "aws_instance", 4052 }, 4053 }, 4054 }, 4055 "aws_instance.foo.1": &ResourceState{ 4056 Type: "aws_instance", 4057 Primary: &InstanceState{ 4058 ID: "bar", 4059 }, 4060 }, 4061 "aws_instance.foo.2": &ResourceState{ 4062 Type: "aws_instance", 4063 Primary: &InstanceState{ 4064 ID: "bar", 4065 }, 4066 }, 4067 }, 4068 }, 4069 }, 4070 } 4071 ctx := testContext2(t, &ContextOpts{ 4072 Module: m, 4073 Providers: map[string]ResourceProviderFactory{ 4074 "aws": testProviderFuncFixed(p), 4075 }, 4076 State: s, 4077 }) 4078 4079 if _, err := ctx.Plan(); err != nil { 4080 t.Fatalf("err: %s", err) 4081 } 4082 4083 state, err := ctx.Apply() 4084 if err != nil { 4085 t.Fatalf("err: %s", err) 4086 } 4087 4088 actual := strings.TrimSpace(state.String()) 4089 expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr) 4090 if actual != expected { 4091 t.Fatalf("bad: \n%s", actual) 4092 } 4093 } 4094 4095 // https://github.com/PeoplePerHour/terraform/pull/11 4096 // 4097 // This tests a case where both a "resource" and "resource.0" are in 4098 // the state file, which apparently is a reasonable backwards compatibility 4099 // concern found in the above 3rd party repo. 4100 func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) { 4101 m := testModule(t, "apply-count-dec-one") 4102 p := testProvider("aws") 4103 p.ApplyFn = testApplyFn 4104 p.DiffFn = testDiffFn 4105 s := &State{ 4106 Modules: []*ModuleState{ 4107 &ModuleState{ 4108 Path: rootModulePath, 4109 Resources: map[string]*ResourceState{ 4110 "aws_instance.foo": &ResourceState{ 4111 Type: "aws_instance", 4112 Primary: &InstanceState{ 4113 ID: "bar", 4114 Attributes: map[string]string{ 4115 "foo": "foo", 4116 "type": "aws_instance", 4117 }, 4118 }, 4119 }, 4120 "aws_instance.foo.0": &ResourceState{ 4121 Type: "aws_instance", 4122 Primary: &InstanceState{ 4123 ID: "baz", 4124 Attributes: map[string]string{ 4125 "type": "aws_instance", 4126 }, 4127 }, 4128 }, 4129 }, 4130 }, 4131 }, 4132 } 4133 ctx := testContext2(t, &ContextOpts{ 4134 Module: m, 4135 Providers: map[string]ResourceProviderFactory{ 4136 "aws": testProviderFuncFixed(p), 4137 }, 4138 State: s, 4139 }) 4140 4141 if p, err := ctx.Plan(); err != nil { 4142 t.Fatalf("err: %s", err) 4143 } else { 4144 testStringMatch(t, p, testTerraformApplyCountDecToOneCorruptedPlanStr) 4145 } 4146 4147 state, err := ctx.Apply() 4148 if err != nil { 4149 t.Fatalf("err: %s", err) 4150 } 4151 4152 actual := strings.TrimSpace(state.String()) 4153 expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr) 4154 if actual != expected { 4155 t.Fatalf("bad: \n%s", actual) 4156 } 4157 } 4158 4159 func TestContext2Apply_countTainted(t *testing.T) { 4160 m := testModule(t, "apply-count-tainted") 4161 p := testProvider("aws") 4162 p.DiffFn = testDiffFn 4163 s := &State{ 4164 Modules: []*ModuleState{ 4165 &ModuleState{ 4166 Path: rootModulePath, 4167 Resources: map[string]*ResourceState{ 4168 "aws_instance.foo.0": &ResourceState{ 4169 Type: "aws_instance", 4170 Tainted: []*InstanceState{ 4171 &InstanceState{ 4172 ID: "bar", 4173 Attributes: map[string]string{ 4174 "foo": "foo", 4175 "type": "aws_instance", 4176 }, 4177 }, 4178 }, 4179 }, 4180 }, 4181 }, 4182 }, 4183 } 4184 ctx := testContext2(t, &ContextOpts{ 4185 Module: m, 4186 Providers: map[string]ResourceProviderFactory{ 4187 "aws": testProviderFuncFixed(p), 4188 }, 4189 State: s, 4190 }) 4191 4192 if _, err := ctx.Plan(); err != nil { 4193 t.Fatalf("err: %s", err) 4194 } 4195 4196 state, err := ctx.Apply() 4197 if err != nil { 4198 t.Fatalf("err: %s", err) 4199 } 4200 4201 actual := strings.TrimSpace(state.String()) 4202 expected := strings.TrimSpace(testTerraformApplyCountTaintedStr) 4203 if actual != expected { 4204 t.Fatalf("bad: \n%s", actual) 4205 } 4206 } 4207 4208 func TestContext2Apply_countVariable(t *testing.T) { 4209 m := testModule(t, "apply-count-variable") 4210 p := testProvider("aws") 4211 p.ApplyFn = testApplyFn 4212 p.DiffFn = testDiffFn 4213 ctx := testContext2(t, &ContextOpts{ 4214 Module: m, 4215 Providers: map[string]ResourceProviderFactory{ 4216 "aws": testProviderFuncFixed(p), 4217 }, 4218 }) 4219 4220 if _, err := ctx.Plan(); err != nil { 4221 t.Fatalf("err: %s", err) 4222 } 4223 4224 state, err := ctx.Apply() 4225 if err != nil { 4226 t.Fatalf("err: %s", err) 4227 } 4228 4229 actual := strings.TrimSpace(state.String()) 4230 expected := strings.TrimSpace(testTerraformApplyCountVariableStr) 4231 if actual != expected { 4232 t.Fatalf("bad: \n%s", actual) 4233 } 4234 } 4235 4236 func TestContext2Apply_module(t *testing.T) { 4237 m := testModule(t, "apply-module") 4238 p := testProvider("aws") 4239 p.ApplyFn = testApplyFn 4240 p.DiffFn = testDiffFn 4241 ctx := testContext2(t, &ContextOpts{ 4242 Module: m, 4243 Providers: map[string]ResourceProviderFactory{ 4244 "aws": testProviderFuncFixed(p), 4245 }, 4246 }) 4247 4248 if _, err := ctx.Plan(); err != nil { 4249 t.Fatalf("err: %s", err) 4250 } 4251 4252 state, err := ctx.Apply() 4253 if err != nil { 4254 t.Fatalf("err: %s", err) 4255 } 4256 4257 actual := strings.TrimSpace(state.String()) 4258 expected := strings.TrimSpace(testTerraformApplyModuleStr) 4259 if actual != expected { 4260 t.Fatalf("bad: \n%s", actual) 4261 } 4262 } 4263 4264 func TestContext2Apply_moduleDestroyOrder(t *testing.T) { 4265 m := testModule(t, "apply-module-destroy-order") 4266 p := testProvider("aws") 4267 p.DiffFn = testDiffFn 4268 4269 // Create a custom apply function to track the order they were destroyed 4270 var order []string 4271 var orderLock sync.Mutex 4272 p.ApplyFn = func( 4273 info *InstanceInfo, 4274 is *InstanceState, 4275 id *InstanceDiff) (*InstanceState, error) { 4276 orderLock.Lock() 4277 defer orderLock.Unlock() 4278 4279 order = append(order, is.ID) 4280 return nil, nil 4281 } 4282 4283 state := &State{ 4284 Modules: []*ModuleState{ 4285 &ModuleState{ 4286 Path: rootModulePath, 4287 Resources: map[string]*ResourceState{ 4288 "aws_instance.b": &ResourceState{ 4289 Type: "aws_instance", 4290 Primary: &InstanceState{ 4291 ID: "b", 4292 }, 4293 }, 4294 }, 4295 }, 4296 4297 &ModuleState{ 4298 Path: []string{"root", "child"}, 4299 Resources: map[string]*ResourceState{ 4300 "aws_instance.a": &ResourceState{ 4301 Type: "aws_instance", 4302 Primary: &InstanceState{ 4303 ID: "a", 4304 }, 4305 }, 4306 }, 4307 Outputs: map[string]string{ 4308 "a_output": "a", 4309 }, 4310 }, 4311 }, 4312 } 4313 4314 ctx := testContext2(t, &ContextOpts{ 4315 Module: m, 4316 Providers: map[string]ResourceProviderFactory{ 4317 "aws": testProviderFuncFixed(p), 4318 }, 4319 State: state, 4320 Destroy: true, 4321 }) 4322 4323 if _, err := ctx.Plan(); err != nil { 4324 t.Fatalf("err: %s", err) 4325 } 4326 4327 state, err := ctx.Apply() 4328 if err != nil { 4329 t.Fatalf("err: %s", err) 4330 } 4331 4332 expected := []string{"b", "a"} 4333 if !reflect.DeepEqual(order, expected) { 4334 t.Fatalf("bad: %#v", order) 4335 } 4336 4337 { 4338 actual := strings.TrimSpace(state.String()) 4339 expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr) 4340 if actual != expected { 4341 t.Fatalf("bad: \n%s", actual) 4342 } 4343 } 4344 } 4345 4346 func TestContext2Apply_moduleVarResourceCount(t *testing.T) { 4347 m := testModule(t, "apply-module-var-resource-count") 4348 p := testProvider("aws") 4349 p.ApplyFn = testApplyFn 4350 p.DiffFn = testDiffFn 4351 ctx := testContext2(t, &ContextOpts{ 4352 Module: m, 4353 Providers: map[string]ResourceProviderFactory{ 4354 "aws": testProviderFuncFixed(p), 4355 }, 4356 Variables: map[string]string{ 4357 "count": "2", 4358 }, 4359 Destroy: true, 4360 }) 4361 4362 if _, err := ctx.Plan(); err != nil { 4363 t.Fatalf("err: %s", err) 4364 } 4365 4366 if _, err := ctx.Apply(); err != nil { 4367 t.Fatalf("err: %s", err) 4368 } 4369 4370 ctx = testContext2(t, &ContextOpts{ 4371 Module: m, 4372 Providers: map[string]ResourceProviderFactory{ 4373 "aws": testProviderFuncFixed(p), 4374 }, 4375 Variables: map[string]string{ 4376 "count": "5", 4377 }, 4378 }) 4379 4380 if _, err := ctx.Plan(); err != nil { 4381 t.Fatalf("err: %s", err) 4382 } 4383 4384 if _, err := ctx.Apply(); err != nil { 4385 t.Fatalf("err: %s", err) 4386 } 4387 } 4388 4389 // GH-819 4390 func TestContext2Apply_moduleBool(t *testing.T) { 4391 m := testModule(t, "apply-module-bool") 4392 p := testProvider("aws") 4393 p.ApplyFn = testApplyFn 4394 p.DiffFn = testDiffFn 4395 ctx := testContext2(t, &ContextOpts{ 4396 Module: m, 4397 Providers: map[string]ResourceProviderFactory{ 4398 "aws": testProviderFuncFixed(p), 4399 }, 4400 }) 4401 4402 if _, err := ctx.Plan(); err != nil { 4403 t.Fatalf("err: %s", err) 4404 } 4405 4406 state, err := ctx.Apply() 4407 if err != nil { 4408 t.Fatalf("err: %s", err) 4409 } 4410 4411 actual := strings.TrimSpace(state.String()) 4412 expected := strings.TrimSpace(testTerraformApplyModuleBoolStr) 4413 if actual != expected { 4414 t.Fatalf("bad: \n%s", actual) 4415 } 4416 } 4417 4418 func TestContext2Apply_multiProvider(t *testing.T) { 4419 m := testModule(t, "apply-multi-provider") 4420 p := testProvider("aws") 4421 p.ApplyFn = testApplyFn 4422 p.DiffFn = testDiffFn 4423 4424 pDO := testProvider("do") 4425 pDO.ApplyFn = testApplyFn 4426 pDO.DiffFn = testDiffFn 4427 4428 ctx := testContext2(t, &ContextOpts{ 4429 Module: m, 4430 Providers: map[string]ResourceProviderFactory{ 4431 "aws": testProviderFuncFixed(p), 4432 "do": testProviderFuncFixed(pDO), 4433 }, 4434 }) 4435 4436 if _, err := ctx.Plan(); err != nil { 4437 t.Fatalf("err: %s", err) 4438 } 4439 4440 state, err := ctx.Apply() 4441 if err != nil { 4442 t.Fatalf("err: %s", err) 4443 } 4444 4445 mod := state.RootModule() 4446 if len(mod.Resources) < 2 { 4447 t.Fatalf("bad: %#v", mod.Resources) 4448 } 4449 4450 actual := strings.TrimSpace(state.String()) 4451 expected := strings.TrimSpace(testTerraformApplyMultiProviderStr) 4452 if actual != expected { 4453 t.Fatalf("bad: \n%s", actual) 4454 } 4455 } 4456 4457 func TestContext2Apply_nilDiff(t *testing.T) { 4458 m := testModule(t, "apply-good") 4459 p := testProvider("aws") 4460 p.ApplyFn = testApplyFn 4461 p.DiffFn = testDiffFn 4462 ctx := testContext2(t, &ContextOpts{ 4463 Module: m, 4464 Providers: map[string]ResourceProviderFactory{ 4465 "aws": testProviderFuncFixed(p), 4466 }, 4467 }) 4468 4469 if _, err := ctx.Plan(); err != nil { 4470 t.Fatalf("err: %s", err) 4471 } 4472 4473 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 4474 return nil, nil 4475 } 4476 4477 if _, err := ctx.Apply(); err == nil { 4478 t.Fatal("should error") 4479 } 4480 } 4481 4482 func TestContext2Apply_outputOrphan(t *testing.T) { 4483 m := testModule(t, "apply-output-orphan") 4484 p := testProvider("aws") 4485 p.ApplyFn = testApplyFn 4486 p.DiffFn = testDiffFn 4487 4488 state := &State{ 4489 Modules: []*ModuleState{ 4490 &ModuleState{ 4491 Path: rootModulePath, 4492 Outputs: map[string]string{ 4493 "foo": "bar", 4494 "bar": "baz", 4495 }, 4496 }, 4497 }, 4498 } 4499 4500 ctx := testContext2(t, &ContextOpts{ 4501 Module: m, 4502 Providers: map[string]ResourceProviderFactory{ 4503 "aws": testProviderFuncFixed(p), 4504 }, 4505 State: state, 4506 }) 4507 4508 if _, err := ctx.Plan(); err != nil { 4509 t.Fatalf("err: %s", err) 4510 } 4511 4512 state, err := ctx.Apply() 4513 if err != nil { 4514 t.Fatalf("err: %s", err) 4515 } 4516 4517 actual := strings.TrimSpace(state.String()) 4518 expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr) 4519 if actual != expected { 4520 t.Fatalf("bad: \n%s", actual) 4521 } 4522 } 4523 4524 func TestContext2Apply_Provisioner_compute(t *testing.T) { 4525 m := testModule(t, "apply-provisioner-compute") 4526 p := testProvider("aws") 4527 pr := testProvisioner() 4528 p.ApplyFn = testApplyFn 4529 p.DiffFn = testDiffFn 4530 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4531 val, ok := c.Config["foo"] 4532 if !ok || val != "computed_dynamical" { 4533 t.Fatalf("bad value for foo: %v %#v", val, c) 4534 } 4535 4536 return nil 4537 } 4538 ctx := testContext2(t, &ContextOpts{ 4539 Module: m, 4540 Providers: map[string]ResourceProviderFactory{ 4541 "aws": testProviderFuncFixed(p), 4542 }, 4543 Provisioners: map[string]ResourceProvisionerFactory{ 4544 "shell": testProvisionerFuncFixed(pr), 4545 }, 4546 Variables: map[string]string{ 4547 "value": "1", 4548 }, 4549 }) 4550 4551 if _, err := ctx.Plan(); err != nil { 4552 t.Fatalf("err: %s", err) 4553 } 4554 4555 state, err := ctx.Apply() 4556 if err != nil { 4557 t.Fatalf("err: %s", err) 4558 } 4559 4560 actual := strings.TrimSpace(state.String()) 4561 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 4562 if actual != expected { 4563 t.Fatalf("bad: \n%s", actual) 4564 } 4565 4566 // Verify apply was invoked 4567 if !pr.ApplyCalled { 4568 t.Fatalf("provisioner not invoked") 4569 } 4570 } 4571 4572 func TestContext2Apply_provisionerCreateFail(t *testing.T) { 4573 m := testModule(t, "apply-provisioner-fail-create") 4574 p := testProvider("aws") 4575 pr := testProvisioner() 4576 p.DiffFn = testDiffFn 4577 4578 p.ApplyFn = func( 4579 info *InstanceInfo, 4580 is *InstanceState, 4581 id *InstanceDiff) (*InstanceState, error) { 4582 is.ID = "foo" 4583 return is, fmt.Errorf("error") 4584 } 4585 4586 ctx := testContext2(t, &ContextOpts{ 4587 Module: m, 4588 Providers: map[string]ResourceProviderFactory{ 4589 "aws": testProviderFuncFixed(p), 4590 }, 4591 Provisioners: map[string]ResourceProvisionerFactory{ 4592 "shell": testProvisionerFuncFixed(pr), 4593 }, 4594 }) 4595 4596 if _, err := ctx.Plan(); err != nil { 4597 t.Fatalf("err: %s", err) 4598 } 4599 4600 state, err := ctx.Apply() 4601 if err == nil { 4602 t.Fatal("should error") 4603 } 4604 4605 actual := strings.TrimSpace(state.String()) 4606 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr) 4607 if actual != expected { 4608 t.Fatalf("bad: \n%s", actual) 4609 } 4610 } 4611 4612 func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) { 4613 m := testModule(t, "apply-provisioner-fail-create") 4614 p := testProvider("aws") 4615 pr := testProvisioner() 4616 p.DiffFn = testDiffFn 4617 4618 p.ApplyFn = func( 4619 info *InstanceInfo, 4620 is *InstanceState, 4621 id *InstanceDiff) (*InstanceState, error) { 4622 return nil, fmt.Errorf("error") 4623 } 4624 4625 ctx := testContext2(t, &ContextOpts{ 4626 Module: m, 4627 Providers: map[string]ResourceProviderFactory{ 4628 "aws": testProviderFuncFixed(p), 4629 }, 4630 Provisioners: map[string]ResourceProvisionerFactory{ 4631 "shell": testProvisionerFuncFixed(pr), 4632 }, 4633 }) 4634 4635 if _, err := ctx.Plan(); err != nil { 4636 t.Fatalf("err: %s", err) 4637 } 4638 4639 state, err := ctx.Apply() 4640 if err == nil { 4641 t.Fatal("should error") 4642 } 4643 4644 actual := strings.TrimSpace(state.String()) 4645 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr) 4646 if actual != expected { 4647 t.Fatalf("bad: \n%s", actual) 4648 } 4649 } 4650 4651 func TestContext2Apply_provisionerFail(t *testing.T) { 4652 m := testModule(t, "apply-provisioner-fail") 4653 p := testProvider("aws") 4654 pr := testProvisioner() 4655 p.ApplyFn = testApplyFn 4656 p.DiffFn = testDiffFn 4657 4658 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 4659 return fmt.Errorf("EXPLOSION") 4660 } 4661 4662 ctx := testContext2(t, &ContextOpts{ 4663 Module: m, 4664 Providers: map[string]ResourceProviderFactory{ 4665 "aws": testProviderFuncFixed(p), 4666 }, 4667 Provisioners: map[string]ResourceProvisionerFactory{ 4668 "shell": testProvisionerFuncFixed(pr), 4669 }, 4670 Variables: map[string]string{ 4671 "value": "1", 4672 }, 4673 }) 4674 4675 if _, err := ctx.Plan(); err != nil { 4676 t.Fatalf("err: %s", err) 4677 } 4678 4679 state, err := ctx.Apply() 4680 if err == nil { 4681 t.Fatal("should error") 4682 } 4683 4684 actual := strings.TrimSpace(state.String()) 4685 expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr) 4686 if actual != expected { 4687 t.Fatalf("bad: \n%s", actual) 4688 } 4689 } 4690 4691 func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) { 4692 m := testModule(t, "apply-provisioner-fail-create-before") 4693 p := testProvider("aws") 4694 pr := testProvisioner() 4695 p.ApplyFn = testApplyFn 4696 p.DiffFn = testDiffFn 4697 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 4698 return fmt.Errorf("EXPLOSION") 4699 } 4700 4701 state := &State{ 4702 Modules: []*ModuleState{ 4703 &ModuleState{ 4704 Path: rootModulePath, 4705 Resources: map[string]*ResourceState{ 4706 "aws_instance.bar": &ResourceState{ 4707 Type: "aws_instance", 4708 Primary: &InstanceState{ 4709 ID: "bar", 4710 Attributes: map[string]string{ 4711 "require_new": "abc", 4712 }, 4713 }, 4714 }, 4715 }, 4716 }, 4717 }, 4718 } 4719 ctx := testContext2(t, &ContextOpts{ 4720 Module: m, 4721 Providers: map[string]ResourceProviderFactory{ 4722 "aws": testProviderFuncFixed(p), 4723 }, 4724 Provisioners: map[string]ResourceProvisionerFactory{ 4725 "shell": testProvisionerFuncFixed(pr), 4726 }, 4727 State: state, 4728 }) 4729 4730 if _, err := ctx.Plan(); err != nil { 4731 t.Fatalf("err: %s", err) 4732 } 4733 4734 state, err := ctx.Apply() 4735 if err == nil { 4736 t.Fatal("should error") 4737 } 4738 4739 actual := strings.TrimSpace(state.String()) 4740 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr) 4741 if actual != expected { 4742 t.Fatalf("bad: \n%s", actual) 4743 } 4744 } 4745 4746 func TestContext2Apply_error_createBeforeDestroy(t *testing.T) { 4747 m := testModule(t, "apply-error-create-before") 4748 p := testProvider("aws") 4749 state := &State{ 4750 Modules: []*ModuleState{ 4751 &ModuleState{ 4752 Path: rootModulePath, 4753 Resources: map[string]*ResourceState{ 4754 "aws_instance.bar": &ResourceState{ 4755 Type: "aws_instance", 4756 Primary: &InstanceState{ 4757 ID: "bar", 4758 Attributes: map[string]string{ 4759 "require_new": "abc", 4760 }, 4761 }, 4762 }, 4763 }, 4764 }, 4765 }, 4766 } 4767 ctx := testContext2(t, &ContextOpts{ 4768 Module: m, 4769 Providers: map[string]ResourceProviderFactory{ 4770 "aws": testProviderFuncFixed(p), 4771 }, 4772 State: state, 4773 }) 4774 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4775 return nil, fmt.Errorf("error") 4776 } 4777 p.DiffFn = testDiffFn 4778 4779 if _, err := ctx.Plan(); err != nil { 4780 t.Fatalf("err: %s", err) 4781 } 4782 4783 state, err := ctx.Apply() 4784 if err == nil { 4785 t.Fatal("should have error") 4786 } 4787 4788 actual := strings.TrimSpace(state.String()) 4789 expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr) 4790 if actual != expected { 4791 t.Fatalf("bad: \n%s\n\nExpected:\n\n%s", actual, expected) 4792 } 4793 } 4794 4795 func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) { 4796 m := testModule(t, "apply-error-create-before") 4797 p := testProvider("aws") 4798 state := &State{ 4799 Modules: []*ModuleState{ 4800 &ModuleState{ 4801 Path: rootModulePath, 4802 Resources: map[string]*ResourceState{ 4803 "aws_instance.bar": &ResourceState{ 4804 Type: "aws_instance", 4805 Primary: &InstanceState{ 4806 ID: "bar", 4807 Attributes: map[string]string{ 4808 "require_new": "abc", 4809 }, 4810 }, 4811 }, 4812 }, 4813 }, 4814 }, 4815 } 4816 ctx := testContext2(t, &ContextOpts{ 4817 Module: m, 4818 Providers: map[string]ResourceProviderFactory{ 4819 "aws": testProviderFuncFixed(p), 4820 }, 4821 State: state, 4822 }) 4823 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4824 // Fail the destroy! 4825 if id.Destroy { 4826 return is, fmt.Errorf("error") 4827 } 4828 4829 // Create should work 4830 is = &InstanceState{ 4831 ID: "foo", 4832 } 4833 return is, nil 4834 } 4835 p.DiffFn = testDiffFn 4836 4837 if _, err := ctx.Plan(); err != nil { 4838 t.Fatalf("err: %s", err) 4839 } 4840 4841 state, err := ctx.Apply() 4842 if err == nil { 4843 t.Fatal("should have error") 4844 } 4845 4846 actual := strings.TrimSpace(state.String()) 4847 expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr) 4848 if actual != expected { 4849 t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected) 4850 } 4851 } 4852 4853 func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) { 4854 m := testModule(t, "apply-multi-depose-create-before-destroy") 4855 p := testProvider("aws") 4856 p.DiffFn = testDiffFn 4857 ps := map[string]ResourceProviderFactory{"aws": testProviderFuncFixed(p)} 4858 state := &State{ 4859 Modules: []*ModuleState{ 4860 &ModuleState{ 4861 Path: rootModulePath, 4862 Resources: map[string]*ResourceState{ 4863 "aws_instance.web": &ResourceState{ 4864 Type: "aws_instance", 4865 Primary: &InstanceState{ID: "foo"}, 4866 }, 4867 }, 4868 }, 4869 }, 4870 } 4871 4872 ctx := testContext2(t, &ContextOpts{ 4873 Module: m, 4874 Providers: ps, 4875 State: state, 4876 }) 4877 createdInstanceId := "bar" 4878 // Create works 4879 createFunc := func(is *InstanceState) (*InstanceState, error) { 4880 return &InstanceState{ID: createdInstanceId}, nil 4881 } 4882 // Destroy starts broken 4883 destroyFunc := func(is *InstanceState) (*InstanceState, error) { 4884 return is, fmt.Errorf("destroy failed") 4885 } 4886 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4887 if id.Destroy { 4888 return destroyFunc(is) 4889 } else { 4890 return createFunc(is) 4891 } 4892 } 4893 4894 if _, err := ctx.Plan(); err != nil { 4895 t.Fatalf("err: %s", err) 4896 } 4897 4898 // Destroy is broken, so even though CBD successfully replaces the instance, 4899 // we'll have to save the Deposed instance to destroy later 4900 state, err := ctx.Apply() 4901 if err == nil { 4902 t.Fatal("should have error") 4903 } 4904 4905 checkStateString(t, state, ` 4906 aws_instance.web: (1 deposed) 4907 ID = bar 4908 Deposed ID 1 = foo 4909 `) 4910 4911 createdInstanceId = "baz" 4912 ctx = testContext2(t, &ContextOpts{ 4913 Module: m, 4914 Providers: ps, 4915 State: state, 4916 }) 4917 4918 if _, err := ctx.Plan(); err != nil { 4919 t.Fatalf("err: %s", err) 4920 } 4921 4922 // We're replacing the primary instance once again. Destroy is _still_ 4923 // broken, so the Deposed list gets longer 4924 state, err = ctx.Apply() 4925 if err == nil { 4926 t.Fatal("should have error") 4927 } 4928 4929 checkStateString(t, state, ` 4930 aws_instance.web: (2 deposed) 4931 ID = baz 4932 Deposed ID 1 = foo 4933 Deposed ID 2 = bar 4934 `) 4935 4936 // Destroy partially fixed! 4937 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4938 if is.ID == "foo" || is.ID == "baz" { 4939 return nil, nil 4940 } else { 4941 return is, fmt.Errorf("destroy partially failed") 4942 } 4943 } 4944 4945 createdInstanceId = "qux" 4946 if _, err := ctx.Plan(); err != nil { 4947 t.Fatalf("err: %s", err) 4948 } 4949 state, err = ctx.Apply() 4950 // Expect error because 1/2 of Deposed destroys failed 4951 if err == nil { 4952 t.Fatal("should have error") 4953 } 4954 4955 // foo and baz are now gone, bar sticks around 4956 checkStateString(t, state, ` 4957 aws_instance.web: (1 deposed) 4958 ID = qux 4959 Deposed ID 1 = bar 4960 `) 4961 4962 // Destroy working fully! 4963 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4964 return nil, nil 4965 } 4966 4967 createdInstanceId = "quux" 4968 if _, err := ctx.Plan(); err != nil { 4969 t.Fatalf("err: %s", err) 4970 } 4971 state, err = ctx.Apply() 4972 if err != nil { 4973 t.Fatal("should not have error:", err) 4974 } 4975 4976 // And finally the state is clean 4977 checkStateString(t, state, ` 4978 aws_instance.web: 4979 ID = quux 4980 `) 4981 } 4982 4983 func TestContext2Apply_provisionerResourceRef(t *testing.T) { 4984 m := testModule(t, "apply-provisioner-resource-ref") 4985 p := testProvider("aws") 4986 pr := testProvisioner() 4987 p.ApplyFn = testApplyFn 4988 p.DiffFn = testDiffFn 4989 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4990 val, ok := c.Config["foo"] 4991 if !ok || val != "2" { 4992 t.Fatalf("bad value for foo: %v %#v", val, c) 4993 } 4994 4995 return nil 4996 } 4997 4998 ctx := testContext2(t, &ContextOpts{ 4999 Module: m, 5000 Providers: map[string]ResourceProviderFactory{ 5001 "aws": testProviderFuncFixed(p), 5002 }, 5003 Provisioners: map[string]ResourceProvisionerFactory{ 5004 "shell": testProvisionerFuncFixed(pr), 5005 }, 5006 }) 5007 5008 if _, err := ctx.Plan(); err != nil { 5009 t.Fatalf("err: %s", err) 5010 } 5011 5012 state, err := ctx.Apply() 5013 if err != nil { 5014 t.Fatalf("err: %s", err) 5015 } 5016 5017 actual := strings.TrimSpace(state.String()) 5018 expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr) 5019 if actual != expected { 5020 t.Fatalf("bad: \n%s", actual) 5021 } 5022 5023 // Verify apply was invoked 5024 if !pr.ApplyCalled { 5025 t.Fatalf("provisioner not invoked") 5026 } 5027 } 5028 5029 func TestContext2Apply_provisionerSelfRef(t *testing.T) { 5030 m := testModule(t, "apply-provisioner-self-ref") 5031 p := testProvider("aws") 5032 pr := testProvisioner() 5033 p.ApplyFn = testApplyFn 5034 p.DiffFn = testDiffFn 5035 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5036 val, ok := c.Config["command"] 5037 if !ok || val != "bar" { 5038 t.Fatalf("bad value for command: %v %#v", val, c) 5039 } 5040 5041 return nil 5042 } 5043 5044 ctx := testContext2(t, &ContextOpts{ 5045 Module: m, 5046 Providers: map[string]ResourceProviderFactory{ 5047 "aws": testProviderFuncFixed(p), 5048 }, 5049 Provisioners: map[string]ResourceProvisionerFactory{ 5050 "shell": testProvisionerFuncFixed(pr), 5051 }, 5052 }) 5053 5054 if _, err := ctx.Plan(); err != nil { 5055 t.Fatalf("err: %s", err) 5056 } 5057 5058 state, err := ctx.Apply() 5059 if err != nil { 5060 t.Fatalf("err: %s", err) 5061 } 5062 5063 actual := strings.TrimSpace(state.String()) 5064 expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) 5065 if actual != expected { 5066 t.Fatalf("bad: \n%s", actual) 5067 } 5068 5069 // Verify apply was invoked 5070 if !pr.ApplyCalled { 5071 t.Fatalf("provisioner not invoked") 5072 } 5073 } 5074 5075 func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { 5076 var lock sync.Mutex 5077 commands := make([]string, 0, 5) 5078 5079 m := testModule(t, "apply-provisioner-multi-self-ref") 5080 p := testProvider("aws") 5081 pr := testProvisioner() 5082 p.ApplyFn = testApplyFn 5083 p.DiffFn = testDiffFn 5084 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5085 lock.Lock() 5086 defer lock.Unlock() 5087 5088 val, ok := c.Config["command"] 5089 if !ok { 5090 t.Fatalf("bad value for command: %v %#v", val, c) 5091 } 5092 5093 commands = append(commands, val.(string)) 5094 return nil 5095 } 5096 5097 ctx := testContext2(t, &ContextOpts{ 5098 Module: m, 5099 Providers: map[string]ResourceProviderFactory{ 5100 "aws": testProviderFuncFixed(p), 5101 }, 5102 Provisioners: map[string]ResourceProvisionerFactory{ 5103 "shell": testProvisionerFuncFixed(pr), 5104 }, 5105 }) 5106 5107 if _, err := ctx.Plan(); err != nil { 5108 t.Fatalf("err: %s", err) 5109 } 5110 5111 state, err := ctx.Apply() 5112 if err != nil { 5113 t.Fatalf("err: %s", err) 5114 } 5115 5116 actual := strings.TrimSpace(state.String()) 5117 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr) 5118 if actual != expected { 5119 t.Fatalf("bad: \n%s", actual) 5120 } 5121 5122 // Verify apply was invoked 5123 if !pr.ApplyCalled { 5124 t.Fatalf("provisioner not invoked") 5125 } 5126 5127 // Verify our result 5128 sort.Strings(commands) 5129 expectedCommands := []string{"number 0", "number 1", "number 2"} 5130 if !reflect.DeepEqual(commands, expectedCommands) { 5131 t.Fatalf("bad: %#v", commands) 5132 } 5133 } 5134 5135 // Provisioner should NOT run on a diff, only create 5136 func TestContext2Apply_Provisioner_Diff(t *testing.T) { 5137 m := testModule(t, "apply-provisioner-diff") 5138 p := testProvider("aws") 5139 pr := testProvisioner() 5140 p.ApplyFn = testApplyFn 5141 p.DiffFn = testDiffFn 5142 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5143 return nil 5144 } 5145 ctx := testContext2(t, &ContextOpts{ 5146 Module: m, 5147 Providers: map[string]ResourceProviderFactory{ 5148 "aws": testProviderFuncFixed(p), 5149 }, 5150 Provisioners: map[string]ResourceProvisionerFactory{ 5151 "shell": testProvisionerFuncFixed(pr), 5152 }, 5153 }) 5154 5155 if _, err := ctx.Plan(); err != nil { 5156 t.Fatalf("err: %s", err) 5157 } 5158 5159 state, err := ctx.Apply() 5160 if err != nil { 5161 t.Fatalf("err: %s", err) 5162 } 5163 5164 actual := strings.TrimSpace(state.String()) 5165 expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr) 5166 if actual != expected { 5167 t.Fatalf("bad: \n%s", actual) 5168 } 5169 5170 // Verify apply was invoked 5171 if !pr.ApplyCalled { 5172 t.Fatalf("provisioner not invoked") 5173 } 5174 pr.ApplyCalled = false 5175 5176 // Change the state to force a diff 5177 mod := state.RootModule() 5178 mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz" 5179 5180 // Re-create context with state 5181 ctx = testContext2(t, &ContextOpts{ 5182 Module: m, 5183 Providers: map[string]ResourceProviderFactory{ 5184 "aws": testProviderFuncFixed(p), 5185 }, 5186 Provisioners: map[string]ResourceProvisionerFactory{ 5187 "shell": testProvisionerFuncFixed(pr), 5188 }, 5189 State: state, 5190 }) 5191 5192 if _, err := ctx.Plan(); err != nil { 5193 t.Fatalf("err: %s", err) 5194 } 5195 5196 state2, err := ctx.Apply() 5197 if err != nil { 5198 t.Fatalf("err: %s", err) 5199 } 5200 5201 actual = strings.TrimSpace(state2.String()) 5202 if actual != expected { 5203 t.Fatalf("bad: \n%s", actual) 5204 } 5205 5206 // Verify apply was NOT invoked 5207 if pr.ApplyCalled { 5208 t.Fatalf("provisioner invoked") 5209 } 5210 } 5211 5212 func TestContext2Apply_outputDiffVars(t *testing.T) { 5213 m := testModule(t, "apply-good") 5214 p := testProvider("aws") 5215 s := &State{ 5216 Modules: []*ModuleState{ 5217 &ModuleState{ 5218 Path: rootModulePath, 5219 Resources: map[string]*ResourceState{ 5220 "aws_instance.baz": &ResourceState{ 5221 Type: "aws_instance", 5222 Primary: &InstanceState{ 5223 ID: "bar", 5224 }, 5225 }, 5226 }, 5227 }, 5228 }, 5229 } 5230 ctx := testContext2(t, &ContextOpts{ 5231 Module: m, 5232 Providers: map[string]ResourceProviderFactory{ 5233 "aws": testProviderFuncFixed(p), 5234 }, 5235 State: s, 5236 }) 5237 5238 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5239 for k, ad := range d.Attributes { 5240 if ad.NewComputed { 5241 return nil, fmt.Errorf("%s: computed", k) 5242 } 5243 } 5244 5245 result := s.MergeDiff(d) 5246 result.ID = "foo" 5247 return result, nil 5248 } 5249 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5250 return &InstanceDiff{ 5251 Attributes: map[string]*ResourceAttrDiff{ 5252 "foo": &ResourceAttrDiff{ 5253 NewComputed: true, 5254 Type: DiffAttrOutput, 5255 }, 5256 "bar": &ResourceAttrDiff{ 5257 New: "baz", 5258 }, 5259 }, 5260 }, nil 5261 } 5262 5263 if _, err := ctx.Plan(); err != nil { 5264 t.Fatalf("err: %s", err) 5265 } 5266 if _, err := ctx.Apply(); err != nil { 5267 t.Fatalf("err: %s", err) 5268 } 5269 } 5270 5271 func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { 5272 m := testModule(t, "apply-provisioner-conninfo") 5273 p := testProvider("aws") 5274 pr := testProvisioner() 5275 5276 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5277 if s.Ephemeral.ConnInfo == nil { 5278 t.Fatalf("ConnInfo not initialized") 5279 } 5280 5281 result, _ := testApplyFn(info, s, d) 5282 result.Ephemeral.ConnInfo = map[string]string{ 5283 "type": "ssh", 5284 "host": "127.0.0.1", 5285 "port": "22", 5286 } 5287 return result, nil 5288 } 5289 p.DiffFn = testDiffFn 5290 5291 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5292 conn := rs.Ephemeral.ConnInfo 5293 if conn["type"] != "telnet" { 5294 t.Fatalf("Bad: %#v", conn) 5295 } 5296 if conn["host"] != "127.0.0.1" { 5297 t.Fatalf("Bad: %#v", conn) 5298 } 5299 if conn["port"] != "2222" { 5300 t.Fatalf("Bad: %#v", conn) 5301 } 5302 if conn["user"] != "superuser" { 5303 t.Fatalf("Bad: %#v", conn) 5304 } 5305 if conn["pass"] != "test" { 5306 t.Fatalf("Bad: %#v", conn) 5307 } 5308 5309 return nil 5310 } 5311 5312 ctx := testContext2(t, &ContextOpts{ 5313 Module: m, 5314 Providers: map[string]ResourceProviderFactory{ 5315 "aws": testProviderFuncFixed(p), 5316 }, 5317 Provisioners: map[string]ResourceProvisionerFactory{ 5318 "shell": testProvisionerFuncFixed(pr), 5319 }, 5320 Variables: map[string]string{ 5321 "value": "1", 5322 "pass": "test", 5323 }, 5324 }) 5325 5326 if _, err := ctx.Plan(); err != nil { 5327 t.Fatalf("err: %s", err) 5328 } 5329 5330 state, err := ctx.Apply() 5331 if err != nil { 5332 t.Fatalf("err: %s", err) 5333 } 5334 5335 actual := strings.TrimSpace(state.String()) 5336 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 5337 if actual != expected { 5338 t.Fatalf("bad: \n%s", actual) 5339 } 5340 5341 // Verify apply was invoked 5342 if !pr.ApplyCalled { 5343 t.Fatalf("provisioner not invoked") 5344 } 5345 } 5346 5347 func TestContext2Apply_destroy(t *testing.T) { 5348 m := testModule(t, "apply-destroy") 5349 h := new(HookRecordApplyOrder) 5350 p := testProvider("aws") 5351 p.ApplyFn = testApplyFn 5352 p.DiffFn = testDiffFn 5353 ctx := testContext2(t, &ContextOpts{ 5354 Module: m, 5355 Hooks: []Hook{h}, 5356 Providers: map[string]ResourceProviderFactory{ 5357 "aws": testProviderFuncFixed(p), 5358 }, 5359 }) 5360 5361 // First plan and apply a create operation 5362 if _, err := ctx.Plan(); err != nil { 5363 t.Fatalf("err: %s", err) 5364 } 5365 5366 state, err := ctx.Apply() 5367 if err != nil { 5368 t.Fatalf("err: %s", err) 5369 } 5370 5371 // Next, plan and apply a destroy operation 5372 h.Active = true 5373 ctx = testContext2(t, &ContextOpts{ 5374 Destroy: true, 5375 State: state, 5376 Module: m, 5377 Hooks: []Hook{h}, 5378 Providers: map[string]ResourceProviderFactory{ 5379 "aws": testProviderFuncFixed(p), 5380 }, 5381 }) 5382 5383 if _, err := ctx.Plan(); err != nil { 5384 t.Fatalf("err: %s", err) 5385 } 5386 5387 state, err = ctx.Apply() 5388 if err != nil { 5389 t.Fatalf("err: %s", err) 5390 } 5391 5392 // Test that things were destroyed 5393 actual := strings.TrimSpace(state.String()) 5394 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5395 if actual != expected { 5396 t.Fatalf("bad: \n%s", actual) 5397 } 5398 5399 // Test that things were destroyed _in the right order_ 5400 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 5401 actual2 := h.IDs 5402 if !reflect.DeepEqual(actual2, expected2) { 5403 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 5404 } 5405 } 5406 5407 func TestContext2Apply_destroyOutputs(t *testing.T) { 5408 m := testModule(t, "apply-destroy-outputs") 5409 h := new(HookRecordApplyOrder) 5410 p := testProvider("aws") 5411 p.ApplyFn = testApplyFn 5412 p.DiffFn = testDiffFn 5413 ctx := testContext2(t, &ContextOpts{ 5414 Module: m, 5415 Hooks: []Hook{h}, 5416 Providers: map[string]ResourceProviderFactory{ 5417 "aws": testProviderFuncFixed(p), 5418 }, 5419 }) 5420 5421 // First plan and apply a create operation 5422 if _, err := ctx.Plan(); err != nil { 5423 t.Fatalf("err: %s", err) 5424 } 5425 5426 state, err := ctx.Apply() 5427 5428 if err != nil { 5429 t.Fatalf("err: %s", err) 5430 } 5431 5432 // Next, plan and apply a destroy operation 5433 h.Active = true 5434 ctx = testContext2(t, &ContextOpts{ 5435 Destroy: true, 5436 State: state, 5437 Module: m, 5438 Hooks: []Hook{h}, 5439 Providers: map[string]ResourceProviderFactory{ 5440 "aws": testProviderFuncFixed(p), 5441 }, 5442 }) 5443 5444 if _, err := ctx.Plan(); err != nil { 5445 t.Fatalf("err: %s", err) 5446 } 5447 5448 state, err = ctx.Apply() 5449 if err != nil { 5450 t.Fatalf("err: %s", err) 5451 } 5452 5453 mod := state.RootModule() 5454 if len(mod.Resources) > 0 { 5455 t.Fatalf("bad: %#v", mod) 5456 } 5457 } 5458 5459 func TestContext2Apply_destroyOrphan(t *testing.T) { 5460 m := testModule(t, "apply-error") 5461 p := testProvider("aws") 5462 s := &State{ 5463 Modules: []*ModuleState{ 5464 &ModuleState{ 5465 Path: rootModulePath, 5466 Resources: map[string]*ResourceState{ 5467 "aws_instance.baz": &ResourceState{ 5468 Type: "aws_instance", 5469 Primary: &InstanceState{ 5470 ID: "bar", 5471 }, 5472 }, 5473 }, 5474 }, 5475 }, 5476 } 5477 ctx := testContext2(t, &ContextOpts{ 5478 Module: m, 5479 Providers: map[string]ResourceProviderFactory{ 5480 "aws": testProviderFuncFixed(p), 5481 }, 5482 State: s, 5483 }) 5484 5485 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5486 if d.Destroy { 5487 return nil, nil 5488 } 5489 5490 result := s.MergeDiff(d) 5491 result.ID = "foo" 5492 return result, nil 5493 } 5494 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5495 return &InstanceDiff{ 5496 Attributes: map[string]*ResourceAttrDiff{ 5497 "num": &ResourceAttrDiff{ 5498 New: "bar", 5499 }, 5500 }, 5501 }, nil 5502 } 5503 5504 if _, err := ctx.Plan(); err != nil { 5505 t.Fatalf("err: %s", err) 5506 } 5507 5508 state, err := ctx.Apply() 5509 if err != nil { 5510 t.Fatalf("err: %s", err) 5511 } 5512 5513 mod := state.RootModule() 5514 if _, ok := mod.Resources["aws_instance.baz"]; ok { 5515 t.Fatalf("bad: %#v", mod.Resources) 5516 } 5517 } 5518 5519 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 5520 m := testModule(t, "apply-destroy-provisioner") 5521 p := testProvider("aws") 5522 pr := testProvisioner() 5523 p.ApplyFn = testApplyFn 5524 p.DiffFn = testDiffFn 5525 5526 called := false 5527 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5528 called = true 5529 return nil 5530 } 5531 5532 s := &State{ 5533 Modules: []*ModuleState{ 5534 &ModuleState{ 5535 Path: rootModulePath, 5536 Resources: map[string]*ResourceState{ 5537 "aws_instance.foo": &ResourceState{ 5538 Type: "aws_instance", 5539 Tainted: []*InstanceState{ 5540 &InstanceState{ 5541 ID: "bar", 5542 Attributes: map[string]string{ 5543 "id": "bar", 5544 }, 5545 }, 5546 }, 5547 }, 5548 }, 5549 }, 5550 }, 5551 } 5552 5553 ctx := testContext2(t, &ContextOpts{ 5554 Module: m, 5555 Providers: map[string]ResourceProviderFactory{ 5556 "aws": testProviderFuncFixed(p), 5557 }, 5558 Provisioners: map[string]ResourceProvisionerFactory{ 5559 "shell": testProvisionerFuncFixed(pr), 5560 }, 5561 State: s, 5562 Destroy: true, 5563 }) 5564 5565 if _, err := ctx.Plan(); err != nil { 5566 t.Fatalf("err: %s", err) 5567 } 5568 5569 state, err := ctx.Apply() 5570 if err != nil { 5571 t.Fatalf("err: %s", err) 5572 } 5573 5574 if called { 5575 t.Fatal("provisioner should not be called") 5576 } 5577 5578 actual := strings.TrimSpace(state.String()) 5579 expected := strings.TrimSpace("<no state>") 5580 if actual != expected { 5581 t.Fatalf("bad: \n%s", actual) 5582 } 5583 } 5584 5585 func TestContext2Apply_error(t *testing.T) { 5586 errored := false 5587 5588 m := testModule(t, "apply-error") 5589 p := testProvider("aws") 5590 ctx := testContext2(t, &ContextOpts{ 5591 Module: m, 5592 Providers: map[string]ResourceProviderFactory{ 5593 "aws": testProviderFuncFixed(p), 5594 }, 5595 }) 5596 5597 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 5598 if errored { 5599 state := &InstanceState{ 5600 ID: "bar", 5601 } 5602 return state, fmt.Errorf("error") 5603 } 5604 errored = true 5605 5606 return &InstanceState{ 5607 ID: "foo", 5608 Attributes: map[string]string{ 5609 "num": "2", 5610 }, 5611 }, nil 5612 } 5613 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5614 return &InstanceDiff{ 5615 Attributes: map[string]*ResourceAttrDiff{ 5616 "num": &ResourceAttrDiff{ 5617 New: "bar", 5618 }, 5619 }, 5620 }, nil 5621 } 5622 5623 if _, err := ctx.Plan(); err != nil { 5624 t.Fatalf("err: %s", err) 5625 } 5626 5627 state, err := ctx.Apply() 5628 if err == nil { 5629 t.Fatal("should have error") 5630 } 5631 5632 actual := strings.TrimSpace(state.String()) 5633 expected := strings.TrimSpace(testTerraformApplyErrorStr) 5634 if actual != expected { 5635 t.Fatalf("bad: \n%s", actual) 5636 } 5637 } 5638 5639 func TestContext2Apply_errorPartial(t *testing.T) { 5640 errored := false 5641 5642 m := testModule(t, "apply-error") 5643 p := testProvider("aws") 5644 s := &State{ 5645 Modules: []*ModuleState{ 5646 &ModuleState{ 5647 Path: rootModulePath, 5648 Resources: map[string]*ResourceState{ 5649 "aws_instance.bar": &ResourceState{ 5650 Type: "aws_instance", 5651 Primary: &InstanceState{ 5652 ID: "bar", 5653 }, 5654 }, 5655 }, 5656 }, 5657 }, 5658 } 5659 ctx := testContext2(t, &ContextOpts{ 5660 Module: m, 5661 Providers: map[string]ResourceProviderFactory{ 5662 "aws": testProviderFuncFixed(p), 5663 }, 5664 State: s, 5665 }) 5666 5667 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5668 if errored { 5669 return s, fmt.Errorf("error") 5670 } 5671 errored = true 5672 5673 return &InstanceState{ 5674 ID: "foo", 5675 Attributes: map[string]string{ 5676 "num": "2", 5677 }, 5678 }, nil 5679 } 5680 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5681 return &InstanceDiff{ 5682 Attributes: map[string]*ResourceAttrDiff{ 5683 "num": &ResourceAttrDiff{ 5684 New: "bar", 5685 }, 5686 }, 5687 }, nil 5688 } 5689 5690 if _, err := ctx.Plan(); err != nil { 5691 t.Fatalf("err: %s", err) 5692 } 5693 5694 state, err := ctx.Apply() 5695 if err == nil { 5696 t.Fatal("should have error") 5697 } 5698 5699 mod := state.RootModule() 5700 if len(mod.Resources) != 2 { 5701 t.Fatalf("bad: %#v", mod.Resources) 5702 } 5703 5704 actual := strings.TrimSpace(state.String()) 5705 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 5706 if actual != expected { 5707 t.Fatalf("bad: \n%s", actual) 5708 } 5709 } 5710 5711 func TestContext2Apply_hook(t *testing.T) { 5712 m := testModule(t, "apply-good") 5713 h := new(MockHook) 5714 p := testProvider("aws") 5715 p.ApplyFn = testApplyFn 5716 p.DiffFn = testDiffFn 5717 ctx := testContext2(t, &ContextOpts{ 5718 Module: m, 5719 Hooks: []Hook{h}, 5720 Providers: map[string]ResourceProviderFactory{ 5721 "aws": testProviderFuncFixed(p), 5722 }, 5723 }) 5724 5725 if _, err := ctx.Plan(); err != nil { 5726 t.Fatalf("err: %s", err) 5727 } 5728 5729 if _, err := ctx.Apply(); err != nil { 5730 t.Fatalf("err: %s", err) 5731 } 5732 5733 if !h.PreApplyCalled { 5734 t.Fatal("should be called") 5735 } 5736 if !h.PostApplyCalled { 5737 t.Fatal("should be called") 5738 } 5739 if !h.PostStateUpdateCalled { 5740 t.Fatalf("should call post state update") 5741 } 5742 } 5743 5744 func TestContext2Apply_idAttr(t *testing.T) { 5745 m := testModule(t, "apply-idattr") 5746 p := testProvider("aws") 5747 ctx := testContext2(t, &ContextOpts{ 5748 Module: m, 5749 Providers: map[string]ResourceProviderFactory{ 5750 "aws": testProviderFuncFixed(p), 5751 }, 5752 }) 5753 5754 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5755 result := s.MergeDiff(d) 5756 result.ID = "foo" 5757 result.Attributes = map[string]string{ 5758 "id": "bar", 5759 } 5760 5761 return result, nil 5762 } 5763 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5764 return &InstanceDiff{ 5765 Attributes: map[string]*ResourceAttrDiff{ 5766 "num": &ResourceAttrDiff{ 5767 New: "bar", 5768 }, 5769 }, 5770 }, nil 5771 } 5772 5773 if _, err := ctx.Plan(); err != nil { 5774 t.Fatalf("err: %s", err) 5775 } 5776 5777 state, err := ctx.Apply() 5778 if err != nil { 5779 t.Fatalf("err: %s", err) 5780 } 5781 5782 mod := state.RootModule() 5783 rs, ok := mod.Resources["aws_instance.foo"] 5784 if !ok { 5785 t.Fatal("not in state") 5786 } 5787 if rs.Primary.ID != "foo" { 5788 t.Fatalf("bad: %#v", rs.Primary.ID) 5789 } 5790 if rs.Primary.Attributes["id"] != "foo" { 5791 t.Fatalf("bad: %#v", rs.Primary.Attributes) 5792 } 5793 } 5794 5795 func TestContext2Apply_output(t *testing.T) { 5796 m := testModule(t, "apply-output") 5797 p := testProvider("aws") 5798 p.ApplyFn = testApplyFn 5799 p.DiffFn = testDiffFn 5800 ctx := testContext2(t, &ContextOpts{ 5801 Module: m, 5802 Providers: map[string]ResourceProviderFactory{ 5803 "aws": testProviderFuncFixed(p), 5804 }, 5805 }) 5806 5807 if _, err := ctx.Plan(); err != nil { 5808 t.Fatalf("err: %s", err) 5809 } 5810 5811 state, err := ctx.Apply() 5812 if err != nil { 5813 t.Fatalf("err: %s", err) 5814 } 5815 5816 actual := strings.TrimSpace(state.String()) 5817 expected := strings.TrimSpace(testTerraformApplyOutputStr) 5818 if actual != expected { 5819 t.Fatalf("bad: \n%s", actual) 5820 } 5821 } 5822 5823 func TestContext2Apply_outputInvalid(t *testing.T) { 5824 m := testModule(t, "apply-output-invalid") 5825 p := testProvider("aws") 5826 p.ApplyFn = testApplyFn 5827 p.DiffFn = testDiffFn 5828 ctx := testContext2(t, &ContextOpts{ 5829 Module: m, 5830 Providers: map[string]ResourceProviderFactory{ 5831 "aws": testProviderFuncFixed(p), 5832 }, 5833 }) 5834 5835 _, err := ctx.Plan() 5836 if err == nil { 5837 t.Fatalf("err: %s", err) 5838 } 5839 if !strings.Contains(err.Error(), "is not a string") { 5840 t.Fatalf("err: %s", err) 5841 } 5842 } 5843 5844 func TestContext2Apply_outputList(t *testing.T) { 5845 m := testModule(t, "apply-output-list") 5846 p := testProvider("aws") 5847 p.ApplyFn = testApplyFn 5848 p.DiffFn = testDiffFn 5849 ctx := testContext2(t, &ContextOpts{ 5850 Module: m, 5851 Providers: map[string]ResourceProviderFactory{ 5852 "aws": testProviderFuncFixed(p), 5853 }, 5854 }) 5855 5856 if _, err := ctx.Plan(); err != nil { 5857 t.Fatalf("err: %s", err) 5858 } 5859 5860 state, err := ctx.Apply() 5861 if err != nil { 5862 t.Fatalf("err: %s", err) 5863 } 5864 5865 actual := strings.TrimSpace(state.String()) 5866 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 5867 if actual != expected { 5868 t.Fatalf("bad: \n%s", actual) 5869 } 5870 } 5871 5872 func TestContext2Apply_outputMulti(t *testing.T) { 5873 m := testModule(t, "apply-output-multi") 5874 p := testProvider("aws") 5875 p.ApplyFn = testApplyFn 5876 p.DiffFn = testDiffFn 5877 ctx := testContext2(t, &ContextOpts{ 5878 Module: m, 5879 Providers: map[string]ResourceProviderFactory{ 5880 "aws": testProviderFuncFixed(p), 5881 }, 5882 }) 5883 5884 if _, err := ctx.Plan(); err != nil { 5885 t.Fatalf("err: %s", err) 5886 } 5887 5888 state, err := ctx.Apply() 5889 if err != nil { 5890 t.Fatalf("err: %s", err) 5891 } 5892 5893 actual := strings.TrimSpace(state.String()) 5894 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 5895 if actual != expected { 5896 t.Fatalf("bad: \n%s", actual) 5897 } 5898 } 5899 5900 func TestContext2Apply_outputMultiIndex(t *testing.T) { 5901 m := testModule(t, "apply-output-multi-index") 5902 p := testProvider("aws") 5903 p.ApplyFn = testApplyFn 5904 p.DiffFn = testDiffFn 5905 ctx := testContext2(t, &ContextOpts{ 5906 Module: m, 5907 Providers: map[string]ResourceProviderFactory{ 5908 "aws": testProviderFuncFixed(p), 5909 }, 5910 }) 5911 5912 if _, err := ctx.Plan(); err != nil { 5913 t.Fatalf("err: %s", err) 5914 } 5915 5916 state, err := ctx.Apply() 5917 if err != nil { 5918 t.Fatalf("err: %s", err) 5919 } 5920 5921 actual := strings.TrimSpace(state.String()) 5922 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 5923 if actual != expected { 5924 t.Fatalf("bad: \n%s", actual) 5925 } 5926 } 5927 5928 func TestContext2Apply_taint(t *testing.T) { 5929 m := testModule(t, "apply-taint") 5930 p := testProvider("aws") 5931 5932 // destroyCount tests against regression of 5933 // https://github.com/hashicorp/terraform/issues/1056 5934 var destroyCount = int32(0) 5935 var once sync.Once 5936 simulateProviderDelay := func() { 5937 time.Sleep(10 * time.Millisecond) 5938 } 5939 5940 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5941 once.Do(simulateProviderDelay) 5942 if d.Destroy { 5943 atomic.AddInt32(&destroyCount, 1) 5944 } 5945 return testApplyFn(info, s, d) 5946 } 5947 p.DiffFn = testDiffFn 5948 s := &State{ 5949 Modules: []*ModuleState{ 5950 &ModuleState{ 5951 Path: rootModulePath, 5952 Resources: map[string]*ResourceState{ 5953 "aws_instance.bar": &ResourceState{ 5954 Type: "aws_instance", 5955 Tainted: []*InstanceState{ 5956 &InstanceState{ 5957 ID: "baz", 5958 Attributes: map[string]string{ 5959 "num": "2", 5960 "type": "aws_instance", 5961 }, 5962 }, 5963 }, 5964 }, 5965 }, 5966 }, 5967 }, 5968 } 5969 ctx := testContext2(t, &ContextOpts{ 5970 Module: m, 5971 Providers: map[string]ResourceProviderFactory{ 5972 "aws": testProviderFuncFixed(p), 5973 }, 5974 State: s, 5975 }) 5976 5977 if _, err := ctx.Plan(); err != nil { 5978 t.Fatalf("err: %s", err) 5979 } 5980 5981 state, err := ctx.Apply() 5982 if err != nil { 5983 t.Fatalf("err: %s", err) 5984 } 5985 5986 actual := strings.TrimSpace(state.String()) 5987 expected := strings.TrimSpace(testTerraformApplyTaintStr) 5988 if actual != expected { 5989 t.Fatalf("bad:\n%s", actual) 5990 } 5991 5992 if destroyCount != 1 { 5993 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 5994 } 5995 } 5996 5997 func TestContext2Apply_taintDep(t *testing.T) { 5998 m := testModule(t, "apply-taint-dep") 5999 p := testProvider("aws") 6000 p.ApplyFn = testApplyFn 6001 p.DiffFn = testDiffFn 6002 s := &State{ 6003 Modules: []*ModuleState{ 6004 &ModuleState{ 6005 Path: rootModulePath, 6006 Resources: map[string]*ResourceState{ 6007 "aws_instance.foo": &ResourceState{ 6008 Type: "aws_instance", 6009 Tainted: []*InstanceState{ 6010 &InstanceState{ 6011 ID: "baz", 6012 Attributes: map[string]string{ 6013 "num": "2", 6014 "type": "aws_instance", 6015 }, 6016 }, 6017 }, 6018 }, 6019 "aws_instance.bar": &ResourceState{ 6020 Type: "aws_instance", 6021 Primary: &InstanceState{ 6022 ID: "bar", 6023 Attributes: map[string]string{ 6024 "foo": "baz", 6025 "num": "2", 6026 "type": "aws_instance", 6027 }, 6028 }, 6029 }, 6030 }, 6031 }, 6032 }, 6033 } 6034 ctx := testContext2(t, &ContextOpts{ 6035 Module: m, 6036 Providers: map[string]ResourceProviderFactory{ 6037 "aws": testProviderFuncFixed(p), 6038 }, 6039 State: s, 6040 }) 6041 6042 if p, err := ctx.Plan(); err != nil { 6043 t.Fatalf("err: %s", err) 6044 } else { 6045 t.Logf("plan: %s", p) 6046 } 6047 6048 state, err := ctx.Apply() 6049 if err != nil { 6050 t.Fatalf("err: %s", err) 6051 } 6052 6053 actual := strings.TrimSpace(state.String()) 6054 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 6055 if actual != expected { 6056 t.Fatalf("bad:\n%s", actual) 6057 } 6058 } 6059 6060 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 6061 m := testModule(t, "apply-taint-dep-requires-new") 6062 p := testProvider("aws") 6063 p.ApplyFn = testApplyFn 6064 p.DiffFn = testDiffFn 6065 s := &State{ 6066 Modules: []*ModuleState{ 6067 &ModuleState{ 6068 Path: rootModulePath, 6069 Resources: map[string]*ResourceState{ 6070 "aws_instance.foo": &ResourceState{ 6071 Type: "aws_instance", 6072 Tainted: []*InstanceState{ 6073 &InstanceState{ 6074 ID: "baz", 6075 Attributes: map[string]string{ 6076 "num": "2", 6077 "type": "aws_instance", 6078 }, 6079 }, 6080 }, 6081 }, 6082 "aws_instance.bar": &ResourceState{ 6083 Type: "aws_instance", 6084 Primary: &InstanceState{ 6085 ID: "bar", 6086 Attributes: map[string]string{ 6087 "foo": "baz", 6088 "num": "2", 6089 "type": "aws_instance", 6090 }, 6091 }, 6092 }, 6093 }, 6094 }, 6095 }, 6096 } 6097 ctx := testContext2(t, &ContextOpts{ 6098 Module: m, 6099 Providers: map[string]ResourceProviderFactory{ 6100 "aws": testProviderFuncFixed(p), 6101 }, 6102 State: s, 6103 }) 6104 6105 if p, err := ctx.Plan(); err != nil { 6106 t.Fatalf("err: %s", err) 6107 } else { 6108 t.Logf("plan: %s", p) 6109 } 6110 6111 state, err := ctx.Apply() 6112 if err != nil { 6113 t.Fatalf("err: %s", err) 6114 } 6115 6116 actual := strings.TrimSpace(state.String()) 6117 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 6118 if actual != expected { 6119 t.Fatalf("bad:\n%s", actual) 6120 } 6121 } 6122 6123 func TestContext2Apply_targeted(t *testing.T) { 6124 m := testModule(t, "apply-targeted") 6125 p := testProvider("aws") 6126 p.ApplyFn = testApplyFn 6127 p.DiffFn = testDiffFn 6128 ctx := testContext2(t, &ContextOpts{ 6129 Module: m, 6130 Providers: map[string]ResourceProviderFactory{ 6131 "aws": testProviderFuncFixed(p), 6132 }, 6133 Targets: []string{"aws_instance.foo"}, 6134 }) 6135 6136 if _, err := ctx.Plan(); err != nil { 6137 t.Fatalf("err: %s", err) 6138 } 6139 6140 state, err := ctx.Apply() 6141 if err != nil { 6142 t.Fatalf("err: %s", err) 6143 } 6144 6145 mod := state.RootModule() 6146 if len(mod.Resources) != 1 { 6147 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6148 } 6149 6150 checkStateString(t, state, ` 6151 aws_instance.foo: 6152 ID = foo 6153 num = 2 6154 type = aws_instance 6155 `) 6156 } 6157 6158 func TestContext2Apply_targetedCount(t *testing.T) { 6159 m := testModule(t, "apply-targeted-count") 6160 p := testProvider("aws") 6161 p.ApplyFn = testApplyFn 6162 p.DiffFn = testDiffFn 6163 ctx := testContext2(t, &ContextOpts{ 6164 Module: m, 6165 Providers: map[string]ResourceProviderFactory{ 6166 "aws": testProviderFuncFixed(p), 6167 }, 6168 Targets: []string{"aws_instance.foo"}, 6169 }) 6170 6171 if _, err := ctx.Plan(); err != nil { 6172 t.Fatalf("err: %s", err) 6173 } 6174 6175 state, err := ctx.Apply() 6176 if err != nil { 6177 t.Fatalf("err: %s", err) 6178 } 6179 6180 checkStateString(t, state, ` 6181 aws_instance.foo.0: 6182 ID = foo 6183 aws_instance.foo.1: 6184 ID = foo 6185 aws_instance.foo.2: 6186 ID = foo 6187 `) 6188 } 6189 6190 func TestContext2Apply_targetedCountIndex(t *testing.T) { 6191 m := testModule(t, "apply-targeted-count") 6192 p := testProvider("aws") 6193 p.ApplyFn = testApplyFn 6194 p.DiffFn = testDiffFn 6195 ctx := testContext2(t, &ContextOpts{ 6196 Module: m, 6197 Providers: map[string]ResourceProviderFactory{ 6198 "aws": testProviderFuncFixed(p), 6199 }, 6200 Targets: []string{"aws_instance.foo[1]"}, 6201 }) 6202 6203 if _, err := ctx.Plan(); err != nil { 6204 t.Fatalf("err: %s", err) 6205 } 6206 6207 state, err := ctx.Apply() 6208 if err != nil { 6209 t.Fatalf("err: %s", err) 6210 } 6211 6212 checkStateString(t, state, ` 6213 aws_instance.foo.1: 6214 ID = foo 6215 `) 6216 } 6217 6218 func TestContext2Apply_targetedDestroy(t *testing.T) { 6219 m := testModule(t, "apply-targeted") 6220 p := testProvider("aws") 6221 p.ApplyFn = testApplyFn 6222 p.DiffFn = testDiffFn 6223 ctx := testContext2(t, &ContextOpts{ 6224 Module: m, 6225 Providers: map[string]ResourceProviderFactory{ 6226 "aws": testProviderFuncFixed(p), 6227 }, 6228 State: &State{ 6229 Modules: []*ModuleState{ 6230 &ModuleState{ 6231 Path: rootModulePath, 6232 Resources: map[string]*ResourceState{ 6233 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6234 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6235 }, 6236 }, 6237 }, 6238 }, 6239 Targets: []string{"aws_instance.foo"}, 6240 Destroy: true, 6241 }) 6242 6243 if _, err := ctx.Plan(); err != nil { 6244 t.Fatalf("err: %s", err) 6245 } 6246 6247 state, err := ctx.Apply() 6248 if err != nil { 6249 t.Fatalf("err: %s", err) 6250 } 6251 6252 mod := state.RootModule() 6253 if len(mod.Resources) != 1 { 6254 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6255 } 6256 6257 checkStateString(t, state, ` 6258 aws_instance.bar: 6259 ID = i-abc123 6260 `) 6261 } 6262 6263 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 6264 m := testModule(t, "apply-targeted-count") 6265 p := testProvider("aws") 6266 p.ApplyFn = testApplyFn 6267 p.DiffFn = testDiffFn 6268 ctx := testContext2(t, &ContextOpts{ 6269 Module: m, 6270 Providers: map[string]ResourceProviderFactory{ 6271 "aws": testProviderFuncFixed(p), 6272 }, 6273 State: &State{ 6274 Modules: []*ModuleState{ 6275 &ModuleState{ 6276 Path: rootModulePath, 6277 Resources: map[string]*ResourceState{ 6278 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 6279 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 6280 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 6281 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 6282 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 6283 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 6284 }, 6285 }, 6286 }, 6287 }, 6288 Targets: []string{ 6289 "aws_instance.foo[2]", 6290 "aws_instance.bar[1]", 6291 }, 6292 Destroy: true, 6293 }) 6294 6295 if _, err := ctx.Plan(); err != nil { 6296 t.Fatalf("err: %s", err) 6297 } 6298 6299 state, err := ctx.Apply() 6300 if err != nil { 6301 t.Fatalf("err: %s", err) 6302 } 6303 6304 checkStateString(t, state, ` 6305 aws_instance.bar.0: 6306 ID = i-abc123 6307 aws_instance.bar.2: 6308 ID = i-abc123 6309 aws_instance.foo.0: 6310 ID = i-bcd345 6311 aws_instance.foo.1: 6312 ID = i-bcd345 6313 `) 6314 } 6315 6316 func TestContext2Apply_targetedModule(t *testing.T) { 6317 m := testModule(t, "apply-targeted-module") 6318 p := testProvider("aws") 6319 p.ApplyFn = testApplyFn 6320 p.DiffFn = testDiffFn 6321 ctx := testContext2(t, &ContextOpts{ 6322 Module: m, 6323 Providers: map[string]ResourceProviderFactory{ 6324 "aws": testProviderFuncFixed(p), 6325 }, 6326 Targets: []string{"module.child"}, 6327 }) 6328 6329 if _, err := ctx.Plan(); err != nil { 6330 t.Fatalf("err: %s", err) 6331 } 6332 6333 state, err := ctx.Apply() 6334 if err != nil { 6335 t.Fatalf("err: %s", err) 6336 } 6337 6338 mod := state.ModuleByPath([]string{"root", "child"}) 6339 if mod == nil { 6340 t.Fatalf("no child module found in the state!\n\n%#v", state) 6341 } 6342 if len(mod.Resources) != 2 { 6343 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 6344 } 6345 6346 checkStateString(t, state, ` 6347 <no state> 6348 module.child: 6349 aws_instance.bar: 6350 ID = foo 6351 num = 2 6352 type = aws_instance 6353 aws_instance.foo: 6354 ID = foo 6355 num = 2 6356 type = aws_instance 6357 `) 6358 } 6359 6360 func TestContext2Apply_targetedModuleResource(t *testing.T) { 6361 m := testModule(t, "apply-targeted-module-resource") 6362 p := testProvider("aws") 6363 p.ApplyFn = testApplyFn 6364 p.DiffFn = testDiffFn 6365 ctx := testContext2(t, &ContextOpts{ 6366 Module: m, 6367 Providers: map[string]ResourceProviderFactory{ 6368 "aws": testProviderFuncFixed(p), 6369 }, 6370 Targets: []string{"module.child.aws_instance.foo"}, 6371 }) 6372 6373 if _, err := ctx.Plan(); err != nil { 6374 t.Fatalf("err: %s", err) 6375 } 6376 6377 state, err := ctx.Apply() 6378 if err != nil { 6379 t.Fatalf("err: %s", err) 6380 } 6381 6382 mod := state.ModuleByPath([]string{"root", "child"}) 6383 if len(mod.Resources) != 1 { 6384 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6385 } 6386 6387 checkStateString(t, state, ` 6388 <no state> 6389 module.child: 6390 aws_instance.foo: 6391 ID = foo 6392 num = 2 6393 type = aws_instance 6394 `) 6395 } 6396 6397 func TestContext2Apply_unknownAttribute(t *testing.T) { 6398 m := testModule(t, "apply-unknown") 6399 p := testProvider("aws") 6400 p.ApplyFn = testApplyFn 6401 p.DiffFn = testDiffFn 6402 ctx := testContext2(t, &ContextOpts{ 6403 Module: m, 6404 Providers: map[string]ResourceProviderFactory{ 6405 "aws": testProviderFuncFixed(p), 6406 }, 6407 }) 6408 6409 if _, err := ctx.Plan(); err != nil { 6410 t.Fatalf("err: %s", err) 6411 } 6412 6413 state, err := ctx.Apply() 6414 if err == nil { 6415 t.Fatal("should error") 6416 } 6417 6418 actual := strings.TrimSpace(state.String()) 6419 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 6420 if actual != expected { 6421 t.Fatalf("bad: \n%s", actual) 6422 } 6423 } 6424 6425 func TestContext2Apply_vars(t *testing.T) { 6426 m := testModule(t, "apply-vars") 6427 p := testProvider("aws") 6428 p.ApplyFn = testApplyFn 6429 p.DiffFn = testDiffFn 6430 ctx := testContext2(t, &ContextOpts{ 6431 Module: m, 6432 Providers: map[string]ResourceProviderFactory{ 6433 "aws": testProviderFuncFixed(p), 6434 }, 6435 Variables: map[string]string{ 6436 "foo": "us-west-2", 6437 "amis.us-east-1": "override", 6438 }, 6439 }) 6440 6441 w, e := ctx.Validate() 6442 if len(w) > 0 { 6443 t.Fatalf("bad: %#v", w) 6444 } 6445 if len(e) > 0 { 6446 t.Fatalf("bad: %s", e) 6447 } 6448 6449 if _, err := ctx.Plan(); err != nil { 6450 t.Fatalf("err: %s", err) 6451 } 6452 6453 state, err := ctx.Apply() 6454 if err != nil { 6455 t.Fatalf("err: %s", err) 6456 } 6457 6458 actual := strings.TrimSpace(state.String()) 6459 expected := strings.TrimSpace(testTerraformApplyVarsStr) 6460 if actual != expected { 6461 t.Fatalf("bad: \n%s", actual) 6462 } 6463 } 6464 6465 func TestContext2Apply_varsEnv(t *testing.T) { 6466 // Set the env var 6467 old := tempEnv(t, "TF_VAR_ami", "baz") 6468 defer os.Setenv("TF_VAR_ami", old) 6469 6470 m := testModule(t, "apply-vars-env") 6471 p := testProvider("aws") 6472 p.ApplyFn = testApplyFn 6473 p.DiffFn = testDiffFn 6474 ctx := testContext2(t, &ContextOpts{ 6475 Module: m, 6476 Providers: map[string]ResourceProviderFactory{ 6477 "aws": testProviderFuncFixed(p), 6478 }, 6479 }) 6480 6481 w, e := ctx.Validate() 6482 if len(w) > 0 { 6483 t.Fatalf("bad: %#v", w) 6484 } 6485 if len(e) > 0 { 6486 t.Fatalf("bad: %s", e) 6487 } 6488 6489 if _, err := ctx.Plan(); err != nil { 6490 t.Fatalf("err: %s", err) 6491 } 6492 6493 state, err := ctx.Apply() 6494 if err != nil { 6495 t.Fatalf("err: %s", err) 6496 } 6497 6498 actual := strings.TrimSpace(state.String()) 6499 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 6500 if actual != expected { 6501 t.Fatalf("bad: \n%s", actual) 6502 } 6503 } 6504 6505 func TestContext2Apply_createBefore_depends(t *testing.T) { 6506 m := testModule(t, "apply-depends-create-before") 6507 h := new(HookRecordApplyOrder) 6508 p := testProvider("aws") 6509 p.ApplyFn = testApplyFn 6510 p.DiffFn = testDiffFn 6511 state := &State{ 6512 Modules: []*ModuleState{ 6513 &ModuleState{ 6514 Path: rootModulePath, 6515 Resources: map[string]*ResourceState{ 6516 "aws_instance.web": &ResourceState{ 6517 Type: "aws_instance", 6518 Primary: &InstanceState{ 6519 ID: "bar", 6520 Attributes: map[string]string{ 6521 "require_new": "ami-old", 6522 }, 6523 }, 6524 }, 6525 "aws_instance.lb": &ResourceState{ 6526 Type: "aws_instance", 6527 Primary: &InstanceState{ 6528 ID: "baz", 6529 Attributes: map[string]string{ 6530 "instance": "bar", 6531 }, 6532 }, 6533 }, 6534 }, 6535 }, 6536 }, 6537 } 6538 ctx := testContext2(t, &ContextOpts{ 6539 Module: m, 6540 Hooks: []Hook{h}, 6541 Providers: map[string]ResourceProviderFactory{ 6542 "aws": testProviderFuncFixed(p), 6543 }, 6544 State: state, 6545 }) 6546 6547 if _, err := ctx.Plan(); err != nil { 6548 t.Fatalf("err: %s", err) 6549 } 6550 6551 h.Active = true 6552 state, err := ctx.Apply() 6553 if err != nil { 6554 t.Fatalf("err: %s", err) 6555 } 6556 6557 mod := state.RootModule() 6558 if len(mod.Resources) < 2 { 6559 t.Fatalf("bad: %#v", mod.Resources) 6560 } 6561 6562 actual := strings.TrimSpace(state.String()) 6563 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 6564 if actual != expected { 6565 t.Fatalf("bad: \n%s\n%s", actual, expected) 6566 } 6567 6568 // Test that things were managed _in the right order_ 6569 order := h.States 6570 diffs := h.Diffs 6571 if order[0].ID != "" || diffs[0].Destroy { 6572 t.Fatalf("should create new instance first: %#v", order) 6573 } 6574 6575 if order[1].ID != "baz" { 6576 t.Fatalf("update must happen after create: %#v", order) 6577 } 6578 6579 if order[2].ID != "bar" || !diffs[2].Destroy { 6580 t.Fatalf("destroy must happen after update: %#v", order) 6581 } 6582 } 6583 6584 func TestContext2Apply_singleDestroy(t *testing.T) { 6585 m := testModule(t, "apply-depends-create-before") 6586 h := new(HookRecordApplyOrder) 6587 p := testProvider("aws") 6588 6589 invokeCount := 0 6590 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6591 invokeCount++ 6592 switch invokeCount { 6593 case 1: 6594 if d.Destroy { 6595 t.Fatalf("should not destroy") 6596 } 6597 if s.ID != "" { 6598 t.Fatalf("should not have ID") 6599 } 6600 case 2: 6601 if d.Destroy { 6602 t.Fatalf("should not destroy") 6603 } 6604 if s.ID != "baz" { 6605 t.Fatalf("should have id") 6606 } 6607 case 3: 6608 if !d.Destroy { 6609 t.Fatalf("should destroy") 6610 } 6611 if s.ID == "" { 6612 t.Fatalf("should have ID") 6613 } 6614 default: 6615 t.Fatalf("bad invoke count %d", invokeCount) 6616 } 6617 return testApplyFn(info, s, d) 6618 } 6619 p.DiffFn = testDiffFn 6620 state := &State{ 6621 Modules: []*ModuleState{ 6622 &ModuleState{ 6623 Path: rootModulePath, 6624 Resources: map[string]*ResourceState{ 6625 "aws_instance.web": &ResourceState{ 6626 Type: "aws_instance", 6627 Primary: &InstanceState{ 6628 ID: "bar", 6629 Attributes: map[string]string{ 6630 "require_new": "ami-old", 6631 }, 6632 }, 6633 }, 6634 "aws_instance.lb": &ResourceState{ 6635 Type: "aws_instance", 6636 Primary: &InstanceState{ 6637 ID: "baz", 6638 Attributes: map[string]string{ 6639 "instance": "bar", 6640 }, 6641 }, 6642 }, 6643 }, 6644 }, 6645 }, 6646 } 6647 ctx := testContext2(t, &ContextOpts{ 6648 Module: m, 6649 Hooks: []Hook{h}, 6650 Providers: map[string]ResourceProviderFactory{ 6651 "aws": testProviderFuncFixed(p), 6652 }, 6653 State: state, 6654 }) 6655 6656 if _, err := ctx.Plan(); err != nil { 6657 t.Fatalf("err: %s", err) 6658 } 6659 6660 h.Active = true 6661 state, err := ctx.Apply() 6662 if err != nil { 6663 t.Fatalf("err: %s", err) 6664 } 6665 6666 if invokeCount != 3 { 6667 t.Fatalf("bad: %d", invokeCount) 6668 } 6669 } 6670 6671 func testContext2(t *testing.T, opts *ContextOpts) *Context { 6672 return NewContext(opts) 6673 } 6674 6675 func testApplyFn( 6676 info *InstanceInfo, 6677 s *InstanceState, 6678 d *InstanceDiff) (*InstanceState, error) { 6679 if d.Destroy { 6680 return nil, nil 6681 } 6682 6683 id := "foo" 6684 if idAttr, ok := d.Attributes["id"]; ok && !idAttr.NewComputed { 6685 id = idAttr.New 6686 } 6687 6688 result := &InstanceState{ 6689 ID: id, 6690 Attributes: make(map[string]string), 6691 } 6692 6693 // Copy all the prior attributes 6694 for k, v := range s.Attributes { 6695 result.Attributes[k] = v 6696 } 6697 6698 if d != nil { 6699 result = result.MergeDiff(d) 6700 } 6701 return result, nil 6702 } 6703 6704 func testDiffFn( 6705 info *InstanceInfo, 6706 s *InstanceState, 6707 c *ResourceConfig) (*InstanceDiff, error) { 6708 var diff InstanceDiff 6709 diff.Attributes = make(map[string]*ResourceAttrDiff) 6710 6711 for k, v := range c.Raw { 6712 if _, ok := v.(string); !ok { 6713 continue 6714 } 6715 6716 if k == "nil" { 6717 return nil, nil 6718 } 6719 6720 // This key is used for other purposes 6721 if k == "compute_value" { 6722 continue 6723 } 6724 6725 if k == "compute" { 6726 attrDiff := &ResourceAttrDiff{ 6727 Old: "", 6728 New: "", 6729 NewComputed: true, 6730 } 6731 6732 if cv, ok := c.Config["compute_value"]; ok { 6733 if cv.(string) == "1" { 6734 attrDiff.NewComputed = false 6735 attrDiff.New = fmt.Sprintf("computed_%s", v.(string)) 6736 } 6737 } 6738 6739 diff.Attributes[v.(string)] = attrDiff 6740 continue 6741 } 6742 6743 // If this key is not computed, then look it up in the 6744 // cleaned config. 6745 found := false 6746 for _, ck := range c.ComputedKeys { 6747 if ck == k { 6748 found = true 6749 break 6750 } 6751 } 6752 if !found { 6753 v = c.Config[k] 6754 } 6755 6756 attrDiff := &ResourceAttrDiff{ 6757 Old: "", 6758 New: v.(string), 6759 } 6760 6761 if k == "require_new" { 6762 attrDiff.RequiresNew = true 6763 } 6764 diff.Attributes[k] = attrDiff 6765 } 6766 6767 for _, k := range c.ComputedKeys { 6768 diff.Attributes[k] = &ResourceAttrDiff{ 6769 Old: "", 6770 NewComputed: true, 6771 } 6772 } 6773 6774 for k, v := range diff.Attributes { 6775 if v.NewComputed { 6776 continue 6777 } 6778 6779 old, ok := s.Attributes[k] 6780 if !ok { 6781 continue 6782 } 6783 if old == v.New { 6784 delete(diff.Attributes, k) 6785 } 6786 } 6787 6788 if !diff.Empty() { 6789 diff.Attributes["type"] = &ResourceAttrDiff{ 6790 Old: "", 6791 New: info.Type, 6792 } 6793 } 6794 6795 return &diff, nil 6796 } 6797 6798 func testProvider(prefix string) *MockResourceProvider { 6799 p := new(MockResourceProvider) 6800 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 6801 return s, nil 6802 } 6803 p.ResourcesReturn = []ResourceType{ 6804 ResourceType{ 6805 Name: fmt.Sprintf("%s_instance", prefix), 6806 }, 6807 } 6808 6809 return p 6810 } 6811 6812 func testProvisioner() *MockResourceProvisioner { 6813 p := new(MockResourceProvisioner) 6814 return p 6815 } 6816 6817 func checkStateString(t *testing.T, state *State, expected string) { 6818 actual := strings.TrimSpace(state.String()) 6819 expected = strings.TrimSpace(expected) 6820 6821 if actual != expected { 6822 t.Fatalf("state does not match! actual:\n%s\n\nexpected:\n%s", actual, expected) 6823 } 6824 } 6825 6826 func resourceState(resourceType, resourceID string) *ResourceState { 6827 return &ResourceState{ 6828 Type: resourceType, 6829 Primary: &InstanceState{ 6830 ID: resourceID, 6831 }, 6832 } 6833 } 6834 6835 const testContextGraph = ` 6836 root: root 6837 aws_instance.bar 6838 aws_instance.bar -> provider.aws 6839 aws_instance.foo 6840 aws_instance.foo -> provider.aws 6841 provider.aws 6842 root 6843 root -> aws_instance.bar 6844 root -> aws_instance.foo 6845 ` 6846 6847 const testContextRefreshModuleStr = ` 6848 aws_instance.web: (1 tainted) 6849 ID = <not created> 6850 Tainted ID 1 = bar 6851 6852 module.child: 6853 aws_instance.web: 6854 ID = new 6855 ` 6856 6857 const testContextRefreshOutputStr = ` 6858 aws_instance.web: 6859 ID = foo 6860 foo = bar 6861 6862 Outputs: 6863 6864 foo = bar 6865 ` 6866 6867 const testContextRefreshOutputPartialStr = ` 6868 <no state> 6869 ` 6870 6871 const testContextRefreshTaintedStr = ` 6872 aws_instance.web: (1 tainted) 6873 ID = <not created> 6874 Tainted ID 1 = foo 6875 `