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