github.com/kjmkznr/terraform@v0.5.2-0.20180216194316-1d0f5fdac99e/terraform/context_apply_test.go (about) 1 package terraform 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "reflect" 8 "runtime" 9 "sort" 10 "strings" 11 "sync" 12 "sync/atomic" 13 "testing" 14 "time" 15 16 "github.com/davecgh/go-spew/spew" 17 "github.com/hashicorp/terraform/config/module" 18 ) 19 20 func TestContext2Apply_basic(t *testing.T) { 21 m := testModule(t, "apply-good") 22 p := testProvider("aws") 23 p.ApplyFn = testApplyFn 24 p.DiffFn = testDiffFn 25 ctx := testContext2(t, &ContextOpts{ 26 Module: m, 27 ProviderResolver: ResourceProviderResolverFixed( 28 map[string]ResourceProviderFactory{ 29 "aws": testProviderFuncFixed(p), 30 }, 31 ), 32 }) 33 34 if _, err := ctx.Plan(); err != nil { 35 t.Fatalf("err: %s", err) 36 } 37 38 state, err := ctx.Apply() 39 if err != nil { 40 t.Fatalf("err: %s", err) 41 } 42 43 mod := state.RootModule() 44 if len(mod.Resources) < 2 { 45 t.Fatalf("bad: %#v", mod.Resources) 46 } 47 48 actual := strings.TrimSpace(state.String()) 49 expected := strings.TrimSpace(testTerraformApplyStr) 50 if actual != expected { 51 t.Fatalf("bad: \n%s", actual) 52 } 53 } 54 55 func TestContext2Apply_unstable(t *testing.T) { 56 // This tests behavior when the configuration contains an unstable value, 57 // such as the result of uuid() or timestamp(), where each call produces 58 // a different result. 59 // 60 // This is an important case to test because we need to ensure that 61 // we don't re-call the function during the apply phase: the value should 62 // be fixed during plan 63 64 m := testModule(t, "apply-unstable") 65 p := testProvider("test") 66 p.ApplyFn = testApplyFn 67 p.DiffFn = testDiffFn 68 ctx := testContext2(t, &ContextOpts{ 69 Module: m, 70 ProviderResolver: ResourceProviderResolverFixed( 71 map[string]ResourceProviderFactory{ 72 "test": testProviderFuncFixed(p), 73 }, 74 ), 75 }) 76 77 plan, err := ctx.Plan() 78 if err != nil { 79 t.Fatalf("unexpected error during Plan: %s", err) 80 } 81 82 md := plan.Diff.RootModule() 83 rd := md.Resources["test_resource.foo"] 84 randomVal := rd.Attributes["random"].New 85 t.Logf("plan-time value is %q", randomVal) 86 87 state, err := ctx.Apply() 88 if err != nil { 89 t.Fatalf("unexpected error during Apply: %s", err) 90 } 91 92 mod := state.RootModule() 93 if len(mod.Resources) != 1 { 94 t.Fatalf("wrong number of resources %d; want 1", len(mod.Resources)) 95 } 96 97 rs := mod.Resources["test_resource.foo"].Primary 98 if got, want := rs.Attributes["random"], randomVal; got != want { 99 // FIXME: We actually currently have a bug where we re-interpolate 100 // the config during apply and end up with a random result, so this 101 // check fails. This check _should not_ fail, so we should fix this 102 // up in a later release. 103 //t.Errorf("wrong random value %q; want %q", got, want) 104 } 105 } 106 107 func TestContext2Apply_escape(t *testing.T) { 108 m := testModule(t, "apply-escape") 109 p := testProvider("aws") 110 p.ApplyFn = testApplyFn 111 p.DiffFn = testDiffFn 112 ctx := testContext2(t, &ContextOpts{ 113 Module: m, 114 ProviderResolver: ResourceProviderResolverFixed( 115 map[string]ResourceProviderFactory{ 116 "aws": testProviderFuncFixed(p), 117 }, 118 ), 119 }) 120 121 if _, err := ctx.Plan(); err != nil { 122 t.Fatalf("err: %s", err) 123 } 124 125 state, err := ctx.Apply() 126 if err != nil { 127 t.Fatalf("err: %s", err) 128 } 129 130 checkStateString(t, state, ` 131 aws_instance.bar: 132 ID = foo 133 provider = provider.aws 134 foo = "bar" 135 type = aws_instance 136 `) 137 } 138 139 func TestContext2Apply_resourceCountOneList(t *testing.T) { 140 m := testModule(t, "apply-resource-count-one-list") 141 p := testProvider("null") 142 p.ApplyFn = testApplyFn 143 p.DiffFn = testDiffFn 144 ctx := testContext2(t, &ContextOpts{ 145 Module: m, 146 ProviderResolver: ResourceProviderResolverFixed( 147 map[string]ResourceProviderFactory{ 148 "null": testProviderFuncFixed(p), 149 }, 150 ), 151 }) 152 153 if _, err := ctx.Plan(); err != nil { 154 t.Fatalf("err: %s", err) 155 } 156 157 state, err := ctx.Apply() 158 if err != nil { 159 t.Fatalf("err: %s", err) 160 } 161 162 actual := strings.TrimSpace(state.String()) 163 expected := strings.TrimSpace(`null_resource.foo: 164 ID = foo 165 provider = provider.null 166 167 Outputs: 168 169 test = [foo]`) 170 if actual != expected { 171 t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual) 172 } 173 } 174 func TestContext2Apply_resourceCountZeroList(t *testing.T) { 175 m := testModule(t, "apply-resource-count-zero-list") 176 p := testProvider("null") 177 p.ApplyFn = testApplyFn 178 p.DiffFn = testDiffFn 179 ctx := testContext2(t, &ContextOpts{ 180 Module: m, 181 ProviderResolver: ResourceProviderResolverFixed( 182 map[string]ResourceProviderFactory{ 183 "null": testProviderFuncFixed(p), 184 }, 185 ), 186 }) 187 188 if _, err := ctx.Plan(); err != nil { 189 t.Fatalf("err: %s", err) 190 } 191 192 state, err := ctx.Apply() 193 if err != nil { 194 t.Fatalf("err: %s", err) 195 } 196 197 actual := strings.TrimSpace(state.String()) 198 expected := strings.TrimSpace(`<no state> 199 Outputs: 200 201 test = []`) 202 if actual != expected { 203 t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual) 204 } 205 } 206 207 func TestContext2Apply_resourceDependsOnModule(t *testing.T) { 208 m := testModule(t, "apply-resource-depends-on-module") 209 p := testProvider("aws") 210 p.DiffFn = testDiffFn 211 212 { 213 // Wait for the dependency, sleep, and verify the graph never 214 // called a child. 215 var called int32 216 var checked bool 217 p.ApplyFn = func( 218 info *InstanceInfo, 219 is *InstanceState, 220 id *InstanceDiff) (*InstanceState, error) { 221 if info.HumanId() == "module.child.aws_instance.child" { 222 checked = true 223 224 // Sleep to allow parallel execution 225 time.Sleep(50 * time.Millisecond) 226 227 // Verify that called is 0 (dep not called) 228 if atomic.LoadInt32(&called) != 0 { 229 return nil, fmt.Errorf("aws_instance.a should not be called") 230 } 231 } 232 233 atomic.AddInt32(&called, 1) 234 return testApplyFn(info, is, id) 235 } 236 237 ctx := testContext2(t, &ContextOpts{ 238 Module: m, 239 ProviderResolver: ResourceProviderResolverFixed( 240 map[string]ResourceProviderFactory{ 241 "aws": testProviderFuncFixed(p), 242 }, 243 ), 244 }) 245 246 if _, err := ctx.Plan(); err != nil { 247 t.Fatalf("err: %s", err) 248 } 249 250 state, err := ctx.Apply() 251 if err != nil { 252 t.Fatalf("err: %s", err) 253 } 254 255 if !checked { 256 t.Fatal("should check") 257 } 258 259 checkStateString(t, state, testTerraformApplyResourceDependsOnModuleStr) 260 } 261 } 262 263 // Test that without a config, the Dependencies in the state are enough 264 // to maintain proper ordering. 265 func TestContext2Apply_resourceDependsOnModuleStateOnly(t *testing.T) { 266 m := testModule(t, "apply-resource-depends-on-module-empty") 267 p := testProvider("aws") 268 p.DiffFn = testDiffFn 269 270 state := &State{ 271 Modules: []*ModuleState{ 272 &ModuleState{ 273 Path: rootModulePath, 274 Resources: map[string]*ResourceState{ 275 "aws_instance.a": &ResourceState{ 276 Type: "aws_instance", 277 Primary: &InstanceState{ 278 ID: "bar", 279 }, 280 Dependencies: []string{"module.child"}, 281 }, 282 }, 283 }, 284 &ModuleState{ 285 Path: []string{"root", "child"}, 286 Resources: map[string]*ResourceState{ 287 "aws_instance.child": &ResourceState{ 288 Type: "aws_instance", 289 Primary: &InstanceState{ 290 ID: "bar", 291 }, 292 }, 293 }, 294 }, 295 }, 296 } 297 298 { 299 // Wait for the dependency, sleep, and verify the graph never 300 // called a child. 301 var called int32 302 var checked bool 303 p.ApplyFn = func( 304 info *InstanceInfo, 305 is *InstanceState, 306 id *InstanceDiff) (*InstanceState, error) { 307 if info.HumanId() == "aws_instance.a" { 308 checked = true 309 310 // Sleep to allow parallel execution 311 time.Sleep(50 * time.Millisecond) 312 313 // Verify that called is 0 (dep not called) 314 if atomic.LoadInt32(&called) != 0 { 315 return nil, fmt.Errorf("module child should not be called") 316 } 317 } 318 319 atomic.AddInt32(&called, 1) 320 return testApplyFn(info, is, id) 321 } 322 323 ctx := testContext2(t, &ContextOpts{ 324 Module: m, 325 ProviderResolver: ResourceProviderResolverFixed( 326 map[string]ResourceProviderFactory{ 327 "aws": testProviderFuncFixed(p), 328 }, 329 ), 330 State: state, 331 }) 332 333 if _, err := ctx.Plan(); err != nil { 334 t.Fatalf("err: %s", err) 335 } 336 337 state, err := ctx.Apply() 338 if err != nil { 339 t.Fatalf("err: %s", err) 340 } 341 342 if !checked { 343 t.Fatal("should check") 344 } 345 346 checkStateString(t, state, "<no state>") 347 } 348 } 349 350 func TestContext2Apply_resourceDependsOnModuleDestroy(t *testing.T) { 351 m := testModule(t, "apply-resource-depends-on-module") 352 p := testProvider("aws") 353 p.DiffFn = testDiffFn 354 355 var globalState *State 356 { 357 p.ApplyFn = testApplyFn 358 ctx := testContext2(t, &ContextOpts{ 359 Module: m, 360 ProviderResolver: ResourceProviderResolverFixed( 361 map[string]ResourceProviderFactory{ 362 "aws": testProviderFuncFixed(p), 363 }, 364 ), 365 }) 366 367 if _, err := ctx.Plan(); err != nil { 368 t.Fatalf("err: %s", err) 369 } 370 371 state, err := ctx.Apply() 372 if err != nil { 373 t.Fatalf("err: %s", err) 374 } 375 376 globalState = state 377 } 378 379 { 380 // Wait for the dependency, sleep, and verify the graph never 381 // called a child. 382 var called int32 383 var checked bool 384 p.ApplyFn = func( 385 info *InstanceInfo, 386 is *InstanceState, 387 id *InstanceDiff) (*InstanceState, error) { 388 if info.HumanId() == "aws_instance.a" { 389 checked = true 390 391 // Sleep to allow parallel execution 392 time.Sleep(50 * time.Millisecond) 393 394 // Verify that called is 0 (dep not called) 395 if atomic.LoadInt32(&called) != 0 { 396 return nil, fmt.Errorf("module child should not be called") 397 } 398 } 399 400 atomic.AddInt32(&called, 1) 401 return testApplyFn(info, is, id) 402 } 403 404 ctx := testContext2(t, &ContextOpts{ 405 Module: m, 406 ProviderResolver: ResourceProviderResolverFixed( 407 map[string]ResourceProviderFactory{ 408 "aws": testProviderFuncFixed(p), 409 }, 410 ), 411 State: globalState, 412 Destroy: true, 413 }) 414 415 if _, err := ctx.Plan(); err != nil { 416 t.Fatalf("err: %s", err) 417 } 418 419 state, err := ctx.Apply() 420 if err != nil { 421 t.Fatalf("err: %s", err) 422 } 423 424 if !checked { 425 t.Fatal("should check") 426 } 427 428 checkStateString(t, state, ` 429 <no state> 430 module.child: 431 <no state> 432 `) 433 } 434 } 435 436 func TestContext2Apply_resourceDependsOnModuleGrandchild(t *testing.T) { 437 m := testModule(t, "apply-resource-depends-on-module-deep") 438 p := testProvider("aws") 439 p.DiffFn = testDiffFn 440 441 { 442 // Wait for the dependency, sleep, and verify the graph never 443 // called a child. 444 var called int32 445 var checked bool 446 p.ApplyFn = func( 447 info *InstanceInfo, 448 is *InstanceState, 449 id *InstanceDiff) (*InstanceState, error) { 450 if info.HumanId() == "module.child.grandchild.aws_instance.c" { 451 checked = true 452 453 // Sleep to allow parallel execution 454 time.Sleep(50 * time.Millisecond) 455 456 // Verify that called is 0 (dep not called) 457 if atomic.LoadInt32(&called) != 0 { 458 return nil, fmt.Errorf("aws_instance.a should not be called") 459 } 460 } 461 462 atomic.AddInt32(&called, 1) 463 return testApplyFn(info, is, id) 464 } 465 466 ctx := testContext2(t, &ContextOpts{ 467 Module: m, 468 ProviderResolver: ResourceProviderResolverFixed( 469 map[string]ResourceProviderFactory{ 470 "aws": testProviderFuncFixed(p), 471 }, 472 ), 473 }) 474 475 if _, err := ctx.Plan(); err != nil { 476 t.Fatalf("err: %s", err) 477 } 478 479 state, err := ctx.Apply() 480 if err != nil { 481 t.Fatalf("err: %s", err) 482 } 483 484 if !checked { 485 t.Fatal("should check") 486 } 487 488 checkStateString(t, state, testTerraformApplyResourceDependsOnModuleDeepStr) 489 } 490 } 491 492 func TestContext2Apply_resourceDependsOnModuleInModule(t *testing.T) { 493 m := testModule(t, "apply-resource-depends-on-module-in-module") 494 p := testProvider("aws") 495 p.DiffFn = testDiffFn 496 497 { 498 // Wait for the dependency, sleep, and verify the graph never 499 // called a child. 500 var called int32 501 var checked bool 502 p.ApplyFn = func( 503 info *InstanceInfo, 504 is *InstanceState, 505 id *InstanceDiff) (*InstanceState, error) { 506 if info.HumanId() == "module.child.grandchild.aws_instance.c" { 507 checked = true 508 509 // Sleep to allow parallel execution 510 time.Sleep(50 * time.Millisecond) 511 512 // Verify that called is 0 (dep not called) 513 if atomic.LoadInt32(&called) != 0 { 514 return nil, fmt.Errorf("nothing else should not be called") 515 } 516 } 517 518 atomic.AddInt32(&called, 1) 519 return testApplyFn(info, is, id) 520 } 521 522 ctx := testContext2(t, &ContextOpts{ 523 Module: m, 524 ProviderResolver: ResourceProviderResolverFixed( 525 map[string]ResourceProviderFactory{ 526 "aws": testProviderFuncFixed(p), 527 }, 528 ), 529 }) 530 531 if _, err := ctx.Plan(); err != nil { 532 t.Fatalf("err: %s", err) 533 } 534 535 state, err := ctx.Apply() 536 if err != nil { 537 t.Fatalf("err: %s", err) 538 } 539 540 if !checked { 541 t.Fatal("should check") 542 } 543 544 checkStateString(t, state, testTerraformApplyResourceDependsOnModuleInModuleStr) 545 } 546 } 547 548 func TestContext2Apply_mapVarBetweenModules(t *testing.T) { 549 m := testModule(t, "apply-map-var-through-module") 550 p := testProvider("null") 551 p.ApplyFn = testApplyFn 552 p.DiffFn = testDiffFn 553 ctx := testContext2(t, &ContextOpts{ 554 Module: m, 555 ProviderResolver: ResourceProviderResolverFixed( 556 map[string]ResourceProviderFactory{ 557 "null": testProviderFuncFixed(p), 558 }, 559 ), 560 }) 561 562 if _, err := ctx.Plan(); err != nil { 563 t.Fatalf("err: %s", err) 564 } 565 566 state, err := ctx.Apply() 567 if err != nil { 568 t.Fatalf("err: %s", err) 569 } 570 571 actual := strings.TrimSpace(state.String()) 572 expected := strings.TrimSpace(`<no state> 573 Outputs: 574 575 amis_from_module = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 } 576 577 module.test: 578 null_resource.noop: 579 ID = foo 580 provider = provider.null 581 582 Outputs: 583 584 amis_out = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 }`) 585 if actual != expected { 586 t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual) 587 } 588 } 589 590 func TestContext2Apply_refCount(t *testing.T) { 591 m := testModule(t, "apply-ref-count") 592 p := testProvider("aws") 593 p.ApplyFn = testApplyFn 594 p.DiffFn = testDiffFn 595 ctx := testContext2(t, &ContextOpts{ 596 Module: m, 597 ProviderResolver: ResourceProviderResolverFixed( 598 map[string]ResourceProviderFactory{ 599 "aws": testProviderFuncFixed(p), 600 }, 601 ), 602 }) 603 604 if _, err := ctx.Plan(); err != nil { 605 t.Fatalf("err: %s", err) 606 } 607 608 state, err := ctx.Apply() 609 if err != nil { 610 t.Fatalf("err: %s", err) 611 } 612 613 mod := state.RootModule() 614 if len(mod.Resources) < 2 { 615 t.Fatalf("bad: %#v", mod.Resources) 616 } 617 618 actual := strings.TrimSpace(state.String()) 619 expected := strings.TrimSpace(testTerraformApplyRefCountStr) 620 if actual != expected { 621 t.Fatalf("bad: \n%s", actual) 622 } 623 } 624 625 func TestContext2Apply_providerAlias(t *testing.T) { 626 m := testModule(t, "apply-provider-alias") 627 p := testProvider("aws") 628 p.ApplyFn = testApplyFn 629 p.DiffFn = testDiffFn 630 ctx := testContext2(t, &ContextOpts{ 631 Module: m, 632 ProviderResolver: ResourceProviderResolverFixed( 633 map[string]ResourceProviderFactory{ 634 "aws": testProviderFuncFixed(p), 635 }, 636 ), 637 }) 638 639 if _, err := ctx.Plan(); err != nil { 640 t.Fatalf("err: %s", err) 641 } 642 643 state, err := ctx.Apply() 644 if err != nil { 645 t.Fatalf("err: %s", err) 646 } 647 648 mod := state.RootModule() 649 if len(mod.Resources) < 2 { 650 t.Fatalf("bad: %#v", mod.Resources) 651 } 652 653 actual := strings.TrimSpace(state.String()) 654 expected := strings.TrimSpace(testTerraformApplyProviderAliasStr) 655 if actual != expected { 656 t.Fatalf("bad: \n%s", actual) 657 } 658 } 659 660 // Two providers that are configured should both be configured prior to apply 661 func TestContext2Apply_providerAliasConfigure(t *testing.T) { 662 m := testModule(t, "apply-provider-alias-configure") 663 664 p2 := testProvider("another") 665 p2.ApplyFn = testApplyFn 666 p2.DiffFn = testDiffFn 667 668 ctx := testContext2(t, &ContextOpts{ 669 Module: m, 670 ProviderResolver: ResourceProviderResolverFixed( 671 map[string]ResourceProviderFactory{ 672 "another": testProviderFuncFixed(p2), 673 }, 674 ), 675 }) 676 677 if p, err := ctx.Plan(); err != nil { 678 t.Fatalf("err: %s", err) 679 } else { 680 t.Logf(p.String()) 681 } 682 683 // Configure to record calls AFTER Plan above 684 var configCount int32 685 p2.ConfigureFn = func(c *ResourceConfig) error { 686 atomic.AddInt32(&configCount, 1) 687 688 foo, ok := c.Get("foo") 689 if !ok { 690 return fmt.Errorf("foo is not found") 691 } 692 693 if foo != "bar" { 694 return fmt.Errorf("foo: %#v", foo) 695 } 696 697 return nil 698 } 699 700 state, err := ctx.Apply() 701 if err != nil { 702 t.Fatalf("err: %s", err) 703 } 704 705 if configCount != 2 { 706 t.Fatalf("provider config expected 2 calls, got: %d", configCount) 707 } 708 709 actual := strings.TrimSpace(state.String()) 710 expected := strings.TrimSpace(testTerraformApplyProviderAliasConfigStr) 711 if actual != expected { 712 t.Fatalf("bad: \n%s", actual) 713 } 714 } 715 716 // GH-2870 717 func TestContext2Apply_providerWarning(t *testing.T) { 718 m := testModule(t, "apply-provider-warning") 719 p := testProvider("aws") 720 p.ApplyFn = testApplyFn 721 p.DiffFn = testDiffFn 722 p.ValidateFn = func(c *ResourceConfig) (ws []string, es []error) { 723 ws = append(ws, "Just a warning") 724 return 725 } 726 ctx := testContext2(t, &ContextOpts{ 727 Module: m, 728 ProviderResolver: ResourceProviderResolverFixed( 729 map[string]ResourceProviderFactory{ 730 "aws": testProviderFuncFixed(p), 731 }, 732 ), 733 }) 734 735 if _, err := ctx.Plan(); err != nil { 736 t.Fatalf("err: %s", err) 737 } 738 739 state, err := ctx.Apply() 740 if err != nil { 741 t.Fatalf("err: %s", err) 742 } 743 744 actual := strings.TrimSpace(state.String()) 745 expected := strings.TrimSpace(` 746 aws_instance.foo: 747 ID = foo 748 provider = provider.aws 749 `) 750 if actual != expected { 751 t.Fatalf("got: \n%s\n\nexpected:\n%s", actual, expected) 752 } 753 754 if !p.ConfigureCalled { 755 t.Fatalf("provider Configure() was never called!") 756 } 757 } 758 759 // Higher level test at TestResource_dataSourceListApplyPanic 760 func TestContext2Apply_computedAttrRefTypeMismatch(t *testing.T) { 761 m := testModule(t, "apply-computed-attr-ref-type-mismatch") 762 p := testProvider("aws") 763 p.DiffFn = testDiffFn 764 p.ValidateResourceFn = func(t string, c *ResourceConfig) (ws []string, es []error) { 765 // Emulate the type checking behavior of helper/schema based validation 766 if t == "aws_instance" { 767 ami, _ := c.Get("ami") 768 switch a := ami.(type) { 769 case string: 770 // ok 771 default: 772 es = append(es, fmt.Errorf("Expected ami to be string, got %T", a)) 773 } 774 } 775 return 776 } 777 p.DiffFn = func( 778 info *InstanceInfo, 779 state *InstanceState, 780 c *ResourceConfig) (*InstanceDiff, error) { 781 switch info.Type { 782 case "aws_ami_list": 783 // Emulate a diff that says "we'll create this list and ids will be populated" 784 return &InstanceDiff{ 785 Attributes: map[string]*ResourceAttrDiff{ 786 "ids.#": &ResourceAttrDiff{NewComputed: true}, 787 }, 788 }, nil 789 case "aws_instance": 790 // If we get to the diff for instance, we should be able to assume types 791 ami, _ := c.Get("ami") 792 _ = ami.(string) 793 } 794 return nil, nil 795 } 796 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 797 if info.Type != "aws_ami_list" { 798 t.Fatalf("Reached apply for unexpected resource type! %s", info.Type) 799 } 800 // Pretend like we make a thing and the computed list "ids" is populated 801 return &InstanceState{ 802 ID: "someid", 803 Attributes: map[string]string{ 804 "ids.#": "2", 805 "ids.0": "ami-abc123", 806 "ids.1": "ami-bcd345", 807 }, 808 }, nil 809 } 810 ctx := testContext2(t, &ContextOpts{ 811 Module: m, 812 ProviderResolver: ResourceProviderResolverFixed( 813 map[string]ResourceProviderFactory{ 814 "aws": testProviderFuncFixed(p), 815 }, 816 ), 817 }) 818 819 if _, err := ctx.Plan(); err != nil { 820 t.Fatalf("err: %s", err) 821 } 822 823 _, err := ctx.Apply() 824 if err == nil { 825 t.Fatalf("Expected err, got none!") 826 } 827 828 expected := "Expected ami to be string" 829 if !strings.Contains(err.Error(), expected) { 830 t.Fatalf("expected:\n\n%s\n\nto contain:\n\n%s", err, expected) 831 } 832 } 833 834 func TestContext2Apply_emptyModule(t *testing.T) { 835 m := testModule(t, "apply-empty-module") 836 p := testProvider("aws") 837 p.ApplyFn = testApplyFn 838 p.DiffFn = testDiffFn 839 ctx := testContext2(t, &ContextOpts{ 840 Module: m, 841 ProviderResolver: ResourceProviderResolverFixed( 842 map[string]ResourceProviderFactory{ 843 "aws": testProviderFuncFixed(p), 844 }, 845 ), 846 }) 847 848 if _, err := ctx.Plan(); err != nil { 849 t.Fatalf("err: %s", err) 850 } 851 852 state, err := ctx.Apply() 853 if err != nil { 854 t.Fatalf("err: %s", err) 855 } 856 857 actual := strings.TrimSpace(state.String()) 858 actual = strings.Replace(actual, " ", "", -1) 859 expected := strings.TrimSpace(testTerraformApplyEmptyModuleStr) 860 if actual != expected { 861 t.Fatalf("bad: \n%s\nexpect:\n%s", actual, expected) 862 } 863 } 864 865 func TestContext2Apply_createBeforeDestroy(t *testing.T) { 866 m := testModule(t, "apply-good-create-before") 867 p := testProvider("aws") 868 p.ApplyFn = testApplyFn 869 p.DiffFn = testDiffFn 870 state := &State{ 871 Modules: []*ModuleState{ 872 &ModuleState{ 873 Path: rootModulePath, 874 Resources: map[string]*ResourceState{ 875 "aws_instance.bar": &ResourceState{ 876 Type: "aws_instance", 877 Primary: &InstanceState{ 878 ID: "bar", 879 Attributes: map[string]string{ 880 "require_new": "abc", 881 }, 882 }, 883 }, 884 }, 885 }, 886 }, 887 } 888 ctx := testContext2(t, &ContextOpts{ 889 Module: m, 890 ProviderResolver: ResourceProviderResolverFixed( 891 map[string]ResourceProviderFactory{ 892 "aws": testProviderFuncFixed(p), 893 }, 894 ), 895 State: state, 896 }) 897 898 if p, err := ctx.Plan(); err != nil { 899 t.Fatalf("err: %s", err) 900 } else { 901 t.Logf(p.String()) 902 } 903 904 state, err := ctx.Apply() 905 if err != nil { 906 t.Fatalf("err: %s", err) 907 } 908 909 mod := state.RootModule() 910 if len(mod.Resources) != 1 { 911 t.Fatalf("bad: %s", state) 912 } 913 914 actual := strings.TrimSpace(state.String()) 915 expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr) 916 if actual != expected { 917 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 918 } 919 } 920 921 func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) { 922 m := testModule(t, "apply-good-create-before-update") 923 p := testProvider("aws") 924 p.ApplyFn = testApplyFn 925 p.DiffFn = testDiffFn 926 state := &State{ 927 Modules: []*ModuleState{ 928 &ModuleState{ 929 Path: rootModulePath, 930 Resources: map[string]*ResourceState{ 931 "aws_instance.bar": &ResourceState{ 932 Type: "aws_instance", 933 Primary: &InstanceState{ 934 ID: "bar", 935 Attributes: map[string]string{ 936 "foo": "bar", 937 }, 938 }, 939 }, 940 }, 941 }, 942 }, 943 } 944 ctx := testContext2(t, &ContextOpts{ 945 Module: m, 946 ProviderResolver: ResourceProviderResolverFixed( 947 map[string]ResourceProviderFactory{ 948 "aws": testProviderFuncFixed(p), 949 }, 950 ), 951 State: state, 952 }) 953 954 if p, err := ctx.Plan(); err != nil { 955 t.Fatalf("err: %s", err) 956 } else { 957 t.Logf(p.String()) 958 } 959 960 state, err := ctx.Apply() 961 if err != nil { 962 t.Fatalf("err: %s", err) 963 } 964 965 mod := state.RootModule() 966 if len(mod.Resources) != 1 { 967 t.Fatalf("bad: %s", state) 968 } 969 970 actual := strings.TrimSpace(state.String()) 971 expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr) 972 if actual != expected { 973 t.Fatalf("bad: \n%s", actual) 974 } 975 } 976 977 // This tests that when a CBD resource depends on a non-CBD resource, 978 // we can still properly apply changes that require new for both. 979 func TestContext2Apply_createBeforeDestroy_dependsNonCBD(t *testing.T) { 980 m := testModule(t, "apply-cbd-depends-non-cbd") 981 p := testProvider("aws") 982 p.ApplyFn = testApplyFn 983 p.DiffFn = testDiffFn 984 state := &State{ 985 Modules: []*ModuleState{ 986 &ModuleState{ 987 Path: rootModulePath, 988 Resources: map[string]*ResourceState{ 989 "aws_instance.bar": &ResourceState{ 990 Type: "aws_instance", 991 Primary: &InstanceState{ 992 ID: "bar", 993 Attributes: map[string]string{ 994 "require_new": "abc", 995 }, 996 }, 997 }, 998 999 "aws_instance.foo": &ResourceState{ 1000 Type: "aws_instance", 1001 Primary: &InstanceState{ 1002 ID: "foo", 1003 Attributes: map[string]string{ 1004 "require_new": "abc", 1005 }, 1006 }, 1007 }, 1008 }, 1009 }, 1010 }, 1011 } 1012 ctx := testContext2(t, &ContextOpts{ 1013 Module: m, 1014 ProviderResolver: ResourceProviderResolverFixed( 1015 map[string]ResourceProviderFactory{ 1016 "aws": testProviderFuncFixed(p), 1017 }, 1018 ), 1019 State: state, 1020 }) 1021 1022 if p, err := ctx.Plan(); err != nil { 1023 t.Fatalf("err: %s", err) 1024 } else { 1025 t.Logf(p.String()) 1026 } 1027 1028 state, err := ctx.Apply() 1029 if err != nil { 1030 t.Fatalf("err: %s", err) 1031 } 1032 1033 checkStateString(t, state, ` 1034 aws_instance.bar: 1035 ID = foo 1036 provider = provider.aws 1037 require_new = yes 1038 type = aws_instance 1039 value = foo 1040 aws_instance.foo: 1041 ID = foo 1042 provider = provider.aws 1043 require_new = yes 1044 type = aws_instance 1045 `) 1046 } 1047 1048 func TestContext2Apply_createBeforeDestroy_hook(t *testing.T) { 1049 h := new(MockHook) 1050 m := testModule(t, "apply-good-create-before") 1051 p := testProvider("aws") 1052 p.ApplyFn = testApplyFn 1053 p.DiffFn = testDiffFn 1054 state := &State{ 1055 Modules: []*ModuleState{ 1056 &ModuleState{ 1057 Path: rootModulePath, 1058 Resources: map[string]*ResourceState{ 1059 "aws_instance.bar": &ResourceState{ 1060 Type: "aws_instance", 1061 Primary: &InstanceState{ 1062 ID: "bar", 1063 Attributes: map[string]string{ 1064 "require_new": "abc", 1065 }, 1066 }, 1067 }, 1068 }, 1069 }, 1070 }, 1071 } 1072 1073 var actual []string 1074 var actualLock sync.Mutex 1075 h.PostApplyFn = func(n *InstanceInfo, s *InstanceState, e error) (HookAction, error) { 1076 actualLock.Lock() 1077 defer actualLock.Unlock() 1078 actual = append(actual, n.Id) 1079 return HookActionContinue, nil 1080 } 1081 1082 ctx := testContext2(t, &ContextOpts{ 1083 Module: m, 1084 Hooks: []Hook{h}, 1085 ProviderResolver: ResourceProviderResolverFixed( 1086 map[string]ResourceProviderFactory{ 1087 "aws": testProviderFuncFixed(p), 1088 }, 1089 ), 1090 State: state, 1091 }) 1092 1093 if p, err := ctx.Plan(); err != nil { 1094 t.Fatalf("err: %s", err) 1095 } else { 1096 t.Logf(p.String()) 1097 } 1098 1099 if _, err := ctx.Apply(); err != nil { 1100 t.Fatalf("err: %s", err) 1101 } 1102 1103 expected := []string{"aws_instance.bar", "aws_instance.bar (deposed #0)"} 1104 if !reflect.DeepEqual(actual, expected) { 1105 t.Fatalf("bad: %#v", actual) 1106 } 1107 } 1108 1109 // Test that we can perform an apply with CBD in a count with deposed instances. 1110 func TestContext2Apply_createBeforeDestroy_deposedCount(t *testing.T) { 1111 m := testModule(t, "apply-cbd-count") 1112 p := testProvider("aws") 1113 p.ApplyFn = testApplyFn 1114 p.DiffFn = testDiffFn 1115 1116 state := &State{ 1117 Modules: []*ModuleState{ 1118 &ModuleState{ 1119 Path: rootModulePath, 1120 Resources: map[string]*ResourceState{ 1121 "aws_instance.bar.0": &ResourceState{ 1122 Type: "aws_instance", 1123 Primary: &InstanceState{ 1124 ID: "bar", 1125 Tainted: true, 1126 }, 1127 1128 Deposed: []*InstanceState{ 1129 &InstanceState{ 1130 ID: "foo", 1131 }, 1132 }, 1133 }, 1134 "aws_instance.bar.1": &ResourceState{ 1135 Type: "aws_instance", 1136 Primary: &InstanceState{ 1137 ID: "bar", 1138 Tainted: true, 1139 }, 1140 1141 Deposed: []*InstanceState{ 1142 &InstanceState{ 1143 ID: "bar", 1144 }, 1145 }, 1146 }, 1147 }, 1148 }, 1149 }, 1150 } 1151 1152 ctx := testContext2(t, &ContextOpts{ 1153 Module: m, 1154 ProviderResolver: ResourceProviderResolverFixed( 1155 map[string]ResourceProviderFactory{ 1156 "aws": testProviderFuncFixed(p), 1157 }, 1158 ), 1159 State: state, 1160 }) 1161 1162 if p, err := ctx.Plan(); err != nil { 1163 t.Fatalf("err: %s", err) 1164 } else { 1165 t.Logf(p.String()) 1166 } 1167 1168 state, err := ctx.Apply() 1169 if err != nil { 1170 t.Fatalf("err: %s", err) 1171 } 1172 1173 checkStateString(t, state, ` 1174 aws_instance.bar.0: 1175 ID = foo 1176 provider = provider.aws 1177 foo = bar 1178 type = aws_instance 1179 aws_instance.bar.1: 1180 ID = foo 1181 provider = provider.aws 1182 foo = bar 1183 type = aws_instance 1184 `) 1185 } 1186 1187 // Test that when we have a deposed instance but a good primary, we still 1188 // destroy the deposed instance. 1189 func TestContext2Apply_createBeforeDestroy_deposedOnly(t *testing.T) { 1190 m := testModule(t, "apply-cbd-deposed-only") 1191 p := testProvider("aws") 1192 p.ApplyFn = testApplyFn 1193 p.DiffFn = testDiffFn 1194 1195 state := &State{ 1196 Modules: []*ModuleState{ 1197 &ModuleState{ 1198 Path: rootModulePath, 1199 Resources: map[string]*ResourceState{ 1200 "aws_instance.bar": &ResourceState{ 1201 Type: "aws_instance", 1202 Primary: &InstanceState{ 1203 ID: "bar", 1204 }, 1205 1206 Deposed: []*InstanceState{ 1207 &InstanceState{ 1208 ID: "foo", 1209 }, 1210 }, 1211 }, 1212 }, 1213 }, 1214 }, 1215 } 1216 1217 ctx := testContext2(t, &ContextOpts{ 1218 Module: m, 1219 ProviderResolver: ResourceProviderResolverFixed( 1220 map[string]ResourceProviderFactory{ 1221 "aws": testProviderFuncFixed(p), 1222 }, 1223 ), 1224 State: state, 1225 }) 1226 1227 if p, err := ctx.Plan(); err != nil { 1228 t.Fatalf("err: %s", err) 1229 } else { 1230 t.Logf(p.String()) 1231 } 1232 1233 state, err := ctx.Apply() 1234 if err != nil { 1235 t.Fatalf("err: %s", err) 1236 } 1237 1238 checkStateString(t, state, ` 1239 aws_instance.bar: 1240 ID = bar 1241 provider = provider.aws 1242 `) 1243 } 1244 1245 func TestContext2Apply_destroyComputed(t *testing.T) { 1246 m := testModule(t, "apply-destroy-computed") 1247 p := testProvider("aws") 1248 p.ApplyFn = testApplyFn 1249 p.DiffFn = testDiffFn 1250 state := &State{ 1251 Modules: []*ModuleState{ 1252 &ModuleState{ 1253 Path: rootModulePath, 1254 Resources: map[string]*ResourceState{ 1255 "aws_instance.foo": &ResourceState{ 1256 Type: "aws_instance", 1257 Primary: &InstanceState{ 1258 ID: "foo", 1259 Attributes: map[string]string{ 1260 "output": "value", 1261 }, 1262 }, 1263 }, 1264 }, 1265 }, 1266 }, 1267 } 1268 ctx := testContext2(t, &ContextOpts{ 1269 Module: m, 1270 ProviderResolver: ResourceProviderResolverFixed( 1271 map[string]ResourceProviderFactory{ 1272 "aws": testProviderFuncFixed(p), 1273 }, 1274 ), 1275 State: state, 1276 Destroy: true, 1277 }) 1278 1279 if p, err := ctx.Plan(); err != nil { 1280 t.Fatalf("err: %s", err) 1281 } else { 1282 t.Logf(p.String()) 1283 } 1284 1285 if _, err := ctx.Apply(); err != nil { 1286 t.Fatalf("err: %s", err) 1287 } 1288 } 1289 1290 // Test that the destroy operation uses depends_on as a source of ordering. 1291 func TestContext2Apply_destroyDependsOn(t *testing.T) { 1292 // It is possible for this to be racy, so we loop a number of times 1293 // just to check. 1294 for i := 0; i < 10; i++ { 1295 testContext2Apply_destroyDependsOn(t) 1296 } 1297 } 1298 1299 func testContext2Apply_destroyDependsOn(t *testing.T) { 1300 m := testModule(t, "apply-destroy-depends-on") 1301 p := testProvider("aws") 1302 p.ApplyFn = testApplyFn 1303 p.DiffFn = testDiffFn 1304 state := &State{ 1305 Modules: []*ModuleState{ 1306 &ModuleState{ 1307 Path: rootModulePath, 1308 Resources: map[string]*ResourceState{ 1309 "aws_instance.foo": &ResourceState{ 1310 Type: "aws_instance", 1311 Primary: &InstanceState{ 1312 ID: "foo", 1313 Attributes: map[string]string{}, 1314 }, 1315 }, 1316 1317 "aws_instance.bar": &ResourceState{ 1318 Type: "aws_instance", 1319 Primary: &InstanceState{ 1320 ID: "bar", 1321 Attributes: map[string]string{}, 1322 }, 1323 }, 1324 }, 1325 }, 1326 }, 1327 } 1328 1329 // Record the order we see Apply 1330 var actual []string 1331 var actualLock sync.Mutex 1332 p.ApplyFn = func( 1333 info *InstanceInfo, _ *InstanceState, _ *InstanceDiff) (*InstanceState, error) { 1334 actualLock.Lock() 1335 defer actualLock.Unlock() 1336 actual = append(actual, info.Id) 1337 return nil, nil 1338 } 1339 1340 ctx := testContext2(t, &ContextOpts{ 1341 Module: m, 1342 ProviderResolver: ResourceProviderResolverFixed( 1343 map[string]ResourceProviderFactory{ 1344 "aws": testProviderFuncFixed(p), 1345 }, 1346 ), 1347 State: state, 1348 Destroy: true, 1349 Parallelism: 1, // To check ordering 1350 }) 1351 1352 if _, err := ctx.Plan(); err != nil { 1353 t.Fatalf("err: %s", err) 1354 } 1355 1356 if _, err := ctx.Apply(); err != nil { 1357 t.Fatalf("err: %s", err) 1358 } 1359 1360 expected := []string{"aws_instance.foo", "aws_instance.bar"} 1361 if !reflect.DeepEqual(actual, expected) { 1362 t.Fatalf("bad: %#v", actual) 1363 } 1364 } 1365 1366 // Test that destroy ordering is correct with dependencies only 1367 // in the state. 1368 func TestContext2Apply_destroyDependsOnStateOnly(t *testing.T) { 1369 // It is possible for this to be racy, so we loop a number of times 1370 // just to check. 1371 for i := 0; i < 10; i++ { 1372 testContext2Apply_destroyDependsOnStateOnly(t) 1373 } 1374 } 1375 1376 func testContext2Apply_destroyDependsOnStateOnly(t *testing.T) { 1377 m := testModule(t, "empty") 1378 p := testProvider("aws") 1379 p.ApplyFn = testApplyFn 1380 p.DiffFn = testDiffFn 1381 state := &State{ 1382 Modules: []*ModuleState{ 1383 &ModuleState{ 1384 Path: rootModulePath, 1385 Resources: map[string]*ResourceState{ 1386 "aws_instance.foo": &ResourceState{ 1387 Type: "aws_instance", 1388 Primary: &InstanceState{ 1389 ID: "foo", 1390 Attributes: map[string]string{}, 1391 }, 1392 }, 1393 1394 "aws_instance.bar": &ResourceState{ 1395 Type: "aws_instance", 1396 Primary: &InstanceState{ 1397 ID: "bar", 1398 Attributes: map[string]string{}, 1399 }, 1400 Dependencies: []string{"aws_instance.foo"}, 1401 }, 1402 }, 1403 }, 1404 }, 1405 } 1406 1407 // Record the order we see Apply 1408 var actual []string 1409 var actualLock sync.Mutex 1410 p.ApplyFn = func( 1411 info *InstanceInfo, _ *InstanceState, _ *InstanceDiff) (*InstanceState, error) { 1412 actualLock.Lock() 1413 defer actualLock.Unlock() 1414 actual = append(actual, info.Id) 1415 return nil, nil 1416 } 1417 1418 ctx := testContext2(t, &ContextOpts{ 1419 Module: m, 1420 ProviderResolver: ResourceProviderResolverFixed( 1421 map[string]ResourceProviderFactory{ 1422 "aws": testProviderFuncFixed(p), 1423 }, 1424 ), 1425 State: state, 1426 Destroy: true, 1427 Parallelism: 1, // To check ordering 1428 }) 1429 1430 if _, err := ctx.Plan(); err != nil { 1431 t.Fatalf("err: %s", err) 1432 } 1433 1434 if _, err := ctx.Apply(); err != nil { 1435 t.Fatalf("err: %s", err) 1436 } 1437 1438 expected := []string{"aws_instance.bar", "aws_instance.foo"} 1439 if !reflect.DeepEqual(actual, expected) { 1440 t.Fatalf("bad: %#v", actual) 1441 } 1442 } 1443 1444 // Test that destroy ordering is correct with dependencies only 1445 // in the state within a module (GH-11749) 1446 func TestContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) { 1447 // It is possible for this to be racy, so we loop a number of times 1448 // just to check. 1449 for i := 0; i < 10; i++ { 1450 testContext2Apply_destroyDependsOnStateOnlyModule(t) 1451 } 1452 } 1453 1454 func testContext2Apply_destroyDependsOnStateOnlyModule(t *testing.T) { 1455 m := testModule(t, "empty") 1456 p := testProvider("aws") 1457 p.ApplyFn = testApplyFn 1458 p.DiffFn = testDiffFn 1459 state := &State{ 1460 Modules: []*ModuleState{ 1461 &ModuleState{ 1462 Path: []string{"root", "child"}, 1463 Resources: map[string]*ResourceState{ 1464 "aws_instance.foo": &ResourceState{ 1465 Type: "aws_instance", 1466 Primary: &InstanceState{ 1467 ID: "foo", 1468 Attributes: map[string]string{}, 1469 }, 1470 }, 1471 1472 "aws_instance.bar": &ResourceState{ 1473 Type: "aws_instance", 1474 Primary: &InstanceState{ 1475 ID: "bar", 1476 Attributes: map[string]string{}, 1477 }, 1478 Dependencies: []string{"aws_instance.foo"}, 1479 }, 1480 }, 1481 }, 1482 }, 1483 } 1484 1485 // Record the order we see Apply 1486 var actual []string 1487 var actualLock sync.Mutex 1488 p.ApplyFn = func( 1489 info *InstanceInfo, _ *InstanceState, _ *InstanceDiff) (*InstanceState, error) { 1490 actualLock.Lock() 1491 defer actualLock.Unlock() 1492 actual = append(actual, info.Id) 1493 return nil, nil 1494 } 1495 1496 ctx := testContext2(t, &ContextOpts{ 1497 Module: m, 1498 ProviderResolver: ResourceProviderResolverFixed( 1499 map[string]ResourceProviderFactory{ 1500 "aws": testProviderFuncFixed(p), 1501 }, 1502 ), 1503 State: state, 1504 Destroy: true, 1505 Parallelism: 1, // To check ordering 1506 }) 1507 1508 if _, err := ctx.Plan(); err != nil { 1509 t.Fatalf("err: %s", err) 1510 } 1511 1512 if _, err := ctx.Apply(); err != nil { 1513 t.Fatalf("err: %s", err) 1514 } 1515 1516 expected := []string{"aws_instance.bar", "aws_instance.foo"} 1517 if !reflect.DeepEqual(actual, expected) { 1518 t.Fatalf("bad: %#v", actual) 1519 } 1520 } 1521 1522 func TestContext2Apply_dataBasic(t *testing.T) { 1523 m := testModule(t, "apply-data-basic") 1524 p := testProvider("null") 1525 p.ApplyFn = testApplyFn 1526 p.DiffFn = testDiffFn 1527 p.ReadDataApplyReturn = &InstanceState{ID: "yo"} 1528 1529 ctx := testContext2(t, &ContextOpts{ 1530 Module: m, 1531 ProviderResolver: ResourceProviderResolverFixed( 1532 map[string]ResourceProviderFactory{ 1533 "null": testProviderFuncFixed(p), 1534 }, 1535 ), 1536 }) 1537 1538 if p, err := ctx.Plan(); err != nil { 1539 t.Fatalf("err: %s", err) 1540 } else { 1541 t.Logf(p.String()) 1542 } 1543 1544 state, err := ctx.Apply() 1545 if err != nil { 1546 t.Fatalf("err: %s", err) 1547 } 1548 1549 actual := strings.TrimSpace(state.String()) 1550 expected := strings.TrimSpace(testTerraformApplyDataBasicStr) 1551 if actual != expected { 1552 t.Fatalf("bad: \n%s", actual) 1553 } 1554 } 1555 1556 func TestContext2Apply_destroyData(t *testing.T) { 1557 m := testModule(t, "apply-destroy-data-resource") 1558 p := testProvider("null") 1559 p.ApplyFn = testApplyFn 1560 p.DiffFn = testDiffFn 1561 state := &State{ 1562 Modules: []*ModuleState{ 1563 &ModuleState{ 1564 Path: rootModulePath, 1565 Resources: map[string]*ResourceState{ 1566 "data.null_data_source.testing": &ResourceState{ 1567 Type: "null_data_source", 1568 Primary: &InstanceState{ 1569 ID: "-", 1570 Attributes: map[string]string{ 1571 "inputs.#": "1", 1572 "inputs.test": "yes", 1573 }, 1574 }, 1575 }, 1576 }, 1577 }, 1578 }, 1579 } 1580 hook := &testHook{} 1581 ctx := testContext2(t, &ContextOpts{ 1582 Module: m, 1583 ProviderResolver: ResourceProviderResolverFixed( 1584 map[string]ResourceProviderFactory{ 1585 "null": testProviderFuncFixed(p), 1586 }, 1587 ), 1588 State: state, 1589 Destroy: true, 1590 Hooks: []Hook{hook}, 1591 }) 1592 1593 if p, err := ctx.Plan(); err != nil { 1594 t.Fatalf("err: %s", err) 1595 } else { 1596 t.Logf(p.String()) 1597 } 1598 1599 newState, err := ctx.Apply() 1600 if err != nil { 1601 t.Fatalf("err: %s", err) 1602 } 1603 1604 if got := len(newState.Modules); got != 1 { 1605 t.Fatalf("state has %d modules after destroy; want 1", got) 1606 } 1607 1608 if got := len(newState.Modules[0].Resources); got != 0 { 1609 t.Fatalf("state has %d resources after destroy; want 0", got) 1610 } 1611 1612 wantHookCalls := []*testHookCall{ 1613 {"PreDiff", "data.null_data_source.testing"}, 1614 {"PostDiff", "data.null_data_source.testing"}, 1615 {"PostStateUpdate", ""}, 1616 } 1617 if !reflect.DeepEqual(hook.Calls, wantHookCalls) { 1618 t.Errorf("wrong hook calls\ngot: %swant: %s", spew.Sdump(hook.Calls), spew.Sdump(wantHookCalls)) 1619 } 1620 } 1621 1622 // https://github.com/hashicorp/terraform/pull/5096 1623 func TestContext2Apply_destroySkipsCBD(t *testing.T) { 1624 // Config contains CBD resource depending on non-CBD resource, which triggers 1625 // a cycle if they are both replaced, but should _not_ trigger a cycle when 1626 // just doing a `terraform destroy`. 1627 m := testModule(t, "apply-destroy-cbd") 1628 p := testProvider("aws") 1629 p.ApplyFn = testApplyFn 1630 p.DiffFn = testDiffFn 1631 state := &State{ 1632 Modules: []*ModuleState{ 1633 &ModuleState{ 1634 Path: rootModulePath, 1635 Resources: map[string]*ResourceState{ 1636 "aws_instance.foo": &ResourceState{ 1637 Type: "aws_instance", 1638 Primary: &InstanceState{ 1639 ID: "foo", 1640 }, 1641 }, 1642 "aws_instance.bar": &ResourceState{ 1643 Type: "aws_instance", 1644 Primary: &InstanceState{ 1645 ID: "foo", 1646 }, 1647 }, 1648 }, 1649 }, 1650 }, 1651 } 1652 ctx := testContext2(t, &ContextOpts{ 1653 Module: m, 1654 ProviderResolver: ResourceProviderResolverFixed( 1655 map[string]ResourceProviderFactory{ 1656 "aws": testProviderFuncFixed(p), 1657 }, 1658 ), 1659 State: state, 1660 Destroy: true, 1661 }) 1662 1663 if p, err := ctx.Plan(); err != nil { 1664 t.Fatalf("err: %s", err) 1665 } else { 1666 t.Logf(p.String()) 1667 } 1668 1669 if _, err := ctx.Apply(); err != nil { 1670 t.Fatalf("err: %s", err) 1671 } 1672 } 1673 1674 func TestContext2Apply_destroyModuleVarProviderConfig(t *testing.T) { 1675 m := testModule(t, "apply-destroy-mod-var-provider-config") 1676 p := testProvider("aws") 1677 p.ApplyFn = testApplyFn 1678 p.DiffFn = testDiffFn 1679 state := &State{ 1680 Modules: []*ModuleState{ 1681 &ModuleState{ 1682 Path: []string{"root", "child"}, 1683 Resources: map[string]*ResourceState{ 1684 "aws_instance.foo": &ResourceState{ 1685 Type: "aws_instance", 1686 Primary: &InstanceState{ 1687 ID: "foo", 1688 }, 1689 }, 1690 }, 1691 }, 1692 }, 1693 } 1694 ctx := testContext2(t, &ContextOpts{ 1695 Module: m, 1696 ProviderResolver: ResourceProviderResolverFixed( 1697 map[string]ResourceProviderFactory{ 1698 "aws": testProviderFuncFixed(p), 1699 }, 1700 ), 1701 State: state, 1702 Destroy: true, 1703 }) 1704 1705 if _, err := ctx.Plan(); err != nil { 1706 t.Fatalf("err: %s", err) 1707 } 1708 1709 _, err := ctx.Apply() 1710 if err != nil { 1711 t.Fatalf("err: %s", err) 1712 } 1713 } 1714 1715 // https://github.com/hashicorp/terraform/issues/2892 1716 func TestContext2Apply_destroyCrossProviders(t *testing.T) { 1717 m := testModule(t, "apply-destroy-cross-providers") 1718 1719 p_aws := testProvider("aws") 1720 p_aws.ApplyFn = testApplyFn 1721 p_aws.DiffFn = testDiffFn 1722 1723 p_tf := testProvider("terraform") 1724 p_tf.ApplyFn = testApplyFn 1725 p_tf.DiffFn = testDiffFn 1726 1727 providers := map[string]ResourceProviderFactory{ 1728 "aws": testProviderFuncFixed(p_aws), 1729 "terraform": testProviderFuncFixed(p_tf), 1730 } 1731 1732 // Bug only appears from time to time, 1733 // so we run this test multiple times 1734 // to check for the race-condition 1735 for i := 0; i <= 10; i++ { 1736 ctx := getContextForApply_destroyCrossProviders( 1737 t, m, providers) 1738 1739 if p, err := ctx.Plan(); err != nil { 1740 t.Fatalf("err: %s", err) 1741 } else { 1742 t.Logf(p.String()) 1743 } 1744 1745 if _, err := ctx.Apply(); err != nil { 1746 t.Fatalf("err: %s", err) 1747 } 1748 } 1749 } 1750 1751 func getContextForApply_destroyCrossProviders( 1752 t *testing.T, 1753 m *module.Tree, 1754 providers map[string]ResourceProviderFactory) *Context { 1755 state := &State{ 1756 Modules: []*ModuleState{ 1757 &ModuleState{ 1758 Path: rootModulePath, 1759 Resources: map[string]*ResourceState{ 1760 "terraform_remote_state.shared": &ResourceState{ 1761 Type: "terraform_remote_state", 1762 Primary: &InstanceState{ 1763 ID: "remote-2652591293", 1764 Attributes: map[string]string{ 1765 "output.env_name": "test", 1766 }, 1767 }, 1768 }, 1769 }, 1770 }, 1771 &ModuleState{ 1772 Path: []string{"root", "child"}, 1773 Resources: map[string]*ResourceState{ 1774 "aws_vpc.bar": &ResourceState{ 1775 Type: "aws_vpc", 1776 Primary: &InstanceState{ 1777 ID: "vpc-aaabbb12", 1778 Attributes: map[string]string{ 1779 "value": "test", 1780 }, 1781 }, 1782 }, 1783 }, 1784 }, 1785 }, 1786 } 1787 ctx := testContext2(t, &ContextOpts{ 1788 Module: m, 1789 ProviderResolver: ResourceProviderResolverFixed(providers), 1790 State: state, 1791 Destroy: true, 1792 }) 1793 1794 return ctx 1795 } 1796 1797 func TestContext2Apply_minimal(t *testing.T) { 1798 m := testModule(t, "apply-minimal") 1799 p := testProvider("aws") 1800 p.ApplyFn = testApplyFn 1801 p.DiffFn = testDiffFn 1802 ctx := testContext2(t, &ContextOpts{ 1803 Module: m, 1804 ProviderResolver: ResourceProviderResolverFixed( 1805 map[string]ResourceProviderFactory{ 1806 "aws": testProviderFuncFixed(p), 1807 }, 1808 ), 1809 }) 1810 1811 if _, err := ctx.Plan(); err != nil { 1812 t.Fatalf("err: %s", err) 1813 } 1814 1815 state, err := ctx.Apply() 1816 if err != nil { 1817 t.Fatalf("err: %s", err) 1818 } 1819 1820 actual := strings.TrimSpace(state.String()) 1821 expected := strings.TrimSpace(testTerraformApplyMinimalStr) 1822 if actual != expected { 1823 t.Fatalf("bad: \n%s", actual) 1824 } 1825 } 1826 1827 func TestContext2Apply_badDiff(t *testing.T) { 1828 m := testModule(t, "apply-good") 1829 p := testProvider("aws") 1830 p.ApplyFn = testApplyFn 1831 p.DiffFn = testDiffFn 1832 ctx := testContext2(t, &ContextOpts{ 1833 Module: m, 1834 ProviderResolver: ResourceProviderResolverFixed( 1835 map[string]ResourceProviderFactory{ 1836 "aws": testProviderFuncFixed(p), 1837 }, 1838 ), 1839 }) 1840 1841 if _, err := ctx.Plan(); err != nil { 1842 t.Fatalf("err: %s", err) 1843 } 1844 1845 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 1846 return &InstanceDiff{ 1847 Attributes: map[string]*ResourceAttrDiff{ 1848 "newp": nil, 1849 }, 1850 }, nil 1851 } 1852 1853 if _, err := ctx.Apply(); err == nil { 1854 t.Fatal("should error") 1855 } 1856 } 1857 1858 func TestContext2Apply_cancel(t *testing.T) { 1859 stopped := false 1860 1861 m := testModule(t, "apply-cancel") 1862 p := testProvider("aws") 1863 ctx := testContext2(t, &ContextOpts{ 1864 Module: m, 1865 ProviderResolver: ResourceProviderResolverFixed( 1866 map[string]ResourceProviderFactory{ 1867 "aws": testProviderFuncFixed(p), 1868 }, 1869 ), 1870 }) 1871 1872 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 1873 if !stopped { 1874 stopped = true 1875 go ctx.Stop() 1876 1877 for { 1878 if ctx.sh.Stopped() { 1879 break 1880 } 1881 time.Sleep(10 * time.Millisecond) 1882 } 1883 } 1884 1885 return &InstanceState{ 1886 ID: "foo", 1887 Attributes: map[string]string{ 1888 "num": "2", 1889 }, 1890 }, nil 1891 } 1892 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 1893 return &InstanceDiff{ 1894 Attributes: map[string]*ResourceAttrDiff{ 1895 "num": &ResourceAttrDiff{ 1896 New: "bar", 1897 }, 1898 }, 1899 }, nil 1900 } 1901 1902 if _, err := ctx.Plan(); err != nil { 1903 t.Fatalf("err: %s", err) 1904 } 1905 1906 // Start the Apply in a goroutine 1907 var applyErr error 1908 stateCh := make(chan *State) 1909 go func() { 1910 state, err := ctx.Apply() 1911 if err != nil { 1912 applyErr = err 1913 } 1914 1915 stateCh <- state 1916 }() 1917 1918 state := <-stateCh 1919 if applyErr != nil { 1920 t.Fatalf("err: %s", applyErr) 1921 } 1922 1923 mod := state.RootModule() 1924 if len(mod.Resources) != 1 { 1925 t.Fatalf("bad: %s", state.String()) 1926 } 1927 1928 actual := strings.TrimSpace(state.String()) 1929 expected := strings.TrimSpace(testTerraformApplyCancelStr) 1930 if actual != expected { 1931 t.Fatalf("bad: \n%s", actual) 1932 } 1933 1934 if !p.StopCalled { 1935 t.Fatal("stop should be called") 1936 } 1937 } 1938 1939 func TestContext2Apply_cancelBlock(t *testing.T) { 1940 m := testModule(t, "apply-cancel-block") 1941 p := testProvider("aws") 1942 ctx := testContext2(t, &ContextOpts{ 1943 Module: m, 1944 ProviderResolver: ResourceProviderResolverFixed( 1945 map[string]ResourceProviderFactory{ 1946 "aws": testProviderFuncFixed(p), 1947 }, 1948 ), 1949 }) 1950 1951 applyCh := make(chan struct{}) 1952 p.DiffFn = testDiffFn 1953 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 1954 close(applyCh) 1955 1956 for !ctx.sh.Stopped() { 1957 // Wait for stop to be called. We call Gosched here so that 1958 // the other goroutines can always be scheduled to set Stopped. 1959 runtime.Gosched() 1960 } 1961 1962 // Sleep 1963 time.Sleep(100 * time.Millisecond) 1964 1965 return &InstanceState{ 1966 ID: "foo", 1967 }, nil 1968 } 1969 1970 if _, err := ctx.Plan(); err != nil { 1971 t.Fatalf("err: %s", err) 1972 } 1973 1974 // Start the Apply in a goroutine 1975 var applyErr error 1976 stateCh := make(chan *State) 1977 go func() { 1978 state, err := ctx.Apply() 1979 if err != nil { 1980 applyErr = err 1981 } 1982 1983 stateCh <- state 1984 }() 1985 1986 stopDone := make(chan struct{}) 1987 go func() { 1988 defer close(stopDone) 1989 <-applyCh 1990 ctx.Stop() 1991 }() 1992 1993 // Make sure that stop blocks 1994 select { 1995 case <-stopDone: 1996 t.Fatal("stop should block") 1997 case <-time.After(10 * time.Millisecond): 1998 } 1999 2000 // Wait for stop 2001 select { 2002 case <-stopDone: 2003 case <-time.After(500 * time.Millisecond): 2004 t.Fatal("stop should be done") 2005 } 2006 2007 // Wait for apply to complete 2008 state := <-stateCh 2009 if applyErr != nil { 2010 t.Fatalf("err: %s", applyErr) 2011 } 2012 2013 checkStateString(t, state, ` 2014 aws_instance.foo: 2015 ID = foo 2016 provider = provider.aws 2017 `) 2018 } 2019 2020 func TestContext2Apply_cancelProvisioner(t *testing.T) { 2021 m := testModule(t, "apply-cancel-provisioner") 2022 p := testProvider("aws") 2023 p.ApplyFn = testApplyFn 2024 p.DiffFn = testDiffFn 2025 pr := testProvisioner() 2026 ctx := testContext2(t, &ContextOpts{ 2027 Module: m, 2028 ProviderResolver: ResourceProviderResolverFixed( 2029 map[string]ResourceProviderFactory{ 2030 "aws": testProviderFuncFixed(p), 2031 }, 2032 ), 2033 Provisioners: map[string]ResourceProvisionerFactory{ 2034 "shell": testProvisionerFuncFixed(pr), 2035 }, 2036 }) 2037 2038 prStopped := make(chan struct{}) 2039 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2040 // Start the stop process 2041 go ctx.Stop() 2042 2043 <-prStopped 2044 return nil 2045 } 2046 pr.StopFn = func() error { 2047 close(prStopped) 2048 return nil 2049 } 2050 2051 if _, err := ctx.Plan(); err != nil { 2052 t.Fatalf("err: %s", err) 2053 } 2054 2055 // Start the Apply in a goroutine 2056 var applyErr error 2057 stateCh := make(chan *State) 2058 go func() { 2059 state, err := ctx.Apply() 2060 if err != nil { 2061 applyErr = err 2062 } 2063 2064 stateCh <- state 2065 }() 2066 2067 // Wait for completion 2068 state := <-stateCh 2069 if applyErr != nil { 2070 t.Fatalf("err: %s", applyErr) 2071 } 2072 2073 checkStateString(t, state, ` 2074 aws_instance.foo: (tainted) 2075 ID = foo 2076 provider = provider.aws 2077 num = 2 2078 type = aws_instance 2079 `) 2080 2081 if !pr.StopCalled { 2082 t.Fatal("stop should be called") 2083 } 2084 } 2085 2086 func TestContext2Apply_compute(t *testing.T) { 2087 m := testModule(t, "apply-compute") 2088 p := testProvider("aws") 2089 p.ApplyFn = testApplyFn 2090 p.DiffFn = testDiffFn 2091 ctx := testContext2(t, &ContextOpts{ 2092 Module: m, 2093 ProviderResolver: ResourceProviderResolverFixed( 2094 map[string]ResourceProviderFactory{ 2095 "aws": testProviderFuncFixed(p), 2096 }, 2097 ), 2098 }) 2099 2100 if _, err := ctx.Plan(); err != nil { 2101 t.Fatalf("err: %s", err) 2102 } 2103 2104 ctx.variables = map[string]interface{}{"value": "1"} 2105 2106 state, err := ctx.Apply() 2107 if err != nil { 2108 t.Fatalf("err: %s", err) 2109 } 2110 2111 actual := strings.TrimSpace(state.String()) 2112 expected := strings.TrimSpace(testTerraformApplyComputeStr) 2113 if actual != expected { 2114 t.Fatalf("bad: \n%s", actual) 2115 } 2116 } 2117 2118 func TestContext2Apply_countDecrease(t *testing.T) { 2119 m := testModule(t, "apply-count-dec") 2120 p := testProvider("aws") 2121 p.DiffFn = testDiffFn 2122 s := &State{ 2123 Modules: []*ModuleState{ 2124 &ModuleState{ 2125 Path: rootModulePath, 2126 Resources: map[string]*ResourceState{ 2127 "aws_instance.foo.0": &ResourceState{ 2128 Type: "aws_instance", 2129 Primary: &InstanceState{ 2130 ID: "bar", 2131 Attributes: map[string]string{ 2132 "foo": "foo", 2133 "type": "aws_instance", 2134 }, 2135 }, 2136 }, 2137 "aws_instance.foo.1": &ResourceState{ 2138 Type: "aws_instance", 2139 Primary: &InstanceState{ 2140 ID: "bar", 2141 Attributes: map[string]string{ 2142 "foo": "foo", 2143 "type": "aws_instance", 2144 }, 2145 }, 2146 }, 2147 "aws_instance.foo.2": &ResourceState{ 2148 Type: "aws_instance", 2149 Primary: &InstanceState{ 2150 ID: "bar", 2151 Attributes: map[string]string{ 2152 "foo": "foo", 2153 "type": "aws_instance", 2154 }, 2155 }, 2156 }, 2157 }, 2158 }, 2159 }, 2160 } 2161 ctx := testContext2(t, &ContextOpts{ 2162 Module: m, 2163 ProviderResolver: ResourceProviderResolverFixed( 2164 map[string]ResourceProviderFactory{ 2165 "aws": testProviderFuncFixed(p), 2166 }, 2167 ), 2168 State: s, 2169 }) 2170 2171 if _, err := ctx.Plan(); err != nil { 2172 t.Fatalf("err: %s", err) 2173 } 2174 2175 state, err := ctx.Apply() 2176 if err != nil { 2177 t.Fatalf("err: %s", err) 2178 } 2179 2180 actual := strings.TrimSpace(state.String()) 2181 expected := strings.TrimSpace(testTerraformApplyCountDecStr) 2182 if actual != expected { 2183 t.Fatalf("bad: \n%s", actual) 2184 } 2185 } 2186 2187 func TestContext2Apply_countDecreaseToOneX(t *testing.T) { 2188 m := testModule(t, "apply-count-dec-one") 2189 p := testProvider("aws") 2190 p.ApplyFn = testApplyFn 2191 p.DiffFn = testDiffFn 2192 s := &State{ 2193 Modules: []*ModuleState{ 2194 &ModuleState{ 2195 Path: rootModulePath, 2196 Resources: map[string]*ResourceState{ 2197 "aws_instance.foo.0": &ResourceState{ 2198 Type: "aws_instance", 2199 Primary: &InstanceState{ 2200 ID: "bar", 2201 Attributes: map[string]string{ 2202 "foo": "foo", 2203 "type": "aws_instance", 2204 }, 2205 }, 2206 }, 2207 "aws_instance.foo.1": &ResourceState{ 2208 Type: "aws_instance", 2209 Primary: &InstanceState{ 2210 ID: "bar", 2211 }, 2212 }, 2213 "aws_instance.foo.2": &ResourceState{ 2214 Type: "aws_instance", 2215 Primary: &InstanceState{ 2216 ID: "bar", 2217 }, 2218 }, 2219 }, 2220 }, 2221 }, 2222 } 2223 ctx := testContext2(t, &ContextOpts{ 2224 Module: m, 2225 ProviderResolver: ResourceProviderResolverFixed( 2226 map[string]ResourceProviderFactory{ 2227 "aws": testProviderFuncFixed(p), 2228 }, 2229 ), 2230 State: s, 2231 }) 2232 2233 if _, err := ctx.Plan(); err != nil { 2234 t.Fatalf("err: %s", err) 2235 } 2236 2237 state, err := ctx.Apply() 2238 if err != nil { 2239 t.Fatalf("err: %s", err) 2240 } 2241 2242 actual := strings.TrimSpace(state.String()) 2243 expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr) 2244 if actual != expected { 2245 t.Fatalf("bad: \n%s", actual) 2246 } 2247 } 2248 2249 // https://github.com/PeoplePerHour/terraform/pull/11 2250 // 2251 // This tests a case where both a "resource" and "resource.0" are in 2252 // the state file, which apparently is a reasonable backwards compatibility 2253 // concern found in the above 3rd party repo. 2254 func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) { 2255 m := testModule(t, "apply-count-dec-one") 2256 p := testProvider("aws") 2257 p.ApplyFn = testApplyFn 2258 p.DiffFn = testDiffFn 2259 s := &State{ 2260 Modules: []*ModuleState{ 2261 &ModuleState{ 2262 Path: rootModulePath, 2263 Resources: map[string]*ResourceState{ 2264 "aws_instance.foo": &ResourceState{ 2265 Type: "aws_instance", 2266 Primary: &InstanceState{ 2267 ID: "bar", 2268 Attributes: map[string]string{ 2269 "foo": "foo", 2270 "type": "aws_instance", 2271 }, 2272 }, 2273 }, 2274 "aws_instance.foo.0": &ResourceState{ 2275 Type: "aws_instance", 2276 Primary: &InstanceState{ 2277 ID: "baz", 2278 Attributes: map[string]string{ 2279 "type": "aws_instance", 2280 }, 2281 }, 2282 }, 2283 }, 2284 }, 2285 }, 2286 } 2287 ctx := testContext2(t, &ContextOpts{ 2288 Module: m, 2289 ProviderResolver: ResourceProviderResolverFixed( 2290 map[string]ResourceProviderFactory{ 2291 "aws": testProviderFuncFixed(p), 2292 }, 2293 ), 2294 State: s, 2295 }) 2296 2297 if p, err := ctx.Plan(); err != nil { 2298 t.Fatalf("err: %s", err) 2299 } else { 2300 testStringMatch(t, p, testTerraformApplyCountDecToOneCorruptedPlanStr) 2301 } 2302 2303 state, err := ctx.Apply() 2304 if err != nil { 2305 t.Fatalf("err: %s", err) 2306 } 2307 2308 actual := strings.TrimSpace(state.String()) 2309 expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr) 2310 if actual != expected { 2311 t.Fatalf("bad: \n%s", actual) 2312 } 2313 } 2314 2315 func TestContext2Apply_countTainted(t *testing.T) { 2316 m := testModule(t, "apply-count-tainted") 2317 p := testProvider("aws") 2318 p.DiffFn = testDiffFn 2319 s := &State{ 2320 Modules: []*ModuleState{ 2321 &ModuleState{ 2322 Path: rootModulePath, 2323 Resources: map[string]*ResourceState{ 2324 "aws_instance.foo.0": &ResourceState{ 2325 Type: "aws_instance", 2326 Primary: &InstanceState{ 2327 ID: "bar", 2328 Attributes: map[string]string{ 2329 "foo": "foo", 2330 "type": "aws_instance", 2331 }, 2332 Tainted: true, 2333 }, 2334 }, 2335 }, 2336 }, 2337 }, 2338 } 2339 ctx := testContext2(t, &ContextOpts{ 2340 Module: m, 2341 ProviderResolver: ResourceProviderResolverFixed( 2342 map[string]ResourceProviderFactory{ 2343 "aws": testProviderFuncFixed(p), 2344 }, 2345 ), 2346 State: s, 2347 }) 2348 2349 if _, err := ctx.Plan(); err != nil { 2350 t.Fatalf("err: %s", err) 2351 } 2352 2353 state, err := ctx.Apply() 2354 if err != nil { 2355 t.Fatalf("err: %s", err) 2356 } 2357 2358 actual := strings.TrimSpace(state.String()) 2359 expected := strings.TrimSpace(testTerraformApplyCountTaintedStr) 2360 if actual != expected { 2361 t.Fatalf("bad: \n%s", actual) 2362 } 2363 } 2364 2365 func TestContext2Apply_countVariable(t *testing.T) { 2366 m := testModule(t, "apply-count-variable") 2367 p := testProvider("aws") 2368 p.ApplyFn = testApplyFn 2369 p.DiffFn = testDiffFn 2370 ctx := testContext2(t, &ContextOpts{ 2371 Module: m, 2372 ProviderResolver: ResourceProviderResolverFixed( 2373 map[string]ResourceProviderFactory{ 2374 "aws": testProviderFuncFixed(p), 2375 }, 2376 ), 2377 }) 2378 2379 if _, err := ctx.Plan(); err != nil { 2380 t.Fatalf("err: %s", err) 2381 } 2382 2383 state, err := ctx.Apply() 2384 if err != nil { 2385 t.Fatalf("err: %s", err) 2386 } 2387 2388 actual := strings.TrimSpace(state.String()) 2389 expected := strings.TrimSpace(testTerraformApplyCountVariableStr) 2390 if actual != expected { 2391 t.Fatalf("bad: \n%s", actual) 2392 } 2393 } 2394 2395 func TestContext2Apply_countVariableRef(t *testing.T) { 2396 m := testModule(t, "apply-count-variable-ref") 2397 p := testProvider("aws") 2398 p.ApplyFn = testApplyFn 2399 p.DiffFn = testDiffFn 2400 ctx := testContext2(t, &ContextOpts{ 2401 Module: m, 2402 ProviderResolver: ResourceProviderResolverFixed( 2403 map[string]ResourceProviderFactory{ 2404 "aws": testProviderFuncFixed(p), 2405 }, 2406 ), 2407 }) 2408 2409 if _, err := ctx.Plan(); err != nil { 2410 t.Fatalf("err: %s", err) 2411 } 2412 2413 state, err := ctx.Apply() 2414 if err != nil { 2415 t.Fatalf("err: %s", err) 2416 } 2417 2418 actual := strings.TrimSpace(state.String()) 2419 expected := strings.TrimSpace(testTerraformApplyCountVariableRefStr) 2420 if actual != expected { 2421 t.Fatalf("bad: \n%s", actual) 2422 } 2423 } 2424 2425 func TestContext2Apply_provisionerInterpCount(t *testing.T) { 2426 // This test ensures that a provisioner can interpolate a resource count 2427 // even though the provisioner expression is evaluated during the plan 2428 // walk. https://github.com/hashicorp/terraform/issues/16840 2429 2430 m := testModule(t, "apply-provisioner-interp-count") 2431 2432 p := testProvider("aws") 2433 p.ApplyFn = testApplyFn 2434 p.DiffFn = testDiffFn 2435 2436 pr := testProvisioner() 2437 2438 providerResolver := ResourceProviderResolverFixed( 2439 map[string]ResourceProviderFactory{ 2440 "aws": testProviderFuncFixed(p), 2441 }, 2442 ) 2443 provisioners := map[string]ResourceProvisionerFactory{ 2444 "local-exec": testProvisionerFuncFixed(pr), 2445 } 2446 ctx := testContext2(t, &ContextOpts{ 2447 Module: m, 2448 ProviderResolver: providerResolver, 2449 Provisioners: provisioners, 2450 }) 2451 2452 plan, err := ctx.Plan() 2453 if err != nil { 2454 t.Fatalf("plan failed: %s", err) 2455 } 2456 2457 // We'll marshal and unmarshal the plan here, to ensure that we have 2458 // a clean new context as would be created if we separately ran 2459 // terraform plan -out=tfplan && terraform apply tfplan 2460 var planBuf bytes.Buffer 2461 err = WritePlan(plan, &planBuf) 2462 if err != nil { 2463 t.Fatalf("failed to write plan: %s", err) 2464 } 2465 plan, err = ReadPlan(&planBuf) 2466 if err != nil { 2467 t.Fatalf("failed to read plan: %s", err) 2468 } 2469 2470 ctx, err = plan.Context(&ContextOpts{ 2471 // Most options are taken from the plan in this case, but we still 2472 // need to provide the plugins. 2473 ProviderResolver: providerResolver, 2474 Provisioners: provisioners, 2475 }) 2476 if err != nil { 2477 t.Fatalf("failed to create context for plan: %s", err) 2478 } 2479 2480 // Applying the plan should now succeed 2481 _, err = ctx.Apply() 2482 if err != nil { 2483 t.Fatalf("apply failed: %s", err) 2484 } 2485 2486 // Verify apply was invoked 2487 if !pr.ApplyCalled { 2488 t.Fatalf("provisioner was not applied") 2489 } 2490 } 2491 2492 func TestContext2Apply_mapVariableOverride(t *testing.T) { 2493 m := testModule(t, "apply-map-var-override") 2494 p := testProvider("aws") 2495 p.ApplyFn = testApplyFn 2496 p.DiffFn = testDiffFn 2497 ctx := testContext2(t, &ContextOpts{ 2498 Module: m, 2499 ProviderResolver: ResourceProviderResolverFixed( 2500 map[string]ResourceProviderFactory{ 2501 "aws": testProviderFuncFixed(p), 2502 }, 2503 ), 2504 Variables: map[string]interface{}{ 2505 "images": []map[string]interface{}{ 2506 map[string]interface{}{ 2507 "us-west-2": "overridden", 2508 }, 2509 }, 2510 }, 2511 }) 2512 2513 if _, err := ctx.Plan(); err != nil { 2514 t.Fatalf("err: %s", err) 2515 } 2516 2517 state, err := ctx.Apply() 2518 if err != nil { 2519 t.Fatalf("err: %s", err) 2520 } 2521 2522 actual := strings.TrimSpace(state.String()) 2523 expected := strings.TrimSpace(` 2524 aws_instance.bar: 2525 ID = foo 2526 provider = provider.aws 2527 ami = overridden 2528 type = aws_instance 2529 aws_instance.foo: 2530 ID = foo 2531 provider = provider.aws 2532 ami = image-1234 2533 type = aws_instance 2534 `) 2535 if actual != expected { 2536 t.Fatalf("got: \n%s\nexpected: \n%s", actual, expected) 2537 } 2538 } 2539 2540 func TestContext2Apply_moduleBasic(t *testing.T) { 2541 m := testModule(t, "apply-module") 2542 p := testProvider("aws") 2543 p.ApplyFn = testApplyFn 2544 p.DiffFn = testDiffFn 2545 ctx := testContext2(t, &ContextOpts{ 2546 Module: m, 2547 ProviderResolver: ResourceProviderResolverFixed( 2548 map[string]ResourceProviderFactory{ 2549 "aws": testProviderFuncFixed(p), 2550 }, 2551 ), 2552 }) 2553 2554 if _, err := ctx.Plan(); err != nil { 2555 t.Fatalf("err: %s", err) 2556 } 2557 2558 state, err := ctx.Apply() 2559 if err != nil { 2560 t.Fatalf("err: %s", err) 2561 } 2562 2563 actual := strings.TrimSpace(state.String()) 2564 expected := strings.TrimSpace(testTerraformApplyModuleStr) 2565 if actual != expected { 2566 t.Fatalf("bad, expected:\n%s\n\nactual:\n%s", expected, actual) 2567 } 2568 } 2569 2570 func TestContext2Apply_moduleDestroyOrder(t *testing.T) { 2571 m := testModule(t, "apply-module-destroy-order") 2572 p := testProvider("aws") 2573 p.DiffFn = testDiffFn 2574 2575 // Create a custom apply function to track the order they were destroyed 2576 var order []string 2577 var orderLock sync.Mutex 2578 p.ApplyFn = func( 2579 info *InstanceInfo, 2580 is *InstanceState, 2581 id *InstanceDiff) (*InstanceState, error) { 2582 orderLock.Lock() 2583 defer orderLock.Unlock() 2584 2585 order = append(order, is.ID) 2586 return nil, nil 2587 } 2588 2589 state := &State{ 2590 Modules: []*ModuleState{ 2591 &ModuleState{ 2592 Path: rootModulePath, 2593 Resources: map[string]*ResourceState{ 2594 "aws_instance.b": resourceState("aws_instance", "b"), 2595 }, 2596 }, 2597 2598 &ModuleState{ 2599 Path: []string{"root", "child"}, 2600 Resources: map[string]*ResourceState{ 2601 "aws_instance.a": resourceState("aws_instance", "a"), 2602 }, 2603 Outputs: map[string]*OutputState{ 2604 "a_output": &OutputState{ 2605 Type: "string", 2606 Sensitive: false, 2607 Value: "a", 2608 }, 2609 }, 2610 }, 2611 }, 2612 } 2613 2614 ctx := testContext2(t, &ContextOpts{ 2615 Module: m, 2616 ProviderResolver: ResourceProviderResolverFixed( 2617 map[string]ResourceProviderFactory{ 2618 "aws": testProviderFuncFixed(p), 2619 }, 2620 ), 2621 State: state, 2622 Destroy: true, 2623 }) 2624 2625 if _, err := ctx.Plan(); err != nil { 2626 t.Fatalf("err: %s", err) 2627 } 2628 2629 state, err := ctx.Apply() 2630 if err != nil { 2631 t.Fatalf("err: %s", err) 2632 } 2633 2634 expected := []string{"b", "a"} 2635 if !reflect.DeepEqual(order, expected) { 2636 t.Fatalf("bad: %#v", order) 2637 } 2638 2639 { 2640 actual := strings.TrimSpace(state.String()) 2641 expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr) 2642 if actual != expected { 2643 t.Fatalf("bad: \n%s", actual) 2644 } 2645 } 2646 } 2647 2648 func TestContext2Apply_moduleInheritAlias(t *testing.T) { 2649 m := testModule(t, "apply-module-provider-inherit-alias") 2650 p := testProvider("aws") 2651 p.ApplyFn = testApplyFn 2652 p.DiffFn = testDiffFn 2653 2654 p.ConfigureFn = func(c *ResourceConfig) error { 2655 if _, ok := c.Get("child"); !ok { 2656 return nil 2657 } 2658 2659 if _, ok := c.Get("root"); ok { 2660 return fmt.Errorf("child should not get root") 2661 } 2662 2663 return nil 2664 } 2665 2666 ctx := testContext2(t, &ContextOpts{ 2667 Module: m, 2668 ProviderResolver: ResourceProviderResolverFixed( 2669 map[string]ResourceProviderFactory{ 2670 "aws": testProviderFuncFixed(p), 2671 }, 2672 ), 2673 }) 2674 2675 if _, err := ctx.Plan(); err != nil { 2676 t.Fatalf("err: %s", err) 2677 } 2678 2679 state, err := ctx.Apply() 2680 if err != nil { 2681 t.Fatalf("err: %s", err) 2682 } 2683 2684 checkStateString(t, state, ` 2685 <no state> 2686 module.child: 2687 aws_instance.foo: 2688 ID = foo 2689 provider = provider.aws.eu 2690 `) 2691 } 2692 2693 func TestContext2Apply_moduleOrphanInheritAlias(t *testing.T) { 2694 m := testModule(t, "apply-module-provider-inherit-alias-orphan") 2695 p := testProvider("aws") 2696 p.ApplyFn = testApplyFn 2697 p.DiffFn = testDiffFn 2698 2699 called := false 2700 p.ConfigureFn = func(c *ResourceConfig) error { 2701 called = true 2702 2703 if _, ok := c.Get("child"); !ok { 2704 return nil 2705 } 2706 2707 if _, ok := c.Get("root"); ok { 2708 return fmt.Errorf("child should not get root") 2709 } 2710 2711 return nil 2712 } 2713 2714 // Create a state with an orphan module 2715 state := &State{ 2716 Modules: []*ModuleState{ 2717 &ModuleState{ 2718 Path: []string{"root", "child"}, 2719 Resources: map[string]*ResourceState{ 2720 "aws_instance.bar": &ResourceState{ 2721 Type: "aws_instance", 2722 Primary: &InstanceState{ 2723 ID: "bar", 2724 }, 2725 Provider: "aws.eu", 2726 }, 2727 }, 2728 }, 2729 }, 2730 } 2731 2732 ctx := testContext2(t, &ContextOpts{ 2733 Module: m, 2734 State: state, 2735 ProviderResolver: ResourceProviderResolverFixed( 2736 map[string]ResourceProviderFactory{ 2737 "aws": testProviderFuncFixed(p), 2738 }, 2739 ), 2740 }) 2741 2742 if _, err := ctx.Plan(); err != nil { 2743 t.Fatalf("err: %s", err) 2744 } 2745 2746 state, err := ctx.Apply() 2747 if err != nil { 2748 t.Fatalf("err: %s", err) 2749 } 2750 2751 if !called { 2752 t.Fatal("must call configure") 2753 } 2754 2755 checkStateString(t, state, "") 2756 } 2757 2758 func TestContext2Apply_moduleOrphanProvider(t *testing.T) { 2759 m := testModule(t, "apply-module-orphan-provider-inherit") 2760 p := testProvider("aws") 2761 p.ApplyFn = testApplyFn 2762 p.DiffFn = testDiffFn 2763 2764 p.ConfigureFn = func(c *ResourceConfig) error { 2765 if _, ok := c.Get("value"); !ok { 2766 return fmt.Errorf("value is not found") 2767 } 2768 2769 return nil 2770 } 2771 2772 // Create a state with an orphan module 2773 state := &State{ 2774 Modules: []*ModuleState{ 2775 &ModuleState{ 2776 Path: []string{"root", "child"}, 2777 Resources: map[string]*ResourceState{ 2778 "aws_instance.bar": &ResourceState{ 2779 Type: "aws_instance", 2780 Primary: &InstanceState{ 2781 ID: "bar", 2782 }, 2783 }, 2784 }, 2785 }, 2786 }, 2787 } 2788 2789 ctx := testContext2(t, &ContextOpts{ 2790 Module: m, 2791 State: state, 2792 ProviderResolver: ResourceProviderResolverFixed( 2793 map[string]ResourceProviderFactory{ 2794 "aws": testProviderFuncFixed(p), 2795 }, 2796 ), 2797 }) 2798 2799 if _, err := ctx.Plan(); err != nil { 2800 t.Fatalf("err: %s", err) 2801 } 2802 2803 if _, err := ctx.Apply(); err != nil { 2804 t.Fatalf("err: %s", err) 2805 } 2806 } 2807 2808 func TestContext2Apply_moduleOrphanGrandchildProvider(t *testing.T) { 2809 m := testModule(t, "apply-module-orphan-provider-inherit") 2810 p := testProvider("aws") 2811 p.ApplyFn = testApplyFn 2812 p.DiffFn = testDiffFn 2813 2814 p.ConfigureFn = func(c *ResourceConfig) error { 2815 if _, ok := c.Get("value"); !ok { 2816 return fmt.Errorf("value is not found") 2817 } 2818 2819 return nil 2820 } 2821 2822 // Create a state with an orphan module that is nested (grandchild) 2823 state := &State{ 2824 Modules: []*ModuleState{ 2825 &ModuleState{ 2826 Path: []string{"root", "parent", "child"}, 2827 Resources: map[string]*ResourceState{ 2828 "aws_instance.bar": &ResourceState{ 2829 Type: "aws_instance", 2830 Primary: &InstanceState{ 2831 ID: "bar", 2832 }, 2833 }, 2834 }, 2835 }, 2836 }, 2837 } 2838 2839 ctx := testContext2(t, &ContextOpts{ 2840 Module: m, 2841 State: state, 2842 ProviderResolver: ResourceProviderResolverFixed( 2843 map[string]ResourceProviderFactory{ 2844 "aws": testProviderFuncFixed(p), 2845 }, 2846 ), 2847 }) 2848 2849 if _, err := ctx.Plan(); err != nil { 2850 t.Fatalf("err: %s", err) 2851 } 2852 2853 if _, err := ctx.Apply(); err != nil { 2854 t.Fatalf("err: %s", err) 2855 } 2856 } 2857 2858 func TestContext2Apply_moduleGrandchildProvider(t *testing.T) { 2859 m := testModule(t, "apply-module-grandchild-provider-inherit") 2860 p := testProvider("aws") 2861 p.ApplyFn = testApplyFn 2862 p.DiffFn = testDiffFn 2863 2864 var callLock sync.Mutex 2865 called := false 2866 p.ConfigureFn = func(c *ResourceConfig) error { 2867 if _, ok := c.Get("value"); !ok { 2868 return fmt.Errorf("value is not found") 2869 } 2870 callLock.Lock() 2871 called = true 2872 callLock.Unlock() 2873 2874 return nil 2875 } 2876 2877 ctx := testContext2(t, &ContextOpts{ 2878 Module: m, 2879 ProviderResolver: ResourceProviderResolverFixed( 2880 map[string]ResourceProviderFactory{ 2881 "aws": testProviderFuncFixed(p), 2882 }, 2883 ), 2884 }) 2885 2886 if _, err := ctx.Plan(); err != nil { 2887 t.Fatalf("err: %s", err) 2888 } 2889 2890 if _, err := ctx.Apply(); err != nil { 2891 t.Fatalf("err: %s", err) 2892 } 2893 2894 callLock.Lock() 2895 defer callLock.Unlock() 2896 if called != true { 2897 t.Fatalf("err: configure never called") 2898 } 2899 } 2900 2901 // This tests an issue where all the providers in a module but not 2902 // in the root weren't being added to the root properly. In this test 2903 // case: aws is explicitly added to root, but "test" should be added to. 2904 // With the bug, it wasn't. 2905 func TestContext2Apply_moduleOnlyProvider(t *testing.T) { 2906 m := testModule(t, "apply-module-only-provider") 2907 p := testProvider("aws") 2908 p.ApplyFn = testApplyFn 2909 p.DiffFn = testDiffFn 2910 pTest := testProvider("test") 2911 pTest.ApplyFn = testApplyFn 2912 pTest.DiffFn = testDiffFn 2913 2914 ctx := testContext2(t, &ContextOpts{ 2915 Module: m, 2916 ProviderResolver: ResourceProviderResolverFixed( 2917 map[string]ResourceProviderFactory{ 2918 "aws": testProviderFuncFixed(p), 2919 "test": testProviderFuncFixed(pTest), 2920 }, 2921 ), 2922 }) 2923 2924 if _, err := ctx.Plan(); err != nil { 2925 t.Fatalf("err: %s", err) 2926 } 2927 2928 state, err := ctx.Apply() 2929 if err != nil { 2930 t.Fatalf("err: %s", err) 2931 } 2932 2933 actual := strings.TrimSpace(state.String()) 2934 expected := strings.TrimSpace(testTerraformApplyModuleOnlyProviderStr) 2935 if actual != expected { 2936 t.Fatalf("bad: \n%s", actual) 2937 } 2938 } 2939 2940 func TestContext2Apply_moduleProviderAlias(t *testing.T) { 2941 m := testModule(t, "apply-module-provider-alias") 2942 p := testProvider("aws") 2943 p.ApplyFn = testApplyFn 2944 p.DiffFn = testDiffFn 2945 ctx := testContext2(t, &ContextOpts{ 2946 Module: m, 2947 ProviderResolver: ResourceProviderResolverFixed( 2948 map[string]ResourceProviderFactory{ 2949 "aws": testProviderFuncFixed(p), 2950 }, 2951 ), 2952 }) 2953 2954 if _, err := ctx.Plan(); err != nil { 2955 t.Fatalf("err: %s", err) 2956 } 2957 2958 state, err := ctx.Apply() 2959 if err != nil { 2960 t.Fatalf("err: %s", err) 2961 } 2962 2963 actual := strings.TrimSpace(state.String()) 2964 expected := strings.TrimSpace(testTerraformApplyModuleProviderAliasStr) 2965 if actual != expected { 2966 t.Fatalf("bad: \n%s", actual) 2967 } 2968 } 2969 2970 func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) { 2971 m := testModule(t, "apply-module-provider-alias") 2972 p := testProvider("aws") 2973 p.ApplyFn = testApplyFn 2974 p.DiffFn = testDiffFn 2975 ctx := testContext2(t, &ContextOpts{ 2976 Module: m, 2977 ProviderResolver: ResourceProviderResolverFixed( 2978 map[string]ResourceProviderFactory{ 2979 "aws": testProviderFuncFixed(p), 2980 }, 2981 ), 2982 Targets: []string{"no.thing"}, 2983 }) 2984 2985 if _, err := ctx.Plan(); err != nil { 2986 t.Fatalf("err: %s", err) 2987 } 2988 2989 state, err := ctx.Apply() 2990 if err != nil { 2991 t.Fatalf("err: %s", err) 2992 } 2993 2994 actual := strings.TrimSpace(state.String()) 2995 expected := strings.TrimSpace(` 2996 <no state> 2997 `) 2998 if actual != expected { 2999 t.Fatalf("bad: \n%s", actual) 3000 } 3001 } 3002 3003 func TestContext2Apply_moduleProviderCloseNested(t *testing.T) { 3004 m := testModule(t, "apply-module-provider-close-nested") 3005 p := testProvider("aws") 3006 p.ApplyFn = testApplyFn 3007 p.DiffFn = testDiffFn 3008 ctx := testContext2(t, &ContextOpts{ 3009 Module: m, 3010 ProviderResolver: ResourceProviderResolverFixed( 3011 map[string]ResourceProviderFactory{ 3012 "aws": testProviderFuncFixed(p), 3013 }, 3014 ), 3015 State: &State{ 3016 Modules: []*ModuleState{ 3017 &ModuleState{ 3018 Path: []string{"root", "child", "subchild"}, 3019 Resources: map[string]*ResourceState{ 3020 "aws_instance.foo": &ResourceState{ 3021 Type: "aws_instance", 3022 Primary: &InstanceState{ 3023 ID: "bar", 3024 }, 3025 }, 3026 }, 3027 }, 3028 }, 3029 }, 3030 Destroy: true, 3031 }) 3032 3033 if _, err := ctx.Plan(); err != nil { 3034 t.Fatalf("err: %s", err) 3035 } 3036 3037 if _, err := ctx.Apply(); err != nil { 3038 t.Fatalf("err: %s", err) 3039 } 3040 } 3041 3042 // Tests that variables used as module vars that reference data that 3043 // already exists in the state and requires no diff works properly. This 3044 // fixes an issue faced where module variables were pruned because they were 3045 // accessing "non-existent" resources (they existed, just not in the graph 3046 // cause they weren't in the diff). 3047 func TestContext2Apply_moduleVarRefExisting(t *testing.T) { 3048 m := testModule(t, "apply-ref-existing") 3049 p := testProvider("aws") 3050 p.ApplyFn = testApplyFn 3051 p.DiffFn = testDiffFn 3052 3053 state := &State{ 3054 Modules: []*ModuleState{ 3055 &ModuleState{ 3056 Path: rootModulePath, 3057 Resources: map[string]*ResourceState{ 3058 "aws_instance.foo": &ResourceState{ 3059 Type: "aws_instance", 3060 Primary: &InstanceState{ 3061 ID: "foo", 3062 Attributes: map[string]string{ 3063 "foo": "bar", 3064 }, 3065 }, 3066 }, 3067 }, 3068 }, 3069 }, 3070 } 3071 3072 ctx := testContext2(t, &ContextOpts{ 3073 Module: m, 3074 ProviderResolver: ResourceProviderResolverFixed( 3075 map[string]ResourceProviderFactory{ 3076 "aws": testProviderFuncFixed(p), 3077 }, 3078 ), 3079 State: state, 3080 }) 3081 3082 if _, err := ctx.Plan(); err != nil { 3083 t.Fatalf("err: %s", err) 3084 } 3085 3086 state, err := ctx.Apply() 3087 if err != nil { 3088 t.Fatalf("err: %s", err) 3089 } 3090 3091 actual := strings.TrimSpace(state.String()) 3092 expected := strings.TrimSpace(testTerraformApplyModuleVarRefExistingStr) 3093 if actual != expected { 3094 t.Fatalf("bad: \n%s", actual) 3095 } 3096 } 3097 3098 func TestContext2Apply_moduleVarResourceCount(t *testing.T) { 3099 m := testModule(t, "apply-module-var-resource-count") 3100 p := testProvider("aws") 3101 p.ApplyFn = testApplyFn 3102 p.DiffFn = testDiffFn 3103 ctx := testContext2(t, &ContextOpts{ 3104 Module: m, 3105 ProviderResolver: ResourceProviderResolverFixed( 3106 map[string]ResourceProviderFactory{ 3107 "aws": testProviderFuncFixed(p), 3108 }, 3109 ), 3110 Variables: map[string]interface{}{ 3111 "count": "2", 3112 }, 3113 Destroy: true, 3114 }) 3115 3116 if _, err := ctx.Plan(); err != nil { 3117 t.Fatalf("err: %s", err) 3118 } 3119 3120 if _, err := ctx.Apply(); err != nil { 3121 t.Fatalf("err: %s", err) 3122 } 3123 3124 ctx = testContext2(t, &ContextOpts{ 3125 Module: m, 3126 ProviderResolver: ResourceProviderResolverFixed( 3127 map[string]ResourceProviderFactory{ 3128 "aws": testProviderFuncFixed(p), 3129 }, 3130 ), 3131 Variables: map[string]interface{}{ 3132 "count": "5", 3133 }, 3134 }) 3135 3136 if _, err := ctx.Plan(); err != nil { 3137 t.Fatalf("err: %s", err) 3138 } 3139 3140 if _, err := ctx.Apply(); err != nil { 3141 t.Fatalf("err: %s", err) 3142 } 3143 } 3144 3145 // GH-819 3146 func TestContext2Apply_moduleBool(t *testing.T) { 3147 m := testModule(t, "apply-module-bool") 3148 p := testProvider("aws") 3149 p.ApplyFn = testApplyFn 3150 p.DiffFn = testDiffFn 3151 ctx := testContext2(t, &ContextOpts{ 3152 Module: m, 3153 ProviderResolver: ResourceProviderResolverFixed( 3154 map[string]ResourceProviderFactory{ 3155 "aws": testProviderFuncFixed(p), 3156 }, 3157 ), 3158 }) 3159 3160 if _, err := ctx.Plan(); err != nil { 3161 t.Fatalf("err: %s", err) 3162 } 3163 3164 state, err := ctx.Apply() 3165 if err != nil { 3166 t.Fatalf("err: %s", err) 3167 } 3168 3169 actual := strings.TrimSpace(state.String()) 3170 expected := strings.TrimSpace(testTerraformApplyModuleBoolStr) 3171 if actual != expected { 3172 t.Fatalf("bad: \n%s", actual) 3173 } 3174 } 3175 3176 // Tests that a module can be targeted and everything is properly created. 3177 // This adds to the plan test to also just verify that apply works. 3178 func TestContext2Apply_moduleTarget(t *testing.T) { 3179 m := testModule(t, "plan-targeted-cross-module") 3180 p := testProvider("aws") 3181 p.ApplyFn = testApplyFn 3182 p.DiffFn = testDiffFn 3183 ctx := testContext2(t, &ContextOpts{ 3184 Module: m, 3185 ProviderResolver: ResourceProviderResolverFixed( 3186 map[string]ResourceProviderFactory{ 3187 "aws": testProviderFuncFixed(p), 3188 }, 3189 ), 3190 Targets: []string{"module.B"}, 3191 }) 3192 3193 if _, err := ctx.Plan(); err != nil { 3194 t.Fatalf("err: %s", err) 3195 } 3196 3197 state, err := ctx.Apply() 3198 if err != nil { 3199 t.Fatalf("err: %s", err) 3200 } 3201 3202 checkStateString(t, state, ` 3203 <no state> 3204 module.A: 3205 aws_instance.foo: 3206 ID = foo 3207 provider = provider.aws 3208 foo = bar 3209 type = aws_instance 3210 3211 Outputs: 3212 3213 value = foo 3214 module.B: 3215 aws_instance.bar: 3216 ID = foo 3217 provider = provider.aws 3218 foo = foo 3219 type = aws_instance 3220 `) 3221 } 3222 3223 func TestContext2Apply_multiProvider(t *testing.T) { 3224 m := testModule(t, "apply-multi-provider") 3225 p := testProvider("aws") 3226 p.ApplyFn = testApplyFn 3227 p.DiffFn = testDiffFn 3228 3229 pDO := testProvider("do") 3230 pDO.ApplyFn = testApplyFn 3231 pDO.DiffFn = testDiffFn 3232 3233 ctx := testContext2(t, &ContextOpts{ 3234 Module: m, 3235 ProviderResolver: ResourceProviderResolverFixed( 3236 map[string]ResourceProviderFactory{ 3237 "aws": testProviderFuncFixed(p), 3238 "do": testProviderFuncFixed(pDO), 3239 }, 3240 ), 3241 }) 3242 3243 if _, err := ctx.Plan(); err != nil { 3244 t.Fatalf("err: %s", err) 3245 } 3246 3247 state, err := ctx.Apply() 3248 if err != nil { 3249 t.Fatalf("err: %s", err) 3250 } 3251 3252 mod := state.RootModule() 3253 if len(mod.Resources) < 2 { 3254 t.Fatalf("bad: %#v", mod.Resources) 3255 } 3256 3257 actual := strings.TrimSpace(state.String()) 3258 expected := strings.TrimSpace(testTerraformApplyMultiProviderStr) 3259 if actual != expected { 3260 t.Fatalf("bad: \n%s", actual) 3261 } 3262 } 3263 3264 func TestContext2Apply_multiProviderDestroy(t *testing.T) { 3265 m := testModule(t, "apply-multi-provider-destroy") 3266 p := testProvider("aws") 3267 p.ApplyFn = testApplyFn 3268 p.DiffFn = testDiffFn 3269 3270 p2 := testProvider("do") 3271 p2.ApplyFn = testApplyFn 3272 p2.DiffFn = testDiffFn 3273 3274 var state *State 3275 3276 // First, create the instances 3277 { 3278 ctx := testContext2(t, &ContextOpts{ 3279 Module: m, 3280 ProviderResolver: ResourceProviderResolverFixed( 3281 map[string]ResourceProviderFactory{ 3282 "aws": testProviderFuncFixed(p), 3283 "vault": testProviderFuncFixed(p2), 3284 }, 3285 ), 3286 }) 3287 3288 if _, err := ctx.Plan(); err != nil { 3289 t.Fatalf("err: %s", err) 3290 } 3291 3292 s, err := ctx.Apply() 3293 if err != nil { 3294 t.Fatalf("err: %s", err) 3295 } 3296 3297 state = s 3298 } 3299 3300 // Destroy them 3301 { 3302 // Verify that aws_instance.bar is destroyed first 3303 var checked bool 3304 var called int32 3305 var lock sync.Mutex 3306 applyFn := func( 3307 info *InstanceInfo, 3308 is *InstanceState, 3309 id *InstanceDiff) (*InstanceState, error) { 3310 lock.Lock() 3311 defer lock.Unlock() 3312 3313 if info.HumanId() == "aws_instance.bar" { 3314 checked = true 3315 3316 // Sleep to allow parallel execution 3317 time.Sleep(50 * time.Millisecond) 3318 3319 // Verify that called is 0 (dep not called) 3320 if atomic.LoadInt32(&called) != 0 { 3321 return nil, fmt.Errorf("nothing else should be called") 3322 } 3323 } 3324 3325 atomic.AddInt32(&called, 1) 3326 return testApplyFn(info, is, id) 3327 } 3328 3329 // Set the apply functions 3330 p.ApplyFn = applyFn 3331 p2.ApplyFn = applyFn 3332 3333 ctx := testContext2(t, &ContextOpts{ 3334 Destroy: true, 3335 State: state, 3336 Module: m, 3337 ProviderResolver: ResourceProviderResolverFixed( 3338 map[string]ResourceProviderFactory{ 3339 "aws": testProviderFuncFixed(p), 3340 "vault": testProviderFuncFixed(p2), 3341 }, 3342 ), 3343 }) 3344 3345 if _, err := ctx.Plan(); err != nil { 3346 t.Fatalf("err: %s", err) 3347 } 3348 3349 s, err := ctx.Apply() 3350 if err != nil { 3351 t.Fatalf("err: %s", err) 3352 } 3353 3354 if !checked { 3355 t.Fatal("should be checked") 3356 } 3357 3358 state = s 3359 } 3360 3361 checkStateString(t, state, `<no state>`) 3362 } 3363 3364 // This is like the multiProviderDestroy test except it tests that 3365 // dependent resources within a child module that inherit provider 3366 // configuration are still destroyed first. 3367 func TestContext2Apply_multiProviderDestroyChild(t *testing.T) { 3368 m := testModule(t, "apply-multi-provider-destroy-child") 3369 p := testProvider("aws") 3370 p.ApplyFn = testApplyFn 3371 p.DiffFn = testDiffFn 3372 3373 p2 := testProvider("do") 3374 p2.ApplyFn = testApplyFn 3375 p2.DiffFn = testDiffFn 3376 3377 var state *State 3378 3379 // First, create the instances 3380 { 3381 ctx := testContext2(t, &ContextOpts{ 3382 Module: m, 3383 ProviderResolver: ResourceProviderResolverFixed( 3384 map[string]ResourceProviderFactory{ 3385 "aws": testProviderFuncFixed(p), 3386 "vault": testProviderFuncFixed(p2), 3387 }, 3388 ), 3389 }) 3390 3391 if _, err := ctx.Plan(); err != nil { 3392 t.Fatalf("err: %s", err) 3393 } 3394 3395 s, err := ctx.Apply() 3396 if err != nil { 3397 t.Fatalf("err: %s", err) 3398 } 3399 3400 state = s 3401 } 3402 3403 // Destroy them 3404 { 3405 // Verify that aws_instance.bar is destroyed first 3406 var checked bool 3407 var called int32 3408 var lock sync.Mutex 3409 applyFn := func( 3410 info *InstanceInfo, 3411 is *InstanceState, 3412 id *InstanceDiff) (*InstanceState, error) { 3413 lock.Lock() 3414 defer lock.Unlock() 3415 3416 if info.HumanId() == "module.child.aws_instance.bar" { 3417 checked = true 3418 3419 // Sleep to allow parallel execution 3420 time.Sleep(50 * time.Millisecond) 3421 3422 // Verify that called is 0 (dep not called) 3423 if atomic.LoadInt32(&called) != 0 { 3424 return nil, fmt.Errorf("nothing else should be called") 3425 } 3426 } 3427 3428 atomic.AddInt32(&called, 1) 3429 return testApplyFn(info, is, id) 3430 } 3431 3432 // Set the apply functions 3433 p.ApplyFn = applyFn 3434 p2.ApplyFn = applyFn 3435 3436 ctx := testContext2(t, &ContextOpts{ 3437 Destroy: true, 3438 State: state, 3439 Module: m, 3440 ProviderResolver: ResourceProviderResolverFixed( 3441 map[string]ResourceProviderFactory{ 3442 "aws": testProviderFuncFixed(p), 3443 "vault": testProviderFuncFixed(p2), 3444 }, 3445 ), 3446 }) 3447 3448 if _, err := ctx.Plan(); err != nil { 3449 t.Fatalf("err: %s", err) 3450 } 3451 3452 s, err := ctx.Apply() 3453 if err != nil { 3454 t.Fatalf("err: %s", err) 3455 } 3456 3457 if !checked { 3458 t.Fatal("should be checked") 3459 } 3460 3461 state = s 3462 } 3463 3464 checkStateString(t, state, ` 3465 <no state> 3466 module.child: 3467 <no state> 3468 `) 3469 } 3470 3471 func TestContext2Apply_multiVar(t *testing.T) { 3472 m := testModule(t, "apply-multi-var") 3473 p := testProvider("aws") 3474 p.ApplyFn = testApplyFn 3475 p.DiffFn = testDiffFn 3476 3477 // First, apply with a count of 3 3478 ctx := testContext2(t, &ContextOpts{ 3479 Module: m, 3480 ProviderResolver: ResourceProviderResolverFixed( 3481 map[string]ResourceProviderFactory{ 3482 "aws": testProviderFuncFixed(p), 3483 }, 3484 ), 3485 Variables: map[string]interface{}{ 3486 "count": "3", 3487 }, 3488 }) 3489 3490 if _, err := ctx.Plan(); err != nil { 3491 t.Fatalf("err: %s", err) 3492 } 3493 3494 state, err := ctx.Apply() 3495 if err != nil { 3496 t.Fatalf("err: %s", err) 3497 } 3498 3499 actual := state.RootModule().Outputs["output"] 3500 expected := "bar0,bar1,bar2" 3501 if actual == nil || actual.Value != expected { 3502 t.Fatalf("bad: \n%s", actual) 3503 } 3504 3505 t.Logf("Initial state: %s", state.String()) 3506 3507 // Apply again, reduce the count to 1 3508 { 3509 ctx := testContext2(t, &ContextOpts{ 3510 Module: m, 3511 State: state, 3512 ProviderResolver: ResourceProviderResolverFixed( 3513 map[string]ResourceProviderFactory{ 3514 "aws": testProviderFuncFixed(p), 3515 }, 3516 ), 3517 Variables: map[string]interface{}{ 3518 "count": "1", 3519 }, 3520 }) 3521 3522 if _, err := ctx.Plan(); err != nil { 3523 t.Fatalf("err: %s", err) 3524 } 3525 3526 state, err := ctx.Apply() 3527 if err != nil { 3528 t.Fatalf("err: %s", err) 3529 } 3530 3531 t.Logf("End state: %s", state.String()) 3532 3533 actual := state.RootModule().Outputs["output"] 3534 if actual == nil { 3535 t.Fatal("missing output") 3536 } 3537 3538 expected := "bar0" 3539 if actual.Value != expected { 3540 t.Fatalf("bad: \n%s", actual) 3541 } 3542 } 3543 } 3544 3545 // This is a holistic test of multi-var (aka "splat variable") handling 3546 // across several different Terraform subsystems. This is here because 3547 // historically there were quirky differences in handling across different 3548 // parts of Terraform and so here we want to assert the expected behavior and 3549 // ensure that it remains consistent in future. 3550 func TestContext2Apply_multiVarComprehensive(t *testing.T) { 3551 m := testModule(t, "apply-multi-var-comprehensive") 3552 p := testProvider("test") 3553 3554 configs := map[string]*ResourceConfig{} 3555 3556 p.ApplyFn = testApplyFn 3557 3558 p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 3559 configs[info.HumanId()] = c 3560 3561 // Return a minimal diff to make sure this resource gets included in 3562 // the apply graph and thus the final state, but otherwise we're just 3563 // gathering data for assertions. 3564 return &InstanceDiff{ 3565 Attributes: map[string]*ResourceAttrDiff{ 3566 "id": &ResourceAttrDiff{ 3567 NewComputed: true, 3568 }, 3569 "name": &ResourceAttrDiff{ 3570 New: info.HumanId(), 3571 }, 3572 }, 3573 }, nil 3574 } 3575 3576 // First, apply with a count of 3 3577 ctx := testContext2(t, &ContextOpts{ 3578 Module: m, 3579 ProviderResolver: ResourceProviderResolverFixed( 3580 map[string]ResourceProviderFactory{ 3581 "test": testProviderFuncFixed(p), 3582 }, 3583 ), 3584 Variables: map[string]interface{}{ 3585 "count": "3", 3586 }, 3587 }) 3588 3589 if _, err := ctx.Plan(); err != nil { 3590 t.Fatalf("error during plan: %s", err) 3591 } 3592 3593 checkConfig := func(name string, want map[string]interface{}) { 3594 got := configs[name].Config 3595 if !reflect.DeepEqual(got, want) { 3596 t.Errorf( 3597 "wrong config for %s\ngot: %s\nwant: %s", 3598 name, spew.Sdump(got), spew.Sdump(want), 3599 ) 3600 } 3601 } 3602 3603 checkConfig("test_thing.multi_count_var.0", map[string]interface{}{ 3604 "source_id": unknownValue(), 3605 "source_name": "test_thing.source.0", 3606 }) 3607 checkConfig("test_thing.multi_count_var.2", map[string]interface{}{ 3608 "source_id": unknownValue(), 3609 "source_name": "test_thing.source.2", 3610 }) 3611 checkConfig("test_thing.multi_count_derived.0", map[string]interface{}{ 3612 "source_id": unknownValue(), 3613 "source_name": "test_thing.source.0", 3614 }) 3615 checkConfig("test_thing.multi_count_derived.2", map[string]interface{}{ 3616 "source_id": unknownValue(), 3617 "source_name": "test_thing.source.2", 3618 }) 3619 checkConfig("test_thing.whole_splat", map[string]interface{}{ 3620 "source_ids": unknownValue(), 3621 "source_names": []interface{}{ 3622 "test_thing.source.0", 3623 "test_thing.source.1", 3624 "test_thing.source.2", 3625 }, 3626 "source_ids_from_func": unknownValue(), 3627 "source_names_from_func": []interface{}{ 3628 "test_thing.source.0", 3629 "test_thing.source.1", 3630 "test_thing.source.2", 3631 }, 3632 3633 // This one ends up being a list with a single unknown value at this 3634 // layer, but is fixed up inside helper/schema. There is a test for 3635 // this inside the "test" provider, since core tests can't exercise 3636 // helper/schema functionality. 3637 "source_ids_wrapped": []interface{}{unknownValue()}, 3638 3639 "source_names_wrapped": []interface{}{ 3640 "test_thing.source.0", 3641 "test_thing.source.1", 3642 "test_thing.source.2", 3643 }, 3644 "first_source_id": unknownValue(), 3645 "first_source_name": "test_thing.source.0", 3646 }) 3647 checkConfig("module.child.test_thing.whole_splat", map[string]interface{}{ 3648 "source_ids": unknownValue(), 3649 "source_names": []interface{}{ 3650 "test_thing.source.0", 3651 "test_thing.source.1", 3652 "test_thing.source.2", 3653 }, 3654 3655 // This one ends up being a list with a single unknown value at this 3656 // layer, but is fixed up inside helper/schema. There is a test for 3657 // this inside the "test" provider, since core tests can't exercise 3658 // helper/schema functionality. 3659 "source_ids_wrapped": []interface{}{unknownValue()}, 3660 3661 "source_names_wrapped": []interface{}{ 3662 "test_thing.source.0", 3663 "test_thing.source.1", 3664 "test_thing.source.2", 3665 }, 3666 }) 3667 3668 state, err := ctx.Apply() 3669 if err != nil { 3670 t.Fatalf("error during apply: %s", err) 3671 } 3672 3673 { 3674 want := map[string]interface{}{ 3675 "source_ids": []interface{}{"foo", "foo", "foo"}, 3676 "source_names": []interface{}{ 3677 "test_thing.source.0", 3678 "test_thing.source.1", 3679 "test_thing.source.2", 3680 }, 3681 } 3682 got := map[string]interface{}{} 3683 for k, s := range state.RootModule().Outputs { 3684 got[k] = s.Value 3685 } 3686 if !reflect.DeepEqual(got, want) { 3687 t.Errorf( 3688 "wrong outputs\ngot: %s\nwant: %s", 3689 spew.Sdump(got), spew.Sdump(want), 3690 ) 3691 } 3692 } 3693 } 3694 3695 // Test that multi-var (splat) access is ordered by count, not by 3696 // value. 3697 func TestContext2Apply_multiVarOrder(t *testing.T) { 3698 m := testModule(t, "apply-multi-var-order") 3699 p := testProvider("aws") 3700 p.ApplyFn = testApplyFn 3701 p.DiffFn = testDiffFn 3702 3703 // First, apply with a count of 3 3704 ctx := testContext2(t, &ContextOpts{ 3705 Module: m, 3706 ProviderResolver: ResourceProviderResolverFixed( 3707 map[string]ResourceProviderFactory{ 3708 "aws": testProviderFuncFixed(p), 3709 }, 3710 ), 3711 }) 3712 3713 if _, err := ctx.Plan(); err != nil { 3714 t.Fatalf("err: %s", err) 3715 } 3716 3717 state, err := ctx.Apply() 3718 if err != nil { 3719 t.Fatalf("err: %s", err) 3720 } 3721 3722 t.Logf("State: %s", state.String()) 3723 3724 actual := state.RootModule().Outputs["should-be-11"] 3725 expected := "index-11" 3726 if actual == nil || actual.Value != expected { 3727 t.Fatalf("bad: \n%s", actual) 3728 } 3729 } 3730 3731 // Test that multi-var (splat) access is ordered by count, not by 3732 // value, through interpolations. 3733 func TestContext2Apply_multiVarOrderInterp(t *testing.T) { 3734 m := testModule(t, "apply-multi-var-order-interp") 3735 p := testProvider("aws") 3736 p.ApplyFn = testApplyFn 3737 p.DiffFn = testDiffFn 3738 3739 // First, apply with a count of 3 3740 ctx := testContext2(t, &ContextOpts{ 3741 Module: m, 3742 ProviderResolver: ResourceProviderResolverFixed( 3743 map[string]ResourceProviderFactory{ 3744 "aws": testProviderFuncFixed(p), 3745 }, 3746 ), 3747 }) 3748 3749 if _, err := ctx.Plan(); err != nil { 3750 t.Fatalf("err: %s", err) 3751 } 3752 3753 state, err := ctx.Apply() 3754 if err != nil { 3755 t.Fatalf("err: %s", err) 3756 } 3757 3758 t.Logf("State: %s", state.String()) 3759 3760 actual := state.RootModule().Outputs["should-be-11"] 3761 expected := "baz-index-11" 3762 if actual == nil || actual.Value != expected { 3763 t.Fatalf("bad: \n%s", actual) 3764 } 3765 } 3766 3767 // Based on GH-10440 where a graph edge wasn't properly being created 3768 // between a modified resource and a count instance being destroyed. 3769 func TestContext2Apply_multiVarCountDec(t *testing.T) { 3770 var s *State 3771 3772 // First create resources. Nothing sneaky here. 3773 { 3774 m := testModule(t, "apply-multi-var-count-dec") 3775 p := testProvider("aws") 3776 p.ApplyFn = testApplyFn 3777 p.DiffFn = testDiffFn 3778 ctx := testContext2(t, &ContextOpts{ 3779 Module: m, 3780 ProviderResolver: ResourceProviderResolverFixed( 3781 map[string]ResourceProviderFactory{ 3782 "aws": testProviderFuncFixed(p), 3783 }, 3784 ), 3785 Variables: map[string]interface{}{ 3786 "count": "2", 3787 }, 3788 }) 3789 3790 if _, err := ctx.Plan(); err != nil { 3791 t.Fatalf("err: %s", err) 3792 } 3793 3794 state, err := ctx.Apply() 3795 if err != nil { 3796 t.Fatalf("err: %s", err) 3797 } 3798 3799 t.Logf("Step 1 state: %s", state) 3800 3801 s = state 3802 } 3803 3804 // Decrease the count by 1 and verify that everything happens in the 3805 // right order. 3806 { 3807 m := testModule(t, "apply-multi-var-count-dec") 3808 p := testProvider("aws") 3809 p.ApplyFn = testApplyFn 3810 p.DiffFn = testDiffFn 3811 3812 // Verify that aws_instance.bar is modified first and nothing 3813 // else happens at the same time. 3814 var checked bool 3815 var called int32 3816 var lock sync.Mutex 3817 p.ApplyFn = func( 3818 info *InstanceInfo, 3819 is *InstanceState, 3820 id *InstanceDiff) (*InstanceState, error) { 3821 lock.Lock() 3822 defer lock.Unlock() 3823 3824 if info.HumanId() == "aws_instance.bar" { 3825 checked = true 3826 3827 // Sleep to allow parallel execution 3828 time.Sleep(50 * time.Millisecond) 3829 3830 // Verify that called is 0 (dep not called) 3831 if atomic.LoadInt32(&called) != 1 { 3832 return nil, fmt.Errorf("nothing else should be called") 3833 } 3834 } 3835 3836 atomic.AddInt32(&called, 1) 3837 return testApplyFn(info, is, id) 3838 } 3839 3840 ctx := testContext2(t, &ContextOpts{ 3841 State: s, 3842 Module: m, 3843 ProviderResolver: ResourceProviderResolverFixed( 3844 map[string]ResourceProviderFactory{ 3845 "aws": testProviderFuncFixed(p), 3846 }, 3847 ), 3848 Variables: map[string]interface{}{ 3849 "count": "1", 3850 }, 3851 }) 3852 3853 if _, err := ctx.Plan(); err != nil { 3854 t.Fatalf("err: %s", err) 3855 } 3856 3857 state, err := ctx.Apply() 3858 if err != nil { 3859 t.Fatalf("err: %s", err) 3860 } 3861 3862 if !checked { 3863 t.Fatal("apply never called") 3864 } 3865 3866 t.Logf("Step 2 state: %s", state) 3867 3868 s = state 3869 } 3870 } 3871 3872 // Test that we can resolve a multi-var (splat) for the first resource 3873 // created in a non-root module, which happens when the module state doesn't 3874 // exist yet. 3875 // https://github.com/hashicorp/terraform/issues/14438 3876 func TestContext2Apply_multiVarMissingState(t *testing.T) { 3877 m := testModule(t, "apply-multi-var-missing-state") 3878 p := testProvider("test") 3879 p.ApplyFn = testApplyFn 3880 p.DiffFn = testDiffFn 3881 3882 // First, apply with a count of 3 3883 ctx := testContext2(t, &ContextOpts{ 3884 Module: m, 3885 ProviderResolver: ResourceProviderResolverFixed( 3886 map[string]ResourceProviderFactory{ 3887 "test": testProviderFuncFixed(p), 3888 }, 3889 ), 3890 }) 3891 3892 if _, err := ctx.Plan(); err != nil { 3893 t.Fatalf("plan failed: %s", err) 3894 } 3895 3896 // Before the relevant bug was fixed, Terraform would panic during apply. 3897 if _, err := ctx.Apply(); err != nil { 3898 t.Fatalf("apply failed: %s", err) 3899 } 3900 3901 // If we get here with no errors or panics then our test was successful. 3902 } 3903 3904 func TestContext2Apply_nilDiff(t *testing.T) { 3905 m := testModule(t, "apply-good") 3906 p := testProvider("aws") 3907 p.ApplyFn = testApplyFn 3908 p.DiffFn = testDiffFn 3909 ctx := testContext2(t, &ContextOpts{ 3910 Module: m, 3911 ProviderResolver: ResourceProviderResolverFixed( 3912 map[string]ResourceProviderFactory{ 3913 "aws": testProviderFuncFixed(p), 3914 }, 3915 ), 3916 }) 3917 3918 if _, err := ctx.Plan(); err != nil { 3919 t.Fatalf("err: %s", err) 3920 } 3921 3922 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3923 return nil, nil 3924 } 3925 3926 if _, err := ctx.Apply(); err == nil { 3927 t.Fatal("should error") 3928 } 3929 } 3930 3931 func TestContext2Apply_outputDependsOn(t *testing.T) { 3932 m := testModule(t, "apply-output-depends-on") 3933 p := testProvider("aws") 3934 p.DiffFn = testDiffFn 3935 3936 { 3937 // Create a custom apply function that sleeps a bit (to allow parallel 3938 // graph execution) and then returns an error to force a partial state 3939 // return. We then verify the output is NOT there. 3940 p.ApplyFn = func( 3941 info *InstanceInfo, 3942 is *InstanceState, 3943 id *InstanceDiff) (*InstanceState, error) { 3944 // Sleep to allow parallel execution 3945 time.Sleep(50 * time.Millisecond) 3946 3947 // Return error to force partial state 3948 return nil, fmt.Errorf("abcd") 3949 } 3950 3951 ctx := testContext2(t, &ContextOpts{ 3952 Module: m, 3953 ProviderResolver: ResourceProviderResolverFixed( 3954 map[string]ResourceProviderFactory{ 3955 "aws": testProviderFuncFixed(p), 3956 }, 3957 ), 3958 }) 3959 3960 if _, err := ctx.Plan(); err != nil { 3961 t.Fatalf("err: %s", err) 3962 } 3963 3964 state, err := ctx.Apply() 3965 if err == nil || !strings.Contains(err.Error(), "abcd") { 3966 t.Fatalf("err: %s", err) 3967 } 3968 3969 checkStateString(t, state, `<no state>`) 3970 } 3971 3972 { 3973 // Create the standard apply function and verify we get the output 3974 p.ApplyFn = testApplyFn 3975 3976 ctx := testContext2(t, &ContextOpts{ 3977 Module: m, 3978 ProviderResolver: ResourceProviderResolverFixed( 3979 map[string]ResourceProviderFactory{ 3980 "aws": testProviderFuncFixed(p), 3981 }, 3982 ), 3983 }) 3984 3985 if _, err := ctx.Plan(); err != nil { 3986 t.Fatalf("err: %s", err) 3987 } 3988 3989 state, err := ctx.Apply() 3990 if err != nil { 3991 t.Fatalf("err: %s", err) 3992 } 3993 3994 checkStateString(t, state, ` 3995 aws_instance.foo: 3996 ID = foo 3997 provider = provider.aws 3998 3999 Outputs: 4000 4001 value = result 4002 `) 4003 } 4004 } 4005 4006 func TestContext2Apply_outputOrphan(t *testing.T) { 4007 m := testModule(t, "apply-output-orphan") 4008 p := testProvider("aws") 4009 p.ApplyFn = testApplyFn 4010 p.DiffFn = testDiffFn 4011 4012 state := &State{ 4013 Modules: []*ModuleState{ 4014 &ModuleState{ 4015 Path: rootModulePath, 4016 Outputs: map[string]*OutputState{ 4017 "foo": &OutputState{ 4018 Type: "string", 4019 Sensitive: false, 4020 Value: "bar", 4021 }, 4022 "bar": &OutputState{ 4023 Type: "string", 4024 Sensitive: false, 4025 Value: "baz", 4026 }, 4027 }, 4028 }, 4029 }, 4030 } 4031 4032 ctx := testContext2(t, &ContextOpts{ 4033 Module: m, 4034 ProviderResolver: ResourceProviderResolverFixed( 4035 map[string]ResourceProviderFactory{ 4036 "aws": testProviderFuncFixed(p), 4037 }, 4038 ), 4039 State: state, 4040 }) 4041 4042 if _, err := ctx.Plan(); err != nil { 4043 t.Fatalf("err: %s", err) 4044 } 4045 4046 state, err := ctx.Apply() 4047 if err != nil { 4048 t.Fatalf("err: %s", err) 4049 } 4050 4051 actual := strings.TrimSpace(state.String()) 4052 expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr) 4053 if actual != expected { 4054 t.Fatalf("bad: \n%s", actual) 4055 } 4056 } 4057 4058 func TestContext2Apply_outputOrphanModule(t *testing.T) { 4059 m := testModule(t, "apply-output-orphan-module") 4060 p := testProvider("aws") 4061 p.ApplyFn = testApplyFn 4062 p.DiffFn = testDiffFn 4063 4064 state := &State{ 4065 Modules: []*ModuleState{ 4066 &ModuleState{ 4067 Path: []string{"root", "child"}, 4068 Outputs: map[string]*OutputState{ 4069 "foo": &OutputState{ 4070 Type: "string", 4071 Value: "bar", 4072 }, 4073 "bar": &OutputState{ 4074 Type: "string", 4075 Value: "baz", 4076 }, 4077 }, 4078 }, 4079 }, 4080 } 4081 4082 ctx := testContext2(t, &ContextOpts{ 4083 Module: m, 4084 ProviderResolver: ResourceProviderResolverFixed( 4085 map[string]ResourceProviderFactory{ 4086 "aws": testProviderFuncFixed(p), 4087 }, 4088 ), 4089 State: state.DeepCopy(), 4090 }) 4091 4092 if _, err := ctx.Plan(); err != nil { 4093 t.Fatalf("err: %s", err) 4094 } 4095 4096 state, err := ctx.Apply() 4097 if err != nil { 4098 t.Fatalf("err: %s", err) 4099 } 4100 4101 actual := strings.TrimSpace(state.String()) 4102 expected := strings.TrimSpace(testTerraformApplyOutputOrphanModuleStr) 4103 if actual != expected { 4104 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 4105 } 4106 4107 // now apply with no module in the config, which should remove the 4108 // remaining output 4109 ctx = testContext2(t, &ContextOpts{ 4110 Module: module.NewEmptyTree(), 4111 ProviderResolver: ResourceProviderResolverFixed( 4112 map[string]ResourceProviderFactory{ 4113 "aws": testProviderFuncFixed(p), 4114 }, 4115 ), 4116 State: state.DeepCopy(), 4117 }) 4118 4119 if _, err := ctx.Plan(); err != nil { 4120 t.Fatalf("err: %s", err) 4121 } 4122 4123 state, err = ctx.Apply() 4124 if err != nil { 4125 t.Fatalf("err: %s", err) 4126 } 4127 4128 actual = strings.TrimSpace(state.String()) 4129 if actual != "" { 4130 t.Fatalf("expected no state, got:\n%s", actual) 4131 } 4132 } 4133 4134 func TestContext2Apply_providerComputedVar(t *testing.T) { 4135 m := testModule(t, "apply-provider-computed") 4136 p := testProvider("aws") 4137 p.ApplyFn = testApplyFn 4138 p.DiffFn = testDiffFn 4139 4140 pTest := testProvider("test") 4141 pTest.ApplyFn = testApplyFn 4142 pTest.DiffFn = testDiffFn 4143 4144 ctx := testContext2(t, &ContextOpts{ 4145 Module: m, 4146 ProviderResolver: ResourceProviderResolverFixed( 4147 map[string]ResourceProviderFactory{ 4148 "aws": testProviderFuncFixed(p), 4149 "test": testProviderFuncFixed(pTest), 4150 }, 4151 ), 4152 }) 4153 4154 p.ConfigureFn = func(c *ResourceConfig) error { 4155 if c.IsComputed("value") { 4156 return fmt.Errorf("value is computed") 4157 } 4158 4159 v, ok := c.Get("value") 4160 if !ok { 4161 return fmt.Errorf("value is not found") 4162 } 4163 if v != "yes" { 4164 return fmt.Errorf("value is not 'yes': %v", v) 4165 } 4166 4167 return nil 4168 } 4169 4170 if _, err := ctx.Plan(); err != nil { 4171 t.Fatalf("err: %s", err) 4172 } 4173 4174 if _, err := ctx.Apply(); err != nil { 4175 t.Fatalf("err: %s", err) 4176 } 4177 } 4178 4179 func TestContext2Apply_providerConfigureDisabled(t *testing.T) { 4180 m := testModule(t, "apply-provider-configure-disabled") 4181 p := testProvider("aws") 4182 p.ApplyFn = testApplyFn 4183 p.DiffFn = testDiffFn 4184 4185 called := false 4186 p.ConfigureFn = func(c *ResourceConfig) error { 4187 called = true 4188 4189 if _, ok := c.Get("value"); !ok { 4190 return fmt.Errorf("value is not found") 4191 } 4192 4193 return nil 4194 } 4195 4196 ctx := testContext2(t, &ContextOpts{ 4197 Module: m, 4198 ProviderResolver: ResourceProviderResolverFixed( 4199 map[string]ResourceProviderFactory{ 4200 "aws": testProviderFuncFixed(p), 4201 }, 4202 ), 4203 }) 4204 4205 if _, err := ctx.Plan(); err != nil { 4206 t.Fatalf("err: %s", err) 4207 } 4208 4209 if _, err := ctx.Apply(); err != nil { 4210 t.Fatalf("err: %s", err) 4211 } 4212 4213 if !called { 4214 t.Fatal("configure never called") 4215 } 4216 } 4217 4218 func TestContext2Apply_provisionerModule(t *testing.T) { 4219 m := testModule(t, "apply-provisioner-module") 4220 p := testProvider("aws") 4221 pr := testProvisioner() 4222 p.ApplyFn = testApplyFn 4223 p.DiffFn = testDiffFn 4224 ctx := testContext2(t, &ContextOpts{ 4225 Module: m, 4226 ProviderResolver: ResourceProviderResolverFixed( 4227 map[string]ResourceProviderFactory{ 4228 "aws": testProviderFuncFixed(p), 4229 }, 4230 ), 4231 Provisioners: map[string]ResourceProvisionerFactory{ 4232 "shell": testProvisionerFuncFixed(pr), 4233 }, 4234 }) 4235 4236 if _, err := ctx.Plan(); err != nil { 4237 t.Fatalf("err: %s", err) 4238 } 4239 4240 state, err := ctx.Apply() 4241 if err != nil { 4242 t.Fatalf("err: %s", err) 4243 } 4244 4245 actual := strings.TrimSpace(state.String()) 4246 expected := strings.TrimSpace(testTerraformApplyProvisionerModuleStr) 4247 if actual != expected { 4248 t.Fatalf("bad: \n%s", actual) 4249 } 4250 4251 // Verify apply was invoked 4252 if !pr.ApplyCalled { 4253 t.Fatalf("provisioner not invoked") 4254 } 4255 } 4256 4257 func TestContext2Apply_Provisioner_compute(t *testing.T) { 4258 m := testModule(t, "apply-provisioner-compute") 4259 p := testProvider("aws") 4260 pr := testProvisioner() 4261 p.ApplyFn = testApplyFn 4262 p.DiffFn = testDiffFn 4263 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4264 val, ok := c.Config["foo"] 4265 if !ok || val != "computed_dynamical" { 4266 t.Fatalf("bad value for foo: %v %#v", val, c) 4267 } 4268 4269 return nil 4270 } 4271 ctx := testContext2(t, &ContextOpts{ 4272 Module: m, 4273 ProviderResolver: ResourceProviderResolverFixed( 4274 map[string]ResourceProviderFactory{ 4275 "aws": testProviderFuncFixed(p), 4276 }, 4277 ), 4278 Provisioners: map[string]ResourceProvisionerFactory{ 4279 "shell": testProvisionerFuncFixed(pr), 4280 }, 4281 Variables: map[string]interface{}{ 4282 "value": "1", 4283 }, 4284 }) 4285 4286 if _, err := ctx.Plan(); err != nil { 4287 t.Fatalf("err: %s", err) 4288 } 4289 4290 state, err := ctx.Apply() 4291 if err != nil { 4292 t.Fatalf("err: %s", err) 4293 } 4294 4295 actual := strings.TrimSpace(state.String()) 4296 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 4297 if actual != expected { 4298 t.Fatalf("bad: \n%s", actual) 4299 } 4300 4301 // Verify apply was invoked 4302 if !pr.ApplyCalled { 4303 t.Fatalf("provisioner not invoked") 4304 } 4305 } 4306 4307 func TestContext2Apply_provisionerCreateFail(t *testing.T) { 4308 m := testModule(t, "apply-provisioner-fail-create") 4309 p := testProvider("aws") 4310 pr := testProvisioner() 4311 p.DiffFn = testDiffFn 4312 4313 p.ApplyFn = func( 4314 info *InstanceInfo, 4315 is *InstanceState, 4316 id *InstanceDiff) (*InstanceState, error) { 4317 is.ID = "foo" 4318 return is, fmt.Errorf("error") 4319 } 4320 4321 ctx := testContext2(t, &ContextOpts{ 4322 Module: m, 4323 ProviderResolver: ResourceProviderResolverFixed( 4324 map[string]ResourceProviderFactory{ 4325 "aws": testProviderFuncFixed(p), 4326 }, 4327 ), 4328 Provisioners: map[string]ResourceProvisionerFactory{ 4329 "shell": testProvisionerFuncFixed(pr), 4330 }, 4331 }) 4332 4333 if _, err := ctx.Plan(); err != nil { 4334 t.Fatalf("err: %s", err) 4335 } 4336 4337 state, err := ctx.Apply() 4338 if err == nil { 4339 t.Fatal("should error") 4340 } 4341 4342 actual := strings.TrimSpace(state.String()) 4343 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr) 4344 if actual != expected { 4345 t.Fatalf("bad: \n%s", actual) 4346 } 4347 } 4348 4349 func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) { 4350 m := testModule(t, "apply-provisioner-fail-create") 4351 p := testProvider("aws") 4352 pr := testProvisioner() 4353 p.DiffFn = testDiffFn 4354 4355 p.ApplyFn = func( 4356 info *InstanceInfo, 4357 is *InstanceState, 4358 id *InstanceDiff) (*InstanceState, error) { 4359 return nil, fmt.Errorf("error") 4360 } 4361 4362 ctx := testContext2(t, &ContextOpts{ 4363 Module: m, 4364 ProviderResolver: ResourceProviderResolverFixed( 4365 map[string]ResourceProviderFactory{ 4366 "aws": testProviderFuncFixed(p), 4367 }, 4368 ), 4369 Provisioners: map[string]ResourceProvisionerFactory{ 4370 "shell": testProvisionerFuncFixed(pr), 4371 }, 4372 }) 4373 4374 if _, err := ctx.Plan(); err != nil { 4375 t.Fatalf("err: %s", err) 4376 } 4377 4378 state, err := ctx.Apply() 4379 if err == nil { 4380 t.Fatal("should error") 4381 } 4382 4383 actual := strings.TrimSpace(state.String()) 4384 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr) 4385 if actual != expected { 4386 t.Fatalf("bad: \n%s", actual) 4387 } 4388 } 4389 4390 func TestContext2Apply_provisionerFail(t *testing.T) { 4391 m := testModule(t, "apply-provisioner-fail") 4392 p := testProvider("aws") 4393 pr := testProvisioner() 4394 p.ApplyFn = testApplyFn 4395 p.DiffFn = testDiffFn 4396 4397 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 4398 return fmt.Errorf("EXPLOSION") 4399 } 4400 4401 ctx := testContext2(t, &ContextOpts{ 4402 Module: m, 4403 ProviderResolver: ResourceProviderResolverFixed( 4404 map[string]ResourceProviderFactory{ 4405 "aws": testProviderFuncFixed(p), 4406 }, 4407 ), 4408 Provisioners: map[string]ResourceProvisionerFactory{ 4409 "shell": testProvisionerFuncFixed(pr), 4410 }, 4411 Variables: map[string]interface{}{ 4412 "value": "1", 4413 }, 4414 }) 4415 4416 if _, err := ctx.Plan(); err != nil { 4417 t.Fatalf("err: %s", err) 4418 } 4419 4420 state, err := ctx.Apply() 4421 if err == nil { 4422 t.Fatal("should error") 4423 } 4424 4425 actual := strings.TrimSpace(state.String()) 4426 expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr) 4427 if actual != expected { 4428 t.Fatalf("bad: \n%s", actual) 4429 } 4430 } 4431 4432 func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) { 4433 m := testModule(t, "apply-provisioner-fail-create-before") 4434 p := testProvider("aws") 4435 pr := testProvisioner() 4436 p.ApplyFn = testApplyFn 4437 p.DiffFn = testDiffFn 4438 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 4439 return fmt.Errorf("EXPLOSION") 4440 } 4441 4442 state := &State{ 4443 Modules: []*ModuleState{ 4444 &ModuleState{ 4445 Path: rootModulePath, 4446 Resources: map[string]*ResourceState{ 4447 "aws_instance.bar": &ResourceState{ 4448 Type: "aws_instance", 4449 Primary: &InstanceState{ 4450 ID: "bar", 4451 Attributes: map[string]string{ 4452 "require_new": "abc", 4453 }, 4454 }, 4455 }, 4456 }, 4457 }, 4458 }, 4459 } 4460 ctx := testContext2(t, &ContextOpts{ 4461 Module: m, 4462 ProviderResolver: ResourceProviderResolverFixed( 4463 map[string]ResourceProviderFactory{ 4464 "aws": testProviderFuncFixed(p), 4465 }, 4466 ), 4467 Provisioners: map[string]ResourceProvisionerFactory{ 4468 "shell": testProvisionerFuncFixed(pr), 4469 }, 4470 State: state, 4471 }) 4472 4473 if _, err := ctx.Plan(); err != nil { 4474 t.Fatalf("err: %s", err) 4475 } 4476 4477 state, err := ctx.Apply() 4478 if err == nil { 4479 t.Fatal("should error") 4480 } 4481 4482 actual := strings.TrimSpace(state.String()) 4483 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr) 4484 if actual != expected { 4485 t.Fatalf("bad: \n%s", actual) 4486 } 4487 } 4488 4489 func TestContext2Apply_error_createBeforeDestroy(t *testing.T) { 4490 m := testModule(t, "apply-error-create-before") 4491 p := testProvider("aws") 4492 state := &State{ 4493 Modules: []*ModuleState{ 4494 &ModuleState{ 4495 Path: rootModulePath, 4496 Resources: map[string]*ResourceState{ 4497 "aws_instance.bar": &ResourceState{ 4498 Type: "aws_instance", 4499 Primary: &InstanceState{ 4500 ID: "bar", 4501 Attributes: map[string]string{ 4502 "require_new": "abc", 4503 }, 4504 }, 4505 }, 4506 }, 4507 }, 4508 }, 4509 } 4510 ctx := testContext2(t, &ContextOpts{ 4511 Module: m, 4512 ProviderResolver: ResourceProviderResolverFixed( 4513 map[string]ResourceProviderFactory{ 4514 "aws": testProviderFuncFixed(p), 4515 }, 4516 ), 4517 State: state, 4518 }) 4519 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4520 return nil, fmt.Errorf("error") 4521 } 4522 p.DiffFn = testDiffFn 4523 4524 if _, err := ctx.Plan(); err != nil { 4525 t.Fatalf("err: %s", err) 4526 } 4527 4528 state, err := ctx.Apply() 4529 if err == nil { 4530 t.Fatal("should have error") 4531 } 4532 4533 actual := strings.TrimSpace(state.String()) 4534 expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr) 4535 if actual != expected { 4536 t.Fatalf("bad: \n%s\n\nExpected:\n\n%s", actual, expected) 4537 } 4538 } 4539 4540 func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) { 4541 m := testModule(t, "apply-error-create-before") 4542 p := testProvider("aws") 4543 state := &State{ 4544 Modules: []*ModuleState{ 4545 &ModuleState{ 4546 Path: rootModulePath, 4547 Resources: map[string]*ResourceState{ 4548 "aws_instance.bar": &ResourceState{ 4549 Type: "aws_instance", 4550 Primary: &InstanceState{ 4551 ID: "bar", 4552 Attributes: map[string]string{ 4553 "require_new": "abc", 4554 }, 4555 }, 4556 }, 4557 }, 4558 }, 4559 }, 4560 } 4561 ctx := testContext2(t, &ContextOpts{ 4562 Module: m, 4563 ProviderResolver: ResourceProviderResolverFixed( 4564 map[string]ResourceProviderFactory{ 4565 "aws": testProviderFuncFixed(p), 4566 }, 4567 ), 4568 State: state, 4569 }) 4570 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4571 // Fail the destroy! 4572 if id.Destroy { 4573 return is, fmt.Errorf("error") 4574 } 4575 4576 // Create should work 4577 is = &InstanceState{ 4578 ID: "foo", 4579 } 4580 return is, nil 4581 } 4582 p.DiffFn = testDiffFn 4583 4584 if _, err := ctx.Plan(); err != nil { 4585 t.Fatalf("err: %s", err) 4586 } 4587 4588 state, err := ctx.Apply() 4589 if err == nil { 4590 t.Fatal("should have error") 4591 } 4592 4593 actual := strings.TrimSpace(state.String()) 4594 expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr) 4595 if actual != expected { 4596 t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected) 4597 } 4598 } 4599 4600 func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) { 4601 m := testModule(t, "apply-multi-depose-create-before-destroy") 4602 p := testProvider("aws") 4603 p.DiffFn = testDiffFn 4604 ps := map[string]ResourceProviderFactory{"aws": testProviderFuncFixed(p)} 4605 state := &State{ 4606 Modules: []*ModuleState{ 4607 &ModuleState{ 4608 Path: rootModulePath, 4609 Resources: map[string]*ResourceState{ 4610 "aws_instance.web": &ResourceState{ 4611 Type: "aws_instance", 4612 Primary: &InstanceState{ID: "foo"}, 4613 }, 4614 }, 4615 }, 4616 }, 4617 } 4618 4619 ctx := testContext2(t, &ContextOpts{ 4620 Module: m, 4621 ProviderResolver: ResourceProviderResolverFixed(ps), 4622 State: state, 4623 }) 4624 createdInstanceId := "bar" 4625 // Create works 4626 createFunc := func(is *InstanceState) (*InstanceState, error) { 4627 return &InstanceState{ID: createdInstanceId}, nil 4628 } 4629 // Destroy starts broken 4630 destroyFunc := func(is *InstanceState) (*InstanceState, error) { 4631 return is, fmt.Errorf("destroy failed") 4632 } 4633 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4634 if id.Destroy { 4635 return destroyFunc(is) 4636 } else { 4637 return createFunc(is) 4638 } 4639 } 4640 4641 if _, err := ctx.Plan(); err != nil { 4642 t.Fatalf("err: %s", err) 4643 } 4644 4645 // Destroy is broken, so even though CBD successfully replaces the instance, 4646 // we'll have to save the Deposed instance to destroy later 4647 state, err := ctx.Apply() 4648 if err == nil { 4649 t.Fatal("should have error") 4650 } 4651 4652 checkStateString(t, state, ` 4653 aws_instance.web: (1 deposed) 4654 ID = bar 4655 provider = provider.aws 4656 Deposed ID 1 = foo 4657 `) 4658 4659 createdInstanceId = "baz" 4660 ctx = testContext2(t, &ContextOpts{ 4661 Module: m, 4662 ProviderResolver: ResourceProviderResolverFixed(ps), 4663 State: state, 4664 }) 4665 4666 if _, err := ctx.Plan(); err != nil { 4667 t.Fatalf("err: %s", err) 4668 } 4669 4670 // We're replacing the primary instance once again. Destroy is _still_ 4671 // broken, so the Deposed list gets longer 4672 state, err = ctx.Apply() 4673 if err == nil { 4674 t.Fatal("should have error") 4675 } 4676 4677 checkStateString(t, state, ` 4678 aws_instance.web: (2 deposed) 4679 ID = baz 4680 provider = provider.aws 4681 Deposed ID 1 = foo 4682 Deposed ID 2 = bar 4683 `) 4684 4685 // Destroy partially fixed! 4686 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4687 if is.ID == "foo" || is.ID == "baz" { 4688 return nil, nil 4689 } else { 4690 return is, fmt.Errorf("destroy partially failed") 4691 } 4692 } 4693 4694 createdInstanceId = "qux" 4695 if _, err := ctx.Plan(); err != nil { 4696 t.Fatalf("err: %s", err) 4697 } 4698 state, err = ctx.Apply() 4699 // Expect error because 1/2 of Deposed destroys failed 4700 if err == nil { 4701 t.Fatal("should have error") 4702 } 4703 4704 // foo and baz are now gone, bar sticks around 4705 checkStateString(t, state, ` 4706 aws_instance.web: (1 deposed) 4707 ID = qux 4708 provider = provider.aws 4709 Deposed ID 1 = bar 4710 `) 4711 4712 // Destroy working fully! 4713 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4714 return nil, nil 4715 } 4716 4717 createdInstanceId = "quux" 4718 if _, err := ctx.Plan(); err != nil { 4719 t.Fatalf("err: %s", err) 4720 } 4721 state, err = ctx.Apply() 4722 if err != nil { 4723 t.Fatal("should not have error:", err) 4724 } 4725 4726 // And finally the state is clean 4727 checkStateString(t, state, ` 4728 aws_instance.web: 4729 ID = quux 4730 provider = provider.aws 4731 `) 4732 } 4733 4734 // Verify that a normal provisioner with on_failure "continue" set won't 4735 // taint the resource and continues executing. 4736 func TestContext2Apply_provisionerFailContinue(t *testing.T) { 4737 m := testModule(t, "apply-provisioner-fail-continue") 4738 p := testProvider("aws") 4739 pr := testProvisioner() 4740 p.ApplyFn = testApplyFn 4741 p.DiffFn = testDiffFn 4742 4743 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4744 return fmt.Errorf("provisioner error") 4745 } 4746 4747 ctx := testContext2(t, &ContextOpts{ 4748 Module: m, 4749 ProviderResolver: ResourceProviderResolverFixed( 4750 map[string]ResourceProviderFactory{ 4751 "aws": testProviderFuncFixed(p), 4752 }, 4753 ), 4754 Provisioners: map[string]ResourceProvisionerFactory{ 4755 "shell": testProvisionerFuncFixed(pr), 4756 }, 4757 }) 4758 4759 if _, err := ctx.Plan(); err != nil { 4760 t.Fatalf("err: %s", err) 4761 } 4762 4763 state, err := ctx.Apply() 4764 if err != nil { 4765 t.Fatalf("err: %s", err) 4766 } 4767 4768 checkStateString(t, state, ` 4769 aws_instance.foo: 4770 ID = foo 4771 provider = provider.aws 4772 foo = bar 4773 type = aws_instance 4774 `) 4775 4776 // Verify apply was invoked 4777 if !pr.ApplyCalled { 4778 t.Fatalf("provisioner not invoked") 4779 } 4780 } 4781 4782 // Verify that a normal provisioner with on_failure "continue" records 4783 // the error with the hook. 4784 func TestContext2Apply_provisionerFailContinueHook(t *testing.T) { 4785 h := new(MockHook) 4786 m := testModule(t, "apply-provisioner-fail-continue") 4787 p := testProvider("aws") 4788 pr := testProvisioner() 4789 p.ApplyFn = testApplyFn 4790 p.DiffFn = testDiffFn 4791 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4792 return fmt.Errorf("provisioner error") 4793 } 4794 4795 ctx := testContext2(t, &ContextOpts{ 4796 Module: m, 4797 Hooks: []Hook{h}, 4798 ProviderResolver: ResourceProviderResolverFixed( 4799 map[string]ResourceProviderFactory{ 4800 "aws": testProviderFuncFixed(p), 4801 }, 4802 ), 4803 Provisioners: map[string]ResourceProvisionerFactory{ 4804 "shell": testProvisionerFuncFixed(pr), 4805 }, 4806 }) 4807 4808 if _, err := ctx.Plan(); err != nil { 4809 t.Fatalf("err: %s", err) 4810 } 4811 4812 if _, err := ctx.Apply(); err != nil { 4813 t.Fatalf("err: %s", err) 4814 } 4815 4816 if !h.PostProvisionCalled { 4817 t.Fatal("PostProvision not called") 4818 } 4819 if h.PostProvisionErrorArg == nil { 4820 t.Fatal("should have error") 4821 } 4822 } 4823 4824 func TestContext2Apply_provisionerDestroy(t *testing.T) { 4825 m := testModule(t, "apply-provisioner-destroy") 4826 p := testProvider("aws") 4827 pr := testProvisioner() 4828 p.ApplyFn = testApplyFn 4829 p.DiffFn = testDiffFn 4830 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4831 val, ok := c.Config["foo"] 4832 if !ok || val != "destroy" { 4833 t.Fatalf("bad value for foo: %v %#v", val, c) 4834 } 4835 4836 return nil 4837 } 4838 4839 state := &State{ 4840 Modules: []*ModuleState{ 4841 &ModuleState{ 4842 Path: rootModulePath, 4843 Resources: map[string]*ResourceState{ 4844 "aws_instance.foo": &ResourceState{ 4845 Type: "aws_instance", 4846 Primary: &InstanceState{ 4847 ID: "bar", 4848 }, 4849 }, 4850 }, 4851 }, 4852 }, 4853 } 4854 4855 ctx := testContext2(t, &ContextOpts{ 4856 Module: m, 4857 State: state, 4858 Destroy: true, 4859 ProviderResolver: ResourceProviderResolverFixed( 4860 map[string]ResourceProviderFactory{ 4861 "aws": testProviderFuncFixed(p), 4862 }, 4863 ), 4864 Provisioners: map[string]ResourceProvisionerFactory{ 4865 "shell": testProvisionerFuncFixed(pr), 4866 }, 4867 }) 4868 4869 if _, err := ctx.Plan(); err != nil { 4870 t.Fatalf("err: %s", err) 4871 } 4872 4873 state, err := ctx.Apply() 4874 if err != nil { 4875 t.Fatalf("err: %s", err) 4876 } 4877 4878 checkStateString(t, state, `<no state>`) 4879 4880 // Verify apply was invoked 4881 if !pr.ApplyCalled { 4882 t.Fatalf("provisioner not invoked") 4883 } 4884 } 4885 4886 // Verify that on destroy provisioner failure, nothing happens to the instance 4887 func TestContext2Apply_provisionerDestroyFail(t *testing.T) { 4888 m := testModule(t, "apply-provisioner-destroy") 4889 p := testProvider("aws") 4890 pr := testProvisioner() 4891 p.ApplyFn = testApplyFn 4892 p.DiffFn = testDiffFn 4893 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4894 return fmt.Errorf("provisioner error") 4895 } 4896 4897 state := &State{ 4898 Modules: []*ModuleState{ 4899 &ModuleState{ 4900 Path: rootModulePath, 4901 Resources: map[string]*ResourceState{ 4902 "aws_instance.foo": &ResourceState{ 4903 Type: "aws_instance", 4904 Primary: &InstanceState{ 4905 ID: "bar", 4906 }, 4907 }, 4908 }, 4909 }, 4910 }, 4911 } 4912 4913 ctx := testContext2(t, &ContextOpts{ 4914 Module: m, 4915 State: state, 4916 Destroy: true, 4917 ProviderResolver: ResourceProviderResolverFixed( 4918 map[string]ResourceProviderFactory{ 4919 "aws": testProviderFuncFixed(p), 4920 }, 4921 ), 4922 Provisioners: map[string]ResourceProvisionerFactory{ 4923 "shell": testProvisionerFuncFixed(pr), 4924 }, 4925 }) 4926 4927 if _, err := ctx.Plan(); err != nil { 4928 t.Fatalf("err: %s", err) 4929 } 4930 4931 state, err := ctx.Apply() 4932 if err == nil { 4933 t.Fatal("should error") 4934 } 4935 4936 checkStateString(t, state, ` 4937 aws_instance.foo: 4938 ID = bar 4939 `) 4940 4941 // Verify apply was invoked 4942 if !pr.ApplyCalled { 4943 t.Fatalf("provisioner not invoked") 4944 } 4945 } 4946 4947 // Verify that on destroy provisioner failure with "continue" that 4948 // we continue to the next provisioner. 4949 func TestContext2Apply_provisionerDestroyFailContinue(t *testing.T) { 4950 m := testModule(t, "apply-provisioner-destroy-continue") 4951 p := testProvider("aws") 4952 pr := testProvisioner() 4953 p.ApplyFn = testApplyFn 4954 p.DiffFn = testDiffFn 4955 4956 var l sync.Mutex 4957 var calls []string 4958 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4959 val, ok := c.Config["foo"] 4960 if !ok { 4961 t.Fatalf("bad value for foo: %v %#v", val, c) 4962 } 4963 4964 l.Lock() 4965 defer l.Unlock() 4966 calls = append(calls, val.(string)) 4967 return fmt.Errorf("provisioner error") 4968 } 4969 4970 state := &State{ 4971 Modules: []*ModuleState{ 4972 &ModuleState{ 4973 Path: rootModulePath, 4974 Resources: map[string]*ResourceState{ 4975 "aws_instance.foo": &ResourceState{ 4976 Type: "aws_instance", 4977 Primary: &InstanceState{ 4978 ID: "bar", 4979 }, 4980 }, 4981 }, 4982 }, 4983 }, 4984 } 4985 4986 ctx := testContext2(t, &ContextOpts{ 4987 Module: m, 4988 State: state, 4989 Destroy: true, 4990 ProviderResolver: ResourceProviderResolverFixed( 4991 map[string]ResourceProviderFactory{ 4992 "aws": testProviderFuncFixed(p), 4993 }, 4994 ), 4995 Provisioners: map[string]ResourceProvisionerFactory{ 4996 "shell": testProvisionerFuncFixed(pr), 4997 }, 4998 }) 4999 5000 if _, err := ctx.Plan(); err != nil { 5001 t.Fatalf("err: %s", err) 5002 } 5003 5004 state, err := ctx.Apply() 5005 if err != nil { 5006 t.Fatalf("err: %s", err) 5007 } 5008 5009 checkStateString(t, state, `<no state>`) 5010 5011 // Verify apply was invoked 5012 if !pr.ApplyCalled { 5013 t.Fatalf("provisioner not invoked") 5014 } 5015 5016 expected := []string{"one", "two"} 5017 if !reflect.DeepEqual(calls, expected) { 5018 t.Fatalf("bad: %#v", calls) 5019 } 5020 } 5021 5022 // Verify that on destroy provisioner failure with "continue" that 5023 // we continue to the next provisioner. But if the next provisioner defines 5024 // to fail, then we fail after running it. 5025 func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) { 5026 m := testModule(t, "apply-provisioner-destroy-fail") 5027 p := testProvider("aws") 5028 pr := testProvisioner() 5029 p.ApplyFn = testApplyFn 5030 p.DiffFn = testDiffFn 5031 5032 var l sync.Mutex 5033 var calls []string 5034 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5035 val, ok := c.Config["foo"] 5036 if !ok { 5037 t.Fatalf("bad value for foo: %v %#v", val, c) 5038 } 5039 5040 l.Lock() 5041 defer l.Unlock() 5042 calls = append(calls, val.(string)) 5043 return fmt.Errorf("provisioner error") 5044 } 5045 5046 state := &State{ 5047 Modules: []*ModuleState{ 5048 &ModuleState{ 5049 Path: rootModulePath, 5050 Resources: map[string]*ResourceState{ 5051 "aws_instance.foo": &ResourceState{ 5052 Type: "aws_instance", 5053 Primary: &InstanceState{ 5054 ID: "bar", 5055 }, 5056 }, 5057 }, 5058 }, 5059 }, 5060 } 5061 5062 ctx := testContext2(t, &ContextOpts{ 5063 Module: m, 5064 State: state, 5065 Destroy: true, 5066 ProviderResolver: ResourceProviderResolverFixed( 5067 map[string]ResourceProviderFactory{ 5068 "aws": testProviderFuncFixed(p), 5069 }, 5070 ), 5071 Provisioners: map[string]ResourceProvisionerFactory{ 5072 "shell": testProvisionerFuncFixed(pr), 5073 }, 5074 }) 5075 5076 if _, err := ctx.Plan(); err != nil { 5077 t.Fatalf("err: %s", err) 5078 } 5079 5080 state, err := ctx.Apply() 5081 if err == nil { 5082 t.Fatal("should error") 5083 } 5084 5085 checkStateString(t, state, ` 5086 aws_instance.foo: 5087 ID = bar 5088 `) 5089 5090 // Verify apply was invoked 5091 if !pr.ApplyCalled { 5092 t.Fatalf("provisioner not invoked") 5093 } 5094 5095 expected := []string{"one", "two"} 5096 if !reflect.DeepEqual(calls, expected) { 5097 t.Fatalf("bad: %#v", calls) 5098 } 5099 } 5100 5101 // Verify destroy provisioners are not run for tainted instances. 5102 func TestContext2Apply_provisionerDestroyTainted(t *testing.T) { 5103 m := testModule(t, "apply-provisioner-destroy") 5104 p := testProvider("aws") 5105 pr := testProvisioner() 5106 p.ApplyFn = testApplyFn 5107 p.DiffFn = testDiffFn 5108 5109 destroyCalled := false 5110 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5111 expected := "create" 5112 if rs.ID == "bar" { 5113 destroyCalled = true 5114 return nil 5115 } 5116 5117 val, ok := c.Config["foo"] 5118 if !ok || val != expected { 5119 t.Fatalf("bad value for foo: %v %#v", val, c) 5120 } 5121 5122 return nil 5123 } 5124 5125 state := &State{ 5126 Modules: []*ModuleState{ 5127 &ModuleState{ 5128 Path: rootModulePath, 5129 Resources: map[string]*ResourceState{ 5130 "aws_instance.foo": &ResourceState{ 5131 Type: "aws_instance", 5132 Primary: &InstanceState{ 5133 ID: "bar", 5134 Tainted: true, 5135 }, 5136 }, 5137 }, 5138 }, 5139 }, 5140 } 5141 5142 ctx := testContext2(t, &ContextOpts{ 5143 Module: m, 5144 State: state, 5145 ProviderResolver: ResourceProviderResolverFixed( 5146 map[string]ResourceProviderFactory{ 5147 "aws": testProviderFuncFixed(p), 5148 }, 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 checkStateString(t, state, ` 5165 aws_instance.foo: 5166 ID = foo 5167 provider = provider.aws 5168 foo = bar 5169 type = aws_instance 5170 `) 5171 5172 // Verify apply was invoked 5173 if !pr.ApplyCalled { 5174 t.Fatalf("provisioner not invoked") 5175 } 5176 5177 if destroyCalled { 5178 t.Fatal("destroy should not be called") 5179 } 5180 } 5181 5182 func TestContext2Apply_provisionerDestroyModule(t *testing.T) { 5183 m := testModule(t, "apply-provisioner-destroy-module") 5184 p := testProvider("aws") 5185 pr := testProvisioner() 5186 p.ApplyFn = testApplyFn 5187 p.DiffFn = testDiffFn 5188 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5189 val, ok := c.Config["foo"] 5190 if !ok || val != "value" { 5191 t.Fatalf("bad value for foo: %v %#v", val, c) 5192 } 5193 5194 return nil 5195 } 5196 5197 state := &State{ 5198 Modules: []*ModuleState{ 5199 &ModuleState{ 5200 Path: []string{"root", "child"}, 5201 Resources: map[string]*ResourceState{ 5202 "aws_instance.foo": &ResourceState{ 5203 Type: "aws_instance", 5204 Primary: &InstanceState{ 5205 ID: "bar", 5206 }, 5207 }, 5208 }, 5209 }, 5210 }, 5211 } 5212 5213 ctx := testContext2(t, &ContextOpts{ 5214 Module: m, 5215 State: state, 5216 Destroy: true, 5217 ProviderResolver: ResourceProviderResolverFixed( 5218 map[string]ResourceProviderFactory{ 5219 "aws": testProviderFuncFixed(p), 5220 }, 5221 ), 5222 Provisioners: map[string]ResourceProvisionerFactory{ 5223 "shell": testProvisionerFuncFixed(pr), 5224 }, 5225 }) 5226 5227 if _, err := ctx.Plan(); err != nil { 5228 t.Fatalf("err: %s", err) 5229 } 5230 5231 state, err := ctx.Apply() 5232 if err != nil { 5233 t.Fatalf("err: %s", err) 5234 } 5235 5236 checkStateString(t, state, ` 5237 module.child: 5238 <no state>`) 5239 5240 // Verify apply was invoked 5241 if !pr.ApplyCalled { 5242 t.Fatalf("provisioner not invoked") 5243 } 5244 } 5245 5246 func TestContext2Apply_provisionerDestroyRef(t *testing.T) { 5247 m := testModule(t, "apply-provisioner-destroy-ref") 5248 p := testProvider("aws") 5249 pr := testProvisioner() 5250 p.ApplyFn = testApplyFn 5251 p.DiffFn = testDiffFn 5252 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5253 val, ok := c.Config["foo"] 5254 if !ok || val != "hello" { 5255 return fmt.Errorf("bad value for foo: %v %#v", val, c) 5256 } 5257 5258 return nil 5259 } 5260 5261 state := &State{ 5262 Modules: []*ModuleState{ 5263 &ModuleState{ 5264 Path: rootModulePath, 5265 Resources: map[string]*ResourceState{ 5266 "aws_instance.bar": &ResourceState{ 5267 Type: "aws_instance", 5268 Primary: &InstanceState{ 5269 ID: "bar", 5270 Attributes: map[string]string{ 5271 "key": "hello", 5272 }, 5273 }, 5274 }, 5275 5276 "aws_instance.foo": &ResourceState{ 5277 Type: "aws_instance", 5278 Primary: &InstanceState{ 5279 ID: "bar", 5280 }, 5281 }, 5282 }, 5283 }, 5284 }, 5285 } 5286 5287 ctx := testContext2(t, &ContextOpts{ 5288 Module: m, 5289 State: state, 5290 Destroy: true, 5291 ProviderResolver: ResourceProviderResolverFixed( 5292 map[string]ResourceProviderFactory{ 5293 "aws": testProviderFuncFixed(p), 5294 }, 5295 ), 5296 Provisioners: map[string]ResourceProvisionerFactory{ 5297 "shell": testProvisionerFuncFixed(pr), 5298 }, 5299 }) 5300 5301 if _, err := ctx.Plan(); err != nil { 5302 t.Fatalf("err: %s", err) 5303 } 5304 5305 state, err := ctx.Apply() 5306 if err != nil { 5307 t.Fatalf("err: %s", err) 5308 } 5309 5310 checkStateString(t, state, `<no state>`) 5311 5312 // Verify apply was invoked 5313 if !pr.ApplyCalled { 5314 t.Fatalf("provisioner not invoked") 5315 } 5316 } 5317 5318 // Test that a destroy provisioner referencing an invalid key errors. 5319 func TestContext2Apply_provisionerDestroyRefInvalid(t *testing.T) { 5320 m := testModule(t, "apply-provisioner-destroy-ref") 5321 p := testProvider("aws") 5322 pr := testProvisioner() 5323 p.ApplyFn = testApplyFn 5324 p.DiffFn = testDiffFn 5325 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5326 return nil 5327 } 5328 5329 state := &State{ 5330 Modules: []*ModuleState{ 5331 &ModuleState{ 5332 Path: rootModulePath, 5333 Resources: map[string]*ResourceState{ 5334 "aws_instance.bar": &ResourceState{ 5335 Type: "aws_instance", 5336 Primary: &InstanceState{ 5337 ID: "bar", 5338 }, 5339 }, 5340 5341 "aws_instance.foo": &ResourceState{ 5342 Type: "aws_instance", 5343 Primary: &InstanceState{ 5344 ID: "bar", 5345 }, 5346 }, 5347 }, 5348 }, 5349 }, 5350 } 5351 5352 ctx := testContext2(t, &ContextOpts{ 5353 Module: m, 5354 State: state, 5355 Destroy: true, 5356 ProviderResolver: ResourceProviderResolverFixed( 5357 map[string]ResourceProviderFactory{ 5358 "aws": testProviderFuncFixed(p), 5359 }, 5360 ), 5361 Provisioners: map[string]ResourceProvisionerFactory{ 5362 "shell": testProvisionerFuncFixed(pr), 5363 }, 5364 }) 5365 5366 if _, err := ctx.Plan(); err != nil { 5367 t.Fatalf("err: %s", err) 5368 } 5369 5370 if _, err := ctx.Apply(); err == nil { 5371 t.Fatal("expected error") 5372 } 5373 } 5374 5375 func TestContext2Apply_provisionerResourceRef(t *testing.T) { 5376 m := testModule(t, "apply-provisioner-resource-ref") 5377 p := testProvider("aws") 5378 pr := testProvisioner() 5379 p.ApplyFn = testApplyFn 5380 p.DiffFn = testDiffFn 5381 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5382 val, ok := c.Config["foo"] 5383 if !ok || val != "2" { 5384 t.Fatalf("bad value for foo: %v %#v", val, c) 5385 } 5386 5387 return nil 5388 } 5389 5390 ctx := testContext2(t, &ContextOpts{ 5391 Module: m, 5392 ProviderResolver: ResourceProviderResolverFixed( 5393 map[string]ResourceProviderFactory{ 5394 "aws": testProviderFuncFixed(p), 5395 }, 5396 ), 5397 Provisioners: map[string]ResourceProvisionerFactory{ 5398 "shell": testProvisionerFuncFixed(pr), 5399 }, 5400 }) 5401 5402 if _, err := ctx.Plan(); err != nil { 5403 t.Fatalf("err: %s", err) 5404 } 5405 5406 state, err := ctx.Apply() 5407 if err != nil { 5408 t.Fatalf("err: %s", err) 5409 } 5410 5411 actual := strings.TrimSpace(state.String()) 5412 expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr) 5413 if actual != expected { 5414 t.Fatalf("bad: \n%s", actual) 5415 } 5416 5417 // Verify apply was invoked 5418 if !pr.ApplyCalled { 5419 t.Fatalf("provisioner not invoked") 5420 } 5421 } 5422 5423 func TestContext2Apply_provisionerSelfRef(t *testing.T) { 5424 m := testModule(t, "apply-provisioner-self-ref") 5425 p := testProvider("aws") 5426 pr := testProvisioner() 5427 p.ApplyFn = testApplyFn 5428 p.DiffFn = testDiffFn 5429 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5430 val, ok := c.Config["command"] 5431 if !ok || val != "bar" { 5432 t.Fatalf("bad value for command: %v %#v", val, c) 5433 } 5434 5435 return nil 5436 } 5437 5438 ctx := testContext2(t, &ContextOpts{ 5439 Module: m, 5440 ProviderResolver: ResourceProviderResolverFixed( 5441 map[string]ResourceProviderFactory{ 5442 "aws": testProviderFuncFixed(p), 5443 }, 5444 ), 5445 Provisioners: map[string]ResourceProvisionerFactory{ 5446 "shell": testProvisionerFuncFixed(pr), 5447 }, 5448 }) 5449 5450 if _, err := ctx.Plan(); err != nil { 5451 t.Fatalf("err: %s", err) 5452 } 5453 5454 state, err := ctx.Apply() 5455 if err != nil { 5456 t.Fatalf("err: %s", err) 5457 } 5458 5459 actual := strings.TrimSpace(state.String()) 5460 expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) 5461 if actual != expected { 5462 t.Fatalf("bad: \n%s", actual) 5463 } 5464 5465 // Verify apply was invoked 5466 if !pr.ApplyCalled { 5467 t.Fatalf("provisioner not invoked") 5468 } 5469 } 5470 5471 func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { 5472 var lock sync.Mutex 5473 commands := make([]string, 0, 5) 5474 5475 m := testModule(t, "apply-provisioner-multi-self-ref") 5476 p := testProvider("aws") 5477 pr := testProvisioner() 5478 p.ApplyFn = testApplyFn 5479 p.DiffFn = testDiffFn 5480 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5481 lock.Lock() 5482 defer lock.Unlock() 5483 5484 val, ok := c.Config["command"] 5485 if !ok { 5486 t.Fatalf("bad value for command: %v %#v", val, c) 5487 } 5488 5489 commands = append(commands, val.(string)) 5490 return nil 5491 } 5492 5493 ctx := testContext2(t, &ContextOpts{ 5494 Module: m, 5495 ProviderResolver: ResourceProviderResolverFixed( 5496 map[string]ResourceProviderFactory{ 5497 "aws": testProviderFuncFixed(p), 5498 }, 5499 ), 5500 Provisioners: map[string]ResourceProvisionerFactory{ 5501 "shell": testProvisionerFuncFixed(pr), 5502 }, 5503 }) 5504 5505 if _, err := ctx.Plan(); err != nil { 5506 t.Fatalf("err: %s", err) 5507 } 5508 5509 state, err := ctx.Apply() 5510 if err != nil { 5511 t.Fatalf("err: %s", err) 5512 } 5513 5514 actual := strings.TrimSpace(state.String()) 5515 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr) 5516 if actual != expected { 5517 t.Fatalf("bad: \n%s", actual) 5518 } 5519 5520 // Verify apply was invoked 5521 if !pr.ApplyCalled { 5522 t.Fatalf("provisioner not invoked") 5523 } 5524 5525 // Verify our result 5526 sort.Strings(commands) 5527 expectedCommands := []string{"number 0", "number 1", "number 2"} 5528 if !reflect.DeepEqual(commands, expectedCommands) { 5529 t.Fatalf("bad: %#v", commands) 5530 } 5531 } 5532 5533 func TestContext2Apply_provisionerMultiSelfRefSingle(t *testing.T) { 5534 var lock sync.Mutex 5535 order := make([]string, 0, 5) 5536 5537 m := testModule(t, "apply-provisioner-multi-self-ref-single") 5538 p := testProvider("aws") 5539 pr := testProvisioner() 5540 p.ApplyFn = testApplyFn 5541 p.DiffFn = testDiffFn 5542 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5543 lock.Lock() 5544 defer lock.Unlock() 5545 5546 val, ok := c.Config["order"] 5547 if !ok { 5548 t.Fatalf("bad value for order: %v %#v", val, c) 5549 } 5550 5551 order = append(order, val.(string)) 5552 return nil 5553 } 5554 5555 ctx := testContext2(t, &ContextOpts{ 5556 Module: m, 5557 ProviderResolver: ResourceProviderResolverFixed( 5558 map[string]ResourceProviderFactory{ 5559 "aws": testProviderFuncFixed(p), 5560 }, 5561 ), 5562 Provisioners: map[string]ResourceProvisionerFactory{ 5563 "shell": testProvisionerFuncFixed(pr), 5564 }, 5565 }) 5566 5567 if _, err := ctx.Plan(); err != nil { 5568 t.Fatalf("err: %s", err) 5569 } 5570 5571 state, err := ctx.Apply() 5572 if err != nil { 5573 t.Fatalf("err: %s", err) 5574 } 5575 5576 actual := strings.TrimSpace(state.String()) 5577 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefSingleStr) 5578 if actual != expected { 5579 t.Fatalf("bad: \n%s", actual) 5580 } 5581 5582 // Verify apply was invoked 5583 if !pr.ApplyCalled { 5584 t.Fatalf("provisioner not invoked") 5585 } 5586 5587 // Verify our result 5588 sort.Strings(order) 5589 expectedOrder := []string{"0", "1", "2"} 5590 if !reflect.DeepEqual(order, expectedOrder) { 5591 t.Fatalf("bad: %#v", order) 5592 } 5593 } 5594 5595 func TestContext2Apply_provisionerMultiSelfRefCount(t *testing.T) { 5596 var lock sync.Mutex 5597 commands := make([]string, 0, 5) 5598 5599 m := testModule(t, "apply-provisioner-multi-self-ref-count") 5600 p := testProvider("aws") 5601 pr := testProvisioner() 5602 p.ApplyFn = testApplyFn 5603 p.DiffFn = testDiffFn 5604 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5605 lock.Lock() 5606 defer lock.Unlock() 5607 5608 val, ok := c.Config["command"] 5609 if !ok { 5610 t.Fatalf("bad value for command: %v %#v", val, c) 5611 } 5612 5613 commands = append(commands, val.(string)) 5614 return nil 5615 } 5616 5617 ctx := testContext2(t, &ContextOpts{ 5618 Module: m, 5619 ProviderResolver: ResourceProviderResolverFixed( 5620 map[string]ResourceProviderFactory{ 5621 "aws": testProviderFuncFixed(p), 5622 }, 5623 ), 5624 Provisioners: map[string]ResourceProvisionerFactory{ 5625 "shell": testProvisionerFuncFixed(pr), 5626 }, 5627 }) 5628 5629 if _, err := ctx.Plan(); err != nil { 5630 t.Fatalf("err: %s", err) 5631 } 5632 5633 if _, err := ctx.Apply(); err != nil { 5634 t.Fatalf("err: %s", err) 5635 } 5636 5637 // Verify apply was invoked 5638 if !pr.ApplyCalled { 5639 t.Fatalf("provisioner not invoked") 5640 } 5641 5642 // Verify our result 5643 sort.Strings(commands) 5644 expectedCommands := []string{"3", "3", "3"} 5645 if !reflect.DeepEqual(commands, expectedCommands) { 5646 t.Fatalf("bad: %#v", commands) 5647 } 5648 } 5649 5650 func TestContext2Apply_provisionerExplicitSelfRef(t *testing.T) { 5651 m := testModule(t, "apply-provisioner-explicit-self-ref") 5652 p := testProvider("aws") 5653 pr := testProvisioner() 5654 p.ApplyFn = testApplyFn 5655 p.DiffFn = testDiffFn 5656 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5657 val, ok := c.Config["command"] 5658 if !ok || val != "bar" { 5659 t.Fatalf("bad value for command: %v %#v", val, c) 5660 } 5661 5662 return nil 5663 } 5664 5665 var state *State 5666 { 5667 ctx := testContext2(t, &ContextOpts{ 5668 Module: m, 5669 ProviderResolver: ResourceProviderResolverFixed( 5670 map[string]ResourceProviderFactory{ 5671 "aws": testProviderFuncFixed(p), 5672 }, 5673 ), 5674 Provisioners: map[string]ResourceProvisionerFactory{ 5675 "shell": testProvisionerFuncFixed(pr), 5676 }, 5677 }) 5678 5679 _, err := ctx.Plan() 5680 if err != nil { 5681 t.Fatalf("err: %s", err) 5682 } 5683 5684 state, err = ctx.Apply() 5685 if err != nil { 5686 t.Fatalf("err: %s", err) 5687 } 5688 5689 // Verify apply was invoked 5690 if !pr.ApplyCalled { 5691 t.Fatalf("provisioner not invoked") 5692 } 5693 } 5694 5695 { 5696 ctx := testContext2(t, &ContextOpts{ 5697 Module: m, 5698 Destroy: true, 5699 State: state, 5700 ProviderResolver: ResourceProviderResolverFixed( 5701 map[string]ResourceProviderFactory{ 5702 "aws": testProviderFuncFixed(p), 5703 }, 5704 ), 5705 Provisioners: map[string]ResourceProvisionerFactory{ 5706 "shell": testProvisionerFuncFixed(pr), 5707 }, 5708 }) 5709 5710 _, err := ctx.Plan() 5711 if err != nil { 5712 t.Fatalf("err: %s", err) 5713 } 5714 5715 state, err = ctx.Apply() 5716 if err != nil { 5717 t.Fatalf("err: %s", err) 5718 } 5719 5720 checkStateString(t, state, `<no state>`) 5721 } 5722 } 5723 5724 // Provisioner should NOT run on a diff, only create 5725 func TestContext2Apply_Provisioner_Diff(t *testing.T) { 5726 m := testModule(t, "apply-provisioner-diff") 5727 p := testProvider("aws") 5728 pr := testProvisioner() 5729 p.ApplyFn = testApplyFn 5730 p.DiffFn = testDiffFn 5731 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5732 return nil 5733 } 5734 ctx := testContext2(t, &ContextOpts{ 5735 Module: m, 5736 ProviderResolver: ResourceProviderResolverFixed( 5737 map[string]ResourceProviderFactory{ 5738 "aws": testProviderFuncFixed(p), 5739 }, 5740 ), 5741 Provisioners: map[string]ResourceProvisionerFactory{ 5742 "shell": testProvisionerFuncFixed(pr), 5743 }, 5744 }) 5745 5746 if _, err := ctx.Plan(); err != nil { 5747 t.Fatalf("err: %s", err) 5748 } 5749 5750 state, err := ctx.Apply() 5751 if err != nil { 5752 t.Fatalf("err: %s", err) 5753 } 5754 5755 actual := strings.TrimSpace(state.String()) 5756 expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr) 5757 if actual != expected { 5758 t.Fatalf("bad: \n%s", actual) 5759 } 5760 5761 // Verify apply was invoked 5762 if !pr.ApplyCalled { 5763 t.Fatalf("provisioner not invoked") 5764 } 5765 pr.ApplyCalled = false 5766 5767 // Change the state to force a diff 5768 mod := state.RootModule() 5769 mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz" 5770 5771 // Re-create context with state 5772 ctx = testContext2(t, &ContextOpts{ 5773 Module: m, 5774 ProviderResolver: ResourceProviderResolverFixed( 5775 map[string]ResourceProviderFactory{ 5776 "aws": testProviderFuncFixed(p), 5777 }, 5778 ), 5779 Provisioners: map[string]ResourceProvisionerFactory{ 5780 "shell": testProvisionerFuncFixed(pr), 5781 }, 5782 State: state, 5783 }) 5784 5785 if _, err := ctx.Plan(); err != nil { 5786 t.Fatalf("err: %s", err) 5787 } 5788 5789 state2, err := ctx.Apply() 5790 if err != nil { 5791 t.Fatalf("err: %s", err) 5792 } 5793 5794 actual = strings.TrimSpace(state2.String()) 5795 if actual != expected { 5796 t.Fatalf("bad: \n%s", actual) 5797 } 5798 5799 // Verify apply was NOT invoked 5800 if pr.ApplyCalled { 5801 t.Fatalf("provisioner invoked") 5802 } 5803 } 5804 5805 func TestContext2Apply_outputDiffVars(t *testing.T) { 5806 m := testModule(t, "apply-good") 5807 p := testProvider("aws") 5808 s := &State{ 5809 Modules: []*ModuleState{ 5810 &ModuleState{ 5811 Path: rootModulePath, 5812 Resources: map[string]*ResourceState{ 5813 "aws_instance.baz": &ResourceState{ 5814 Type: "aws_instance", 5815 Primary: &InstanceState{ 5816 ID: "bar", 5817 }, 5818 }, 5819 }, 5820 }, 5821 }, 5822 } 5823 ctx := testContext2(t, &ContextOpts{ 5824 Module: m, 5825 ProviderResolver: ResourceProviderResolverFixed( 5826 map[string]ResourceProviderFactory{ 5827 "aws": testProviderFuncFixed(p), 5828 }, 5829 ), 5830 State: s, 5831 }) 5832 5833 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5834 for k, ad := range d.Attributes { 5835 if ad.NewComputed { 5836 return nil, fmt.Errorf("%s: computed", k) 5837 } 5838 } 5839 5840 result := s.MergeDiff(d) 5841 result.ID = "foo" 5842 return result, nil 5843 } 5844 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5845 return &InstanceDiff{ 5846 Attributes: map[string]*ResourceAttrDiff{ 5847 "foo": &ResourceAttrDiff{ 5848 NewComputed: true, 5849 Type: DiffAttrOutput, 5850 }, 5851 "bar": &ResourceAttrDiff{ 5852 New: "baz", 5853 }, 5854 }, 5855 }, nil 5856 } 5857 5858 if _, err := ctx.Plan(); err != nil { 5859 t.Fatalf("err: %s", err) 5860 } 5861 if _, err := ctx.Apply(); err != nil { 5862 t.Fatalf("err: %s", err) 5863 } 5864 } 5865 5866 func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { 5867 m := testModule(t, "apply-provisioner-conninfo") 5868 p := testProvider("aws") 5869 pr := testProvisioner() 5870 5871 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5872 if s.Ephemeral.ConnInfo == nil { 5873 t.Fatalf("ConnInfo not initialized") 5874 } 5875 5876 result, _ := testApplyFn(info, s, d) 5877 result.Ephemeral.ConnInfo = map[string]string{ 5878 "type": "ssh", 5879 "host": "127.0.0.1", 5880 "port": "22", 5881 } 5882 return result, nil 5883 } 5884 p.DiffFn = testDiffFn 5885 5886 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5887 conn := rs.Ephemeral.ConnInfo 5888 if conn["type"] != "telnet" { 5889 t.Fatalf("Bad: %#v", conn) 5890 } 5891 if conn["host"] != "127.0.0.1" { 5892 t.Fatalf("Bad: %#v", conn) 5893 } 5894 if conn["port"] != "2222" { 5895 t.Fatalf("Bad: %#v", conn) 5896 } 5897 if conn["user"] != "superuser" { 5898 t.Fatalf("Bad: %#v", conn) 5899 } 5900 if conn["pass"] != "test" { 5901 t.Fatalf("Bad: %#v", conn) 5902 } 5903 5904 return nil 5905 } 5906 5907 ctx := testContext2(t, &ContextOpts{ 5908 Module: m, 5909 ProviderResolver: ResourceProviderResolverFixed( 5910 map[string]ResourceProviderFactory{ 5911 "aws": testProviderFuncFixed(p), 5912 }, 5913 ), 5914 Provisioners: map[string]ResourceProvisionerFactory{ 5915 "shell": testProvisionerFuncFixed(pr), 5916 }, 5917 Variables: map[string]interface{}{ 5918 "value": "1", 5919 "pass": "test", 5920 }, 5921 }) 5922 5923 if _, err := ctx.Plan(); err != nil { 5924 t.Fatalf("err: %s", err) 5925 } 5926 5927 state, err := ctx.Apply() 5928 if err != nil { 5929 t.Fatalf("err: %s", err) 5930 } 5931 5932 actual := strings.TrimSpace(state.String()) 5933 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 5934 if actual != expected { 5935 t.Fatalf("bad: \n%s", actual) 5936 } 5937 5938 // Verify apply was invoked 5939 if !pr.ApplyCalled { 5940 t.Fatalf("provisioner not invoked") 5941 } 5942 } 5943 5944 func TestContext2Apply_destroyX(t *testing.T) { 5945 m := testModule(t, "apply-destroy") 5946 h := new(HookRecordApplyOrder) 5947 p := testProvider("aws") 5948 p.ApplyFn = testApplyFn 5949 p.DiffFn = testDiffFn 5950 ctx := testContext2(t, &ContextOpts{ 5951 Module: m, 5952 Hooks: []Hook{h}, 5953 ProviderResolver: ResourceProviderResolverFixed( 5954 map[string]ResourceProviderFactory{ 5955 "aws": testProviderFuncFixed(p), 5956 }, 5957 ), 5958 }) 5959 5960 // First plan and apply a create operation 5961 if _, err := ctx.Plan(); err != nil { 5962 t.Fatalf("err: %s", err) 5963 } 5964 5965 state, err := ctx.Apply() 5966 if err != nil { 5967 t.Fatalf("err: %s", err) 5968 } 5969 5970 // Next, plan and apply a destroy operation 5971 h.Active = true 5972 ctx = testContext2(t, &ContextOpts{ 5973 Destroy: true, 5974 State: state, 5975 Module: m, 5976 Hooks: []Hook{h}, 5977 ProviderResolver: ResourceProviderResolverFixed( 5978 map[string]ResourceProviderFactory{ 5979 "aws": testProviderFuncFixed(p), 5980 }, 5981 ), 5982 }) 5983 5984 if _, err := ctx.Plan(); err != nil { 5985 t.Fatalf("err: %s", err) 5986 } 5987 5988 state, err = ctx.Apply() 5989 if err != nil { 5990 t.Fatalf("err: %s", err) 5991 } 5992 5993 // Test that things were destroyed 5994 actual := strings.TrimSpace(state.String()) 5995 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5996 if actual != expected { 5997 t.Fatalf("bad: \n%s", actual) 5998 } 5999 6000 // Test that things were destroyed _in the right order_ 6001 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 6002 actual2 := h.IDs 6003 if !reflect.DeepEqual(actual2, expected2) { 6004 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 6005 } 6006 } 6007 6008 func TestContext2Apply_destroyOrder(t *testing.T) { 6009 m := testModule(t, "apply-destroy") 6010 h := new(HookRecordApplyOrder) 6011 p := testProvider("aws") 6012 p.ApplyFn = testApplyFn 6013 p.DiffFn = testDiffFn 6014 ctx := testContext2(t, &ContextOpts{ 6015 Module: m, 6016 Hooks: []Hook{h}, 6017 ProviderResolver: ResourceProviderResolverFixed( 6018 map[string]ResourceProviderFactory{ 6019 "aws": testProviderFuncFixed(p), 6020 }, 6021 ), 6022 }) 6023 6024 // First plan and apply a create operation 6025 if _, err := ctx.Plan(); err != nil { 6026 t.Fatalf("err: %s", err) 6027 } 6028 6029 state, err := ctx.Apply() 6030 if err != nil { 6031 t.Fatalf("err: %s", err) 6032 } 6033 6034 t.Logf("State 1: %s", state) 6035 6036 // Next, plan and apply a destroy 6037 h.Active = true 6038 ctx = testContext2(t, &ContextOpts{ 6039 Destroy: true, 6040 State: state, 6041 Module: m, 6042 Hooks: []Hook{h}, 6043 ProviderResolver: ResourceProviderResolverFixed( 6044 map[string]ResourceProviderFactory{ 6045 "aws": testProviderFuncFixed(p), 6046 }, 6047 ), 6048 }) 6049 6050 if _, err := ctx.Plan(); err != nil { 6051 t.Fatalf("err: %s", err) 6052 } 6053 6054 state, err = ctx.Apply() 6055 if err != nil { 6056 t.Fatalf("err: %s", err) 6057 } 6058 6059 // Test that things were destroyed 6060 actual := strings.TrimSpace(state.String()) 6061 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 6062 if actual != expected { 6063 t.Fatalf("bad: \n%s", actual) 6064 } 6065 6066 // Test that things were destroyed _in the right order_ 6067 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 6068 actual2 := h.IDs 6069 if !reflect.DeepEqual(actual2, expected2) { 6070 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 6071 } 6072 } 6073 6074 // https://github.com/hashicorp/terraform/issues/2767 6075 func TestContext2Apply_destroyModulePrefix(t *testing.T) { 6076 m := testModule(t, "apply-destroy-module-resource-prefix") 6077 h := new(MockHook) 6078 p := testProvider("aws") 6079 p.ApplyFn = testApplyFn 6080 p.DiffFn = testDiffFn 6081 ctx := testContext2(t, &ContextOpts{ 6082 Module: m, 6083 Hooks: []Hook{h}, 6084 ProviderResolver: ResourceProviderResolverFixed( 6085 map[string]ResourceProviderFactory{ 6086 "aws": testProviderFuncFixed(p), 6087 }, 6088 ), 6089 }) 6090 6091 // First plan and apply a create operation 6092 if _, err := ctx.Plan(); err != nil { 6093 t.Fatalf("err: %s", err) 6094 } 6095 6096 state, err := ctx.Apply() 6097 if err != nil { 6098 t.Fatalf("err: %s", err) 6099 } 6100 6101 // Verify that we got the apply info correct 6102 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 6103 t.Fatalf("bad: %s", v) 6104 } 6105 6106 // Next, plan and apply a destroy operation and reset the hook 6107 h = new(MockHook) 6108 ctx = testContext2(t, &ContextOpts{ 6109 Destroy: true, 6110 State: state, 6111 Module: m, 6112 Hooks: []Hook{h}, 6113 ProviderResolver: ResourceProviderResolverFixed( 6114 map[string]ResourceProviderFactory{ 6115 "aws": testProviderFuncFixed(p), 6116 }, 6117 ), 6118 }) 6119 6120 if _, err := ctx.Plan(); err != nil { 6121 t.Fatalf("err: %s", err) 6122 } 6123 6124 state, err = ctx.Apply() 6125 if err != nil { 6126 t.Fatalf("err: %s", err) 6127 } 6128 6129 // Test that things were destroyed 6130 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 6131 t.Fatalf("bad: %s", v) 6132 } 6133 } 6134 6135 func TestContext2Apply_destroyNestedModule(t *testing.T) { 6136 m := testModule(t, "apply-destroy-nested-module") 6137 p := testProvider("aws") 6138 p.ApplyFn = testApplyFn 6139 p.DiffFn = testDiffFn 6140 6141 s := &State{ 6142 Modules: []*ModuleState{ 6143 &ModuleState{ 6144 Path: []string{"root", "child", "subchild"}, 6145 Resources: map[string]*ResourceState{ 6146 "aws_instance.bar": &ResourceState{ 6147 Type: "aws_instance", 6148 Primary: &InstanceState{ 6149 ID: "bar", 6150 }, 6151 }, 6152 }, 6153 }, 6154 }, 6155 } 6156 6157 ctx := testContext2(t, &ContextOpts{ 6158 Module: m, 6159 ProviderResolver: ResourceProviderResolverFixed( 6160 map[string]ResourceProviderFactory{ 6161 "aws": testProviderFuncFixed(p), 6162 }, 6163 ), 6164 State: s, 6165 }) 6166 6167 // First plan and apply a create operation 6168 if _, err := ctx.Plan(); err != nil { 6169 t.Fatalf("err: %s", err) 6170 } 6171 6172 state, err := ctx.Apply() 6173 if err != nil { 6174 t.Fatalf("err: %s", err) 6175 } 6176 6177 // Test that things were destroyed 6178 actual := strings.TrimSpace(state.String()) 6179 if actual != "" { 6180 t.Fatalf("expected no state, got: %s", actual) 6181 } 6182 } 6183 6184 func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) { 6185 m := testModule(t, "apply-destroy-deeply-nested-module") 6186 p := testProvider("aws") 6187 p.ApplyFn = testApplyFn 6188 p.DiffFn = testDiffFn 6189 6190 s := &State{ 6191 Modules: []*ModuleState{ 6192 &ModuleState{ 6193 Path: []string{"root", "child", "subchild", "subsubchild"}, 6194 Resources: map[string]*ResourceState{ 6195 "aws_instance.bar": &ResourceState{ 6196 Type: "aws_instance", 6197 Primary: &InstanceState{ 6198 ID: "bar", 6199 }, 6200 }, 6201 }, 6202 }, 6203 }, 6204 } 6205 6206 ctx := testContext2(t, &ContextOpts{ 6207 Module: m, 6208 ProviderResolver: ResourceProviderResolverFixed( 6209 map[string]ResourceProviderFactory{ 6210 "aws": testProviderFuncFixed(p), 6211 }, 6212 ), 6213 State: s, 6214 }) 6215 6216 // First plan and apply a create operation 6217 if _, err := ctx.Plan(); err != nil { 6218 t.Fatalf("err: %s", err) 6219 } 6220 6221 state, err := ctx.Apply() 6222 if err != nil { 6223 t.Fatalf("err: %s", err) 6224 } 6225 6226 // Test that things were destroyed 6227 actual := strings.TrimSpace(state.String()) 6228 if actual != "" { 6229 t.Fatalf("epected no state, got: %s", actual) 6230 } 6231 } 6232 6233 // https://github.com/hashicorp/terraform/issues/5440 6234 func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) { 6235 m := testModule(t, "apply-destroy-module-with-attrs") 6236 p := testProvider("aws") 6237 p.ApplyFn = testApplyFn 6238 p.DiffFn = testDiffFn 6239 6240 var state *State 6241 var err error 6242 { 6243 ctx := testContext2(t, &ContextOpts{ 6244 Module: m, 6245 ProviderResolver: ResourceProviderResolverFixed( 6246 map[string]ResourceProviderFactory{ 6247 "aws": testProviderFuncFixed(p), 6248 }, 6249 ), 6250 }) 6251 6252 // First plan and apply a create operation 6253 if p, err := ctx.Plan(); err != nil { 6254 t.Fatalf("plan err: %s", err) 6255 } else { 6256 t.Logf("Step 1 plan: %s", p) 6257 } 6258 6259 state, err = ctx.Apply() 6260 if err != nil { 6261 t.Fatalf("apply err: %s", err) 6262 } 6263 6264 t.Logf("Step 1 state: %s", state) 6265 } 6266 6267 h := new(HookRecordApplyOrder) 6268 h.Active = true 6269 6270 { 6271 ctx := testContext2(t, &ContextOpts{ 6272 Destroy: true, 6273 Module: m, 6274 State: state, 6275 Hooks: []Hook{h}, 6276 ProviderResolver: ResourceProviderResolverFixed( 6277 map[string]ResourceProviderFactory{ 6278 "aws": testProviderFuncFixed(p), 6279 }, 6280 ), 6281 Variables: map[string]interface{}{ 6282 "key_name": "foobarkey", 6283 }, 6284 }) 6285 6286 // First plan and apply a create operation 6287 plan, err := ctx.Plan() 6288 if err != nil { 6289 t.Fatalf("destroy plan err: %s", err) 6290 } 6291 6292 t.Logf("Step 2 plan: %s", plan) 6293 6294 var buf bytes.Buffer 6295 if err := WritePlan(plan, &buf); err != nil { 6296 t.Fatalf("plan write err: %s", err) 6297 } 6298 6299 planFromFile, err := ReadPlan(&buf) 6300 if err != nil { 6301 t.Fatalf("plan read err: %s", err) 6302 } 6303 6304 ctx, err = planFromFile.Context(&ContextOpts{ 6305 ProviderResolver: ResourceProviderResolverFixed( 6306 map[string]ResourceProviderFactory{ 6307 "aws": testProviderFuncFixed(p), 6308 }, 6309 ), 6310 }) 6311 if err != nil { 6312 t.Fatalf("err: %s", err) 6313 } 6314 6315 state, err = ctx.Apply() 6316 if err != nil { 6317 t.Fatalf("destroy apply err: %s", err) 6318 } 6319 6320 t.Logf("Step 2 state: %s", state) 6321 } 6322 6323 //Test that things were destroyed 6324 actual := strings.TrimSpace(state.String()) 6325 expected := strings.TrimSpace(` 6326 <no state> 6327 module.child: 6328 <no state> 6329 `) 6330 if actual != expected { 6331 t.Fatalf("expected:\n\n%s\n\nactual:\n\n%s", expected, actual) 6332 } 6333 } 6334 6335 func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) { 6336 m := testModule(t, "apply-destroy-mod-var-and-count") 6337 p := testProvider("aws") 6338 p.ApplyFn = testApplyFn 6339 p.DiffFn = testDiffFn 6340 6341 var state *State 6342 var err error 6343 { 6344 ctx := testContext2(t, &ContextOpts{ 6345 Module: m, 6346 ProviderResolver: ResourceProviderResolverFixed( 6347 map[string]ResourceProviderFactory{ 6348 "aws": testProviderFuncFixed(p), 6349 }, 6350 ), 6351 }) 6352 6353 // First plan and apply a create operation 6354 if _, err := ctx.Plan(); err != nil { 6355 t.Fatalf("plan err: %s", err) 6356 } 6357 6358 state, err = ctx.Apply() 6359 if err != nil { 6360 t.Fatalf("apply err: %s", err) 6361 } 6362 } 6363 6364 h := new(HookRecordApplyOrder) 6365 h.Active = true 6366 6367 { 6368 ctx := testContext2(t, &ContextOpts{ 6369 Destroy: true, 6370 Module: m, 6371 State: state, 6372 Hooks: []Hook{h}, 6373 ProviderResolver: ResourceProviderResolverFixed( 6374 map[string]ResourceProviderFactory{ 6375 "aws": testProviderFuncFixed(p), 6376 }, 6377 ), 6378 }) 6379 6380 // First plan and apply a create operation 6381 plan, err := ctx.Plan() 6382 if err != nil { 6383 t.Fatalf("destroy plan err: %s", err) 6384 } 6385 6386 var buf bytes.Buffer 6387 if err := WritePlan(plan, &buf); err != nil { 6388 t.Fatalf("plan write err: %s", err) 6389 } 6390 6391 planFromFile, err := ReadPlan(&buf) 6392 if err != nil { 6393 t.Fatalf("plan read err: %s", err) 6394 } 6395 6396 ctx, err = planFromFile.Context(&ContextOpts{ 6397 ProviderResolver: ResourceProviderResolverFixed( 6398 map[string]ResourceProviderFactory{ 6399 "aws": testProviderFuncFixed(p), 6400 }, 6401 ), 6402 }) 6403 if err != nil { 6404 t.Fatalf("err: %s", err) 6405 } 6406 6407 state, err = ctx.Apply() 6408 if err != nil { 6409 t.Fatalf("destroy apply err: %s", err) 6410 } 6411 } 6412 6413 //Test that things were destroyed 6414 actual := strings.TrimSpace(state.String()) 6415 expected := strings.TrimSpace(` 6416 <no state> 6417 module.child: 6418 <no state> 6419 `) 6420 if actual != expected { 6421 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 6422 } 6423 } 6424 6425 func TestContext2Apply_destroyTargetWithModuleVariableAndCount(t *testing.T) { 6426 m := testModule(t, "apply-destroy-mod-var-and-count") 6427 p := testProvider("aws") 6428 p.ApplyFn = testApplyFn 6429 p.DiffFn = testDiffFn 6430 6431 var state *State 6432 var err error 6433 { 6434 ctx := testContext2(t, &ContextOpts{ 6435 Module: m, 6436 ProviderResolver: ResourceProviderResolverFixed( 6437 map[string]ResourceProviderFactory{ 6438 "aws": testProviderFuncFixed(p), 6439 }, 6440 ), 6441 }) 6442 6443 // First plan and apply a create operation 6444 if _, err := ctx.Plan(); err != nil { 6445 t.Fatalf("plan err: %s", err) 6446 } 6447 6448 state, err = ctx.Apply() 6449 if err != nil { 6450 t.Fatalf("apply err: %s", err) 6451 } 6452 } 6453 6454 { 6455 ctx := testContext2(t, &ContextOpts{ 6456 Destroy: true, 6457 Module: m, 6458 State: state, 6459 ProviderResolver: ResourceProviderResolverFixed( 6460 map[string]ResourceProviderFactory{ 6461 "aws": testProviderFuncFixed(p), 6462 }, 6463 ), 6464 Targets: []string{"module.child"}, 6465 }) 6466 6467 _, err := ctx.Plan() 6468 if err != nil { 6469 t.Fatalf("plan err: %s", err) 6470 } 6471 6472 // Destroy, targeting the module explicitly 6473 state, err = ctx.Apply() 6474 if err != nil { 6475 t.Fatalf("destroy apply err: %s", err) 6476 } 6477 } 6478 6479 //Test that things were destroyed 6480 actual := strings.TrimSpace(state.String()) 6481 expected := strings.TrimSpace(` 6482 <no state> 6483 module.child: 6484 <no state> 6485 `) 6486 if actual != expected { 6487 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 6488 } 6489 } 6490 6491 func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) { 6492 m := testModule(t, "apply-destroy-mod-var-and-count-nested") 6493 p := testProvider("aws") 6494 p.ApplyFn = testApplyFn 6495 p.DiffFn = testDiffFn 6496 6497 var state *State 6498 var err error 6499 { 6500 ctx := testContext2(t, &ContextOpts{ 6501 Module: m, 6502 ProviderResolver: ResourceProviderResolverFixed( 6503 map[string]ResourceProviderFactory{ 6504 "aws": testProviderFuncFixed(p), 6505 }, 6506 ), 6507 }) 6508 6509 // First plan and apply a create operation 6510 if _, err := ctx.Plan(); err != nil { 6511 t.Fatalf("plan err: %s", err) 6512 } 6513 6514 state, err = ctx.Apply() 6515 if err != nil { 6516 t.Fatalf("apply err: %s", err) 6517 } 6518 } 6519 6520 h := new(HookRecordApplyOrder) 6521 h.Active = true 6522 6523 { 6524 ctx := testContext2(t, &ContextOpts{ 6525 Destroy: true, 6526 Module: m, 6527 State: state, 6528 Hooks: []Hook{h}, 6529 ProviderResolver: ResourceProviderResolverFixed( 6530 map[string]ResourceProviderFactory{ 6531 "aws": testProviderFuncFixed(p), 6532 }, 6533 ), 6534 }) 6535 6536 // First plan and apply a create operation 6537 plan, err := ctx.Plan() 6538 if err != nil { 6539 t.Fatalf("destroy plan err: %s", err) 6540 } 6541 6542 var buf bytes.Buffer 6543 if err := WritePlan(plan, &buf); err != nil { 6544 t.Fatalf("plan write err: %s", err) 6545 } 6546 6547 planFromFile, err := ReadPlan(&buf) 6548 if err != nil { 6549 t.Fatalf("plan read err: %s", err) 6550 } 6551 6552 ctx, err = planFromFile.Context(&ContextOpts{ 6553 ProviderResolver: ResourceProviderResolverFixed( 6554 map[string]ResourceProviderFactory{ 6555 "aws": testProviderFuncFixed(p), 6556 }, 6557 ), 6558 }) 6559 if err != nil { 6560 t.Fatalf("err: %s", err) 6561 } 6562 6563 state, err = ctx.Apply() 6564 if err != nil { 6565 t.Fatalf("destroy apply err: %s", err) 6566 } 6567 } 6568 6569 //Test that things were destroyed 6570 actual := strings.TrimSpace(state.String()) 6571 expected := strings.TrimSpace(` 6572 <no state> 6573 module.child: 6574 <no state> 6575 module.child.child2: 6576 <no state> 6577 `) 6578 if actual != expected { 6579 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 6580 } 6581 } 6582 6583 func TestContext2Apply_destroyOutputs(t *testing.T) { 6584 m := testModule(t, "apply-destroy-outputs") 6585 h := new(HookRecordApplyOrder) 6586 p := testProvider("aws") 6587 p.ApplyFn = testApplyFn 6588 p.DiffFn = testDiffFn 6589 ctx := testContext2(t, &ContextOpts{ 6590 Module: m, 6591 Hooks: []Hook{h}, 6592 ProviderResolver: ResourceProviderResolverFixed( 6593 map[string]ResourceProviderFactory{ 6594 "aws": testProviderFuncFixed(p), 6595 }, 6596 ), 6597 }) 6598 6599 // First plan and apply a create operation 6600 if _, err := ctx.Plan(); err != nil { 6601 t.Fatalf("err: %s", err) 6602 } 6603 6604 state, err := ctx.Apply() 6605 6606 if err != nil { 6607 t.Fatalf("err: %s", err) 6608 } 6609 6610 // Next, plan and apply a destroy operation 6611 h.Active = true 6612 ctx = testContext2(t, &ContextOpts{ 6613 Destroy: true, 6614 State: state, 6615 Module: m, 6616 Hooks: []Hook{h}, 6617 ProviderResolver: ResourceProviderResolverFixed( 6618 map[string]ResourceProviderFactory{ 6619 "aws": testProviderFuncFixed(p), 6620 }, 6621 ), 6622 }) 6623 6624 if _, err := ctx.Plan(); err != nil { 6625 t.Fatalf("err: %s", err) 6626 } 6627 6628 state, err = ctx.Apply() 6629 if err != nil { 6630 t.Fatalf("err: %s", err) 6631 } 6632 6633 mod := state.RootModule() 6634 if len(mod.Resources) > 0 { 6635 t.Fatalf("bad: %#v", mod) 6636 } 6637 } 6638 6639 func TestContext2Apply_destroyOrphan(t *testing.T) { 6640 m := testModule(t, "apply-error") 6641 p := testProvider("aws") 6642 s := &State{ 6643 Modules: []*ModuleState{ 6644 &ModuleState{ 6645 Path: rootModulePath, 6646 Resources: map[string]*ResourceState{ 6647 "aws_instance.baz": &ResourceState{ 6648 Type: "aws_instance", 6649 Primary: &InstanceState{ 6650 ID: "bar", 6651 }, 6652 }, 6653 }, 6654 }, 6655 }, 6656 } 6657 ctx := testContext2(t, &ContextOpts{ 6658 Module: m, 6659 ProviderResolver: ResourceProviderResolverFixed( 6660 map[string]ResourceProviderFactory{ 6661 "aws": testProviderFuncFixed(p), 6662 }, 6663 ), 6664 State: s, 6665 }) 6666 6667 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6668 if d.Destroy { 6669 return nil, nil 6670 } 6671 6672 result := s.MergeDiff(d) 6673 result.ID = "foo" 6674 return result, nil 6675 } 6676 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6677 return &InstanceDiff{ 6678 Attributes: map[string]*ResourceAttrDiff{ 6679 "num": &ResourceAttrDiff{ 6680 New: "bar", 6681 }, 6682 }, 6683 }, nil 6684 } 6685 6686 if _, err := ctx.Plan(); err != nil { 6687 t.Fatalf("err: %s", err) 6688 } 6689 6690 state, err := ctx.Apply() 6691 if err != nil { 6692 t.Fatalf("err: %s", err) 6693 } 6694 6695 mod := state.RootModule() 6696 if _, ok := mod.Resources["aws_instance.baz"]; ok { 6697 t.Fatalf("bad: %#v", mod.Resources) 6698 } 6699 } 6700 6701 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 6702 m := testModule(t, "apply-destroy-provisioner") 6703 p := testProvider("aws") 6704 pr := testProvisioner() 6705 p.ApplyFn = testApplyFn 6706 p.DiffFn = testDiffFn 6707 6708 called := false 6709 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 6710 called = true 6711 return nil 6712 } 6713 6714 s := &State{ 6715 Modules: []*ModuleState{ 6716 &ModuleState{ 6717 Path: rootModulePath, 6718 Resources: map[string]*ResourceState{ 6719 "aws_instance.foo": &ResourceState{ 6720 Type: "aws_instance", 6721 Primary: &InstanceState{ 6722 ID: "bar", 6723 Attributes: map[string]string{ 6724 "id": "bar", 6725 }, 6726 Tainted: true, 6727 }, 6728 }, 6729 }, 6730 }, 6731 }, 6732 } 6733 6734 ctx := testContext2(t, &ContextOpts{ 6735 Module: m, 6736 ProviderResolver: ResourceProviderResolverFixed( 6737 map[string]ResourceProviderFactory{ 6738 "aws": testProviderFuncFixed(p), 6739 }, 6740 ), 6741 Provisioners: map[string]ResourceProvisionerFactory{ 6742 "shell": testProvisionerFuncFixed(pr), 6743 }, 6744 State: s, 6745 Destroy: true, 6746 }) 6747 6748 if _, err := ctx.Plan(); err != nil { 6749 t.Fatalf("err: %s", err) 6750 } 6751 6752 state, err := ctx.Apply() 6753 if err != nil { 6754 t.Fatalf("err: %s", err) 6755 } 6756 6757 if called { 6758 t.Fatal("provisioner should not be called") 6759 } 6760 6761 actual := strings.TrimSpace(state.String()) 6762 expected := strings.TrimSpace("<no state>") 6763 if actual != expected { 6764 t.Fatalf("bad: \n%s", actual) 6765 } 6766 } 6767 6768 func TestContext2Apply_error(t *testing.T) { 6769 errored := false 6770 6771 m := testModule(t, "apply-error") 6772 p := testProvider("aws") 6773 ctx := testContext2(t, &ContextOpts{ 6774 Module: m, 6775 ProviderResolver: ResourceProviderResolverFixed( 6776 map[string]ResourceProviderFactory{ 6777 "aws": testProviderFuncFixed(p), 6778 }, 6779 ), 6780 }) 6781 6782 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 6783 if errored { 6784 state := &InstanceState{ 6785 ID: "bar", 6786 } 6787 return state, fmt.Errorf("error") 6788 } 6789 errored = true 6790 6791 return &InstanceState{ 6792 ID: "foo", 6793 Attributes: map[string]string{ 6794 "num": "2", 6795 }, 6796 }, nil 6797 } 6798 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6799 return &InstanceDiff{ 6800 Attributes: map[string]*ResourceAttrDiff{ 6801 "num": &ResourceAttrDiff{ 6802 New: "bar", 6803 }, 6804 }, 6805 }, nil 6806 } 6807 6808 if _, err := ctx.Plan(); err != nil { 6809 t.Fatalf("err: %s", err) 6810 } 6811 6812 state, err := ctx.Apply() 6813 if err == nil { 6814 t.Fatal("should have error") 6815 } 6816 6817 actual := strings.TrimSpace(state.String()) 6818 expected := strings.TrimSpace(testTerraformApplyErrorStr) 6819 if actual != expected { 6820 t.Fatalf("bad: \n%s", actual) 6821 } 6822 } 6823 6824 func TestContext2Apply_errorPartial(t *testing.T) { 6825 errored := false 6826 6827 m := testModule(t, "apply-error") 6828 p := testProvider("aws") 6829 s := &State{ 6830 Modules: []*ModuleState{ 6831 &ModuleState{ 6832 Path: rootModulePath, 6833 Resources: map[string]*ResourceState{ 6834 "aws_instance.bar": &ResourceState{ 6835 Type: "aws_instance", 6836 Primary: &InstanceState{ 6837 ID: "bar", 6838 }, 6839 }, 6840 }, 6841 }, 6842 }, 6843 } 6844 ctx := testContext2(t, &ContextOpts{ 6845 Module: m, 6846 ProviderResolver: ResourceProviderResolverFixed( 6847 map[string]ResourceProviderFactory{ 6848 "aws": testProviderFuncFixed(p), 6849 }, 6850 ), 6851 State: s, 6852 }) 6853 6854 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6855 if errored { 6856 return s, fmt.Errorf("error") 6857 } 6858 errored = true 6859 6860 return &InstanceState{ 6861 ID: "foo", 6862 Attributes: map[string]string{ 6863 "num": "2", 6864 }, 6865 }, nil 6866 } 6867 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6868 return &InstanceDiff{ 6869 Attributes: map[string]*ResourceAttrDiff{ 6870 "num": &ResourceAttrDiff{ 6871 New: "bar", 6872 }, 6873 }, 6874 }, nil 6875 } 6876 6877 if _, err := ctx.Plan(); err != nil { 6878 t.Fatalf("err: %s", err) 6879 } 6880 6881 state, err := ctx.Apply() 6882 if err == nil { 6883 t.Fatal("should have error") 6884 } 6885 6886 mod := state.RootModule() 6887 if len(mod.Resources) != 2 { 6888 t.Fatalf("bad: %#v", mod.Resources) 6889 } 6890 6891 actual := strings.TrimSpace(state.String()) 6892 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 6893 if actual != expected { 6894 t.Fatalf("bad: \n%s", actual) 6895 } 6896 } 6897 6898 func TestContext2Apply_hook(t *testing.T) { 6899 m := testModule(t, "apply-good") 6900 h := new(MockHook) 6901 p := testProvider("aws") 6902 p.ApplyFn = testApplyFn 6903 p.DiffFn = testDiffFn 6904 ctx := testContext2(t, &ContextOpts{ 6905 Module: m, 6906 Hooks: []Hook{h}, 6907 ProviderResolver: ResourceProviderResolverFixed( 6908 map[string]ResourceProviderFactory{ 6909 "aws": testProviderFuncFixed(p), 6910 }, 6911 ), 6912 }) 6913 6914 if _, err := ctx.Plan(); err != nil { 6915 t.Fatalf("err: %s", err) 6916 } 6917 6918 if _, err := ctx.Apply(); err != nil { 6919 t.Fatalf("err: %s", err) 6920 } 6921 6922 if !h.PreApplyCalled { 6923 t.Fatal("should be called") 6924 } 6925 if !h.PostApplyCalled { 6926 t.Fatal("should be called") 6927 } 6928 if !h.PostStateUpdateCalled { 6929 t.Fatalf("should call post state update") 6930 } 6931 } 6932 6933 func TestContext2Apply_hookOrphan(t *testing.T) { 6934 m := testModule(t, "apply-blank") 6935 h := new(MockHook) 6936 p := testProvider("aws") 6937 p.ApplyFn = testApplyFn 6938 p.DiffFn = testDiffFn 6939 6940 state := &State{ 6941 Modules: []*ModuleState{ 6942 &ModuleState{ 6943 Path: rootModulePath, 6944 Resources: map[string]*ResourceState{ 6945 "aws_instance.bar": &ResourceState{ 6946 Type: "aws_instance", 6947 Primary: &InstanceState{ 6948 ID: "bar", 6949 }, 6950 }, 6951 }, 6952 }, 6953 }, 6954 } 6955 6956 ctx := testContext2(t, &ContextOpts{ 6957 Module: m, 6958 State: state, 6959 Hooks: []Hook{h}, 6960 ProviderResolver: ResourceProviderResolverFixed( 6961 map[string]ResourceProviderFactory{ 6962 "aws": testProviderFuncFixed(p), 6963 }, 6964 ), 6965 }) 6966 6967 if _, err := ctx.Plan(); err != nil { 6968 t.Fatalf("err: %s", err) 6969 } 6970 6971 if _, err := ctx.Apply(); err != nil { 6972 t.Fatalf("err: %s", err) 6973 } 6974 6975 if !h.PreApplyCalled { 6976 t.Fatal("should be called") 6977 } 6978 if !h.PostApplyCalled { 6979 t.Fatal("should be called") 6980 } 6981 if !h.PostStateUpdateCalled { 6982 t.Fatalf("should call post state update") 6983 } 6984 } 6985 6986 func TestContext2Apply_idAttr(t *testing.T) { 6987 m := testModule(t, "apply-idattr") 6988 p := testProvider("aws") 6989 ctx := testContext2(t, &ContextOpts{ 6990 Module: m, 6991 ProviderResolver: ResourceProviderResolverFixed( 6992 map[string]ResourceProviderFactory{ 6993 "aws": testProviderFuncFixed(p), 6994 }, 6995 ), 6996 }) 6997 6998 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6999 result := s.MergeDiff(d) 7000 result.ID = "foo" 7001 result.Attributes = map[string]string{ 7002 "id": "bar", 7003 } 7004 7005 return result, nil 7006 } 7007 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 7008 return &InstanceDiff{ 7009 Attributes: map[string]*ResourceAttrDiff{ 7010 "num": &ResourceAttrDiff{ 7011 New: "bar", 7012 }, 7013 }, 7014 }, nil 7015 } 7016 7017 if _, err := ctx.Plan(); err != nil { 7018 t.Fatalf("err: %s", err) 7019 } 7020 7021 state, err := ctx.Apply() 7022 if err != nil { 7023 t.Fatalf("err: %s", err) 7024 } 7025 7026 mod := state.RootModule() 7027 rs, ok := mod.Resources["aws_instance.foo"] 7028 if !ok { 7029 t.Fatal("not in state") 7030 } 7031 if rs.Primary.ID != "foo" { 7032 t.Fatalf("bad: %#v", rs.Primary.ID) 7033 } 7034 if rs.Primary.Attributes["id"] != "foo" { 7035 t.Fatalf("bad: %#v", rs.Primary.Attributes) 7036 } 7037 } 7038 7039 func TestContext2Apply_outputBasic(t *testing.T) { 7040 m := testModule(t, "apply-output") 7041 p := testProvider("aws") 7042 p.ApplyFn = testApplyFn 7043 p.DiffFn = testDiffFn 7044 ctx := testContext2(t, &ContextOpts{ 7045 Module: m, 7046 ProviderResolver: ResourceProviderResolverFixed( 7047 map[string]ResourceProviderFactory{ 7048 "aws": testProviderFuncFixed(p), 7049 }, 7050 ), 7051 }) 7052 7053 if _, err := ctx.Plan(); err != nil { 7054 t.Fatalf("err: %s", err) 7055 } 7056 7057 state, err := ctx.Apply() 7058 if err != nil { 7059 t.Fatalf("err: %s", err) 7060 } 7061 7062 actual := strings.TrimSpace(state.String()) 7063 expected := strings.TrimSpace(testTerraformApplyOutputStr) 7064 if actual != expected { 7065 t.Fatalf("bad: \n%s", actual) 7066 } 7067 } 7068 7069 func TestContext2Apply_outputInvalid(t *testing.T) { 7070 m := testModule(t, "apply-output-invalid") 7071 p := testProvider("aws") 7072 p.ApplyFn = testApplyFn 7073 p.DiffFn = testDiffFn 7074 ctx := testContext2(t, &ContextOpts{ 7075 Module: m, 7076 ProviderResolver: ResourceProviderResolverFixed( 7077 map[string]ResourceProviderFactory{ 7078 "aws": testProviderFuncFixed(p), 7079 }, 7080 ), 7081 }) 7082 7083 _, err := ctx.Plan() 7084 if err == nil { 7085 t.Fatalf("err: %s", err) 7086 } 7087 if !strings.Contains(err.Error(), "is not a valid type") { 7088 t.Fatalf("err: %s", err) 7089 } 7090 } 7091 7092 func TestContext2Apply_outputAdd(t *testing.T) { 7093 m1 := testModule(t, "apply-output-add-before") 7094 p1 := testProvider("aws") 7095 p1.ApplyFn = testApplyFn 7096 p1.DiffFn = testDiffFn 7097 ctx1 := testContext2(t, &ContextOpts{ 7098 Module: m1, 7099 ProviderResolver: ResourceProviderResolverFixed( 7100 map[string]ResourceProviderFactory{ 7101 "aws": testProviderFuncFixed(p1), 7102 }, 7103 ), 7104 }) 7105 7106 if _, err := ctx1.Plan(); err != nil { 7107 t.Fatalf("err: %s", err) 7108 } 7109 7110 state1, err := ctx1.Apply() 7111 if err != nil { 7112 t.Fatalf("err: %s", err) 7113 } 7114 7115 m2 := testModule(t, "apply-output-add-after") 7116 p2 := testProvider("aws") 7117 p2.ApplyFn = testApplyFn 7118 p2.DiffFn = testDiffFn 7119 ctx2 := testContext2(t, &ContextOpts{ 7120 Module: m2, 7121 ProviderResolver: ResourceProviderResolverFixed( 7122 map[string]ResourceProviderFactory{ 7123 "aws": testProviderFuncFixed(p2), 7124 }, 7125 ), 7126 State: state1, 7127 }) 7128 7129 if _, err := ctx2.Plan(); err != nil { 7130 t.Fatalf("err: %s", err) 7131 } 7132 7133 state2, err := ctx2.Apply() 7134 if err != nil { 7135 t.Fatalf("err: %s", err) 7136 } 7137 7138 actual := strings.TrimSpace(state2.String()) 7139 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 7140 if actual != expected { 7141 t.Fatalf("bad: \n%s", actual) 7142 } 7143 } 7144 7145 func TestContext2Apply_outputList(t *testing.T) { 7146 m := testModule(t, "apply-output-list") 7147 p := testProvider("aws") 7148 p.ApplyFn = testApplyFn 7149 p.DiffFn = testDiffFn 7150 ctx := testContext2(t, &ContextOpts{ 7151 Module: m, 7152 ProviderResolver: ResourceProviderResolverFixed( 7153 map[string]ResourceProviderFactory{ 7154 "aws": testProviderFuncFixed(p), 7155 }, 7156 ), 7157 }) 7158 7159 if _, err := ctx.Plan(); err != nil { 7160 t.Fatalf("err: %s", err) 7161 } 7162 7163 state, err := ctx.Apply() 7164 if err != nil { 7165 t.Fatalf("err: %s", err) 7166 } 7167 7168 actual := strings.TrimSpace(state.String()) 7169 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 7170 if actual != expected { 7171 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 7172 } 7173 } 7174 7175 func TestContext2Apply_outputMulti(t *testing.T) { 7176 m := testModule(t, "apply-output-multi") 7177 p := testProvider("aws") 7178 p.ApplyFn = testApplyFn 7179 p.DiffFn = testDiffFn 7180 ctx := testContext2(t, &ContextOpts{ 7181 Module: m, 7182 ProviderResolver: ResourceProviderResolverFixed( 7183 map[string]ResourceProviderFactory{ 7184 "aws": testProviderFuncFixed(p), 7185 }, 7186 ), 7187 }) 7188 7189 if _, err := ctx.Plan(); err != nil { 7190 t.Fatalf("err: %s", err) 7191 } 7192 7193 state, err := ctx.Apply() 7194 if err != nil { 7195 t.Fatalf("err: %s", err) 7196 } 7197 7198 actual := strings.TrimSpace(state.String()) 7199 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 7200 if actual != expected { 7201 t.Fatalf("bad: \n%s", actual) 7202 } 7203 } 7204 7205 func TestContext2Apply_outputMultiIndex(t *testing.T) { 7206 m := testModule(t, "apply-output-multi-index") 7207 p := testProvider("aws") 7208 p.ApplyFn = testApplyFn 7209 p.DiffFn = testDiffFn 7210 ctx := testContext2(t, &ContextOpts{ 7211 Module: m, 7212 ProviderResolver: ResourceProviderResolverFixed( 7213 map[string]ResourceProviderFactory{ 7214 "aws": testProviderFuncFixed(p), 7215 }, 7216 ), 7217 }) 7218 7219 if _, err := ctx.Plan(); err != nil { 7220 t.Fatalf("err: %s", err) 7221 } 7222 7223 state, err := ctx.Apply() 7224 if err != nil { 7225 t.Fatalf("err: %s", err) 7226 } 7227 7228 actual := strings.TrimSpace(state.String()) 7229 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 7230 if actual != expected { 7231 t.Fatalf("bad: \n%s", actual) 7232 } 7233 } 7234 7235 func TestContext2Apply_taintX(t *testing.T) { 7236 m := testModule(t, "apply-taint") 7237 p := testProvider("aws") 7238 7239 // destroyCount tests against regression of 7240 // https://github.com/hashicorp/terraform/issues/1056 7241 var destroyCount = int32(0) 7242 var once sync.Once 7243 simulateProviderDelay := func() { 7244 time.Sleep(10 * time.Millisecond) 7245 } 7246 7247 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 7248 once.Do(simulateProviderDelay) 7249 if d.Destroy { 7250 atomic.AddInt32(&destroyCount, 1) 7251 } 7252 return testApplyFn(info, s, d) 7253 } 7254 p.DiffFn = testDiffFn 7255 s := &State{ 7256 Modules: []*ModuleState{ 7257 &ModuleState{ 7258 Path: rootModulePath, 7259 Resources: map[string]*ResourceState{ 7260 "aws_instance.bar": &ResourceState{ 7261 Type: "aws_instance", 7262 Primary: &InstanceState{ 7263 ID: "baz", 7264 Attributes: map[string]string{ 7265 "num": "2", 7266 "type": "aws_instance", 7267 }, 7268 Tainted: true, 7269 }, 7270 }, 7271 }, 7272 }, 7273 }, 7274 } 7275 ctx := testContext2(t, &ContextOpts{ 7276 Module: m, 7277 ProviderResolver: ResourceProviderResolverFixed( 7278 map[string]ResourceProviderFactory{ 7279 "aws": testProviderFuncFixed(p), 7280 }, 7281 ), 7282 State: s, 7283 }) 7284 7285 if p, err := ctx.Plan(); err != nil { 7286 t.Fatalf("err: %s", err) 7287 } else { 7288 t.Logf("plan: %s", p) 7289 } 7290 7291 state, err := ctx.Apply() 7292 if err != nil { 7293 t.Fatalf("err: %s", err) 7294 } 7295 7296 actual := strings.TrimSpace(state.String()) 7297 expected := strings.TrimSpace(testTerraformApplyTaintStr) 7298 if actual != expected { 7299 t.Fatalf("bad:\n%s", actual) 7300 } 7301 7302 if destroyCount != 1 { 7303 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 7304 } 7305 } 7306 7307 func TestContext2Apply_taintDep(t *testing.T) { 7308 m := testModule(t, "apply-taint-dep") 7309 p := testProvider("aws") 7310 p.ApplyFn = testApplyFn 7311 p.DiffFn = testDiffFn 7312 s := &State{ 7313 Modules: []*ModuleState{ 7314 &ModuleState{ 7315 Path: rootModulePath, 7316 Resources: map[string]*ResourceState{ 7317 "aws_instance.foo": &ResourceState{ 7318 Type: "aws_instance", 7319 Primary: &InstanceState{ 7320 ID: "baz", 7321 Attributes: map[string]string{ 7322 "num": "2", 7323 "type": "aws_instance", 7324 }, 7325 Tainted: true, 7326 }, 7327 }, 7328 "aws_instance.bar": &ResourceState{ 7329 Type: "aws_instance", 7330 Primary: &InstanceState{ 7331 ID: "bar", 7332 Attributes: map[string]string{ 7333 "foo": "baz", 7334 "num": "2", 7335 "type": "aws_instance", 7336 }, 7337 }, 7338 }, 7339 }, 7340 }, 7341 }, 7342 } 7343 ctx := testContext2(t, &ContextOpts{ 7344 Module: m, 7345 ProviderResolver: ResourceProviderResolverFixed( 7346 map[string]ResourceProviderFactory{ 7347 "aws": testProviderFuncFixed(p), 7348 }, 7349 ), 7350 State: s, 7351 }) 7352 7353 if p, err := ctx.Plan(); err != nil { 7354 t.Fatalf("err: %s", err) 7355 } else { 7356 t.Logf("plan: %s", p) 7357 } 7358 7359 state, err := ctx.Apply() 7360 if err != nil { 7361 t.Fatalf("err: %s", err) 7362 } 7363 7364 actual := strings.TrimSpace(state.String()) 7365 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 7366 if actual != expected { 7367 t.Fatalf("bad:\n%s", actual) 7368 } 7369 } 7370 7371 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 7372 m := testModule(t, "apply-taint-dep-requires-new") 7373 p := testProvider("aws") 7374 p.ApplyFn = testApplyFn 7375 p.DiffFn = testDiffFn 7376 s := &State{ 7377 Modules: []*ModuleState{ 7378 &ModuleState{ 7379 Path: rootModulePath, 7380 Resources: map[string]*ResourceState{ 7381 "aws_instance.foo": &ResourceState{ 7382 Type: "aws_instance", 7383 Primary: &InstanceState{ 7384 ID: "baz", 7385 Attributes: map[string]string{ 7386 "num": "2", 7387 "type": "aws_instance", 7388 }, 7389 Tainted: true, 7390 }, 7391 }, 7392 "aws_instance.bar": &ResourceState{ 7393 Type: "aws_instance", 7394 Primary: &InstanceState{ 7395 ID: "bar", 7396 Attributes: map[string]string{ 7397 "foo": "baz", 7398 "num": "2", 7399 "type": "aws_instance", 7400 }, 7401 }, 7402 }, 7403 }, 7404 }, 7405 }, 7406 } 7407 ctx := testContext2(t, &ContextOpts{ 7408 Module: m, 7409 ProviderResolver: ResourceProviderResolverFixed( 7410 map[string]ResourceProviderFactory{ 7411 "aws": testProviderFuncFixed(p), 7412 }, 7413 ), 7414 State: s, 7415 }) 7416 7417 if p, err := ctx.Plan(); err != nil { 7418 t.Fatalf("err: %s", err) 7419 } else { 7420 t.Logf("plan: %s", p) 7421 } 7422 7423 state, err := ctx.Apply() 7424 if err != nil { 7425 t.Fatalf("err: %s", err) 7426 } 7427 7428 actual := strings.TrimSpace(state.String()) 7429 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 7430 if actual != expected { 7431 t.Fatalf("bad:\n%s", actual) 7432 } 7433 } 7434 7435 func TestContext2Apply_targeted(t *testing.T) { 7436 m := testModule(t, "apply-targeted") 7437 p := testProvider("aws") 7438 p.ApplyFn = testApplyFn 7439 p.DiffFn = testDiffFn 7440 ctx := testContext2(t, &ContextOpts{ 7441 Module: m, 7442 ProviderResolver: ResourceProviderResolverFixed( 7443 map[string]ResourceProviderFactory{ 7444 "aws": testProviderFuncFixed(p), 7445 }, 7446 ), 7447 Targets: []string{"aws_instance.foo"}, 7448 }) 7449 7450 if _, err := ctx.Plan(); err != nil { 7451 t.Fatalf("err: %s", err) 7452 } 7453 7454 state, err := ctx.Apply() 7455 if err != nil { 7456 t.Fatalf("err: %s", err) 7457 } 7458 7459 mod := state.RootModule() 7460 if len(mod.Resources) != 1 { 7461 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 7462 } 7463 7464 checkStateString(t, state, ` 7465 aws_instance.foo: 7466 ID = foo 7467 provider = provider.aws 7468 num = 2 7469 type = aws_instance 7470 `) 7471 } 7472 7473 func TestContext2Apply_targetedCount(t *testing.T) { 7474 m := testModule(t, "apply-targeted-count") 7475 p := testProvider("aws") 7476 p.ApplyFn = testApplyFn 7477 p.DiffFn = testDiffFn 7478 ctx := testContext2(t, &ContextOpts{ 7479 Module: m, 7480 ProviderResolver: ResourceProviderResolverFixed( 7481 map[string]ResourceProviderFactory{ 7482 "aws": testProviderFuncFixed(p), 7483 }, 7484 ), 7485 Targets: []string{"aws_instance.foo"}, 7486 }) 7487 7488 if _, err := ctx.Plan(); err != nil { 7489 t.Fatalf("err: %s", err) 7490 } 7491 7492 state, err := ctx.Apply() 7493 if err != nil { 7494 t.Fatalf("err: %s", err) 7495 } 7496 7497 checkStateString(t, state, ` 7498 aws_instance.foo.0: 7499 ID = foo 7500 provider = provider.aws 7501 aws_instance.foo.1: 7502 ID = foo 7503 provider = provider.aws 7504 aws_instance.foo.2: 7505 ID = foo 7506 provider = provider.aws 7507 `) 7508 } 7509 7510 func TestContext2Apply_targetedCountIndex(t *testing.T) { 7511 m := testModule(t, "apply-targeted-count") 7512 p := testProvider("aws") 7513 p.ApplyFn = testApplyFn 7514 p.DiffFn = testDiffFn 7515 ctx := testContext2(t, &ContextOpts{ 7516 Module: m, 7517 ProviderResolver: ResourceProviderResolverFixed( 7518 map[string]ResourceProviderFactory{ 7519 "aws": testProviderFuncFixed(p), 7520 }, 7521 ), 7522 Targets: []string{"aws_instance.foo[1]"}, 7523 }) 7524 7525 if _, err := ctx.Plan(); err != nil { 7526 t.Fatalf("err: %s", err) 7527 } 7528 7529 state, err := ctx.Apply() 7530 if err != nil { 7531 t.Fatalf("err: %s", err) 7532 } 7533 7534 checkStateString(t, state, ` 7535 aws_instance.foo.1: 7536 ID = foo 7537 provider = provider.aws 7538 `) 7539 } 7540 7541 func TestContext2Apply_targetedDestroy(t *testing.T) { 7542 m := testModule(t, "apply-targeted") 7543 p := testProvider("aws") 7544 p.ApplyFn = testApplyFn 7545 p.DiffFn = testDiffFn 7546 ctx := testContext2(t, &ContextOpts{ 7547 Module: m, 7548 ProviderResolver: ResourceProviderResolverFixed( 7549 map[string]ResourceProviderFactory{ 7550 "aws": testProviderFuncFixed(p), 7551 }, 7552 ), 7553 State: &State{ 7554 Modules: []*ModuleState{ 7555 &ModuleState{ 7556 Path: rootModulePath, 7557 Resources: map[string]*ResourceState{ 7558 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7559 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7560 }, 7561 }, 7562 }, 7563 }, 7564 Targets: []string{"aws_instance.foo"}, 7565 Destroy: true, 7566 }) 7567 7568 if _, err := ctx.Plan(); err != nil { 7569 t.Fatalf("err: %s", err) 7570 } 7571 7572 state, err := ctx.Apply() 7573 if err != nil { 7574 t.Fatalf("err: %s", err) 7575 } 7576 7577 mod := state.RootModule() 7578 if len(mod.Resources) != 1 { 7579 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 7580 } 7581 7582 checkStateString(t, state, ` 7583 aws_instance.bar: 7584 ID = i-abc123 7585 `) 7586 } 7587 7588 func TestContext2Apply_destroyProvisionerWithLocals(t *testing.T) { 7589 m := testModule(t, "apply-provisioner-destroy-locals") 7590 p := testProvider("aws") 7591 p.ApplyFn = testApplyFn 7592 p.DiffFn = testDiffFn 7593 7594 pr := testProvisioner() 7595 pr.ApplyFn = func(_ *InstanceState, rc *ResourceConfig) error { 7596 cmd, ok := rc.Get("command") 7597 if !ok || cmd != "local" { 7598 fmt.Printf("%#v\n", rc.Config) 7599 return fmt.Errorf("provisioner got %v:%s", ok, cmd) 7600 } 7601 return nil 7602 } 7603 7604 ctx := testContext2(t, &ContextOpts{ 7605 Module: m, 7606 ProviderResolver: ResourceProviderResolverFixed( 7607 map[string]ResourceProviderFactory{ 7608 "aws": testProviderFuncFixed(p), 7609 }, 7610 ), 7611 Provisioners: map[string]ResourceProvisionerFactory{ 7612 "shell": testProvisionerFuncFixed(pr), 7613 }, 7614 State: &State{ 7615 Modules: []*ModuleState{ 7616 &ModuleState{ 7617 Path: []string{"root"}, 7618 Resources: map[string]*ResourceState{ 7619 "aws_instance.foo": resourceState("aws_instance", "1234"), 7620 }, 7621 }, 7622 }, 7623 }, 7624 Destroy: true, 7625 // the test works without targeting, but this also tests that the local 7626 // node isn't inadvertently pruned because of the wrong evaluation 7627 // order. 7628 Targets: []string{"aws_instance.foo"}, 7629 }) 7630 7631 if _, err := ctx.Plan(); err != nil { 7632 t.Fatal(err) 7633 } 7634 7635 if _, err := ctx.Apply(); err != nil { 7636 t.Fatal(err) 7637 } 7638 7639 if !pr.ApplyCalled { 7640 t.Fatal("provisioner not called") 7641 } 7642 } 7643 7644 // this also tests a local value in the config referencing a resource that 7645 // wasn't in the state during destroy. 7646 func TestContext2Apply_destroyProvisionerWithMultipleLocals(t *testing.T) { 7647 m := testModule(t, "apply-provisioner-destroy-multiple-locals") 7648 p := testProvider("aws") 7649 p.ApplyFn = testApplyFn 7650 p.DiffFn = testDiffFn 7651 7652 pr := testProvisioner() 7653 pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error { 7654 cmd, ok := rc.Get("command") 7655 if !ok { 7656 return errors.New("no command in provisioner") 7657 } 7658 7659 switch is.ID { 7660 case "1234": 7661 if cmd != "local" { 7662 return fmt.Errorf("provisioner %q got:%q", is.ID, cmd) 7663 } 7664 case "3456": 7665 if cmd != "1234" { 7666 return fmt.Errorf("provisioner %q got:%q", is.ID, cmd) 7667 } 7668 default: 7669 t.Fatal("unknown instance") 7670 } 7671 return nil 7672 } 7673 7674 ctx := testContext2(t, &ContextOpts{ 7675 Module: m, 7676 ProviderResolver: ResourceProviderResolverFixed( 7677 map[string]ResourceProviderFactory{ 7678 "aws": testProviderFuncFixed(p), 7679 }, 7680 ), 7681 Provisioners: map[string]ResourceProvisionerFactory{ 7682 "shell": testProvisionerFuncFixed(pr), 7683 }, 7684 State: &State{ 7685 Modules: []*ModuleState{ 7686 &ModuleState{ 7687 Path: []string{"root"}, 7688 Resources: map[string]*ResourceState{ 7689 "aws_instance.foo": resourceState("aws_instance", "1234"), 7690 "aws_instance.bar": resourceState("aws_instance", "3456"), 7691 }, 7692 }, 7693 }, 7694 }, 7695 Destroy: true, 7696 }) 7697 7698 if _, err := ctx.Plan(); err != nil { 7699 t.Fatal(err) 7700 } 7701 7702 if _, err := ctx.Apply(); err != nil { 7703 t.Fatal(err) 7704 } 7705 7706 if !pr.ApplyCalled { 7707 t.Fatal("provisioner not called") 7708 } 7709 } 7710 7711 func TestContext2Apply_destroyProvisionerWithOutput(t *testing.T) { 7712 m := testModule(t, "apply-provisioner-destroy-outputs") 7713 p := testProvider("aws") 7714 p.ApplyFn = testApplyFn 7715 p.DiffFn = testDiffFn 7716 7717 pr := testProvisioner() 7718 pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error { 7719 cmd, ok := rc.Get("command") 7720 if !ok || cmd != "3" { 7721 fmt.Printf("%#v\n", rc.Config) 7722 return fmt.Errorf("provisioner for %s got %v:%s", is.ID, ok, cmd) 7723 } 7724 return nil 7725 } 7726 7727 ctx := testContext2(t, &ContextOpts{ 7728 Module: m, 7729 ProviderResolver: ResourceProviderResolverFixed( 7730 map[string]ResourceProviderFactory{ 7731 "aws": testProviderFuncFixed(p), 7732 }, 7733 ), 7734 Provisioners: map[string]ResourceProvisionerFactory{ 7735 "shell": testProvisionerFuncFixed(pr), 7736 }, 7737 State: &State{ 7738 Modules: []*ModuleState{ 7739 &ModuleState{ 7740 Path: []string{"root"}, 7741 Resources: map[string]*ResourceState{ 7742 "aws_instance.foo": resourceState("aws_instance", "1"), 7743 }, 7744 Outputs: map[string]*OutputState{ 7745 "value": { 7746 Type: "string", 7747 Value: "3", 7748 }, 7749 }, 7750 }, 7751 &ModuleState{ 7752 Path: []string{"root", "mod"}, 7753 Resources: map[string]*ResourceState{ 7754 "aws_instance.baz": resourceState("aws_instance", "3"), 7755 }, 7756 // state needs to be properly initialized 7757 Outputs: map[string]*OutputState{}, 7758 }, 7759 &ModuleState{ 7760 Path: []string{"root", "mod2"}, 7761 Resources: map[string]*ResourceState{ 7762 "aws_instance.bar": resourceState("aws_instance", "2"), 7763 }, 7764 }, 7765 }, 7766 }, 7767 Destroy: true, 7768 7769 // targeting the source of the value used by all resources shoudl still 7770 // destroy them all. 7771 Targets: []string{"module.mod.aws_instance.baz"}, 7772 }) 7773 7774 if _, err := ctx.Plan(); err != nil { 7775 t.Fatal(err) 7776 } 7777 7778 state, err := ctx.Apply() 7779 if err != nil { 7780 t.Fatal(err) 7781 } 7782 if !pr.ApplyCalled { 7783 t.Fatal("provisioner not called") 7784 } 7785 7786 // confirm all outputs were removed too 7787 for _, mod := range state.Modules { 7788 if len(mod.Outputs) > 0 { 7789 t.Fatalf("output left in module state: %#v\n", mod) 7790 } 7791 } 7792 } 7793 7794 func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) { 7795 m := testModule(t, "apply-destroy-targeted-count") 7796 p := testProvider("aws") 7797 p.ApplyFn = testApplyFn 7798 p.DiffFn = testDiffFn 7799 ctx := testContext2(t, &ContextOpts{ 7800 Module: m, 7801 ProviderResolver: ResourceProviderResolverFixed( 7802 map[string]ResourceProviderFactory{ 7803 "aws": testProviderFuncFixed(p), 7804 }, 7805 ), 7806 State: &State{ 7807 Modules: []*ModuleState{ 7808 &ModuleState{ 7809 Path: rootModulePath, 7810 Resources: map[string]*ResourceState{ 7811 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7812 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7813 }, 7814 }, 7815 }, 7816 }, 7817 Targets: []string{"aws_instance.foo"}, 7818 Destroy: true, 7819 }) 7820 7821 if _, err := ctx.Plan(); err != nil { 7822 t.Fatalf("err: %s", err) 7823 } 7824 7825 state, err := ctx.Apply() 7826 if err != nil { 7827 t.Fatalf("err: %s", err) 7828 } 7829 7830 checkStateString(t, state, `<no state>`) 7831 } 7832 7833 // https://github.com/hashicorp/terraform/issues/4462 7834 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 7835 m := testModule(t, "apply-targeted-module") 7836 p := testProvider("aws") 7837 p.ApplyFn = testApplyFn 7838 p.DiffFn = testDiffFn 7839 ctx := testContext2(t, &ContextOpts{ 7840 Module: m, 7841 ProviderResolver: ResourceProviderResolverFixed( 7842 map[string]ResourceProviderFactory{ 7843 "aws": testProviderFuncFixed(p), 7844 }, 7845 ), 7846 State: &State{ 7847 Modules: []*ModuleState{ 7848 &ModuleState{ 7849 Path: rootModulePath, 7850 Resources: map[string]*ResourceState{ 7851 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7852 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7853 }, 7854 }, 7855 &ModuleState{ 7856 Path: []string{"root", "child"}, 7857 Resources: map[string]*ResourceState{ 7858 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7859 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7860 }, 7861 }, 7862 }, 7863 }, 7864 Targets: []string{"module.child.aws_instance.foo"}, 7865 Destroy: true, 7866 }) 7867 7868 if _, err := ctx.Plan(); err != nil { 7869 t.Fatalf("err: %s", err) 7870 } 7871 7872 state, err := ctx.Apply() 7873 if err != nil { 7874 t.Fatalf("err: %s", err) 7875 } 7876 7877 checkStateString(t, state, ` 7878 aws_instance.bar: 7879 ID = i-abc123 7880 aws_instance.foo: 7881 ID = i-bcd345 7882 7883 module.child: 7884 aws_instance.bar: 7885 ID = i-abc123 7886 `) 7887 } 7888 7889 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 7890 m := testModule(t, "apply-targeted-count") 7891 p := testProvider("aws") 7892 p.ApplyFn = testApplyFn 7893 p.DiffFn = testDiffFn 7894 ctx := testContext2(t, &ContextOpts{ 7895 Module: m, 7896 ProviderResolver: ResourceProviderResolverFixed( 7897 map[string]ResourceProviderFactory{ 7898 "aws": testProviderFuncFixed(p), 7899 }, 7900 ), 7901 State: &State{ 7902 Modules: []*ModuleState{ 7903 &ModuleState{ 7904 Path: rootModulePath, 7905 Resources: map[string]*ResourceState{ 7906 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 7907 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 7908 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 7909 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 7910 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 7911 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 7912 }, 7913 }, 7914 }, 7915 }, 7916 Targets: []string{ 7917 "aws_instance.foo[2]", 7918 "aws_instance.bar[1]", 7919 }, 7920 Destroy: true, 7921 }) 7922 7923 if _, err := ctx.Plan(); err != nil { 7924 t.Fatalf("err: %s", err) 7925 } 7926 7927 state, err := ctx.Apply() 7928 if err != nil { 7929 t.Fatalf("err: %s", err) 7930 } 7931 7932 checkStateString(t, state, ` 7933 aws_instance.bar.0: 7934 ID = i-abc123 7935 aws_instance.bar.2: 7936 ID = i-abc123 7937 aws_instance.foo.0: 7938 ID = i-bcd345 7939 aws_instance.foo.1: 7940 ID = i-bcd345 7941 `) 7942 } 7943 7944 func TestContext2Apply_targetedModule(t *testing.T) { 7945 m := testModule(t, "apply-targeted-module") 7946 p := testProvider("aws") 7947 p.ApplyFn = testApplyFn 7948 p.DiffFn = testDiffFn 7949 ctx := testContext2(t, &ContextOpts{ 7950 Module: m, 7951 ProviderResolver: ResourceProviderResolverFixed( 7952 map[string]ResourceProviderFactory{ 7953 "aws": testProviderFuncFixed(p), 7954 }, 7955 ), 7956 Targets: []string{"module.child"}, 7957 }) 7958 7959 if _, err := ctx.Plan(); err != nil { 7960 t.Fatalf("err: %s", err) 7961 } 7962 7963 state, err := ctx.Apply() 7964 if err != nil { 7965 t.Fatalf("err: %s", err) 7966 } 7967 7968 mod := state.ModuleByPath([]string{"root", "child"}) 7969 if mod == nil { 7970 t.Fatalf("no child module found in the state!\n\n%#v", state) 7971 } 7972 if len(mod.Resources) != 2 { 7973 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 7974 } 7975 7976 checkStateString(t, state, ` 7977 <no state> 7978 module.child: 7979 aws_instance.bar: 7980 ID = foo 7981 provider = provider.aws 7982 num = 2 7983 type = aws_instance 7984 aws_instance.foo: 7985 ID = foo 7986 provider = provider.aws 7987 num = 2 7988 type = aws_instance 7989 `) 7990 } 7991 7992 // GH-1858 7993 func TestContext2Apply_targetedModuleDep(t *testing.T) { 7994 m := testModule(t, "apply-targeted-module-dep") 7995 p := testProvider("aws") 7996 p.ApplyFn = testApplyFn 7997 p.DiffFn = testDiffFn 7998 ctx := testContext2(t, &ContextOpts{ 7999 Module: m, 8000 ProviderResolver: ResourceProviderResolverFixed( 8001 map[string]ResourceProviderFactory{ 8002 "aws": testProviderFuncFixed(p), 8003 }, 8004 ), 8005 Targets: []string{"aws_instance.foo"}, 8006 }) 8007 8008 if p, err := ctx.Plan(); err != nil { 8009 t.Fatalf("err: %s", err) 8010 } else { 8011 t.Logf("Diff: %s", p) 8012 } 8013 8014 state, err := ctx.Apply() 8015 if err != nil { 8016 t.Fatalf("err: %s", err) 8017 } 8018 8019 checkStateString(t, state, ` 8020 aws_instance.foo: 8021 ID = foo 8022 provider = provider.aws 8023 foo = foo 8024 type = aws_instance 8025 8026 Dependencies: 8027 module.child 8028 8029 module.child: 8030 aws_instance.mod: 8031 ID = foo 8032 provider = provider.aws 8033 8034 Outputs: 8035 8036 output = foo 8037 `) 8038 } 8039 8040 // GH-10911 untargeted outputs should not be in the graph, and therefore 8041 // not execute. 8042 func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) { 8043 m := testModule(t, "apply-targeted-module-unrelated-outputs") 8044 p := testProvider("aws") 8045 p.ApplyFn = testApplyFn 8046 p.DiffFn = testDiffFn 8047 ctx := testContext2(t, &ContextOpts{ 8048 Module: m, 8049 ProviderResolver: ResourceProviderResolverFixed( 8050 map[string]ResourceProviderFactory{ 8051 "aws": testProviderFuncFixed(p), 8052 }, 8053 ), 8054 Targets: []string{"module.child2"}, 8055 State: &State{ 8056 Modules: []*ModuleState{ 8057 { 8058 Path: []string{"root"}, 8059 Outputs: map[string]*OutputState{}, 8060 Resources: map[string]*ResourceState{}, 8061 }, 8062 { 8063 Path: []string{"root", "child1"}, 8064 Outputs: map[string]*OutputState{ 8065 "instance_id": { 8066 Type: "string", 8067 Value: "foo-bar-baz", 8068 }, 8069 }, 8070 Resources: map[string]*ResourceState{}, 8071 }, 8072 { 8073 Path: []string{"root", "child2"}, 8074 Outputs: map[string]*OutputState{}, 8075 Resources: map[string]*ResourceState{}, 8076 }, 8077 }, 8078 }, 8079 }) 8080 8081 if _, err := ctx.Plan(); err != nil { 8082 t.Fatalf("err: %s", err) 8083 } 8084 8085 state, err := ctx.Apply() 8086 if err != nil { 8087 t.Fatalf("err: %s", err) 8088 } 8089 8090 // module.child1's instance_id output should be retained from state 8091 // module.child2's instance_id is updated because its dependency is updated 8092 // child2_id is updated because if its transitive dependency via module.child2 8093 checkStateString(t, state, ` 8094 <no state> 8095 Outputs: 8096 8097 child2_id = foo 8098 8099 module.child1: 8100 <no state> 8101 Outputs: 8102 8103 instance_id = foo-bar-baz 8104 module.child2: 8105 aws_instance.foo: 8106 ID = foo 8107 provider = provider.aws 8108 8109 Outputs: 8110 8111 instance_id = foo 8112 `) 8113 } 8114 8115 func TestContext2Apply_targetedModuleResource(t *testing.T) { 8116 m := testModule(t, "apply-targeted-module-resource") 8117 p := testProvider("aws") 8118 p.ApplyFn = testApplyFn 8119 p.DiffFn = testDiffFn 8120 ctx := testContext2(t, &ContextOpts{ 8121 Module: m, 8122 ProviderResolver: ResourceProviderResolverFixed( 8123 map[string]ResourceProviderFactory{ 8124 "aws": testProviderFuncFixed(p), 8125 }, 8126 ), 8127 Targets: []string{"module.child.aws_instance.foo"}, 8128 }) 8129 8130 if _, err := ctx.Plan(); err != nil { 8131 t.Fatalf("err: %s", err) 8132 } 8133 8134 state, err := ctx.Apply() 8135 if err != nil { 8136 t.Fatalf("err: %s", err) 8137 } 8138 8139 mod := state.ModuleByPath([]string{"root", "child"}) 8140 if mod == nil || len(mod.Resources) != 1 { 8141 t.Fatalf("expected 1 resource, got: %#v", mod) 8142 } 8143 8144 checkStateString(t, state, ` 8145 <no state> 8146 module.child: 8147 aws_instance.foo: 8148 ID = foo 8149 provider = provider.aws 8150 num = 2 8151 type = aws_instance 8152 `) 8153 } 8154 8155 func TestContext2Apply_unknownAttribute(t *testing.T) { 8156 m := testModule(t, "apply-unknown") 8157 p := testProvider("aws") 8158 p.ApplyFn = testApplyFn 8159 p.DiffFn = testDiffFn 8160 ctx := testContext2(t, &ContextOpts{ 8161 Module: m, 8162 ProviderResolver: ResourceProviderResolverFixed( 8163 map[string]ResourceProviderFactory{ 8164 "aws": testProviderFuncFixed(p), 8165 }, 8166 ), 8167 }) 8168 8169 if _, err := ctx.Plan(); err != nil { 8170 t.Fatalf("err: %s", err) 8171 } 8172 8173 state, err := ctx.Apply() 8174 if err == nil { 8175 t.Fatal("should error") 8176 } 8177 8178 actual := strings.TrimSpace(state.String()) 8179 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 8180 if actual != expected { 8181 t.Fatalf("bad: \n%s", actual) 8182 } 8183 } 8184 8185 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 8186 m := testModule(t, "apply-unknown-interpolate") 8187 p := testProvider("aws") 8188 p.ApplyFn = testApplyFn 8189 p.DiffFn = testDiffFn 8190 ctx := testContext2(t, &ContextOpts{ 8191 Module: m, 8192 ProviderResolver: ResourceProviderResolverFixed( 8193 map[string]ResourceProviderFactory{ 8194 "aws": testProviderFuncFixed(p), 8195 }, 8196 ), 8197 }) 8198 8199 if _, err := ctx.Plan(); err == nil { 8200 t.Fatal("should error") 8201 } 8202 } 8203 8204 func TestContext2Apply_vars(t *testing.T) { 8205 m := testModule(t, "apply-vars") 8206 p := testProvider("aws") 8207 p.ApplyFn = testApplyFn 8208 p.DiffFn = testDiffFn 8209 ctx := testContext2(t, &ContextOpts{ 8210 Module: m, 8211 ProviderResolver: ResourceProviderResolverFixed( 8212 map[string]ResourceProviderFactory{ 8213 "aws": testProviderFuncFixed(p), 8214 }, 8215 ), 8216 Variables: map[string]interface{}{ 8217 "foo": "us-west-2", 8218 "test_list": []interface{}{"Hello", "World"}, 8219 "test_map": map[string]interface{}{ 8220 "Hello": "World", 8221 "Foo": "Bar", 8222 "Baz": "Foo", 8223 }, 8224 "amis": []map[string]interface{}{ 8225 map[string]interface{}{ 8226 "us-east-1": "override", 8227 }, 8228 }, 8229 }, 8230 }) 8231 8232 diags := ctx.Validate() 8233 if len(diags) != 0 { 8234 t.Fatalf("bad: %#v", diags) 8235 } 8236 8237 if _, err := ctx.Plan(); err != nil { 8238 t.Fatalf("err: %s", err) 8239 } 8240 8241 state, err := ctx.Apply() 8242 if err != nil { 8243 t.Fatalf("err: %s", err) 8244 } 8245 8246 actual := strings.TrimSpace(state.String()) 8247 expected := strings.TrimSpace(testTerraformApplyVarsStr) 8248 if actual != expected { 8249 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 8250 } 8251 } 8252 8253 func TestContext2Apply_varsEnv(t *testing.T) { 8254 // Set the env var 8255 defer tempEnv(t, "TF_VAR_ami", "baz")() 8256 defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() 8257 defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() 8258 8259 m := testModule(t, "apply-vars-env") 8260 p := testProvider("aws") 8261 p.ApplyFn = testApplyFn 8262 p.DiffFn = testDiffFn 8263 ctx := testContext2(t, &ContextOpts{ 8264 Module: m, 8265 ProviderResolver: ResourceProviderResolverFixed( 8266 map[string]ResourceProviderFactory{ 8267 "aws": testProviderFuncFixed(p), 8268 }, 8269 ), 8270 }) 8271 8272 diags := ctx.Validate() 8273 if len(diags) != 0 { 8274 t.Fatalf("bad: %#v", diags) 8275 } 8276 8277 if _, err := ctx.Plan(); err != nil { 8278 t.Fatalf("err: %s", err) 8279 } 8280 8281 state, err := ctx.Apply() 8282 if err != nil { 8283 t.Fatalf("err: %s", err) 8284 } 8285 8286 actual := strings.TrimSpace(state.String()) 8287 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 8288 if actual != expected { 8289 t.Fatalf("bad: \n%s", actual) 8290 } 8291 } 8292 8293 func TestContext2Apply_createBefore_depends(t *testing.T) { 8294 m := testModule(t, "apply-depends-create-before") 8295 h := new(HookRecordApplyOrder) 8296 p := testProvider("aws") 8297 p.ApplyFn = testApplyFn 8298 p.DiffFn = testDiffFn 8299 state := &State{ 8300 Modules: []*ModuleState{ 8301 &ModuleState{ 8302 Path: rootModulePath, 8303 Resources: map[string]*ResourceState{ 8304 "aws_instance.web": &ResourceState{ 8305 Type: "aws_instance", 8306 Primary: &InstanceState{ 8307 ID: "bar", 8308 Attributes: map[string]string{ 8309 "require_new": "ami-old", 8310 }, 8311 }, 8312 }, 8313 "aws_instance.lb": &ResourceState{ 8314 Type: "aws_instance", 8315 Primary: &InstanceState{ 8316 ID: "baz", 8317 Attributes: map[string]string{ 8318 "instance": "bar", 8319 }, 8320 }, 8321 }, 8322 }, 8323 }, 8324 }, 8325 } 8326 ctx := testContext2(t, &ContextOpts{ 8327 Module: m, 8328 Hooks: []Hook{h}, 8329 ProviderResolver: ResourceProviderResolverFixed( 8330 map[string]ResourceProviderFactory{ 8331 "aws": testProviderFuncFixed(p), 8332 }, 8333 ), 8334 State: state, 8335 }) 8336 8337 if p, err := ctx.Plan(); err != nil { 8338 t.Fatalf("err: %s", err) 8339 } else { 8340 t.Logf("plan: %s", p) 8341 } 8342 8343 h.Active = true 8344 state, err := ctx.Apply() 8345 if err != nil { 8346 t.Fatalf("err: %s", err) 8347 } 8348 8349 mod := state.RootModule() 8350 if len(mod.Resources) < 2 { 8351 t.Fatalf("bad: %#v", mod.Resources) 8352 } 8353 8354 actual := strings.TrimSpace(state.String()) 8355 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 8356 if actual != expected { 8357 t.Fatalf("bad: \n%s\n\n%s", actual, expected) 8358 } 8359 8360 // Test that things were managed _in the right order_ 8361 order := h.States 8362 diffs := h.Diffs 8363 if order[0].ID != "" || diffs[0].Destroy { 8364 t.Fatalf("should create new instance first: %#v", order) 8365 } 8366 8367 if order[1].ID != "baz" { 8368 t.Fatalf("update must happen after create: %#v", order) 8369 } 8370 8371 if order[2].ID != "bar" || !diffs[2].Destroy { 8372 t.Fatalf("destroy must happen after update: %#v", order) 8373 } 8374 } 8375 8376 func TestContext2Apply_singleDestroy(t *testing.T) { 8377 m := testModule(t, "apply-depends-create-before") 8378 h := new(HookRecordApplyOrder) 8379 p := testProvider("aws") 8380 8381 invokeCount := 0 8382 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 8383 invokeCount++ 8384 switch invokeCount { 8385 case 1: 8386 if d.Destroy { 8387 t.Fatalf("should not destroy") 8388 } 8389 if s.ID != "" { 8390 t.Fatalf("should not have ID") 8391 } 8392 case 2: 8393 if d.Destroy { 8394 t.Fatalf("should not destroy") 8395 } 8396 if s.ID != "baz" { 8397 t.Fatalf("should have id") 8398 } 8399 case 3: 8400 if !d.Destroy { 8401 t.Fatalf("should destroy") 8402 } 8403 if s.ID == "" { 8404 t.Fatalf("should have ID") 8405 } 8406 default: 8407 t.Fatalf("bad invoke count %d", invokeCount) 8408 } 8409 return testApplyFn(info, s, d) 8410 } 8411 p.DiffFn = testDiffFn 8412 state := &State{ 8413 Modules: []*ModuleState{ 8414 &ModuleState{ 8415 Path: rootModulePath, 8416 Resources: map[string]*ResourceState{ 8417 "aws_instance.web": &ResourceState{ 8418 Type: "aws_instance", 8419 Primary: &InstanceState{ 8420 ID: "bar", 8421 Attributes: map[string]string{ 8422 "require_new": "ami-old", 8423 }, 8424 }, 8425 }, 8426 "aws_instance.lb": &ResourceState{ 8427 Type: "aws_instance", 8428 Primary: &InstanceState{ 8429 ID: "baz", 8430 Attributes: map[string]string{ 8431 "instance": "bar", 8432 }, 8433 }, 8434 }, 8435 }, 8436 }, 8437 }, 8438 } 8439 ctx := testContext2(t, &ContextOpts{ 8440 Module: m, 8441 Hooks: []Hook{h}, 8442 ProviderResolver: ResourceProviderResolverFixed( 8443 map[string]ResourceProviderFactory{ 8444 "aws": testProviderFuncFixed(p), 8445 }, 8446 ), 8447 State: state, 8448 }) 8449 8450 if _, err := ctx.Plan(); err != nil { 8451 t.Fatalf("err: %s", err) 8452 } 8453 8454 h.Active = true 8455 state, err := ctx.Apply() 8456 if err != nil { 8457 t.Fatalf("err: %s", err) 8458 } 8459 8460 if invokeCount != 3 { 8461 t.Fatalf("bad: %d", invokeCount) 8462 } 8463 } 8464 8465 // GH-7824 8466 func TestContext2Apply_issue7824(t *testing.T) { 8467 p := testProvider("template") 8468 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 8469 Name: "template_file", 8470 }) 8471 8472 p.ApplyFn = testApplyFn 8473 p.DiffFn = testDiffFn 8474 8475 // Apply cleanly step 0 8476 ctx := testContext2(t, &ContextOpts{ 8477 Module: testModule(t, "issue-7824"), 8478 ProviderResolver: ResourceProviderResolverFixed( 8479 map[string]ResourceProviderFactory{ 8480 "template": testProviderFuncFixed(p), 8481 }, 8482 ), 8483 }) 8484 8485 plan, err := ctx.Plan() 8486 if err != nil { 8487 t.Fatalf("err: %s", err) 8488 } 8489 8490 // Write / Read plan to simulate running it through a Plan file 8491 var buf bytes.Buffer 8492 if err := WritePlan(plan, &buf); err != nil { 8493 t.Fatalf("err: %s", err) 8494 } 8495 8496 planFromFile, err := ReadPlan(&buf) 8497 if err != nil { 8498 t.Fatalf("err: %s", err) 8499 } 8500 8501 ctx, err = planFromFile.Context(&ContextOpts{ 8502 ProviderResolver: ResourceProviderResolverFixed( 8503 map[string]ResourceProviderFactory{ 8504 "template": testProviderFuncFixed(p), 8505 }, 8506 ), 8507 }) 8508 if err != nil { 8509 t.Fatalf("err: %s", err) 8510 } 8511 8512 _, err = ctx.Apply() 8513 if err != nil { 8514 t.Fatalf("err: %s", err) 8515 } 8516 } 8517 8518 // GH-5254 8519 func TestContext2Apply_issue5254(t *testing.T) { 8520 // Create a provider. We use "template" here just to match the repro 8521 // we got from the issue itself. 8522 p := testProvider("template") 8523 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 8524 Name: "template_file", 8525 }) 8526 8527 p.ApplyFn = testApplyFn 8528 p.DiffFn = testDiffFn 8529 8530 // Apply cleanly step 0 8531 ctx := testContext2(t, &ContextOpts{ 8532 Module: testModule(t, "issue-5254/step-0"), 8533 ProviderResolver: ResourceProviderResolverFixed( 8534 map[string]ResourceProviderFactory{ 8535 "template": testProviderFuncFixed(p), 8536 }, 8537 ), 8538 }) 8539 8540 plan, err := ctx.Plan() 8541 if err != nil { 8542 t.Fatalf("err: %s", err) 8543 } 8544 8545 state, err := ctx.Apply() 8546 if err != nil { 8547 t.Fatalf("err: %s", err) 8548 } 8549 8550 // Application success. Now make the modification and store a plan 8551 ctx = testContext2(t, &ContextOpts{ 8552 Module: testModule(t, "issue-5254/step-1"), 8553 State: state, 8554 ProviderResolver: ResourceProviderResolverFixed( 8555 map[string]ResourceProviderFactory{ 8556 "template": testProviderFuncFixed(p), 8557 }, 8558 ), 8559 }) 8560 8561 plan, err = ctx.Plan() 8562 if err != nil { 8563 t.Fatalf("err: %s", err) 8564 } 8565 8566 // Write / Read plan to simulate running it through a Plan file 8567 var buf bytes.Buffer 8568 if err := WritePlan(plan, &buf); err != nil { 8569 t.Fatalf("err: %s", err) 8570 } 8571 8572 planFromFile, err := ReadPlan(&buf) 8573 if err != nil { 8574 t.Fatalf("err: %s", err) 8575 } 8576 8577 ctx, err = planFromFile.Context(&ContextOpts{ 8578 ProviderResolver: ResourceProviderResolverFixed( 8579 map[string]ResourceProviderFactory{ 8580 "template": testProviderFuncFixed(p), 8581 }, 8582 ), 8583 }) 8584 if err != nil { 8585 t.Fatalf("err: %s", err) 8586 } 8587 8588 state, err = ctx.Apply() 8589 if err != nil { 8590 t.Fatalf("err: %s", err) 8591 } 8592 8593 actual := strings.TrimSpace(state.String()) 8594 expected := strings.TrimSpace(` 8595 template_file.child: 8596 ID = foo 8597 provider = provider.template 8598 template = Hi 8599 type = template_file 8600 8601 Dependencies: 8602 template_file.parent.* 8603 template_file.parent: 8604 ID = foo 8605 provider = provider.template 8606 template = Hi 8607 type = template_file 8608 `) 8609 if actual != expected { 8610 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 8611 } 8612 } 8613 8614 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 8615 p := testProvider("aws") 8616 p.DiffFn = testDiffFn 8617 p.ApplyFn = testApplyFn 8618 ctx := testContext2(t, &ContextOpts{ 8619 Module: testModule(t, "apply-tainted-targets"), 8620 ProviderResolver: ResourceProviderResolverFixed( 8621 map[string]ResourceProviderFactory{ 8622 "aws": testProviderFuncFixed(p), 8623 }, 8624 ), 8625 Targets: []string{"aws_instance.iambeingadded"}, 8626 State: &State{ 8627 Modules: []*ModuleState{ 8628 &ModuleState{ 8629 Path: rootModulePath, 8630 Resources: map[string]*ResourceState{ 8631 "aws_instance.ifailedprovisioners": &ResourceState{ 8632 Type: "aws_instance", 8633 Primary: &InstanceState{ 8634 ID: "ifailedprovisioners", 8635 Tainted: true, 8636 }, 8637 }, 8638 }, 8639 }, 8640 }, 8641 }, 8642 }) 8643 8644 plan, err := ctx.Plan() 8645 if err != nil { 8646 t.Fatalf("err: %s", err) 8647 } 8648 8649 // Write / Read plan to simulate running it through a Plan file 8650 var buf bytes.Buffer 8651 if err := WritePlan(plan, &buf); err != nil { 8652 t.Fatalf("err: %s", err) 8653 } 8654 8655 planFromFile, err := ReadPlan(&buf) 8656 if err != nil { 8657 t.Fatalf("err: %s", err) 8658 } 8659 8660 ctx, err = planFromFile.Context(&ContextOpts{ 8661 Module: testModule(t, "apply-tainted-targets"), 8662 ProviderResolver: ResourceProviderResolverFixed( 8663 map[string]ResourceProviderFactory{ 8664 "aws": testProviderFuncFixed(p), 8665 }, 8666 ), 8667 }) 8668 if err != nil { 8669 t.Fatalf("err: %s", err) 8670 } 8671 8672 state, err := ctx.Apply() 8673 if err != nil { 8674 t.Fatalf("err: %s", err) 8675 } 8676 8677 actual := strings.TrimSpace(state.String()) 8678 expected := strings.TrimSpace(` 8679 aws_instance.iambeingadded: 8680 ID = foo 8681 provider = provider.aws 8682 aws_instance.ifailedprovisioners: (tainted) 8683 ID = ifailedprovisioners 8684 `) 8685 if actual != expected { 8686 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 8687 } 8688 } 8689 8690 // Higher level test exposing the bug this covers in 8691 // TestResource_ignoreChangesRequired 8692 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 8693 m := testModule(t, "apply-ignore-changes-create") 8694 p := testProvider("aws") 8695 p.ApplyFn = testApplyFn 8696 p.DiffFn = testDiffFn 8697 ctx := testContext2(t, &ContextOpts{ 8698 Module: m, 8699 ProviderResolver: ResourceProviderResolverFixed( 8700 map[string]ResourceProviderFactory{ 8701 "aws": testProviderFuncFixed(p), 8702 }, 8703 ), 8704 }) 8705 8706 if p, err := ctx.Plan(); err != nil { 8707 t.Fatalf("err: %s", err) 8708 } else { 8709 t.Logf(p.String()) 8710 } 8711 8712 state, err := ctx.Apply() 8713 if err != nil { 8714 t.Fatalf("err: %s", err) 8715 } 8716 8717 mod := state.RootModule() 8718 if len(mod.Resources) != 1 { 8719 t.Fatalf("bad: %s", state) 8720 } 8721 8722 actual := strings.TrimSpace(state.String()) 8723 // Expect no changes from original state 8724 expected := strings.TrimSpace(` 8725 aws_instance.foo: 8726 ID = foo 8727 provider = provider.aws 8728 required_field = set 8729 type = aws_instance 8730 `) 8731 if actual != expected { 8732 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 8733 } 8734 } 8735 8736 func TestContext2Apply_ignoreChangesWithDep(t *testing.T) { 8737 m := testModule(t, "apply-ignore-changes-dep") 8738 p := testProvider("aws") 8739 p.ApplyFn = testApplyFn 8740 p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 8741 switch i.Type { 8742 case "aws_instance": 8743 newAmi, _ := c.Get("ami") 8744 return &InstanceDiff{ 8745 Attributes: map[string]*ResourceAttrDiff{ 8746 "ami": &ResourceAttrDiff{ 8747 Old: s.Attributes["ami"], 8748 New: newAmi.(string), 8749 RequiresNew: true, 8750 }, 8751 }, 8752 }, nil 8753 case "aws_eip": 8754 return testDiffFn(i, s, c) 8755 default: 8756 t.Fatalf("Unexpected type: %s", i.Type) 8757 return nil, nil 8758 } 8759 } 8760 s := &State{ 8761 Modules: []*ModuleState{ 8762 &ModuleState{ 8763 Path: rootModulePath, 8764 Resources: map[string]*ResourceState{ 8765 "aws_instance.foo.0": &ResourceState{ 8766 Type: "aws_instance", 8767 Primary: &InstanceState{ 8768 ID: "i-abc123", 8769 Attributes: map[string]string{ 8770 "ami": "ami-abcd1234", 8771 "id": "i-abc123", 8772 }, 8773 }, 8774 }, 8775 "aws_instance.foo.1": &ResourceState{ 8776 Type: "aws_instance", 8777 Primary: &InstanceState{ 8778 ID: "i-bcd234", 8779 Attributes: map[string]string{ 8780 "ami": "ami-abcd1234", 8781 "id": "i-bcd234", 8782 }, 8783 }, 8784 }, 8785 "aws_eip.foo.0": &ResourceState{ 8786 Type: "aws_instance", 8787 Primary: &InstanceState{ 8788 ID: "eip-abc123", 8789 Attributes: map[string]string{ 8790 "id": "eip-abc123", 8791 "instance": "i-abc123", 8792 }, 8793 }, 8794 }, 8795 "aws_eip.foo.1": &ResourceState{ 8796 Type: "aws_instance", 8797 Primary: &InstanceState{ 8798 ID: "eip-bcd234", 8799 Attributes: map[string]string{ 8800 "id": "eip-bcd234", 8801 "instance": "i-bcd234", 8802 }, 8803 }, 8804 }, 8805 }, 8806 }, 8807 }, 8808 } 8809 ctx := testContext2(t, &ContextOpts{ 8810 Module: m, 8811 ProviderResolver: ResourceProviderResolverFixed( 8812 map[string]ResourceProviderFactory{ 8813 "aws": testProviderFuncFixed(p), 8814 }, 8815 ), 8816 State: s, 8817 }) 8818 8819 if p, err := ctx.Plan(); err != nil { 8820 t.Fatalf("err: %s", err) 8821 } else { 8822 t.Logf(p.String()) 8823 } 8824 8825 state, err := ctx.Apply() 8826 if err != nil { 8827 t.Fatalf("err: %s", err) 8828 } 8829 8830 actual := strings.TrimSpace(state.String()) 8831 expected := strings.TrimSpace(s.String()) 8832 if actual != expected { 8833 t.Fatalf("bad: \n%s", actual) 8834 } 8835 } 8836 8837 func TestContext2Apply_ignoreChangesWildcard(t *testing.T) { 8838 m := testModule(t, "apply-ignore-changes-wildcard") 8839 p := testProvider("aws") 8840 p.ApplyFn = testApplyFn 8841 p.DiffFn = testDiffFn 8842 ctx := testContext2(t, &ContextOpts{ 8843 Module: m, 8844 ProviderResolver: ResourceProviderResolverFixed( 8845 map[string]ResourceProviderFactory{ 8846 "aws": testProviderFuncFixed(p), 8847 }, 8848 ), 8849 }) 8850 8851 if p, err := ctx.Plan(); err != nil { 8852 t.Fatalf("err: %s", err) 8853 } else { 8854 t.Logf(p.String()) 8855 } 8856 8857 state, err := ctx.Apply() 8858 if err != nil { 8859 t.Fatalf("err: %s", err) 8860 } 8861 8862 mod := state.RootModule() 8863 if len(mod.Resources) != 1 { 8864 t.Fatalf("bad: %s", state) 8865 } 8866 8867 actual := strings.TrimSpace(state.String()) 8868 // Expect no changes from original state 8869 expected := strings.TrimSpace(` 8870 aws_instance.foo: 8871 ID = foo 8872 provider = provider.aws 8873 required_field = set 8874 type = aws_instance 8875 `) 8876 if actual != expected { 8877 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 8878 } 8879 } 8880 8881 // https://github.com/hashicorp/terraform/issues/7378 8882 func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) { 8883 m := testModule(t, "apply-destroy-nested-module-with-attrs") 8884 p := testProvider("null") 8885 p.ApplyFn = testApplyFn 8886 p.DiffFn = testDiffFn 8887 8888 var state *State 8889 var err error 8890 { 8891 ctx := testContext2(t, &ContextOpts{ 8892 Module: m, 8893 ProviderResolver: ResourceProviderResolverFixed( 8894 map[string]ResourceProviderFactory{ 8895 "null": testProviderFuncFixed(p), 8896 }, 8897 ), 8898 }) 8899 8900 // First plan and apply a create operation 8901 if _, err := ctx.Plan(); err != nil { 8902 t.Fatalf("plan err: %s", err) 8903 } 8904 8905 state, err = ctx.Apply() 8906 if err != nil { 8907 t.Fatalf("apply err: %s", err) 8908 } 8909 } 8910 8911 { 8912 ctx := testContext2(t, &ContextOpts{ 8913 Destroy: true, 8914 Module: m, 8915 State: state, 8916 ProviderResolver: ResourceProviderResolverFixed( 8917 map[string]ResourceProviderFactory{ 8918 "null": testProviderFuncFixed(p), 8919 }, 8920 ), 8921 }) 8922 8923 plan, err := ctx.Plan() 8924 if err != nil { 8925 t.Fatalf("destroy plan err: %s", err) 8926 } 8927 8928 var buf bytes.Buffer 8929 if err := WritePlan(plan, &buf); err != nil { 8930 t.Fatalf("plan write err: %s", err) 8931 } 8932 8933 planFromFile, err := ReadPlan(&buf) 8934 if err != nil { 8935 t.Fatalf("plan read err: %s", err) 8936 } 8937 8938 ctx, err = planFromFile.Context(&ContextOpts{ 8939 ProviderResolver: ResourceProviderResolverFixed( 8940 map[string]ResourceProviderFactory{ 8941 "null": testProviderFuncFixed(p), 8942 }, 8943 ), 8944 }) 8945 if err != nil { 8946 t.Fatalf("err: %s", err) 8947 } 8948 8949 state, err = ctx.Apply() 8950 if err != nil { 8951 t.Fatalf("destroy apply err: %s", err) 8952 } 8953 } 8954 8955 //Test that things were destroyed 8956 actual := strings.TrimSpace(state.String()) 8957 expected := strings.TrimSpace(` 8958 <no state> 8959 module.middle: 8960 <no state> 8961 module.middle.bottom: 8962 <no state> 8963 `) 8964 if actual != expected { 8965 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 8966 } 8967 } 8968 8969 // If a data source explicitly depends on another resource, it's because we need 8970 // that resource to be applied first. 8971 func TestContext2Apply_dataDependsOn(t *testing.T) { 8972 p := testProvider("null") 8973 m := testModule(t, "apply-data-depends-on") 8974 8975 ctx := testContext2(t, &ContextOpts{ 8976 Module: m, 8977 ProviderResolver: ResourceProviderResolverFixed( 8978 map[string]ResourceProviderFactory{ 8979 "null": testProviderFuncFixed(p), 8980 }, 8981 ), 8982 }) 8983 8984 // the "provisioner" here writes to this variable, because the intent is to 8985 // create a dependency which can't be viewed through the graph, and depends 8986 // solely on the configuration providing "depends_on" 8987 provisionerOutput := "" 8988 8989 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 8990 // the side effect of the resource being applied 8991 provisionerOutput = "APPLIED" 8992 return testApplyFn(info, s, d) 8993 } 8994 8995 p.DiffFn = testDiffFn 8996 p.ReadDataDiffFn = testDataDiffFn 8997 8998 p.ReadDataApplyFn = func(*InstanceInfo, *InstanceDiff) (*InstanceState, error) { 8999 // Read the artifact created by our dependency being applied. 9000 // Without any "depends_on", this would be skipped as it's assumed the 9001 // initial diff during refresh was all that's needed. 9002 return &InstanceState{ 9003 ID: "read", 9004 Attributes: map[string]string{ 9005 "foo": provisionerOutput, 9006 }, 9007 }, nil 9008 } 9009 9010 _, err := ctx.Refresh() 9011 if err != nil { 9012 t.Fatalf("err: %s", err) 9013 } 9014 9015 if _, err := ctx.Plan(); err != nil { 9016 t.Fatalf("err: %s", err) 9017 } 9018 9019 state, err := ctx.Apply() 9020 if err != nil { 9021 t.Fatalf("err: %s", err) 9022 } 9023 9024 root := state.ModuleByPath(RootModulePath) 9025 actual := root.Resources["data.null_data_source.read"].Primary.Attributes["foo"] 9026 9027 expected := "APPLIED" 9028 if actual != expected { 9029 t.Fatalf("bad:\n%s", strings.TrimSpace(state.String())) 9030 } 9031 } 9032 9033 func TestContext2Apply_terraformEnv(t *testing.T) { 9034 m := testModule(t, "apply-terraform-env") 9035 p := testProvider("aws") 9036 p.ApplyFn = testApplyFn 9037 p.DiffFn = testDiffFn 9038 9039 ctx := testContext2(t, &ContextOpts{ 9040 Meta: &ContextMeta{Env: "foo"}, 9041 Module: m, 9042 ProviderResolver: ResourceProviderResolverFixed( 9043 map[string]ResourceProviderFactory{ 9044 "aws": testProviderFuncFixed(p), 9045 }, 9046 ), 9047 }) 9048 9049 if _, err := ctx.Plan(); err != nil { 9050 t.Fatalf("err: %s", err) 9051 } 9052 9053 state, err := ctx.Apply() 9054 if err != nil { 9055 t.Fatalf("err: %s", err) 9056 } 9057 9058 actual := state.RootModule().Outputs["output"] 9059 expected := "foo" 9060 if actual == nil || actual.Value != expected { 9061 t.Fatalf("bad: \n%s", actual) 9062 } 9063 } 9064 9065 // verify that multiple config references only create a single depends_on entry 9066 func TestContext2Apply_multiRef(t *testing.T) { 9067 m := testModule(t, "apply-multi-ref") 9068 p := testProvider("aws") 9069 p.ApplyFn = testApplyFn 9070 p.DiffFn = testDiffFn 9071 9072 ctx := testContext2(t, &ContextOpts{ 9073 Module: m, 9074 ProviderResolver: ResourceProviderResolverFixed( 9075 map[string]ResourceProviderFactory{ 9076 "aws": testProviderFuncFixed(p), 9077 }, 9078 ), 9079 }) 9080 9081 if _, err := ctx.Plan(); err != nil { 9082 t.Fatalf("err: %s", err) 9083 } 9084 9085 state, err := ctx.Apply() 9086 if err != nil { 9087 t.Fatalf("err: %s", err) 9088 } 9089 9090 deps := state.Modules[0].Resources["aws_instance.other"].Dependencies 9091 if len(deps) > 1 || deps[0] != "aws_instance.create" { 9092 t.Fatalf("expected 1 depends_on entry for aws_instance.create, got %q", deps) 9093 } 9094 } 9095 9096 func TestContext2Apply_targetedModuleRecursive(t *testing.T) { 9097 m := testModule(t, "apply-targeted-module-recursive") 9098 p := testProvider("aws") 9099 p.ApplyFn = testApplyFn 9100 p.DiffFn = testDiffFn 9101 ctx := testContext2(t, &ContextOpts{ 9102 Module: m, 9103 ProviderResolver: ResourceProviderResolverFixed( 9104 map[string]ResourceProviderFactory{ 9105 "aws": testProviderFuncFixed(p), 9106 }, 9107 ), 9108 Targets: []string{"module.child"}, 9109 }) 9110 9111 if _, err := ctx.Plan(); err != nil { 9112 t.Fatalf("err: %s", err) 9113 } 9114 9115 state, err := ctx.Apply() 9116 if err != nil { 9117 t.Fatalf("err: %s", err) 9118 } 9119 9120 mod := state.ModuleByPath([]string{"root", "child", "subchild"}) 9121 if mod == nil { 9122 t.Fatalf("no subchild module found in the state!\n\n%#v", state) 9123 } 9124 if len(mod.Resources) != 1 { 9125 t.Fatalf("expected 1 resources, got: %#v", mod.Resources) 9126 } 9127 9128 checkStateString(t, state, ` 9129 <no state> 9130 module.child.subchild: 9131 aws_instance.foo: 9132 ID = foo 9133 provider = provider.aws 9134 num = 2 9135 type = aws_instance 9136 `) 9137 } 9138 9139 func TestContext2Apply_localVal(t *testing.T) { 9140 m := testModule(t, "apply-local-val") 9141 ctx := testContext2(t, &ContextOpts{ 9142 Module: m, 9143 ProviderResolver: ResourceProviderResolverFixed( 9144 map[string]ResourceProviderFactory{}, 9145 ), 9146 }) 9147 9148 if _, err := ctx.Plan(); err != nil { 9149 t.Fatalf("error during plan: %s", err) 9150 } 9151 9152 state, err := ctx.Apply() 9153 if err != nil { 9154 t.Fatalf("error during apply: %s", err) 9155 } 9156 9157 got := strings.TrimSpace(state.String()) 9158 want := strings.TrimSpace(` 9159 <no state> 9160 Outputs: 9161 9162 result_1 = hello 9163 result_3 = hello world 9164 9165 module.child: 9166 <no state> 9167 Outputs: 9168 9169 result = hello 9170 `) 9171 if got != want { 9172 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9173 } 9174 } 9175 9176 func TestContext2Apply_destroyWithLocals(t *testing.T) { 9177 m := testModule(t, "apply-destroy-with-locals") 9178 p := testProvider("aws") 9179 p.ApplyFn = testApplyFn 9180 p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 9181 d, err := testDiffFn(info, s, c) 9182 return d, err 9183 } 9184 9185 s := &State{ 9186 Modules: []*ModuleState{ 9187 &ModuleState{ 9188 Path: rootModulePath, 9189 Outputs: map[string]*OutputState{ 9190 "name": &OutputState{ 9191 Type: "string", 9192 Value: "test-bar", 9193 }, 9194 }, 9195 Resources: map[string]*ResourceState{ 9196 "aws_instance.foo": &ResourceState{ 9197 Type: "aws_instance", 9198 Primary: &InstanceState{ 9199 ID: "foo", 9200 // FIXME: id should only exist in one place 9201 Attributes: map[string]string{ 9202 "id": "foo", 9203 }, 9204 }, 9205 }, 9206 }, 9207 }, 9208 }, 9209 } 9210 9211 ctx := testContext2(t, &ContextOpts{ 9212 Module: m, 9213 ProviderResolver: ResourceProviderResolverFixed( 9214 map[string]ResourceProviderFactory{ 9215 "aws": testProviderFuncFixed(p), 9216 }, 9217 ), 9218 State: s, 9219 Destroy: true, 9220 }) 9221 9222 if _, err := ctx.Plan(); err != nil { 9223 t.Fatalf("err: %s", err) 9224 } 9225 9226 state, err := ctx.Apply() 9227 if err != nil { 9228 t.Fatalf("error during apply: %s", err) 9229 } 9230 9231 got := strings.TrimSpace(state.String()) 9232 want := strings.TrimSpace(`<no state>`) 9233 if got != want { 9234 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9235 } 9236 } 9237 9238 func TestContext2Apply_providerWithLocals(t *testing.T) { 9239 m := testModule(t, "provider-with-locals") 9240 p := testProvider("aws") 9241 9242 providerRegion := "" 9243 // this should not be overridden during destroy 9244 p.ConfigureFn = func(c *ResourceConfig) error { 9245 if r, ok := c.Get("region"); ok { 9246 providerRegion = r.(string) 9247 } 9248 return nil 9249 } 9250 p.DiffFn = testDiffFn 9251 p.ApplyFn = testApplyFn 9252 ctx := testContext2(t, &ContextOpts{ 9253 Module: m, 9254 ProviderResolver: ResourceProviderResolverFixed( 9255 map[string]ResourceProviderFactory{ 9256 "aws": testProviderFuncFixed(p), 9257 }, 9258 ), 9259 }) 9260 9261 if _, err := ctx.Plan(); err != nil { 9262 t.Fatalf("err: %s", err) 9263 } 9264 9265 state, err := ctx.Apply() 9266 if err != nil { 9267 t.Fatalf("err: %s", err) 9268 } 9269 9270 ctx = testContext2(t, &ContextOpts{ 9271 Module: m, 9272 ProviderResolver: ResourceProviderResolverFixed( 9273 map[string]ResourceProviderFactory{ 9274 "aws": testProviderFuncFixed(p), 9275 }, 9276 ), 9277 State: state, 9278 Destroy: true, 9279 }) 9280 9281 if _, err = ctx.Plan(); err != nil { 9282 t.Fatalf("err: %s", err) 9283 } 9284 9285 state, err = ctx.Apply() 9286 if err != nil { 9287 t.Fatalf("err: %s", err) 9288 } 9289 9290 if state.HasResources() { 9291 t.Fatal("expected no state, got:", state) 9292 } 9293 9294 if providerRegion != "bar" { 9295 t.Fatalf("expected region %q, got: %q", "bar", providerRegion) 9296 } 9297 } 9298 9299 func TestContext2Apply_destroyWithProviders(t *testing.T) { 9300 m := testModule(t, "destroy-module-with-provider") 9301 p := testProvider("aws") 9302 p.ApplyFn = testApplyFn 9303 p.DiffFn = testDiffFn 9304 9305 s := &State{ 9306 Modules: []*ModuleState{ 9307 &ModuleState{ 9308 Path: rootModulePath, 9309 }, 9310 &ModuleState{ 9311 Path: []string{"root", "child"}, 9312 }, 9313 &ModuleState{ 9314 Path: []string{"root", "mod", "removed"}, 9315 Resources: map[string]*ResourceState{ 9316 "aws_instance.child": &ResourceState{ 9317 Type: "aws_instance", 9318 Primary: &InstanceState{ 9319 ID: "bar", 9320 }, 9321 // this provider doesn't exist 9322 Provider: "provider.aws.baz", 9323 }, 9324 }, 9325 }, 9326 }, 9327 } 9328 9329 ctx := testContext2(t, &ContextOpts{ 9330 Module: m, 9331 ProviderResolver: ResourceProviderResolverFixed( 9332 map[string]ResourceProviderFactory{ 9333 "aws": testProviderFuncFixed(p), 9334 }, 9335 ), 9336 State: s, 9337 Destroy: true, 9338 }) 9339 9340 // test that we can't destroy if the provider is missing 9341 if _, err := ctx.Plan(); err == nil { 9342 t.Fatal("expected plan error, provider.aws.baz doesn't exist") 9343 } 9344 9345 // correct the state 9346 s.Modules[2].Resources["aws_instance.child"].Provider = "provider.aws.bar" 9347 9348 if _, err := ctx.Plan(); err != nil { 9349 t.Fatal(err) 9350 } 9351 state, err := ctx.Apply() 9352 if err != nil { 9353 t.Fatalf("error during apply: %s", err) 9354 } 9355 9356 got := strings.TrimSpace(state.String()) 9357 9358 want := strings.TrimSpace("<no state>") 9359 if got != want { 9360 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9361 } 9362 } 9363 9364 func TestContext2Apply_providersFromState(t *testing.T) { 9365 m := module.NewEmptyTree() 9366 p := testProvider("aws") 9367 p.DiffFn = testDiffFn 9368 9369 for _, tc := range []struct { 9370 name string 9371 state *State 9372 output string 9373 err bool 9374 }{ 9375 { 9376 name: "add implicit provider", 9377 state: &State{ 9378 Modules: []*ModuleState{ 9379 &ModuleState{ 9380 Path: []string{"root"}, 9381 Resources: map[string]*ResourceState{ 9382 "aws_instance.a": &ResourceState{ 9383 Type: "aws_instance", 9384 Primary: &InstanceState{ 9385 ID: "bar", 9386 }, 9387 Provider: "provider.aws", 9388 }, 9389 }, 9390 }, 9391 }, 9392 }, 9393 err: false, 9394 output: "<no state>", 9395 }, 9396 9397 // an aliased provider must be in the config to remove a resource 9398 { 9399 name: "add aliased provider", 9400 state: &State{ 9401 Modules: []*ModuleState{ 9402 &ModuleState{ 9403 Path: []string{"root"}, 9404 Resources: map[string]*ResourceState{ 9405 "aws_instance.a": &ResourceState{ 9406 Type: "aws_instance", 9407 Primary: &InstanceState{ 9408 ID: "bar", 9409 }, 9410 Provider: "provider.aws.bar", 9411 }, 9412 }, 9413 }, 9414 }, 9415 }, 9416 err: true, 9417 }, 9418 9419 // a provider in a module implies some sort of config, so this isn't 9420 // allowed even without an alias 9421 { 9422 name: "add unaliased module provider", 9423 state: &State{ 9424 Modules: []*ModuleState{ 9425 &ModuleState{ 9426 Path: []string{"root", "child"}, 9427 Resources: map[string]*ResourceState{ 9428 "aws_instance.a": &ResourceState{ 9429 Type: "aws_instance", 9430 Primary: &InstanceState{ 9431 ID: "bar", 9432 }, 9433 Provider: "module.child.provider.aws", 9434 }, 9435 }, 9436 }, 9437 }, 9438 }, 9439 err: true, 9440 }, 9441 } { 9442 9443 t.Run(tc.name, func(t *testing.T) { 9444 ctx := testContext2(t, &ContextOpts{ 9445 Module: m, 9446 ProviderResolver: ResourceProviderResolverFixed( 9447 map[string]ResourceProviderFactory{ 9448 "aws": testProviderFuncFixed(p), 9449 }, 9450 ), 9451 State: tc.state, 9452 }) 9453 9454 _, err := ctx.Plan() 9455 if tc.err { 9456 if err == nil { 9457 t.Fatal("expected error") 9458 } else { 9459 return 9460 } 9461 } 9462 if !tc.err && err != nil { 9463 t.Fatal(err) 9464 } 9465 9466 state, err := ctx.Apply() 9467 if err != nil { 9468 t.Fatalf("err: %s", err) 9469 } 9470 9471 checkStateString(t, state, "<no state>") 9472 9473 }) 9474 } 9475 9476 }