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