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