github.com/wikibal01/hashicorp-terraform@v0.11.12-beta1/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("expected:\n%s\n:got\n%s", expected, 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 p := testProvider("aws") 6586 p.ApplyFn = testApplyFn 6587 p.DiffFn = testDiffFn 6588 ctx := testContext2(t, &ContextOpts{ 6589 Module: m, 6590 ProviderResolver: ResourceProviderResolverFixed( 6591 map[string]ResourceProviderFactory{ 6592 "aws": testProviderFuncFixed(p), 6593 }, 6594 ), 6595 }) 6596 6597 // First plan and apply a create operation 6598 if _, err := ctx.Plan(); err != nil { 6599 t.Fatalf("err: %s", err) 6600 } 6601 6602 state, err := ctx.Apply() 6603 6604 if err != nil { 6605 t.Fatalf("err: %s", err) 6606 } 6607 6608 // Next, plan and apply a destroy operation 6609 ctx = testContext2(t, &ContextOpts{ 6610 Destroy: true, 6611 State: state, 6612 Module: m, 6613 ProviderResolver: ResourceProviderResolverFixed( 6614 map[string]ResourceProviderFactory{ 6615 "aws": testProviderFuncFixed(p), 6616 }, 6617 ), 6618 }) 6619 6620 if _, err := ctx.Plan(); err != nil { 6621 t.Fatal(err) 6622 } 6623 6624 state, err = ctx.Apply() 6625 if err != nil { 6626 t.Fatal(err) 6627 } 6628 6629 mod := state.RootModule() 6630 if len(mod.Resources) > 0 { 6631 t.Fatalf("expected no resources, got: %#v", mod) 6632 } 6633 6634 // destroying again should produce no errors 6635 ctx = testContext2(t, &ContextOpts{ 6636 Destroy: true, 6637 State: state, 6638 Module: m, 6639 ProviderResolver: ResourceProviderResolverFixed( 6640 map[string]ResourceProviderFactory{ 6641 "aws": testProviderFuncFixed(p), 6642 }, 6643 ), 6644 }) 6645 if _, err := ctx.Plan(); err != nil { 6646 t.Fatal(err) 6647 } 6648 6649 if _, err = ctx.Apply(); err != nil { 6650 t.Fatal(err) 6651 } 6652 } 6653 6654 func TestContext2Apply_destroyOrphan(t *testing.T) { 6655 m := testModule(t, "apply-error") 6656 p := testProvider("aws") 6657 s := &State{ 6658 Modules: []*ModuleState{ 6659 &ModuleState{ 6660 Path: rootModulePath, 6661 Resources: map[string]*ResourceState{ 6662 "aws_instance.baz": &ResourceState{ 6663 Type: "aws_instance", 6664 Primary: &InstanceState{ 6665 ID: "bar", 6666 }, 6667 }, 6668 }, 6669 }, 6670 }, 6671 } 6672 ctx := testContext2(t, &ContextOpts{ 6673 Module: m, 6674 ProviderResolver: ResourceProviderResolverFixed( 6675 map[string]ResourceProviderFactory{ 6676 "aws": testProviderFuncFixed(p), 6677 }, 6678 ), 6679 State: s, 6680 }) 6681 6682 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6683 if d.Destroy { 6684 return nil, nil 6685 } 6686 6687 result := s.MergeDiff(d) 6688 result.ID = "foo" 6689 return result, nil 6690 } 6691 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6692 return &InstanceDiff{ 6693 Attributes: map[string]*ResourceAttrDiff{ 6694 "num": &ResourceAttrDiff{ 6695 New: "bar", 6696 }, 6697 }, 6698 }, nil 6699 } 6700 6701 if _, err := ctx.Plan(); err != nil { 6702 t.Fatalf("err: %s", err) 6703 } 6704 6705 state, err := ctx.Apply() 6706 if err != nil { 6707 t.Fatalf("err: %s", err) 6708 } 6709 6710 mod := state.RootModule() 6711 if _, ok := mod.Resources["aws_instance.baz"]; ok { 6712 t.Fatalf("bad: %#v", mod.Resources) 6713 } 6714 } 6715 6716 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 6717 m := testModule(t, "apply-destroy-provisioner") 6718 p := testProvider("aws") 6719 pr := testProvisioner() 6720 p.ApplyFn = testApplyFn 6721 p.DiffFn = testDiffFn 6722 6723 called := false 6724 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 6725 called = true 6726 return nil 6727 } 6728 6729 s := &State{ 6730 Modules: []*ModuleState{ 6731 &ModuleState{ 6732 Path: rootModulePath, 6733 Resources: map[string]*ResourceState{ 6734 "aws_instance.foo": &ResourceState{ 6735 Type: "aws_instance", 6736 Primary: &InstanceState{ 6737 ID: "bar", 6738 Attributes: map[string]string{ 6739 "id": "bar", 6740 }, 6741 Tainted: true, 6742 }, 6743 }, 6744 }, 6745 }, 6746 }, 6747 } 6748 6749 ctx := testContext2(t, &ContextOpts{ 6750 Module: m, 6751 ProviderResolver: ResourceProviderResolverFixed( 6752 map[string]ResourceProviderFactory{ 6753 "aws": testProviderFuncFixed(p), 6754 }, 6755 ), 6756 Provisioners: map[string]ResourceProvisionerFactory{ 6757 "shell": testProvisionerFuncFixed(pr), 6758 }, 6759 State: s, 6760 Destroy: true, 6761 }) 6762 6763 if _, err := ctx.Plan(); err != nil { 6764 t.Fatalf("err: %s", err) 6765 } 6766 6767 state, err := ctx.Apply() 6768 if err != nil { 6769 t.Fatalf("err: %s", err) 6770 } 6771 6772 if called { 6773 t.Fatal("provisioner should not be called") 6774 } 6775 6776 actual := strings.TrimSpace(state.String()) 6777 expected := strings.TrimSpace("<no state>") 6778 if actual != expected { 6779 t.Fatalf("bad: \n%s", actual) 6780 } 6781 } 6782 6783 func TestContext2Apply_error(t *testing.T) { 6784 errored := false 6785 6786 m := testModule(t, "apply-error") 6787 p := testProvider("aws") 6788 ctx := testContext2(t, &ContextOpts{ 6789 Module: m, 6790 ProviderResolver: ResourceProviderResolverFixed( 6791 map[string]ResourceProviderFactory{ 6792 "aws": testProviderFuncFixed(p), 6793 }, 6794 ), 6795 }) 6796 6797 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 6798 if errored { 6799 state := &InstanceState{ 6800 ID: "bar", 6801 } 6802 return state, fmt.Errorf("error") 6803 } 6804 errored = true 6805 6806 return &InstanceState{ 6807 ID: "foo", 6808 Attributes: map[string]string{ 6809 "num": "2", 6810 }, 6811 }, nil 6812 } 6813 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6814 return &InstanceDiff{ 6815 Attributes: map[string]*ResourceAttrDiff{ 6816 "num": &ResourceAttrDiff{ 6817 New: "bar", 6818 }, 6819 }, 6820 }, nil 6821 } 6822 6823 if _, err := ctx.Plan(); err != nil { 6824 t.Fatalf("err: %s", err) 6825 } 6826 6827 state, err := ctx.Apply() 6828 if err == nil { 6829 t.Fatal("should have error") 6830 } 6831 6832 actual := strings.TrimSpace(state.String()) 6833 expected := strings.TrimSpace(testTerraformApplyErrorStr) 6834 if actual != expected { 6835 t.Fatalf("bad: \n%s", actual) 6836 } 6837 } 6838 6839 func TestContext2Apply_errorPartial(t *testing.T) { 6840 errored := false 6841 6842 m := testModule(t, "apply-error") 6843 p := testProvider("aws") 6844 s := &State{ 6845 Modules: []*ModuleState{ 6846 &ModuleState{ 6847 Path: rootModulePath, 6848 Resources: map[string]*ResourceState{ 6849 "aws_instance.bar": &ResourceState{ 6850 Type: "aws_instance", 6851 Primary: &InstanceState{ 6852 ID: "bar", 6853 }, 6854 }, 6855 }, 6856 }, 6857 }, 6858 } 6859 ctx := testContext2(t, &ContextOpts{ 6860 Module: m, 6861 ProviderResolver: ResourceProviderResolverFixed( 6862 map[string]ResourceProviderFactory{ 6863 "aws": testProviderFuncFixed(p), 6864 }, 6865 ), 6866 State: s, 6867 }) 6868 6869 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6870 if errored { 6871 return s, fmt.Errorf("error") 6872 } 6873 errored = true 6874 6875 return &InstanceState{ 6876 ID: "foo", 6877 Attributes: map[string]string{ 6878 "num": "2", 6879 }, 6880 }, nil 6881 } 6882 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6883 return &InstanceDiff{ 6884 Attributes: map[string]*ResourceAttrDiff{ 6885 "num": &ResourceAttrDiff{ 6886 New: "bar", 6887 }, 6888 }, 6889 }, nil 6890 } 6891 6892 if _, err := ctx.Plan(); err != nil { 6893 t.Fatalf("err: %s", err) 6894 } 6895 6896 state, err := ctx.Apply() 6897 if err == nil { 6898 t.Fatal("should have error") 6899 } 6900 6901 mod := state.RootModule() 6902 if len(mod.Resources) != 2 { 6903 t.Fatalf("bad: %#v", mod.Resources) 6904 } 6905 6906 actual := strings.TrimSpace(state.String()) 6907 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 6908 if actual != expected { 6909 t.Fatalf("bad: \n%s", actual) 6910 } 6911 } 6912 6913 func TestContext2Apply_hook(t *testing.T) { 6914 m := testModule(t, "apply-good") 6915 h := new(MockHook) 6916 p := testProvider("aws") 6917 p.ApplyFn = testApplyFn 6918 p.DiffFn = testDiffFn 6919 ctx := testContext2(t, &ContextOpts{ 6920 Module: m, 6921 Hooks: []Hook{h}, 6922 ProviderResolver: ResourceProviderResolverFixed( 6923 map[string]ResourceProviderFactory{ 6924 "aws": testProviderFuncFixed(p), 6925 }, 6926 ), 6927 }) 6928 6929 if _, err := ctx.Plan(); err != nil { 6930 t.Fatalf("err: %s", err) 6931 } 6932 6933 if _, err := ctx.Apply(); err != nil { 6934 t.Fatalf("err: %s", err) 6935 } 6936 6937 if !h.PreApplyCalled { 6938 t.Fatal("should be called") 6939 } 6940 if !h.PostApplyCalled { 6941 t.Fatal("should be called") 6942 } 6943 if !h.PostStateUpdateCalled { 6944 t.Fatalf("should call post state update") 6945 } 6946 } 6947 6948 func TestContext2Apply_hookOrphan(t *testing.T) { 6949 m := testModule(t, "apply-blank") 6950 h := new(MockHook) 6951 p := testProvider("aws") 6952 p.ApplyFn = testApplyFn 6953 p.DiffFn = testDiffFn 6954 6955 state := &State{ 6956 Modules: []*ModuleState{ 6957 &ModuleState{ 6958 Path: rootModulePath, 6959 Resources: map[string]*ResourceState{ 6960 "aws_instance.bar": &ResourceState{ 6961 Type: "aws_instance", 6962 Primary: &InstanceState{ 6963 ID: "bar", 6964 }, 6965 }, 6966 }, 6967 }, 6968 }, 6969 } 6970 6971 ctx := testContext2(t, &ContextOpts{ 6972 Module: m, 6973 State: state, 6974 Hooks: []Hook{h}, 6975 ProviderResolver: ResourceProviderResolverFixed( 6976 map[string]ResourceProviderFactory{ 6977 "aws": testProviderFuncFixed(p), 6978 }, 6979 ), 6980 }) 6981 6982 if _, err := ctx.Plan(); err != nil { 6983 t.Fatalf("err: %s", err) 6984 } 6985 6986 if _, err := ctx.Apply(); err != nil { 6987 t.Fatalf("err: %s", err) 6988 } 6989 6990 if !h.PreApplyCalled { 6991 t.Fatal("should be called") 6992 } 6993 if !h.PostApplyCalled { 6994 t.Fatal("should be called") 6995 } 6996 if !h.PostStateUpdateCalled { 6997 t.Fatalf("should call post state update") 6998 } 6999 } 7000 7001 func TestContext2Apply_idAttr(t *testing.T) { 7002 m := testModule(t, "apply-idattr") 7003 p := testProvider("aws") 7004 ctx := testContext2(t, &ContextOpts{ 7005 Module: m, 7006 ProviderResolver: ResourceProviderResolverFixed( 7007 map[string]ResourceProviderFactory{ 7008 "aws": testProviderFuncFixed(p), 7009 }, 7010 ), 7011 }) 7012 7013 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 7014 result := s.MergeDiff(d) 7015 result.ID = "foo" 7016 result.Attributes = map[string]string{ 7017 "id": "bar", 7018 } 7019 7020 return result, nil 7021 } 7022 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 7023 return &InstanceDiff{ 7024 Attributes: map[string]*ResourceAttrDiff{ 7025 "num": &ResourceAttrDiff{ 7026 New: "bar", 7027 }, 7028 }, 7029 }, nil 7030 } 7031 7032 if _, err := ctx.Plan(); err != nil { 7033 t.Fatalf("err: %s", err) 7034 } 7035 7036 state, err := ctx.Apply() 7037 if err != nil { 7038 t.Fatalf("err: %s", err) 7039 } 7040 7041 mod := state.RootModule() 7042 rs, ok := mod.Resources["aws_instance.foo"] 7043 if !ok { 7044 t.Fatal("not in state") 7045 } 7046 if rs.Primary.ID != "foo" { 7047 t.Fatalf("bad: %#v", rs.Primary.ID) 7048 } 7049 if rs.Primary.Attributes["id"] != "foo" { 7050 t.Fatalf("bad: %#v", rs.Primary.Attributes) 7051 } 7052 } 7053 7054 func TestContext2Apply_outputBasic(t *testing.T) { 7055 m := testModule(t, "apply-output") 7056 p := testProvider("aws") 7057 p.ApplyFn = testApplyFn 7058 p.DiffFn = testDiffFn 7059 ctx := testContext2(t, &ContextOpts{ 7060 Module: m, 7061 ProviderResolver: ResourceProviderResolverFixed( 7062 map[string]ResourceProviderFactory{ 7063 "aws": testProviderFuncFixed(p), 7064 }, 7065 ), 7066 }) 7067 7068 if _, err := ctx.Plan(); err != nil { 7069 t.Fatalf("err: %s", err) 7070 } 7071 7072 state, err := ctx.Apply() 7073 if err != nil { 7074 t.Fatalf("err: %s", err) 7075 } 7076 7077 actual := strings.TrimSpace(state.String()) 7078 expected := strings.TrimSpace(testTerraformApplyOutputStr) 7079 if actual != expected { 7080 t.Fatalf("bad: \n%s", actual) 7081 } 7082 } 7083 7084 func TestContext2Apply_outputInvalid(t *testing.T) { 7085 m := testModule(t, "apply-output-invalid") 7086 p := testProvider("aws") 7087 p.ApplyFn = testApplyFn 7088 p.DiffFn = testDiffFn 7089 ctx := testContext2(t, &ContextOpts{ 7090 Module: m, 7091 ProviderResolver: ResourceProviderResolverFixed( 7092 map[string]ResourceProviderFactory{ 7093 "aws": testProviderFuncFixed(p), 7094 }, 7095 ), 7096 }) 7097 7098 _, err := ctx.Plan() 7099 if err == nil { 7100 t.Fatalf("err: %s", err) 7101 } 7102 if !strings.Contains(err.Error(), "is not a valid type") { 7103 t.Fatalf("err: %s", err) 7104 } 7105 } 7106 7107 func TestContext2Apply_outputAdd(t *testing.T) { 7108 m1 := testModule(t, "apply-output-add-before") 7109 p1 := testProvider("aws") 7110 p1.ApplyFn = testApplyFn 7111 p1.DiffFn = testDiffFn 7112 ctx1 := testContext2(t, &ContextOpts{ 7113 Module: m1, 7114 ProviderResolver: ResourceProviderResolverFixed( 7115 map[string]ResourceProviderFactory{ 7116 "aws": testProviderFuncFixed(p1), 7117 }, 7118 ), 7119 }) 7120 7121 if _, err := ctx1.Plan(); err != nil { 7122 t.Fatalf("err: %s", err) 7123 } 7124 7125 state1, err := ctx1.Apply() 7126 if err != nil { 7127 t.Fatalf("err: %s", err) 7128 } 7129 7130 m2 := testModule(t, "apply-output-add-after") 7131 p2 := testProvider("aws") 7132 p2.ApplyFn = testApplyFn 7133 p2.DiffFn = testDiffFn 7134 ctx2 := testContext2(t, &ContextOpts{ 7135 Module: m2, 7136 ProviderResolver: ResourceProviderResolverFixed( 7137 map[string]ResourceProviderFactory{ 7138 "aws": testProviderFuncFixed(p2), 7139 }, 7140 ), 7141 State: state1, 7142 }) 7143 7144 if _, err := ctx2.Plan(); err != nil { 7145 t.Fatalf("err: %s", err) 7146 } 7147 7148 state2, err := ctx2.Apply() 7149 if err != nil { 7150 t.Fatalf("err: %s", err) 7151 } 7152 7153 actual := strings.TrimSpace(state2.String()) 7154 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 7155 if actual != expected { 7156 t.Fatalf("bad: \n%s", actual) 7157 } 7158 } 7159 7160 func TestContext2Apply_outputList(t *testing.T) { 7161 m := testModule(t, "apply-output-list") 7162 p := testProvider("aws") 7163 p.ApplyFn = testApplyFn 7164 p.DiffFn = testDiffFn 7165 ctx := testContext2(t, &ContextOpts{ 7166 Module: m, 7167 ProviderResolver: ResourceProviderResolverFixed( 7168 map[string]ResourceProviderFactory{ 7169 "aws": testProviderFuncFixed(p), 7170 }, 7171 ), 7172 }) 7173 7174 if _, err := ctx.Plan(); err != nil { 7175 t.Fatalf("err: %s", err) 7176 } 7177 7178 state, err := ctx.Apply() 7179 if err != nil { 7180 t.Fatalf("err: %s", err) 7181 } 7182 7183 actual := strings.TrimSpace(state.String()) 7184 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 7185 if actual != expected { 7186 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 7187 } 7188 } 7189 7190 func TestContext2Apply_outputMulti(t *testing.T) { 7191 m := testModule(t, "apply-output-multi") 7192 p := testProvider("aws") 7193 p.ApplyFn = testApplyFn 7194 p.DiffFn = testDiffFn 7195 ctx := testContext2(t, &ContextOpts{ 7196 Module: m, 7197 ProviderResolver: ResourceProviderResolverFixed( 7198 map[string]ResourceProviderFactory{ 7199 "aws": testProviderFuncFixed(p), 7200 }, 7201 ), 7202 }) 7203 7204 if _, err := ctx.Plan(); err != nil { 7205 t.Fatalf("err: %s", err) 7206 } 7207 7208 state, err := ctx.Apply() 7209 if err != nil { 7210 t.Fatalf("err: %s", err) 7211 } 7212 7213 actual := strings.TrimSpace(state.String()) 7214 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 7215 if actual != expected { 7216 t.Fatalf("bad: \n%s", actual) 7217 } 7218 } 7219 7220 func TestContext2Apply_outputMultiIndex(t *testing.T) { 7221 m := testModule(t, "apply-output-multi-index") 7222 p := testProvider("aws") 7223 p.ApplyFn = testApplyFn 7224 p.DiffFn = testDiffFn 7225 ctx := testContext2(t, &ContextOpts{ 7226 Module: m, 7227 ProviderResolver: ResourceProviderResolverFixed( 7228 map[string]ResourceProviderFactory{ 7229 "aws": testProviderFuncFixed(p), 7230 }, 7231 ), 7232 }) 7233 7234 if _, err := ctx.Plan(); err != nil { 7235 t.Fatalf("err: %s", err) 7236 } 7237 7238 state, err := ctx.Apply() 7239 if err != nil { 7240 t.Fatalf("err: %s", err) 7241 } 7242 7243 actual := strings.TrimSpace(state.String()) 7244 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 7245 if actual != expected { 7246 t.Fatalf("bad: \n%s", actual) 7247 } 7248 } 7249 7250 func TestContext2Apply_taintX(t *testing.T) { 7251 m := testModule(t, "apply-taint") 7252 p := testProvider("aws") 7253 7254 // destroyCount tests against regression of 7255 // https://github.com/hashicorp/terraform/issues/1056 7256 var destroyCount = int32(0) 7257 var once sync.Once 7258 simulateProviderDelay := func() { 7259 time.Sleep(10 * time.Millisecond) 7260 } 7261 7262 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 7263 once.Do(simulateProviderDelay) 7264 if d.Destroy { 7265 atomic.AddInt32(&destroyCount, 1) 7266 } 7267 return testApplyFn(info, s, d) 7268 } 7269 p.DiffFn = testDiffFn 7270 s := &State{ 7271 Modules: []*ModuleState{ 7272 &ModuleState{ 7273 Path: rootModulePath, 7274 Resources: map[string]*ResourceState{ 7275 "aws_instance.bar": &ResourceState{ 7276 Type: "aws_instance", 7277 Primary: &InstanceState{ 7278 ID: "baz", 7279 Attributes: map[string]string{ 7280 "num": "2", 7281 "type": "aws_instance", 7282 }, 7283 Tainted: true, 7284 }, 7285 }, 7286 }, 7287 }, 7288 }, 7289 } 7290 ctx := testContext2(t, &ContextOpts{ 7291 Module: m, 7292 ProviderResolver: ResourceProviderResolverFixed( 7293 map[string]ResourceProviderFactory{ 7294 "aws": testProviderFuncFixed(p), 7295 }, 7296 ), 7297 State: s, 7298 }) 7299 7300 if p, err := ctx.Plan(); err != nil { 7301 t.Fatalf("err: %s", err) 7302 } else { 7303 t.Logf("plan: %s", p) 7304 } 7305 7306 state, err := ctx.Apply() 7307 if err != nil { 7308 t.Fatalf("err: %s", err) 7309 } 7310 7311 actual := strings.TrimSpace(state.String()) 7312 expected := strings.TrimSpace(testTerraformApplyTaintStr) 7313 if actual != expected { 7314 t.Fatalf("bad:\n%s", actual) 7315 } 7316 7317 if destroyCount != 1 { 7318 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 7319 } 7320 } 7321 7322 func TestContext2Apply_taintDep(t *testing.T) { 7323 m := testModule(t, "apply-taint-dep") 7324 p := testProvider("aws") 7325 p.ApplyFn = testApplyFn 7326 p.DiffFn = testDiffFn 7327 s := &State{ 7328 Modules: []*ModuleState{ 7329 &ModuleState{ 7330 Path: rootModulePath, 7331 Resources: map[string]*ResourceState{ 7332 "aws_instance.foo": &ResourceState{ 7333 Type: "aws_instance", 7334 Primary: &InstanceState{ 7335 ID: "baz", 7336 Attributes: map[string]string{ 7337 "num": "2", 7338 "type": "aws_instance", 7339 }, 7340 Tainted: true, 7341 }, 7342 }, 7343 "aws_instance.bar": &ResourceState{ 7344 Type: "aws_instance", 7345 Primary: &InstanceState{ 7346 ID: "bar", 7347 Attributes: map[string]string{ 7348 "foo": "baz", 7349 "num": "2", 7350 "type": "aws_instance", 7351 }, 7352 }, 7353 }, 7354 }, 7355 }, 7356 }, 7357 } 7358 ctx := testContext2(t, &ContextOpts{ 7359 Module: m, 7360 ProviderResolver: ResourceProviderResolverFixed( 7361 map[string]ResourceProviderFactory{ 7362 "aws": testProviderFuncFixed(p), 7363 }, 7364 ), 7365 State: s, 7366 }) 7367 7368 if p, err := ctx.Plan(); err != nil { 7369 t.Fatalf("err: %s", err) 7370 } else { 7371 t.Logf("plan: %s", p) 7372 } 7373 7374 state, err := ctx.Apply() 7375 if err != nil { 7376 t.Fatalf("err: %s", err) 7377 } 7378 7379 actual := strings.TrimSpace(state.String()) 7380 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 7381 if actual != expected { 7382 t.Fatalf("bad:\n%s", actual) 7383 } 7384 } 7385 7386 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 7387 m := testModule(t, "apply-taint-dep-requires-new") 7388 p := testProvider("aws") 7389 p.ApplyFn = testApplyFn 7390 p.DiffFn = testDiffFn 7391 s := &State{ 7392 Modules: []*ModuleState{ 7393 &ModuleState{ 7394 Path: rootModulePath, 7395 Resources: map[string]*ResourceState{ 7396 "aws_instance.foo": &ResourceState{ 7397 Type: "aws_instance", 7398 Primary: &InstanceState{ 7399 ID: "baz", 7400 Attributes: map[string]string{ 7401 "num": "2", 7402 "type": "aws_instance", 7403 }, 7404 Tainted: true, 7405 }, 7406 }, 7407 "aws_instance.bar": &ResourceState{ 7408 Type: "aws_instance", 7409 Primary: &InstanceState{ 7410 ID: "bar", 7411 Attributes: map[string]string{ 7412 "foo": "baz", 7413 "num": "2", 7414 "type": "aws_instance", 7415 }, 7416 }, 7417 }, 7418 }, 7419 }, 7420 }, 7421 } 7422 ctx := testContext2(t, &ContextOpts{ 7423 Module: m, 7424 ProviderResolver: ResourceProviderResolverFixed( 7425 map[string]ResourceProviderFactory{ 7426 "aws": testProviderFuncFixed(p), 7427 }, 7428 ), 7429 State: s, 7430 }) 7431 7432 if p, err := ctx.Plan(); err != nil { 7433 t.Fatalf("err: %s", err) 7434 } else { 7435 t.Logf("plan: %s", p) 7436 } 7437 7438 state, err := ctx.Apply() 7439 if err != nil { 7440 t.Fatalf("err: %s", err) 7441 } 7442 7443 actual := strings.TrimSpace(state.String()) 7444 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 7445 if actual != expected { 7446 t.Fatalf("bad:\n%s", actual) 7447 } 7448 } 7449 7450 func TestContext2Apply_targeted(t *testing.T) { 7451 m := testModule(t, "apply-targeted") 7452 p := testProvider("aws") 7453 p.ApplyFn = testApplyFn 7454 p.DiffFn = testDiffFn 7455 ctx := testContext2(t, &ContextOpts{ 7456 Module: m, 7457 ProviderResolver: ResourceProviderResolverFixed( 7458 map[string]ResourceProviderFactory{ 7459 "aws": testProviderFuncFixed(p), 7460 }, 7461 ), 7462 Targets: []string{"aws_instance.foo"}, 7463 }) 7464 7465 if _, err := ctx.Plan(); err != nil { 7466 t.Fatalf("err: %s", err) 7467 } 7468 7469 state, err := ctx.Apply() 7470 if err != nil { 7471 t.Fatalf("err: %s", err) 7472 } 7473 7474 mod := state.RootModule() 7475 if len(mod.Resources) != 1 { 7476 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 7477 } 7478 7479 checkStateString(t, state, ` 7480 aws_instance.foo: 7481 ID = foo 7482 provider = provider.aws 7483 num = 2 7484 type = aws_instance 7485 `) 7486 } 7487 7488 func TestContext2Apply_targetEmpty(t *testing.T) { 7489 m := testModule(t, "apply-targeted") 7490 p := testProvider("aws") 7491 p.ApplyFn = testApplyFn 7492 p.DiffFn = testDiffFn 7493 ctx := testContext2(t, &ContextOpts{ 7494 Module: m, 7495 ProviderResolver: ResourceProviderResolverFixed( 7496 map[string]ResourceProviderFactory{ 7497 "aws": testProviderFuncFixed(p), 7498 }, 7499 ), 7500 Targets: []string{""}, 7501 }) 7502 7503 _, err := ctx.Apply() 7504 if err == nil { 7505 t.Fatalf("should error") 7506 } 7507 } 7508 7509 func TestContext2Apply_targetedCount(t *testing.T) { 7510 m := testModule(t, "apply-targeted-count") 7511 p := testProvider("aws") 7512 p.ApplyFn = testApplyFn 7513 p.DiffFn = testDiffFn 7514 ctx := testContext2(t, &ContextOpts{ 7515 Module: m, 7516 ProviderResolver: ResourceProviderResolverFixed( 7517 map[string]ResourceProviderFactory{ 7518 "aws": testProviderFuncFixed(p), 7519 }, 7520 ), 7521 Targets: []string{"aws_instance.foo"}, 7522 }) 7523 7524 if _, err := ctx.Plan(); err != nil { 7525 t.Fatalf("err: %s", err) 7526 } 7527 7528 state, err := ctx.Apply() 7529 if err != nil { 7530 t.Fatalf("err: %s", err) 7531 } 7532 7533 checkStateString(t, state, ` 7534 aws_instance.foo.0: 7535 ID = foo 7536 provider = provider.aws 7537 aws_instance.foo.1: 7538 ID = foo 7539 provider = provider.aws 7540 aws_instance.foo.2: 7541 ID = foo 7542 provider = provider.aws 7543 `) 7544 } 7545 7546 func TestContext2Apply_targetedCountIndex(t *testing.T) { 7547 m := testModule(t, "apply-targeted-count") 7548 p := testProvider("aws") 7549 p.ApplyFn = testApplyFn 7550 p.DiffFn = testDiffFn 7551 ctx := testContext2(t, &ContextOpts{ 7552 Module: m, 7553 ProviderResolver: ResourceProviderResolverFixed( 7554 map[string]ResourceProviderFactory{ 7555 "aws": testProviderFuncFixed(p), 7556 }, 7557 ), 7558 Targets: []string{"aws_instance.foo[1]"}, 7559 }) 7560 7561 if _, err := ctx.Plan(); err != nil { 7562 t.Fatalf("err: %s", err) 7563 } 7564 7565 state, err := ctx.Apply() 7566 if err != nil { 7567 t.Fatalf("err: %s", err) 7568 } 7569 7570 checkStateString(t, state, ` 7571 aws_instance.foo.1: 7572 ID = foo 7573 provider = provider.aws 7574 `) 7575 } 7576 7577 func TestContext2Apply_targetedDestroy(t *testing.T) { 7578 m := testModule(t, "apply-targeted") 7579 p := testProvider("aws") 7580 p.ApplyFn = testApplyFn 7581 p.DiffFn = testDiffFn 7582 ctx := testContext2(t, &ContextOpts{ 7583 Module: m, 7584 ProviderResolver: ResourceProviderResolverFixed( 7585 map[string]ResourceProviderFactory{ 7586 "aws": testProviderFuncFixed(p), 7587 }, 7588 ), 7589 State: &State{ 7590 Modules: []*ModuleState{ 7591 &ModuleState{ 7592 Path: rootModulePath, 7593 Resources: map[string]*ResourceState{ 7594 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7595 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7596 }, 7597 }, 7598 }, 7599 }, 7600 Targets: []string{"aws_instance.foo"}, 7601 Destroy: true, 7602 }) 7603 7604 if _, err := ctx.Plan(); err != nil { 7605 t.Fatalf("err: %s", err) 7606 } 7607 7608 state, err := ctx.Apply() 7609 if err != nil { 7610 t.Fatalf("err: %s", err) 7611 } 7612 7613 mod := state.RootModule() 7614 if len(mod.Resources) != 1 { 7615 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 7616 } 7617 7618 checkStateString(t, state, ` 7619 aws_instance.bar: 7620 ID = i-abc123 7621 `) 7622 } 7623 7624 func TestContext2Apply_destroyProvisionerWithLocals(t *testing.T) { 7625 m := testModule(t, "apply-provisioner-destroy-locals") 7626 p := testProvider("aws") 7627 p.ApplyFn = testApplyFn 7628 p.DiffFn = testDiffFn 7629 7630 pr := testProvisioner() 7631 pr.ApplyFn = func(_ *InstanceState, rc *ResourceConfig) error { 7632 cmd, ok := rc.Get("command") 7633 if !ok || cmd != "local" { 7634 fmt.Printf("%#v\n", rc.Config) 7635 return fmt.Errorf("provisioner got %v:%s", ok, cmd) 7636 } 7637 return nil 7638 } 7639 7640 ctx := testContext2(t, &ContextOpts{ 7641 Module: m, 7642 ProviderResolver: ResourceProviderResolverFixed( 7643 map[string]ResourceProviderFactory{ 7644 "aws": testProviderFuncFixed(p), 7645 }, 7646 ), 7647 Provisioners: map[string]ResourceProvisionerFactory{ 7648 "shell": testProvisionerFuncFixed(pr), 7649 }, 7650 State: &State{ 7651 Modules: []*ModuleState{ 7652 &ModuleState{ 7653 Path: []string{"root"}, 7654 Resources: map[string]*ResourceState{ 7655 "aws_instance.foo": resourceState("aws_instance", "1234"), 7656 }, 7657 }, 7658 }, 7659 }, 7660 Destroy: true, 7661 // the test works without targeting, but this also tests that the local 7662 // node isn't inadvertently pruned because of the wrong evaluation 7663 // order. 7664 Targets: []string{"aws_instance.foo"}, 7665 }) 7666 7667 if _, err := ctx.Plan(); err != nil { 7668 t.Fatal(err) 7669 } 7670 7671 if _, err := ctx.Apply(); err != nil { 7672 t.Fatal(err) 7673 } 7674 7675 if !pr.ApplyCalled { 7676 t.Fatal("provisioner not called") 7677 } 7678 } 7679 7680 // this also tests a local value in the config referencing a resource that 7681 // wasn't in the state during destroy. 7682 func TestContext2Apply_destroyProvisionerWithMultipleLocals(t *testing.T) { 7683 m := testModule(t, "apply-provisioner-destroy-multiple-locals") 7684 p := testProvider("aws") 7685 p.ApplyFn = testApplyFn 7686 p.DiffFn = testDiffFn 7687 7688 pr := testProvisioner() 7689 pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error { 7690 cmd, ok := rc.Get("command") 7691 if !ok { 7692 return errors.New("no command in provisioner") 7693 } 7694 7695 switch is.ID { 7696 case "1234": 7697 if cmd != "local" { 7698 return fmt.Errorf("provisioner %q got:%q", is.ID, cmd) 7699 } 7700 case "3456": 7701 if cmd != "1234" { 7702 return fmt.Errorf("provisioner %q got:%q", is.ID, cmd) 7703 } 7704 default: 7705 t.Fatal("unknown instance") 7706 } 7707 return nil 7708 } 7709 7710 ctx := testContext2(t, &ContextOpts{ 7711 Module: m, 7712 ProviderResolver: ResourceProviderResolverFixed( 7713 map[string]ResourceProviderFactory{ 7714 "aws": testProviderFuncFixed(p), 7715 }, 7716 ), 7717 Provisioners: map[string]ResourceProvisionerFactory{ 7718 "shell": testProvisionerFuncFixed(pr), 7719 }, 7720 State: &State{ 7721 Modules: []*ModuleState{ 7722 &ModuleState{ 7723 Path: []string{"root"}, 7724 Resources: map[string]*ResourceState{ 7725 "aws_instance.foo": resourceState("aws_instance", "1234"), 7726 "aws_instance.bar": resourceState("aws_instance", "3456"), 7727 }, 7728 }, 7729 }, 7730 }, 7731 Destroy: true, 7732 }) 7733 7734 if _, err := ctx.Plan(); err != nil { 7735 t.Fatal(err) 7736 } 7737 7738 if _, err := ctx.Apply(); err != nil { 7739 t.Fatal(err) 7740 } 7741 7742 if !pr.ApplyCalled { 7743 t.Fatal("provisioner not called") 7744 } 7745 } 7746 7747 func TestContext2Apply_destroyProvisionerWithOutput(t *testing.T) { 7748 m := testModule(t, "apply-provisioner-destroy-outputs") 7749 p := testProvider("aws") 7750 p.ApplyFn = testApplyFn 7751 p.DiffFn = testDiffFn 7752 7753 pr := testProvisioner() 7754 pr.ApplyFn = func(is *InstanceState, rc *ResourceConfig) error { 7755 cmd, ok := rc.Get("command") 7756 if !ok || cmd != "3" { 7757 fmt.Printf("%#v\n", rc.Config) 7758 return fmt.Errorf("provisioner for %s got %v:%s", is.ID, ok, cmd) 7759 } 7760 return nil 7761 } 7762 7763 ctx := testContext2(t, &ContextOpts{ 7764 Module: m, 7765 ProviderResolver: ResourceProviderResolverFixed( 7766 map[string]ResourceProviderFactory{ 7767 "aws": testProviderFuncFixed(p), 7768 }, 7769 ), 7770 Provisioners: map[string]ResourceProvisionerFactory{ 7771 "shell": testProvisionerFuncFixed(pr), 7772 }, 7773 State: &State{ 7774 Modules: []*ModuleState{ 7775 &ModuleState{ 7776 Path: []string{"root"}, 7777 Resources: map[string]*ResourceState{ 7778 "aws_instance.foo": resourceState("aws_instance", "1"), 7779 }, 7780 Outputs: map[string]*OutputState{ 7781 "value": { 7782 Type: "string", 7783 Value: "3", 7784 }, 7785 }, 7786 }, 7787 &ModuleState{ 7788 Path: []string{"root", "mod"}, 7789 Resources: map[string]*ResourceState{ 7790 "aws_instance.baz": resourceState("aws_instance", "3"), 7791 }, 7792 // state needs to be properly initialized 7793 Outputs: map[string]*OutputState{}, 7794 }, 7795 &ModuleState{ 7796 Path: []string{"root", "mod2"}, 7797 Resources: map[string]*ResourceState{ 7798 "aws_instance.bar": resourceState("aws_instance", "2"), 7799 }, 7800 }, 7801 }, 7802 }, 7803 Destroy: true, 7804 7805 // targeting the source of the value used by all resources should still 7806 // destroy them all. 7807 Targets: []string{"module.mod.aws_instance.baz"}, 7808 }) 7809 7810 if _, err := ctx.Plan(); err != nil { 7811 t.Fatal(err) 7812 } 7813 7814 state, err := ctx.Apply() 7815 if err != nil { 7816 t.Fatal(err) 7817 } 7818 if !pr.ApplyCalled { 7819 t.Fatal("provisioner not called") 7820 } 7821 7822 // confirm all outputs were removed too 7823 for _, mod := range state.Modules { 7824 if len(mod.Outputs) > 0 { 7825 t.Fatalf("output left in module state: %#v\n", mod) 7826 } 7827 } 7828 } 7829 7830 func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) { 7831 m := testModule(t, "apply-destroy-targeted-count") 7832 p := testProvider("aws") 7833 p.ApplyFn = testApplyFn 7834 p.DiffFn = testDiffFn 7835 ctx := testContext2(t, &ContextOpts{ 7836 Module: m, 7837 ProviderResolver: ResourceProviderResolverFixed( 7838 map[string]ResourceProviderFactory{ 7839 "aws": testProviderFuncFixed(p), 7840 }, 7841 ), 7842 State: &State{ 7843 Modules: []*ModuleState{ 7844 &ModuleState{ 7845 Path: rootModulePath, 7846 Resources: map[string]*ResourceState{ 7847 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7848 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7849 }, 7850 }, 7851 }, 7852 }, 7853 Targets: []string{"aws_instance.foo"}, 7854 Destroy: true, 7855 }) 7856 7857 if _, err := ctx.Plan(); err != nil { 7858 t.Fatalf("err: %s", err) 7859 } 7860 7861 state, err := ctx.Apply() 7862 if err != nil { 7863 t.Fatalf("err: %s", err) 7864 } 7865 7866 checkStateString(t, state, `<no state>`) 7867 } 7868 7869 // https://github.com/hashicorp/terraform/issues/4462 7870 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 7871 m := testModule(t, "apply-targeted-module") 7872 p := testProvider("aws") 7873 p.ApplyFn = testApplyFn 7874 p.DiffFn = testDiffFn 7875 ctx := testContext2(t, &ContextOpts{ 7876 Module: m, 7877 ProviderResolver: ResourceProviderResolverFixed( 7878 map[string]ResourceProviderFactory{ 7879 "aws": testProviderFuncFixed(p), 7880 }, 7881 ), 7882 State: &State{ 7883 Modules: []*ModuleState{ 7884 &ModuleState{ 7885 Path: rootModulePath, 7886 Resources: map[string]*ResourceState{ 7887 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7888 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7889 }, 7890 }, 7891 &ModuleState{ 7892 Path: []string{"root", "child"}, 7893 Resources: map[string]*ResourceState{ 7894 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7895 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7896 }, 7897 }, 7898 }, 7899 }, 7900 Targets: []string{"module.child.aws_instance.foo"}, 7901 Destroy: true, 7902 }) 7903 7904 if _, err := ctx.Plan(); err != nil { 7905 t.Fatalf("err: %s", err) 7906 } 7907 7908 state, err := ctx.Apply() 7909 if err != nil { 7910 t.Fatalf("err: %s", err) 7911 } 7912 7913 checkStateString(t, state, ` 7914 aws_instance.bar: 7915 ID = i-abc123 7916 aws_instance.foo: 7917 ID = i-bcd345 7918 7919 module.child: 7920 aws_instance.bar: 7921 ID = i-abc123 7922 `) 7923 } 7924 7925 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 7926 m := testModule(t, "apply-targeted-count") 7927 p := testProvider("aws") 7928 p.ApplyFn = testApplyFn 7929 p.DiffFn = testDiffFn 7930 ctx := testContext2(t, &ContextOpts{ 7931 Module: m, 7932 ProviderResolver: ResourceProviderResolverFixed( 7933 map[string]ResourceProviderFactory{ 7934 "aws": testProviderFuncFixed(p), 7935 }, 7936 ), 7937 State: &State{ 7938 Modules: []*ModuleState{ 7939 &ModuleState{ 7940 Path: rootModulePath, 7941 Resources: map[string]*ResourceState{ 7942 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 7943 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 7944 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 7945 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 7946 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 7947 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 7948 }, 7949 }, 7950 }, 7951 }, 7952 Targets: []string{ 7953 "aws_instance.foo[2]", 7954 "aws_instance.bar[1]", 7955 }, 7956 Destroy: true, 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 checkStateString(t, state, ` 7969 aws_instance.bar.0: 7970 ID = i-abc123 7971 aws_instance.bar.2: 7972 ID = i-abc123 7973 aws_instance.foo.0: 7974 ID = i-bcd345 7975 aws_instance.foo.1: 7976 ID = i-bcd345 7977 `) 7978 } 7979 7980 func TestContext2Apply_targetedModule(t *testing.T) { 7981 m := testModule(t, "apply-targeted-module") 7982 p := testProvider("aws") 7983 p.ApplyFn = testApplyFn 7984 p.DiffFn = testDiffFn 7985 ctx := testContext2(t, &ContextOpts{ 7986 Module: m, 7987 ProviderResolver: ResourceProviderResolverFixed( 7988 map[string]ResourceProviderFactory{ 7989 "aws": testProviderFuncFixed(p), 7990 }, 7991 ), 7992 Targets: []string{"module.child"}, 7993 }) 7994 7995 if _, err := ctx.Plan(); err != nil { 7996 t.Fatalf("err: %s", err) 7997 } 7998 7999 state, err := ctx.Apply() 8000 if err != nil { 8001 t.Fatalf("err: %s", err) 8002 } 8003 8004 mod := state.ModuleByPath([]string{"root", "child"}) 8005 if mod == nil { 8006 t.Fatalf("no child module found in the state!\n\n%#v", state) 8007 } 8008 if len(mod.Resources) != 2 { 8009 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 8010 } 8011 8012 checkStateString(t, state, ` 8013 <no state> 8014 module.child: 8015 aws_instance.bar: 8016 ID = foo 8017 provider = provider.aws 8018 num = 2 8019 type = aws_instance 8020 aws_instance.foo: 8021 ID = foo 8022 provider = provider.aws 8023 num = 2 8024 type = aws_instance 8025 `) 8026 } 8027 8028 // GH-1858 8029 func TestContext2Apply_targetedModuleDep(t *testing.T) { 8030 m := testModule(t, "apply-targeted-module-dep") 8031 p := testProvider("aws") 8032 p.ApplyFn = testApplyFn 8033 p.DiffFn = testDiffFn 8034 ctx := testContext2(t, &ContextOpts{ 8035 Module: m, 8036 ProviderResolver: ResourceProviderResolverFixed( 8037 map[string]ResourceProviderFactory{ 8038 "aws": testProviderFuncFixed(p), 8039 }, 8040 ), 8041 Targets: []string{"aws_instance.foo"}, 8042 }) 8043 8044 if p, err := ctx.Plan(); err != nil { 8045 t.Fatalf("err: %s", err) 8046 } else { 8047 t.Logf("Diff: %s", p) 8048 } 8049 8050 state, err := ctx.Apply() 8051 if err != nil { 8052 t.Fatalf("err: %s", err) 8053 } 8054 8055 checkStateString(t, state, ` 8056 aws_instance.foo: 8057 ID = foo 8058 provider = provider.aws 8059 foo = foo 8060 type = aws_instance 8061 8062 Dependencies: 8063 module.child 8064 8065 module.child: 8066 aws_instance.mod: 8067 ID = foo 8068 provider = provider.aws 8069 8070 Outputs: 8071 8072 output = foo 8073 `) 8074 } 8075 8076 // GH-10911 untargeted outputs should not be in the graph, and therefore 8077 // not execute. 8078 func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) { 8079 m := testModule(t, "apply-targeted-module-unrelated-outputs") 8080 p := testProvider("aws") 8081 p.ApplyFn = testApplyFn 8082 p.DiffFn = testDiffFn 8083 ctx := testContext2(t, &ContextOpts{ 8084 Module: m, 8085 ProviderResolver: ResourceProviderResolverFixed( 8086 map[string]ResourceProviderFactory{ 8087 "aws": testProviderFuncFixed(p), 8088 }, 8089 ), 8090 Targets: []string{"module.child2"}, 8091 State: &State{ 8092 Modules: []*ModuleState{ 8093 { 8094 Path: []string{"root"}, 8095 Outputs: map[string]*OutputState{}, 8096 Resources: map[string]*ResourceState{}, 8097 }, 8098 { 8099 Path: []string{"root", "child1"}, 8100 Outputs: map[string]*OutputState{ 8101 "instance_id": { 8102 Type: "string", 8103 Value: "foo-bar-baz", 8104 }, 8105 }, 8106 Resources: map[string]*ResourceState{}, 8107 }, 8108 { 8109 Path: []string{"root", "child2"}, 8110 Outputs: map[string]*OutputState{}, 8111 Resources: map[string]*ResourceState{}, 8112 }, 8113 }, 8114 }, 8115 }) 8116 8117 if _, err := ctx.Plan(); err != nil { 8118 t.Fatalf("err: %s", err) 8119 } 8120 8121 state, err := ctx.Apply() 8122 if err != nil { 8123 t.Fatalf("err: %s", err) 8124 } 8125 8126 // module.child1's instance_id output should be retained from state 8127 // module.child2's instance_id is updated because its dependency is updated 8128 // child2_id is updated because if its transitive dependency via module.child2 8129 checkStateString(t, state, ` 8130 <no state> 8131 Outputs: 8132 8133 child2_id = foo 8134 8135 module.child1: 8136 <no state> 8137 Outputs: 8138 8139 instance_id = foo-bar-baz 8140 module.child2: 8141 aws_instance.foo: 8142 ID = foo 8143 provider = provider.aws 8144 8145 Outputs: 8146 8147 instance_id = foo 8148 `) 8149 } 8150 8151 func TestContext2Apply_targetedModuleResource(t *testing.T) { 8152 m := testModule(t, "apply-targeted-module-resource") 8153 p := testProvider("aws") 8154 p.ApplyFn = testApplyFn 8155 p.DiffFn = testDiffFn 8156 ctx := testContext2(t, &ContextOpts{ 8157 Module: m, 8158 ProviderResolver: ResourceProviderResolverFixed( 8159 map[string]ResourceProviderFactory{ 8160 "aws": testProviderFuncFixed(p), 8161 }, 8162 ), 8163 Targets: []string{"module.child.aws_instance.foo"}, 8164 }) 8165 8166 if _, err := ctx.Plan(); err != nil { 8167 t.Fatalf("err: %s", err) 8168 } 8169 8170 state, err := ctx.Apply() 8171 if err != nil { 8172 t.Fatalf("err: %s", err) 8173 } 8174 8175 mod := state.ModuleByPath([]string{"root", "child"}) 8176 if mod == nil || len(mod.Resources) != 1 { 8177 t.Fatalf("expected 1 resource, got: %#v", mod) 8178 } 8179 8180 checkStateString(t, state, ` 8181 <no state> 8182 module.child: 8183 aws_instance.foo: 8184 ID = foo 8185 provider = provider.aws 8186 num = 2 8187 type = aws_instance 8188 `) 8189 } 8190 8191 func TestContext2Apply_unknownAttribute(t *testing.T) { 8192 m := testModule(t, "apply-unknown") 8193 p := testProvider("aws") 8194 p.ApplyFn = testApplyFn 8195 p.DiffFn = testDiffFn 8196 ctx := testContext2(t, &ContextOpts{ 8197 Module: m, 8198 ProviderResolver: ResourceProviderResolverFixed( 8199 map[string]ResourceProviderFactory{ 8200 "aws": testProviderFuncFixed(p), 8201 }, 8202 ), 8203 }) 8204 8205 if _, err := ctx.Plan(); err != nil { 8206 t.Fatalf("err: %s", err) 8207 } 8208 8209 state, err := ctx.Apply() 8210 if err == nil { 8211 t.Fatal("should error") 8212 } 8213 8214 actual := strings.TrimSpace(state.String()) 8215 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 8216 if actual != expected { 8217 t.Fatalf("bad: \n%s", actual) 8218 } 8219 } 8220 8221 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 8222 m := testModule(t, "apply-unknown-interpolate") 8223 p := testProvider("aws") 8224 p.ApplyFn = testApplyFn 8225 p.DiffFn = testDiffFn 8226 ctx := testContext2(t, &ContextOpts{ 8227 Module: m, 8228 ProviderResolver: ResourceProviderResolverFixed( 8229 map[string]ResourceProviderFactory{ 8230 "aws": testProviderFuncFixed(p), 8231 }, 8232 ), 8233 }) 8234 8235 if _, err := ctx.Plan(); err == nil { 8236 t.Fatal("should error") 8237 } 8238 } 8239 8240 func TestContext2Apply_vars(t *testing.T) { 8241 m := testModule(t, "apply-vars") 8242 p := testProvider("aws") 8243 p.ApplyFn = testApplyFn 8244 p.DiffFn = testDiffFn 8245 ctx := testContext2(t, &ContextOpts{ 8246 Module: m, 8247 ProviderResolver: ResourceProviderResolverFixed( 8248 map[string]ResourceProviderFactory{ 8249 "aws": testProviderFuncFixed(p), 8250 }, 8251 ), 8252 Variables: map[string]interface{}{ 8253 "foo": "us-west-2", 8254 "test_list": []interface{}{"Hello", "World"}, 8255 "test_map": map[string]interface{}{ 8256 "Hello": "World", 8257 "Foo": "Bar", 8258 "Baz": "Foo", 8259 }, 8260 "amis": []map[string]interface{}{ 8261 map[string]interface{}{ 8262 "us-east-1": "override", 8263 }, 8264 }, 8265 }, 8266 }) 8267 8268 diags := ctx.Validate() 8269 if len(diags) != 0 { 8270 t.Fatalf("bad: %#v", diags) 8271 } 8272 8273 if _, err := ctx.Plan(); err != nil { 8274 t.Fatalf("err: %s", err) 8275 } 8276 8277 state, err := ctx.Apply() 8278 if err != nil { 8279 t.Fatalf("err: %s", err) 8280 } 8281 8282 actual := strings.TrimSpace(state.String()) 8283 expected := strings.TrimSpace(testTerraformApplyVarsStr) 8284 if actual != expected { 8285 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 8286 } 8287 } 8288 8289 func TestContext2Apply_varsEnv(t *testing.T) { 8290 // Set the env var 8291 defer tempEnv(t, "TF_VAR_ami", "baz")() 8292 defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() 8293 defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() 8294 8295 m := testModule(t, "apply-vars-env") 8296 p := testProvider("aws") 8297 p.ApplyFn = testApplyFn 8298 p.DiffFn = testDiffFn 8299 ctx := testContext2(t, &ContextOpts{ 8300 Module: m, 8301 ProviderResolver: ResourceProviderResolverFixed( 8302 map[string]ResourceProviderFactory{ 8303 "aws": testProviderFuncFixed(p), 8304 }, 8305 ), 8306 }) 8307 8308 diags := ctx.Validate() 8309 if len(diags) != 0 { 8310 t.Fatalf("bad: %#v", diags) 8311 } 8312 8313 if _, err := ctx.Plan(); err != nil { 8314 t.Fatalf("err: %s", err) 8315 } 8316 8317 state, err := ctx.Apply() 8318 if err != nil { 8319 t.Fatalf("err: %s", err) 8320 } 8321 8322 actual := strings.TrimSpace(state.String()) 8323 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 8324 if actual != expected { 8325 t.Fatalf("bad: \n%s", actual) 8326 } 8327 } 8328 8329 func TestContext2Apply_createBefore_depends(t *testing.T) { 8330 m := testModule(t, "apply-depends-create-before") 8331 h := new(HookRecordApplyOrder) 8332 p := testProvider("aws") 8333 p.ApplyFn = testApplyFn 8334 p.DiffFn = testDiffFn 8335 state := &State{ 8336 Modules: []*ModuleState{ 8337 &ModuleState{ 8338 Path: rootModulePath, 8339 Resources: map[string]*ResourceState{ 8340 "aws_instance.web": &ResourceState{ 8341 Type: "aws_instance", 8342 Primary: &InstanceState{ 8343 ID: "bar", 8344 Attributes: map[string]string{ 8345 "require_new": "ami-old", 8346 }, 8347 }, 8348 }, 8349 "aws_instance.lb": &ResourceState{ 8350 Type: "aws_instance", 8351 Primary: &InstanceState{ 8352 ID: "baz", 8353 Attributes: map[string]string{ 8354 "instance": "bar", 8355 }, 8356 }, 8357 }, 8358 }, 8359 }, 8360 }, 8361 } 8362 ctx := testContext2(t, &ContextOpts{ 8363 Module: m, 8364 Hooks: []Hook{h}, 8365 ProviderResolver: ResourceProviderResolverFixed( 8366 map[string]ResourceProviderFactory{ 8367 "aws": testProviderFuncFixed(p), 8368 }, 8369 ), 8370 State: state, 8371 }) 8372 8373 if p, err := ctx.Plan(); err != nil { 8374 t.Fatalf("err: %s", err) 8375 } else { 8376 t.Logf("plan: %s", p) 8377 } 8378 8379 h.Active = true 8380 state, err := ctx.Apply() 8381 if err != nil { 8382 t.Fatalf("err: %s", err) 8383 } 8384 8385 mod := state.RootModule() 8386 if len(mod.Resources) < 2 { 8387 t.Fatalf("bad: %#v", mod.Resources) 8388 } 8389 8390 actual := strings.TrimSpace(state.String()) 8391 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 8392 if actual != expected { 8393 t.Fatalf("bad: \n%s\n\n%s", actual, expected) 8394 } 8395 8396 // Test that things were managed _in the right order_ 8397 order := h.States 8398 diffs := h.Diffs 8399 if order[0].ID != "" || diffs[0].Destroy { 8400 t.Fatalf("should create new instance first: %#v", order) 8401 } 8402 8403 if order[1].ID != "baz" { 8404 t.Fatalf("update must happen after create: %#v", order) 8405 } 8406 8407 if order[2].ID != "bar" || !diffs[2].Destroy { 8408 t.Fatalf("destroy must happen after update: %#v", order) 8409 } 8410 } 8411 8412 func TestContext2Apply_singleDestroy(t *testing.T) { 8413 m := testModule(t, "apply-depends-create-before") 8414 h := new(HookRecordApplyOrder) 8415 p := testProvider("aws") 8416 8417 invokeCount := 0 8418 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 8419 invokeCount++ 8420 switch invokeCount { 8421 case 1: 8422 if d.Destroy { 8423 t.Fatalf("should not destroy") 8424 } 8425 if s.ID != "" { 8426 t.Fatalf("should not have ID") 8427 } 8428 case 2: 8429 if d.Destroy { 8430 t.Fatalf("should not destroy") 8431 } 8432 if s.ID != "baz" { 8433 t.Fatalf("should have id") 8434 } 8435 case 3: 8436 if !d.Destroy { 8437 t.Fatalf("should destroy") 8438 } 8439 if s.ID == "" { 8440 t.Fatalf("should have ID") 8441 } 8442 default: 8443 t.Fatalf("bad invoke count %d", invokeCount) 8444 } 8445 return testApplyFn(info, s, d) 8446 } 8447 p.DiffFn = testDiffFn 8448 state := &State{ 8449 Modules: []*ModuleState{ 8450 &ModuleState{ 8451 Path: rootModulePath, 8452 Resources: map[string]*ResourceState{ 8453 "aws_instance.web": &ResourceState{ 8454 Type: "aws_instance", 8455 Primary: &InstanceState{ 8456 ID: "bar", 8457 Attributes: map[string]string{ 8458 "require_new": "ami-old", 8459 }, 8460 }, 8461 }, 8462 "aws_instance.lb": &ResourceState{ 8463 Type: "aws_instance", 8464 Primary: &InstanceState{ 8465 ID: "baz", 8466 Attributes: map[string]string{ 8467 "instance": "bar", 8468 }, 8469 }, 8470 }, 8471 }, 8472 }, 8473 }, 8474 } 8475 ctx := testContext2(t, &ContextOpts{ 8476 Module: m, 8477 Hooks: []Hook{h}, 8478 ProviderResolver: ResourceProviderResolverFixed( 8479 map[string]ResourceProviderFactory{ 8480 "aws": testProviderFuncFixed(p), 8481 }, 8482 ), 8483 State: state, 8484 }) 8485 8486 if _, err := ctx.Plan(); err != nil { 8487 t.Fatalf("err: %s", err) 8488 } 8489 8490 h.Active = true 8491 state, err := ctx.Apply() 8492 if err != nil { 8493 t.Fatalf("err: %s", err) 8494 } 8495 8496 if invokeCount != 3 { 8497 t.Fatalf("bad: %d", invokeCount) 8498 } 8499 } 8500 8501 // GH-7824 8502 func TestContext2Apply_issue7824(t *testing.T) { 8503 p := testProvider("template") 8504 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 8505 Name: "template_file", 8506 }) 8507 8508 p.ApplyFn = testApplyFn 8509 p.DiffFn = testDiffFn 8510 8511 // Apply cleanly step 0 8512 ctx := testContext2(t, &ContextOpts{ 8513 Module: testModule(t, "issue-7824"), 8514 ProviderResolver: ResourceProviderResolverFixed( 8515 map[string]ResourceProviderFactory{ 8516 "template": testProviderFuncFixed(p), 8517 }, 8518 ), 8519 }) 8520 8521 plan, err := ctx.Plan() 8522 if err != nil { 8523 t.Fatalf("err: %s", err) 8524 } 8525 8526 // Write / Read plan to simulate running it through a Plan file 8527 var buf bytes.Buffer 8528 if err := WritePlan(plan, &buf); err != nil { 8529 t.Fatalf("err: %s", err) 8530 } 8531 8532 planFromFile, err := ReadPlan(&buf) 8533 if err != nil { 8534 t.Fatalf("err: %s", err) 8535 } 8536 8537 ctx, err = planFromFile.Context(&ContextOpts{ 8538 ProviderResolver: ResourceProviderResolverFixed( 8539 map[string]ResourceProviderFactory{ 8540 "template": testProviderFuncFixed(p), 8541 }, 8542 ), 8543 }) 8544 if err != nil { 8545 t.Fatalf("err: %s", err) 8546 } 8547 8548 _, err = ctx.Apply() 8549 if err != nil { 8550 t.Fatalf("err: %s", err) 8551 } 8552 } 8553 8554 // GH-5254 8555 func TestContext2Apply_issue5254(t *testing.T) { 8556 // Create a provider. We use "template" here just to match the repro 8557 // we got from the issue itself. 8558 p := testProvider("template") 8559 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 8560 Name: "template_file", 8561 }) 8562 8563 p.ApplyFn = testApplyFn 8564 p.DiffFn = testDiffFn 8565 8566 // Apply cleanly step 0 8567 ctx := testContext2(t, &ContextOpts{ 8568 Module: testModule(t, "issue-5254/step-0"), 8569 ProviderResolver: ResourceProviderResolverFixed( 8570 map[string]ResourceProviderFactory{ 8571 "template": testProviderFuncFixed(p), 8572 }, 8573 ), 8574 }) 8575 8576 plan, err := ctx.Plan() 8577 if err != nil { 8578 t.Fatalf("err: %s", err) 8579 } 8580 8581 state, err := ctx.Apply() 8582 if err != nil { 8583 t.Fatalf("err: %s", err) 8584 } 8585 8586 // Application success. Now make the modification and store a plan 8587 ctx = testContext2(t, &ContextOpts{ 8588 Module: testModule(t, "issue-5254/step-1"), 8589 State: state, 8590 ProviderResolver: ResourceProviderResolverFixed( 8591 map[string]ResourceProviderFactory{ 8592 "template": testProviderFuncFixed(p), 8593 }, 8594 ), 8595 }) 8596 8597 plan, err = ctx.Plan() 8598 if err != nil { 8599 t.Fatalf("err: %s", err) 8600 } 8601 8602 // Write / Read plan to simulate running it through a Plan file 8603 var buf bytes.Buffer 8604 if err := WritePlan(plan, &buf); err != nil { 8605 t.Fatalf("err: %s", err) 8606 } 8607 8608 planFromFile, err := ReadPlan(&buf) 8609 if err != nil { 8610 t.Fatalf("err: %s", err) 8611 } 8612 8613 ctx, err = planFromFile.Context(&ContextOpts{ 8614 ProviderResolver: ResourceProviderResolverFixed( 8615 map[string]ResourceProviderFactory{ 8616 "template": testProviderFuncFixed(p), 8617 }, 8618 ), 8619 }) 8620 if err != nil { 8621 t.Fatalf("err: %s", err) 8622 } 8623 8624 state, err = ctx.Apply() 8625 if err != nil { 8626 t.Fatalf("err: %s", err) 8627 } 8628 8629 actual := strings.TrimSpace(state.String()) 8630 expected := strings.TrimSpace(` 8631 template_file.child: 8632 ID = foo 8633 provider = provider.template 8634 template = Hi 8635 type = template_file 8636 8637 Dependencies: 8638 template_file.parent.* 8639 template_file.parent: 8640 ID = foo 8641 provider = provider.template 8642 template = Hi 8643 type = template_file 8644 `) 8645 if actual != expected { 8646 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 8647 } 8648 } 8649 8650 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 8651 p := testProvider("aws") 8652 p.DiffFn = testDiffFn 8653 p.ApplyFn = testApplyFn 8654 ctx := testContext2(t, &ContextOpts{ 8655 Module: testModule(t, "apply-tainted-targets"), 8656 ProviderResolver: ResourceProviderResolverFixed( 8657 map[string]ResourceProviderFactory{ 8658 "aws": testProviderFuncFixed(p), 8659 }, 8660 ), 8661 Targets: []string{"aws_instance.iambeingadded"}, 8662 State: &State{ 8663 Modules: []*ModuleState{ 8664 &ModuleState{ 8665 Path: rootModulePath, 8666 Resources: map[string]*ResourceState{ 8667 "aws_instance.ifailedprovisioners": &ResourceState{ 8668 Type: "aws_instance", 8669 Primary: &InstanceState{ 8670 ID: "ifailedprovisioners", 8671 Tainted: true, 8672 }, 8673 }, 8674 }, 8675 }, 8676 }, 8677 }, 8678 }) 8679 8680 plan, err := ctx.Plan() 8681 if err != nil { 8682 t.Fatalf("err: %s", err) 8683 } 8684 8685 // Write / Read plan to simulate running it through a Plan file 8686 var buf bytes.Buffer 8687 if err := WritePlan(plan, &buf); err != nil { 8688 t.Fatalf("err: %s", err) 8689 } 8690 8691 planFromFile, err := ReadPlan(&buf) 8692 if err != nil { 8693 t.Fatalf("err: %s", err) 8694 } 8695 8696 ctx, err = planFromFile.Context(&ContextOpts{ 8697 Module: testModule(t, "apply-tainted-targets"), 8698 ProviderResolver: ResourceProviderResolverFixed( 8699 map[string]ResourceProviderFactory{ 8700 "aws": testProviderFuncFixed(p), 8701 }, 8702 ), 8703 }) 8704 if err != nil { 8705 t.Fatalf("err: %s", err) 8706 } 8707 8708 state, err := ctx.Apply() 8709 if err != nil { 8710 t.Fatalf("err: %s", err) 8711 } 8712 8713 actual := strings.TrimSpace(state.String()) 8714 expected := strings.TrimSpace(` 8715 aws_instance.iambeingadded: 8716 ID = foo 8717 provider = provider.aws 8718 aws_instance.ifailedprovisioners: (tainted) 8719 ID = ifailedprovisioners 8720 `) 8721 if actual != expected { 8722 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 8723 } 8724 } 8725 8726 // Higher level test exposing the bug this covers in 8727 // TestResource_ignoreChangesRequired 8728 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 8729 m := testModule(t, "apply-ignore-changes-create") 8730 p := testProvider("aws") 8731 p.ApplyFn = testApplyFn 8732 p.DiffFn = testDiffFn 8733 ctx := testContext2(t, &ContextOpts{ 8734 Module: m, 8735 ProviderResolver: ResourceProviderResolverFixed( 8736 map[string]ResourceProviderFactory{ 8737 "aws": testProviderFuncFixed(p), 8738 }, 8739 ), 8740 }) 8741 8742 if p, err := ctx.Plan(); err != nil { 8743 t.Fatalf("err: %s", err) 8744 } else { 8745 t.Logf(p.String()) 8746 } 8747 8748 state, err := ctx.Apply() 8749 if err != nil { 8750 t.Fatalf("err: %s", err) 8751 } 8752 8753 mod := state.RootModule() 8754 if len(mod.Resources) != 1 { 8755 t.Fatalf("bad: %s", state) 8756 } 8757 8758 actual := strings.TrimSpace(state.String()) 8759 // Expect no changes from original state 8760 expected := strings.TrimSpace(` 8761 aws_instance.foo: 8762 ID = foo 8763 provider = provider.aws 8764 required_field = set 8765 type = aws_instance 8766 `) 8767 if actual != expected { 8768 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 8769 } 8770 } 8771 8772 func TestContext2Apply_ignoreChangesWithDep(t *testing.T) { 8773 m := testModule(t, "apply-ignore-changes-dep") 8774 p := testProvider("aws") 8775 p.ApplyFn = testApplyFn 8776 p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 8777 switch i.Type { 8778 case "aws_instance": 8779 newAmi, _ := c.Get("ami") 8780 return &InstanceDiff{ 8781 Attributes: map[string]*ResourceAttrDiff{ 8782 "ami": &ResourceAttrDiff{ 8783 Old: s.Attributes["ami"], 8784 New: newAmi.(string), 8785 RequiresNew: true, 8786 }, 8787 }, 8788 }, nil 8789 case "aws_eip": 8790 return testDiffFn(i, s, c) 8791 default: 8792 t.Fatalf("Unexpected type: %s", i.Type) 8793 return nil, nil 8794 } 8795 } 8796 s := &State{ 8797 Modules: []*ModuleState{ 8798 &ModuleState{ 8799 Path: rootModulePath, 8800 Resources: map[string]*ResourceState{ 8801 "aws_instance.foo.0": &ResourceState{ 8802 Type: "aws_instance", 8803 Primary: &InstanceState{ 8804 ID: "i-abc123", 8805 Attributes: map[string]string{ 8806 "ami": "ami-abcd1234", 8807 "id": "i-abc123", 8808 }, 8809 }, 8810 }, 8811 "aws_instance.foo.1": &ResourceState{ 8812 Type: "aws_instance", 8813 Primary: &InstanceState{ 8814 ID: "i-bcd234", 8815 Attributes: map[string]string{ 8816 "ami": "ami-abcd1234", 8817 "id": "i-bcd234", 8818 }, 8819 }, 8820 }, 8821 "aws_eip.foo.0": &ResourceState{ 8822 Type: "aws_instance", 8823 Primary: &InstanceState{ 8824 ID: "eip-abc123", 8825 Attributes: map[string]string{ 8826 "id": "eip-abc123", 8827 "instance": "i-abc123", 8828 }, 8829 }, 8830 }, 8831 "aws_eip.foo.1": &ResourceState{ 8832 Type: "aws_instance", 8833 Primary: &InstanceState{ 8834 ID: "eip-bcd234", 8835 Attributes: map[string]string{ 8836 "id": "eip-bcd234", 8837 "instance": "i-bcd234", 8838 }, 8839 }, 8840 }, 8841 }, 8842 }, 8843 }, 8844 } 8845 ctx := testContext2(t, &ContextOpts{ 8846 Module: m, 8847 ProviderResolver: ResourceProviderResolverFixed( 8848 map[string]ResourceProviderFactory{ 8849 "aws": testProviderFuncFixed(p), 8850 }, 8851 ), 8852 State: s, 8853 }) 8854 8855 if p, err := ctx.Plan(); err != nil { 8856 t.Fatalf("err: %s", err) 8857 } else { 8858 t.Logf(p.String()) 8859 } 8860 8861 state, err := ctx.Apply() 8862 if err != nil { 8863 t.Fatalf("err: %s", err) 8864 } 8865 8866 actual := strings.TrimSpace(state.String()) 8867 expected := strings.TrimSpace(s.String()) 8868 if actual != expected { 8869 t.Fatalf("bad: \n%s", actual) 8870 } 8871 } 8872 8873 func TestContext2Apply_ignoreChangesWildcard(t *testing.T) { 8874 m := testModule(t, "apply-ignore-changes-wildcard") 8875 p := testProvider("aws") 8876 p.ApplyFn = testApplyFn 8877 p.DiffFn = testDiffFn 8878 ctx := testContext2(t, &ContextOpts{ 8879 Module: m, 8880 ProviderResolver: ResourceProviderResolverFixed( 8881 map[string]ResourceProviderFactory{ 8882 "aws": testProviderFuncFixed(p), 8883 }, 8884 ), 8885 }) 8886 8887 if p, err := ctx.Plan(); err != nil { 8888 t.Fatalf("err: %s", err) 8889 } else { 8890 t.Logf(p.String()) 8891 } 8892 8893 state, err := ctx.Apply() 8894 if err != nil { 8895 t.Fatalf("err: %s", err) 8896 } 8897 8898 mod := state.RootModule() 8899 if len(mod.Resources) != 1 { 8900 t.Fatalf("bad: %s", state) 8901 } 8902 8903 actual := strings.TrimSpace(state.String()) 8904 // Expect no changes from original state 8905 expected := strings.TrimSpace(` 8906 aws_instance.foo: 8907 ID = foo 8908 provider = provider.aws 8909 required_field = set 8910 type = aws_instance 8911 `) 8912 if actual != expected { 8913 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 8914 } 8915 } 8916 8917 // https://github.com/hashicorp/terraform/issues/7378 8918 func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) { 8919 m := testModule(t, "apply-destroy-nested-module-with-attrs") 8920 p := testProvider("null") 8921 p.ApplyFn = testApplyFn 8922 p.DiffFn = testDiffFn 8923 8924 var state *State 8925 var err error 8926 { 8927 ctx := testContext2(t, &ContextOpts{ 8928 Module: m, 8929 ProviderResolver: ResourceProviderResolverFixed( 8930 map[string]ResourceProviderFactory{ 8931 "null": testProviderFuncFixed(p), 8932 }, 8933 ), 8934 }) 8935 8936 // First plan and apply a create operation 8937 if _, err := ctx.Plan(); err != nil { 8938 t.Fatalf("plan err: %s", err) 8939 } 8940 8941 state, err = ctx.Apply() 8942 if err != nil { 8943 t.Fatalf("apply err: %s", err) 8944 } 8945 } 8946 8947 { 8948 ctx := testContext2(t, &ContextOpts{ 8949 Destroy: true, 8950 Module: m, 8951 State: state, 8952 ProviderResolver: ResourceProviderResolverFixed( 8953 map[string]ResourceProviderFactory{ 8954 "null": testProviderFuncFixed(p), 8955 }, 8956 ), 8957 }) 8958 8959 plan, err := ctx.Plan() 8960 if err != nil { 8961 t.Fatalf("destroy plan err: %s", err) 8962 } 8963 8964 var buf bytes.Buffer 8965 if err := WritePlan(plan, &buf); err != nil { 8966 t.Fatalf("plan write err: %s", err) 8967 } 8968 8969 planFromFile, err := ReadPlan(&buf) 8970 if err != nil { 8971 t.Fatalf("plan read err: %s", err) 8972 } 8973 8974 ctx, err = planFromFile.Context(&ContextOpts{ 8975 ProviderResolver: ResourceProviderResolverFixed( 8976 map[string]ResourceProviderFactory{ 8977 "null": testProviderFuncFixed(p), 8978 }, 8979 ), 8980 }) 8981 if err != nil { 8982 t.Fatalf("err: %s", err) 8983 } 8984 8985 state, err = ctx.Apply() 8986 if err != nil { 8987 t.Fatalf("destroy apply err: %s", err) 8988 } 8989 } 8990 8991 //Test that things were destroyed 8992 actual := strings.TrimSpace(state.String()) 8993 expected := strings.TrimSpace(` 8994 <no state> 8995 module.middle: 8996 <no state> 8997 module.middle.bottom: 8998 <no state> 8999 `) 9000 if actual != expected { 9001 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 9002 } 9003 } 9004 9005 // If a data source explicitly depends on another resource, it's because we need 9006 // that resource to be applied first. 9007 func TestContext2Apply_dataDependsOn(t *testing.T) { 9008 p := testProvider("null") 9009 m := testModule(t, "apply-data-depends-on") 9010 9011 ctx := testContext2(t, &ContextOpts{ 9012 Module: m, 9013 ProviderResolver: ResourceProviderResolverFixed( 9014 map[string]ResourceProviderFactory{ 9015 "null": testProviderFuncFixed(p), 9016 }, 9017 ), 9018 }) 9019 9020 // the "provisioner" here writes to this variable, because the intent is to 9021 // create a dependency which can't be viewed through the graph, and depends 9022 // solely on the configuration providing "depends_on" 9023 provisionerOutput := "" 9024 9025 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 9026 // the side effect of the resource being applied 9027 provisionerOutput = "APPLIED" 9028 return testApplyFn(info, s, d) 9029 } 9030 9031 p.DiffFn = testDiffFn 9032 p.ReadDataDiffFn = testDataDiffFn 9033 9034 p.ReadDataApplyFn = func(*InstanceInfo, *InstanceDiff) (*InstanceState, error) { 9035 // Read the artifact created by our dependency being applied. 9036 // Without any "depends_on", this would be skipped as it's assumed the 9037 // initial diff during refresh was all that's needed. 9038 return &InstanceState{ 9039 ID: "read", 9040 Attributes: map[string]string{ 9041 "foo": provisionerOutput, 9042 }, 9043 }, nil 9044 } 9045 9046 _, err := ctx.Refresh() 9047 if err != nil { 9048 t.Fatalf("err: %s", err) 9049 } 9050 9051 if _, err := ctx.Plan(); err != nil { 9052 t.Fatalf("err: %s", err) 9053 } 9054 9055 state, err := ctx.Apply() 9056 if err != nil { 9057 t.Fatalf("err: %s", err) 9058 } 9059 9060 root := state.ModuleByPath(RootModulePath) 9061 actual := root.Resources["data.null_data_source.read"].Primary.Attributes["foo"] 9062 9063 expected := "APPLIED" 9064 if actual != expected { 9065 t.Fatalf("bad:\n%s", strings.TrimSpace(state.String())) 9066 } 9067 } 9068 9069 func TestContext2Apply_terraformEnv(t *testing.T) { 9070 m := testModule(t, "apply-terraform-env") 9071 p := testProvider("aws") 9072 p.ApplyFn = testApplyFn 9073 p.DiffFn = testDiffFn 9074 9075 ctx := testContext2(t, &ContextOpts{ 9076 Meta: &ContextMeta{Env: "foo"}, 9077 Module: m, 9078 ProviderResolver: ResourceProviderResolverFixed( 9079 map[string]ResourceProviderFactory{ 9080 "aws": testProviderFuncFixed(p), 9081 }, 9082 ), 9083 }) 9084 9085 if _, err := ctx.Plan(); err != nil { 9086 t.Fatalf("err: %s", err) 9087 } 9088 9089 state, err := ctx.Apply() 9090 if err != nil { 9091 t.Fatalf("err: %s", err) 9092 } 9093 9094 actual := state.RootModule().Outputs["output"] 9095 expected := "foo" 9096 if actual == nil || actual.Value != expected { 9097 t.Fatalf("bad: \n%s", actual) 9098 } 9099 } 9100 9101 // verify that multiple config references only create a single depends_on entry 9102 func TestContext2Apply_multiRef(t *testing.T) { 9103 m := testModule(t, "apply-multi-ref") 9104 p := testProvider("aws") 9105 p.ApplyFn = testApplyFn 9106 p.DiffFn = testDiffFn 9107 9108 ctx := testContext2(t, &ContextOpts{ 9109 Module: m, 9110 ProviderResolver: ResourceProviderResolverFixed( 9111 map[string]ResourceProviderFactory{ 9112 "aws": testProviderFuncFixed(p), 9113 }, 9114 ), 9115 }) 9116 9117 if _, err := ctx.Plan(); err != nil { 9118 t.Fatalf("err: %s", err) 9119 } 9120 9121 state, err := ctx.Apply() 9122 if err != nil { 9123 t.Fatalf("err: %s", err) 9124 } 9125 9126 deps := state.Modules[0].Resources["aws_instance.other"].Dependencies 9127 if len(deps) > 1 || deps[0] != "aws_instance.create" { 9128 t.Fatalf("expected 1 depends_on entry for aws_instance.create, got %q", deps) 9129 } 9130 } 9131 9132 func TestContext2Apply_targetedModuleRecursive(t *testing.T) { 9133 m := testModule(t, "apply-targeted-module-recursive") 9134 p := testProvider("aws") 9135 p.ApplyFn = testApplyFn 9136 p.DiffFn = testDiffFn 9137 ctx := testContext2(t, &ContextOpts{ 9138 Module: m, 9139 ProviderResolver: ResourceProviderResolverFixed( 9140 map[string]ResourceProviderFactory{ 9141 "aws": testProviderFuncFixed(p), 9142 }, 9143 ), 9144 Targets: []string{"module.child"}, 9145 }) 9146 9147 if _, err := ctx.Plan(); err != nil { 9148 t.Fatalf("err: %s", err) 9149 } 9150 9151 state, err := ctx.Apply() 9152 if err != nil { 9153 t.Fatalf("err: %s", err) 9154 } 9155 9156 mod := state.ModuleByPath([]string{"root", "child", "subchild"}) 9157 if mod == nil { 9158 t.Fatalf("no subchild module found in the state!\n\n%#v", state) 9159 } 9160 if len(mod.Resources) != 1 { 9161 t.Fatalf("expected 1 resources, got: %#v", mod.Resources) 9162 } 9163 9164 checkStateString(t, state, ` 9165 <no state> 9166 module.child.subchild: 9167 aws_instance.foo: 9168 ID = foo 9169 provider = provider.aws 9170 num = 2 9171 type = aws_instance 9172 `) 9173 } 9174 9175 func TestContext2Apply_localVal(t *testing.T) { 9176 m := testModule(t, "apply-local-val") 9177 ctx := testContext2(t, &ContextOpts{ 9178 Module: m, 9179 ProviderResolver: ResourceProviderResolverFixed( 9180 map[string]ResourceProviderFactory{}, 9181 ), 9182 }) 9183 9184 if _, err := ctx.Plan(); err != nil { 9185 t.Fatalf("error during plan: %s", err) 9186 } 9187 9188 state, err := ctx.Apply() 9189 if err != nil { 9190 t.Fatalf("error during apply: %s", err) 9191 } 9192 9193 got := strings.TrimSpace(state.String()) 9194 want := strings.TrimSpace(` 9195 <no state> 9196 Outputs: 9197 9198 result_1 = hello 9199 result_3 = hello world 9200 9201 module.child: 9202 <no state> 9203 Outputs: 9204 9205 result = hello 9206 `) 9207 if got != want { 9208 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9209 } 9210 } 9211 9212 func TestContext2Apply_destroyWithLocals(t *testing.T) { 9213 m := testModule(t, "apply-destroy-with-locals") 9214 p := testProvider("aws") 9215 p.ApplyFn = testApplyFn 9216 p.DiffFn = func(info *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 9217 d, err := testDiffFn(info, s, c) 9218 return d, err 9219 } 9220 9221 s := &State{ 9222 Modules: []*ModuleState{ 9223 &ModuleState{ 9224 Path: rootModulePath, 9225 Outputs: map[string]*OutputState{ 9226 "name": &OutputState{ 9227 Type: "string", 9228 Value: "test-bar", 9229 }, 9230 }, 9231 Resources: map[string]*ResourceState{ 9232 "aws_instance.foo": &ResourceState{ 9233 Type: "aws_instance", 9234 Primary: &InstanceState{ 9235 ID: "foo", 9236 // FIXME: id should only exist in one place 9237 Attributes: map[string]string{ 9238 "id": "foo", 9239 }, 9240 }, 9241 }, 9242 }, 9243 }, 9244 }, 9245 } 9246 9247 ctx := testContext2(t, &ContextOpts{ 9248 Module: m, 9249 ProviderResolver: ResourceProviderResolverFixed( 9250 map[string]ResourceProviderFactory{ 9251 "aws": testProviderFuncFixed(p), 9252 }, 9253 ), 9254 State: s, 9255 Destroy: true, 9256 }) 9257 9258 if _, err := ctx.Plan(); err != nil { 9259 t.Fatalf("err: %s", err) 9260 } 9261 9262 state, err := ctx.Apply() 9263 if err != nil { 9264 t.Fatalf("error during apply: %s", err) 9265 } 9266 9267 got := strings.TrimSpace(state.String()) 9268 want := strings.TrimSpace(`<no state>`) 9269 if got != want { 9270 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9271 } 9272 } 9273 9274 func TestContext2Apply_providerWithLocals(t *testing.T) { 9275 m := testModule(t, "provider-with-locals") 9276 p := testProvider("aws") 9277 9278 providerRegion := "" 9279 // this should not be overridden during destroy 9280 p.ConfigureFn = func(c *ResourceConfig) error { 9281 if r, ok := c.Get("region"); ok { 9282 providerRegion = r.(string) 9283 } 9284 return nil 9285 } 9286 p.DiffFn = testDiffFn 9287 p.ApplyFn = testApplyFn 9288 ctx := testContext2(t, &ContextOpts{ 9289 Module: m, 9290 ProviderResolver: ResourceProviderResolverFixed( 9291 map[string]ResourceProviderFactory{ 9292 "aws": testProviderFuncFixed(p), 9293 }, 9294 ), 9295 }) 9296 9297 if _, err := ctx.Plan(); err != nil { 9298 t.Fatalf("err: %s", err) 9299 } 9300 9301 state, err := ctx.Apply() 9302 if err != nil { 9303 t.Fatalf("err: %s", err) 9304 } 9305 9306 ctx = testContext2(t, &ContextOpts{ 9307 Module: m, 9308 ProviderResolver: ResourceProviderResolverFixed( 9309 map[string]ResourceProviderFactory{ 9310 "aws": testProviderFuncFixed(p), 9311 }, 9312 ), 9313 State: state, 9314 Destroy: true, 9315 }) 9316 9317 if _, err = ctx.Plan(); err != nil { 9318 t.Fatalf("err: %s", err) 9319 } 9320 9321 state, err = ctx.Apply() 9322 if err != nil { 9323 t.Fatalf("err: %s", err) 9324 } 9325 9326 if state.HasResources() { 9327 t.Fatal("expected no state, got:", state) 9328 } 9329 9330 if providerRegion != "bar" { 9331 t.Fatalf("expected region %q, got: %q", "bar", providerRegion) 9332 } 9333 } 9334 9335 func TestContext2Apply_destroyWithProviders(t *testing.T) { 9336 m := testModule(t, "destroy-module-with-provider") 9337 p := testProvider("aws") 9338 p.ApplyFn = testApplyFn 9339 p.DiffFn = testDiffFn 9340 9341 s := &State{ 9342 Modules: []*ModuleState{ 9343 &ModuleState{ 9344 Path: rootModulePath, 9345 }, 9346 &ModuleState{ 9347 Path: []string{"root", "child"}, 9348 }, 9349 &ModuleState{ 9350 Path: []string{"root", "mod", "removed"}, 9351 Resources: map[string]*ResourceState{ 9352 "aws_instance.child": &ResourceState{ 9353 Type: "aws_instance", 9354 Primary: &InstanceState{ 9355 ID: "bar", 9356 }, 9357 // this provider doesn't exist 9358 Provider: "provider.aws.baz", 9359 }, 9360 }, 9361 }, 9362 }, 9363 } 9364 9365 ctx := testContext2(t, &ContextOpts{ 9366 Module: m, 9367 ProviderResolver: ResourceProviderResolverFixed( 9368 map[string]ResourceProviderFactory{ 9369 "aws": testProviderFuncFixed(p), 9370 }, 9371 ), 9372 State: s, 9373 Destroy: true, 9374 }) 9375 9376 // test that we can't destroy if the provider is missing 9377 if _, err := ctx.Plan(); err == nil { 9378 t.Fatal("expected plan error, provider.aws.baz doesn't exist") 9379 } 9380 9381 // correct the state 9382 s.Modules[2].Resources["aws_instance.child"].Provider = "provider.aws.bar" 9383 9384 if _, err := ctx.Plan(); err != nil { 9385 t.Fatal(err) 9386 } 9387 state, err := ctx.Apply() 9388 if err != nil { 9389 t.Fatalf("error during apply: %s", err) 9390 } 9391 9392 got := strings.TrimSpace(state.String()) 9393 9394 want := strings.TrimSpace("<no state>") 9395 if got != want { 9396 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", got, want) 9397 } 9398 } 9399 9400 func TestContext2Apply_providersFromState(t *testing.T) { 9401 m := module.NewEmptyTree() 9402 p := testProvider("aws") 9403 p.DiffFn = testDiffFn 9404 9405 for _, tc := range []struct { 9406 name string 9407 state *State 9408 output string 9409 err bool 9410 }{ 9411 { 9412 name: "add implicit provider", 9413 state: &State{ 9414 Modules: []*ModuleState{ 9415 &ModuleState{ 9416 Path: []string{"root"}, 9417 Resources: map[string]*ResourceState{ 9418 "aws_instance.a": &ResourceState{ 9419 Type: "aws_instance", 9420 Primary: &InstanceState{ 9421 ID: "bar", 9422 }, 9423 Provider: "provider.aws", 9424 }, 9425 }, 9426 }, 9427 }, 9428 }, 9429 err: false, 9430 output: "<no state>", 9431 }, 9432 9433 // an aliased provider must be in the config to remove a resource 9434 { 9435 name: "add aliased provider", 9436 state: &State{ 9437 Modules: []*ModuleState{ 9438 &ModuleState{ 9439 Path: []string{"root"}, 9440 Resources: map[string]*ResourceState{ 9441 "aws_instance.a": &ResourceState{ 9442 Type: "aws_instance", 9443 Primary: &InstanceState{ 9444 ID: "bar", 9445 }, 9446 Provider: "provider.aws.bar", 9447 }, 9448 }, 9449 }, 9450 }, 9451 }, 9452 err: true, 9453 }, 9454 9455 // a provider in a module implies some sort of config, so this isn't 9456 // allowed even without an alias 9457 { 9458 name: "add unaliased module provider", 9459 state: &State{ 9460 Modules: []*ModuleState{ 9461 &ModuleState{ 9462 Path: []string{"root", "child"}, 9463 Resources: map[string]*ResourceState{ 9464 "aws_instance.a": &ResourceState{ 9465 Type: "aws_instance", 9466 Primary: &InstanceState{ 9467 ID: "bar", 9468 }, 9469 Provider: "module.child.provider.aws", 9470 }, 9471 }, 9472 }, 9473 }, 9474 }, 9475 err: true, 9476 }, 9477 } { 9478 9479 t.Run(tc.name, func(t *testing.T) { 9480 ctx := testContext2(t, &ContextOpts{ 9481 Module: m, 9482 ProviderResolver: ResourceProviderResolverFixed( 9483 map[string]ResourceProviderFactory{ 9484 "aws": testProviderFuncFixed(p), 9485 }, 9486 ), 9487 State: tc.state, 9488 }) 9489 9490 _, err := ctx.Plan() 9491 if tc.err { 9492 if err == nil { 9493 t.Fatal("expected error") 9494 } else { 9495 return 9496 } 9497 } 9498 if !tc.err && err != nil { 9499 t.Fatal(err) 9500 } 9501 9502 state, err := ctx.Apply() 9503 if err != nil { 9504 t.Fatalf("err: %s", err) 9505 } 9506 9507 checkStateString(t, state, "<no state>") 9508 9509 }) 9510 } 9511 } 9512 9513 func TestContext2Apply_plannedInterpolatedCount(t *testing.T) { 9514 m := testModule(t, "apply-interpolated-count") 9515 9516 p := testProvider("aws") 9517 p.ApplyFn = testApplyFn 9518 p.DiffFn = testDiffFn 9519 9520 providerResolver := ResourceProviderResolverFixed( 9521 map[string]ResourceProviderFactory{ 9522 "aws": testProviderFuncFixed(p), 9523 }, 9524 ) 9525 9526 s := &State{ 9527 Modules: []*ModuleState{ 9528 &ModuleState{ 9529 Path: rootModulePath, 9530 Resources: map[string]*ResourceState{ 9531 "aws_instance.test": { 9532 Type: "aws_instance", 9533 Primary: &InstanceState{ 9534 ID: "foo", 9535 }, 9536 Provider: "provider.aws", 9537 }, 9538 }, 9539 }, 9540 }, 9541 } 9542 9543 ctx := testContext2(t, &ContextOpts{ 9544 Module: m, 9545 ProviderResolver: providerResolver, 9546 State: s, 9547 }) 9548 9549 plan, err := ctx.Plan() 9550 if err != nil { 9551 t.Fatalf("plan failed: %s", err) 9552 } 9553 9554 // We'll marshal and unmarshal the plan here, to ensure that we have 9555 // a clean new context as would be created if we separately ran 9556 // terraform plan -out=tfplan && terraform apply tfplan 9557 var planBuf bytes.Buffer 9558 err = WritePlan(plan, &planBuf) 9559 if err != nil { 9560 t.Fatalf("failed to write plan: %s", err) 9561 } 9562 plan, err = ReadPlan(&planBuf) 9563 if err != nil { 9564 t.Fatalf("failed to read plan: %s", err) 9565 } 9566 9567 ctx, err = plan.Context(&ContextOpts{ 9568 ProviderResolver: providerResolver, 9569 }) 9570 if err != nil { 9571 t.Fatalf("failed to create context for plan: %s", err) 9572 } 9573 9574 // Applying the plan should now succeed 9575 _, err = ctx.Apply() 9576 if err != nil { 9577 t.Fatalf("apply failed: %s", err) 9578 } 9579 } 9580 9581 func TestContext2Apply_plannedDestroyInterpolatedCount(t *testing.T) { 9582 m := testModule(t, "plan-destroy-interpolated-count") 9583 9584 p := testProvider("aws") 9585 p.ApplyFn = testApplyFn 9586 p.DiffFn = testDiffFn 9587 9588 providerResolver := ResourceProviderResolverFixed( 9589 map[string]ResourceProviderFactory{ 9590 "aws": testProviderFuncFixed(p), 9591 }, 9592 ) 9593 9594 s := &State{ 9595 Modules: []*ModuleState{ 9596 &ModuleState{ 9597 Path: rootModulePath, 9598 Resources: map[string]*ResourceState{ 9599 "aws_instance.a.0": { 9600 Type: "aws_instance", 9601 Primary: &InstanceState{ 9602 ID: "foo", 9603 }, 9604 Provider: "provider.aws", 9605 }, 9606 "aws_instance.a.1": { 9607 Type: "aws_instance", 9608 Primary: &InstanceState{ 9609 ID: "foo", 9610 }, 9611 Provider: "provider.aws", 9612 }, 9613 }, 9614 Outputs: map[string]*OutputState{ 9615 "out": { 9616 Type: "list", 9617 Value: []string{"foo", "foo"}, 9618 }, 9619 }, 9620 }, 9621 }, 9622 } 9623 9624 ctx := testContext2(t, &ContextOpts{ 9625 Module: m, 9626 ProviderResolver: providerResolver, 9627 State: s, 9628 Destroy: true, 9629 }) 9630 9631 plan, err := ctx.Plan() 9632 if err != nil { 9633 t.Fatalf("plan failed: %s", err) 9634 } 9635 9636 // We'll marshal and unmarshal the plan here, to ensure that we have 9637 // a clean new context as would be created if we separately ran 9638 // terraform plan -out=tfplan && terraform apply tfplan 9639 var planBuf bytes.Buffer 9640 err = WritePlan(plan, &planBuf) 9641 if err != nil { 9642 t.Fatalf("failed to write plan: %s", err) 9643 } 9644 plan, err = ReadPlan(&planBuf) 9645 if err != nil { 9646 t.Fatalf("failed to read plan: %s", err) 9647 } 9648 9649 ctx, err = plan.Context(&ContextOpts{ 9650 ProviderResolver: providerResolver, 9651 Destroy: true, 9652 }) 9653 if err != nil { 9654 t.Fatalf("failed to create context for plan: %s", err) 9655 } 9656 9657 // Applying the plan should now succeed 9658 _, err = ctx.Apply() 9659 if err != nil { 9660 t.Fatalf("apply failed: %s", err) 9661 } 9662 } 9663 9664 func TestContext2Apply_scaleInMultivarRef(t *testing.T) { 9665 m := testModule(t, "apply-resource-scale-in") 9666 9667 p := testProvider("aws") 9668 p.ApplyFn = testApplyFn 9669 p.DiffFn = testDiffFn 9670 9671 providerResolver := ResourceProviderResolverFixed( 9672 map[string]ResourceProviderFactory{ 9673 "aws": testProviderFuncFixed(p), 9674 }, 9675 ) 9676 9677 s := &State{ 9678 Modules: []*ModuleState{ 9679 &ModuleState{ 9680 Path: rootModulePath, 9681 Resources: map[string]*ResourceState{ 9682 "aws_instance.one": { 9683 Type: "aws_instance", 9684 Primary: &InstanceState{ 9685 ID: "foo", 9686 }, 9687 Provider: "provider.aws", 9688 }, 9689 "aws_instance.two": { 9690 Type: "aws_instance", 9691 Primary: &InstanceState{ 9692 ID: "foo", 9693 Attributes: map[string]string{ 9694 "val": "foo", 9695 }, 9696 }, 9697 Provider: "provider.aws", 9698 }, 9699 }, 9700 }, 9701 }, 9702 } 9703 9704 ctx := testContext2(t, &ContextOpts{ 9705 Module: m, 9706 ProviderResolver: providerResolver, 9707 State: s, 9708 Variables: map[string]interface{}{"count": "0"}, 9709 }) 9710 9711 _, err := ctx.Plan() 9712 if err != nil { 9713 t.Fatalf("plan failed: %s", err) 9714 } 9715 9716 // Applying the plan should now succeed 9717 _, err = ctx.Apply() 9718 if err != nil { 9719 t.Fatalf("apply failed: %s", err) 9720 } 9721 }