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