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