github.com/dougneal/terraform@v0.6.15-0.20170330092735-b6a3840768a4/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 calls []string 4434 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4435 val, ok := c.Config["foo"] 4436 if !ok { 4437 t.Fatalf("bad value for foo: %v %#v", val, c) 4438 } 4439 4440 calls = append(calls, val.(string)) 4441 return fmt.Errorf("provisioner error") 4442 } 4443 4444 state := &State{ 4445 Modules: []*ModuleState{ 4446 &ModuleState{ 4447 Path: rootModulePath, 4448 Resources: map[string]*ResourceState{ 4449 "aws_instance.foo": &ResourceState{ 4450 Type: "aws_instance", 4451 Primary: &InstanceState{ 4452 ID: "bar", 4453 }, 4454 }, 4455 }, 4456 }, 4457 }, 4458 } 4459 4460 ctx := testContext2(t, &ContextOpts{ 4461 Module: m, 4462 State: state, 4463 Destroy: true, 4464 Providers: map[string]ResourceProviderFactory{ 4465 "aws": testProviderFuncFixed(p), 4466 }, 4467 Provisioners: map[string]ResourceProvisionerFactory{ 4468 "shell": testProvisionerFuncFixed(pr), 4469 }, 4470 }) 4471 4472 if _, err := ctx.Plan(); err != nil { 4473 t.Fatalf("err: %s", err) 4474 } 4475 4476 state, err := ctx.Apply() 4477 if err != nil { 4478 t.Fatalf("err: %s", err) 4479 } 4480 4481 checkStateString(t, state, `<no state>`) 4482 4483 // Verify apply was invoked 4484 if !pr.ApplyCalled { 4485 t.Fatalf("provisioner not invoked") 4486 } 4487 4488 expected := []string{"one", "two"} 4489 if !reflect.DeepEqual(calls, expected) { 4490 t.Fatalf("bad: %#v", calls) 4491 } 4492 } 4493 4494 // Verify that on destroy provisioner failure with "continue" that 4495 // we continue to the next provisioner. But if the next provisioner defines 4496 // to fail, then we fail after running it. 4497 func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) { 4498 m := testModule(t, "apply-provisioner-destroy-fail") 4499 p := testProvider("aws") 4500 pr := testProvisioner() 4501 p.ApplyFn = testApplyFn 4502 p.DiffFn = testDiffFn 4503 4504 var calls []string 4505 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4506 val, ok := c.Config["foo"] 4507 if !ok { 4508 t.Fatalf("bad value for foo: %v %#v", val, c) 4509 } 4510 4511 calls = append(calls, val.(string)) 4512 return fmt.Errorf("provisioner error") 4513 } 4514 4515 state := &State{ 4516 Modules: []*ModuleState{ 4517 &ModuleState{ 4518 Path: rootModulePath, 4519 Resources: map[string]*ResourceState{ 4520 "aws_instance.foo": &ResourceState{ 4521 Type: "aws_instance", 4522 Primary: &InstanceState{ 4523 ID: "bar", 4524 }, 4525 }, 4526 }, 4527 }, 4528 }, 4529 } 4530 4531 ctx := testContext2(t, &ContextOpts{ 4532 Module: m, 4533 State: state, 4534 Destroy: true, 4535 Providers: map[string]ResourceProviderFactory{ 4536 "aws": testProviderFuncFixed(p), 4537 }, 4538 Provisioners: map[string]ResourceProvisionerFactory{ 4539 "shell": testProvisionerFuncFixed(pr), 4540 }, 4541 }) 4542 4543 if _, err := ctx.Plan(); err != nil { 4544 t.Fatalf("err: %s", err) 4545 } 4546 4547 state, err := ctx.Apply() 4548 if err == nil { 4549 t.Fatal("should error") 4550 } 4551 4552 checkStateString(t, state, ` 4553 aws_instance.foo: 4554 ID = bar 4555 `) 4556 4557 // Verify apply was invoked 4558 if !pr.ApplyCalled { 4559 t.Fatalf("provisioner not invoked") 4560 } 4561 4562 expected := []string{"one", "two"} 4563 if !reflect.DeepEqual(calls, expected) { 4564 t.Fatalf("bad: %#v", calls) 4565 } 4566 } 4567 4568 // Verify destroy provisioners are not run for tainted instances. 4569 func TestContext2Apply_provisionerDestroyTainted(t *testing.T) { 4570 m := testModule(t, "apply-provisioner-destroy") 4571 p := testProvider("aws") 4572 pr := testProvisioner() 4573 p.ApplyFn = testApplyFn 4574 p.DiffFn = testDiffFn 4575 4576 destroyCalled := false 4577 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4578 expected := "create" 4579 if rs.ID == "bar" { 4580 destroyCalled = true 4581 return nil 4582 } 4583 4584 val, ok := c.Config["foo"] 4585 if !ok || val != expected { 4586 t.Fatalf("bad value for foo: %v %#v", val, c) 4587 } 4588 4589 return nil 4590 } 4591 4592 state := &State{ 4593 Modules: []*ModuleState{ 4594 &ModuleState{ 4595 Path: rootModulePath, 4596 Resources: map[string]*ResourceState{ 4597 "aws_instance.foo": &ResourceState{ 4598 Type: "aws_instance", 4599 Primary: &InstanceState{ 4600 ID: "bar", 4601 Tainted: true, 4602 }, 4603 }, 4604 }, 4605 }, 4606 }, 4607 } 4608 4609 ctx := testContext2(t, &ContextOpts{ 4610 Module: m, 4611 State: state, 4612 Providers: map[string]ResourceProviderFactory{ 4613 "aws": testProviderFuncFixed(p), 4614 }, 4615 Provisioners: map[string]ResourceProvisionerFactory{ 4616 "shell": testProvisionerFuncFixed(pr), 4617 }, 4618 }) 4619 4620 if _, err := ctx.Plan(); err != nil { 4621 t.Fatalf("err: %s", err) 4622 } 4623 4624 state, err := ctx.Apply() 4625 if err != nil { 4626 t.Fatalf("err: %s", err) 4627 } 4628 4629 checkStateString(t, state, ` 4630 aws_instance.foo: 4631 ID = foo 4632 foo = bar 4633 type = aws_instance 4634 `) 4635 4636 // Verify apply was invoked 4637 if !pr.ApplyCalled { 4638 t.Fatalf("provisioner not invoked") 4639 } 4640 4641 if destroyCalled { 4642 t.Fatal("destroy should not be called") 4643 } 4644 } 4645 4646 func TestContext2Apply_provisionerDestroyModule(t *testing.T) { 4647 m := testModule(t, "apply-provisioner-destroy-module") 4648 p := testProvider("aws") 4649 pr := testProvisioner() 4650 p.ApplyFn = testApplyFn 4651 p.DiffFn = testDiffFn 4652 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4653 val, ok := c.Config["foo"] 4654 if !ok || val != "value" { 4655 t.Fatalf("bad value for foo: %v %#v", val, c) 4656 } 4657 4658 return nil 4659 } 4660 4661 state := &State{ 4662 Modules: []*ModuleState{ 4663 &ModuleState{ 4664 Path: []string{"root", "child"}, 4665 Resources: map[string]*ResourceState{ 4666 "aws_instance.foo": &ResourceState{ 4667 Type: "aws_instance", 4668 Primary: &InstanceState{ 4669 ID: "bar", 4670 }, 4671 }, 4672 }, 4673 }, 4674 }, 4675 } 4676 4677 ctx := testContext2(t, &ContextOpts{ 4678 Module: m, 4679 State: state, 4680 Destroy: true, 4681 Providers: map[string]ResourceProviderFactory{ 4682 "aws": testProviderFuncFixed(p), 4683 }, 4684 Provisioners: map[string]ResourceProvisionerFactory{ 4685 "shell": testProvisionerFuncFixed(pr), 4686 }, 4687 }) 4688 4689 if _, err := ctx.Plan(); err != nil { 4690 t.Fatalf("err: %s", err) 4691 } 4692 4693 state, err := ctx.Apply() 4694 if err != nil { 4695 t.Fatalf("err: %s", err) 4696 } 4697 4698 checkStateString(t, state, ` 4699 module.child: 4700 <no state>`) 4701 4702 // Verify apply was invoked 4703 if !pr.ApplyCalled { 4704 t.Fatalf("provisioner not invoked") 4705 } 4706 } 4707 4708 func TestContext2Apply_provisionerDestroyRef(t *testing.T) { 4709 m := testModule(t, "apply-provisioner-destroy-ref") 4710 p := testProvider("aws") 4711 pr := testProvisioner() 4712 p.ApplyFn = testApplyFn 4713 p.DiffFn = testDiffFn 4714 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4715 val, ok := c.Config["foo"] 4716 if !ok || val != "hello" { 4717 return fmt.Errorf("bad value for foo: %v %#v", val, c) 4718 } 4719 4720 return nil 4721 } 4722 4723 state := &State{ 4724 Modules: []*ModuleState{ 4725 &ModuleState{ 4726 Path: rootModulePath, 4727 Resources: map[string]*ResourceState{ 4728 "aws_instance.bar": &ResourceState{ 4729 Type: "aws_instance", 4730 Primary: &InstanceState{ 4731 ID: "bar", 4732 Attributes: map[string]string{ 4733 "key": "hello", 4734 }, 4735 }, 4736 }, 4737 4738 "aws_instance.foo": &ResourceState{ 4739 Type: "aws_instance", 4740 Primary: &InstanceState{ 4741 ID: "bar", 4742 }, 4743 }, 4744 }, 4745 }, 4746 }, 4747 } 4748 4749 ctx := testContext2(t, &ContextOpts{ 4750 Module: m, 4751 State: state, 4752 Destroy: true, 4753 Providers: map[string]ResourceProviderFactory{ 4754 "aws": testProviderFuncFixed(p), 4755 }, 4756 Provisioners: map[string]ResourceProvisionerFactory{ 4757 "shell": testProvisionerFuncFixed(pr), 4758 }, 4759 }) 4760 4761 if _, err := ctx.Plan(); err != nil { 4762 t.Fatalf("err: %s", err) 4763 } 4764 4765 state, err := ctx.Apply() 4766 if err != nil { 4767 t.Fatalf("err: %s", err) 4768 } 4769 4770 checkStateString(t, state, `<no state>`) 4771 4772 // Verify apply was invoked 4773 if !pr.ApplyCalled { 4774 t.Fatalf("provisioner not invoked") 4775 } 4776 } 4777 4778 // Test that a destroy provisioner referencing an invalid key errors. 4779 func TestContext2Apply_provisionerDestroyRefInvalid(t *testing.T) { 4780 m := testModule(t, "apply-provisioner-destroy-ref") 4781 p := testProvider("aws") 4782 pr := testProvisioner() 4783 p.ApplyFn = testApplyFn 4784 p.DiffFn = testDiffFn 4785 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4786 return nil 4787 } 4788 4789 state := &State{ 4790 Modules: []*ModuleState{ 4791 &ModuleState{ 4792 Path: rootModulePath, 4793 Resources: map[string]*ResourceState{ 4794 "aws_instance.bar": &ResourceState{ 4795 Type: "aws_instance", 4796 Primary: &InstanceState{ 4797 ID: "bar", 4798 }, 4799 }, 4800 4801 "aws_instance.foo": &ResourceState{ 4802 Type: "aws_instance", 4803 Primary: &InstanceState{ 4804 ID: "bar", 4805 }, 4806 }, 4807 }, 4808 }, 4809 }, 4810 } 4811 4812 ctx := testContext2(t, &ContextOpts{ 4813 Module: m, 4814 State: state, 4815 Destroy: true, 4816 Providers: map[string]ResourceProviderFactory{ 4817 "aws": testProviderFuncFixed(p), 4818 }, 4819 Provisioners: map[string]ResourceProvisionerFactory{ 4820 "shell": testProvisionerFuncFixed(pr), 4821 }, 4822 }) 4823 4824 if _, err := ctx.Plan(); err != nil { 4825 t.Fatalf("err: %s", err) 4826 } 4827 4828 if _, err := ctx.Apply(); err == nil { 4829 t.Fatal("expected error") 4830 } 4831 } 4832 4833 func TestContext2Apply_provisionerResourceRef(t *testing.T) { 4834 m := testModule(t, "apply-provisioner-resource-ref") 4835 p := testProvider("aws") 4836 pr := testProvisioner() 4837 p.ApplyFn = testApplyFn 4838 p.DiffFn = testDiffFn 4839 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4840 val, ok := c.Config["foo"] 4841 if !ok || val != "2" { 4842 t.Fatalf("bad value for foo: %v %#v", val, c) 4843 } 4844 4845 return nil 4846 } 4847 4848 ctx := testContext2(t, &ContextOpts{ 4849 Module: m, 4850 Providers: map[string]ResourceProviderFactory{ 4851 "aws": testProviderFuncFixed(p), 4852 }, 4853 Provisioners: map[string]ResourceProvisionerFactory{ 4854 "shell": testProvisionerFuncFixed(pr), 4855 }, 4856 }) 4857 4858 if _, err := ctx.Plan(); err != nil { 4859 t.Fatalf("err: %s", err) 4860 } 4861 4862 state, err := ctx.Apply() 4863 if err != nil { 4864 t.Fatalf("err: %s", err) 4865 } 4866 4867 actual := strings.TrimSpace(state.String()) 4868 expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr) 4869 if actual != expected { 4870 t.Fatalf("bad: \n%s", actual) 4871 } 4872 4873 // Verify apply was invoked 4874 if !pr.ApplyCalled { 4875 t.Fatalf("provisioner not invoked") 4876 } 4877 } 4878 4879 func TestContext2Apply_provisionerSelfRef(t *testing.T) { 4880 m := testModule(t, "apply-provisioner-self-ref") 4881 p := testProvider("aws") 4882 pr := testProvisioner() 4883 p.ApplyFn = testApplyFn 4884 p.DiffFn = testDiffFn 4885 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4886 val, ok := c.Config["command"] 4887 if !ok || val != "bar" { 4888 t.Fatalf("bad value for command: %v %#v", val, c) 4889 } 4890 4891 return nil 4892 } 4893 4894 ctx := testContext2(t, &ContextOpts{ 4895 Module: m, 4896 Providers: map[string]ResourceProviderFactory{ 4897 "aws": testProviderFuncFixed(p), 4898 }, 4899 Provisioners: map[string]ResourceProvisionerFactory{ 4900 "shell": testProvisionerFuncFixed(pr), 4901 }, 4902 }) 4903 4904 if _, err := ctx.Plan(); err != nil { 4905 t.Fatalf("err: %s", err) 4906 } 4907 4908 state, err := ctx.Apply() 4909 if err != nil { 4910 t.Fatalf("err: %s", err) 4911 } 4912 4913 actual := strings.TrimSpace(state.String()) 4914 expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) 4915 if actual != expected { 4916 t.Fatalf("bad: \n%s", actual) 4917 } 4918 4919 // Verify apply was invoked 4920 if !pr.ApplyCalled { 4921 t.Fatalf("provisioner not invoked") 4922 } 4923 } 4924 4925 func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { 4926 var lock sync.Mutex 4927 commands := make([]string, 0, 5) 4928 4929 m := testModule(t, "apply-provisioner-multi-self-ref") 4930 p := testProvider("aws") 4931 pr := testProvisioner() 4932 p.ApplyFn = testApplyFn 4933 p.DiffFn = testDiffFn 4934 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4935 lock.Lock() 4936 defer lock.Unlock() 4937 4938 val, ok := c.Config["command"] 4939 if !ok { 4940 t.Fatalf("bad value for command: %v %#v", val, c) 4941 } 4942 4943 commands = append(commands, val.(string)) 4944 return nil 4945 } 4946 4947 ctx := testContext2(t, &ContextOpts{ 4948 Module: m, 4949 Providers: map[string]ResourceProviderFactory{ 4950 "aws": testProviderFuncFixed(p), 4951 }, 4952 Provisioners: map[string]ResourceProvisionerFactory{ 4953 "shell": testProvisionerFuncFixed(pr), 4954 }, 4955 }) 4956 4957 if _, err := ctx.Plan(); err != nil { 4958 t.Fatalf("err: %s", err) 4959 } 4960 4961 state, err := ctx.Apply() 4962 if err != nil { 4963 t.Fatalf("err: %s", err) 4964 } 4965 4966 actual := strings.TrimSpace(state.String()) 4967 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr) 4968 if actual != expected { 4969 t.Fatalf("bad: \n%s", actual) 4970 } 4971 4972 // Verify apply was invoked 4973 if !pr.ApplyCalled { 4974 t.Fatalf("provisioner not invoked") 4975 } 4976 4977 // Verify our result 4978 sort.Strings(commands) 4979 expectedCommands := []string{"number 0", "number 1", "number 2"} 4980 if !reflect.DeepEqual(commands, expectedCommands) { 4981 t.Fatalf("bad: %#v", commands) 4982 } 4983 } 4984 4985 func TestContext2Apply_provisionerMultiSelfRefSingle(t *testing.T) { 4986 var lock sync.Mutex 4987 order := make([]string, 0, 5) 4988 4989 m := testModule(t, "apply-provisioner-multi-self-ref-single") 4990 p := testProvider("aws") 4991 pr := testProvisioner() 4992 p.ApplyFn = testApplyFn 4993 p.DiffFn = testDiffFn 4994 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4995 lock.Lock() 4996 defer lock.Unlock() 4997 4998 val, ok := c.Config["order"] 4999 if !ok { 5000 t.Fatalf("bad value for order: %v %#v", val, c) 5001 } 5002 5003 order = append(order, val.(string)) 5004 return nil 5005 } 5006 5007 ctx := testContext2(t, &ContextOpts{ 5008 Module: m, 5009 Providers: map[string]ResourceProviderFactory{ 5010 "aws": testProviderFuncFixed(p), 5011 }, 5012 Provisioners: map[string]ResourceProvisionerFactory{ 5013 "shell": testProvisionerFuncFixed(pr), 5014 }, 5015 }) 5016 5017 if _, err := ctx.Plan(); err != nil { 5018 t.Fatalf("err: %s", err) 5019 } 5020 5021 state, err := ctx.Apply() 5022 if err != nil { 5023 t.Fatalf("err: %s", err) 5024 } 5025 5026 actual := strings.TrimSpace(state.String()) 5027 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefSingleStr) 5028 if actual != expected { 5029 t.Fatalf("bad: \n%s", actual) 5030 } 5031 5032 // Verify apply was invoked 5033 if !pr.ApplyCalled { 5034 t.Fatalf("provisioner not invoked") 5035 } 5036 5037 // Verify our result 5038 sort.Strings(order) 5039 expectedOrder := []string{"0", "1", "2"} 5040 if !reflect.DeepEqual(order, expectedOrder) { 5041 t.Fatalf("bad: %#v", order) 5042 } 5043 } 5044 5045 func TestContext2Apply_provisionerMultiSelfRefCount(t *testing.T) { 5046 var lock sync.Mutex 5047 commands := make([]string, 0, 5) 5048 5049 m := testModule(t, "apply-provisioner-multi-self-ref-count") 5050 p := testProvider("aws") 5051 pr := testProvisioner() 5052 p.ApplyFn = testApplyFn 5053 p.DiffFn = testDiffFn 5054 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5055 lock.Lock() 5056 defer lock.Unlock() 5057 5058 val, ok := c.Config["command"] 5059 if !ok { 5060 t.Fatalf("bad value for command: %v %#v", val, c) 5061 } 5062 5063 commands = append(commands, val.(string)) 5064 return nil 5065 } 5066 5067 ctx := testContext2(t, &ContextOpts{ 5068 Module: m, 5069 Providers: map[string]ResourceProviderFactory{ 5070 "aws": testProviderFuncFixed(p), 5071 }, 5072 Provisioners: map[string]ResourceProvisionerFactory{ 5073 "shell": testProvisionerFuncFixed(pr), 5074 }, 5075 }) 5076 5077 if _, err := ctx.Plan(); err != nil { 5078 t.Fatalf("err: %s", err) 5079 } 5080 5081 if _, err := ctx.Apply(); err != nil { 5082 t.Fatalf("err: %s", err) 5083 } 5084 5085 // Verify apply was invoked 5086 if !pr.ApplyCalled { 5087 t.Fatalf("provisioner not invoked") 5088 } 5089 5090 // Verify our result 5091 sort.Strings(commands) 5092 expectedCommands := []string{"3", "3", "3"} 5093 if !reflect.DeepEqual(commands, expectedCommands) { 5094 t.Fatalf("bad: %#v", commands) 5095 } 5096 } 5097 5098 func TestContext2Apply_provisionerExplicitSelfRef(t *testing.T) { 5099 m := testModule(t, "apply-provisioner-explicit-self-ref") 5100 p := testProvider("aws") 5101 pr := testProvisioner() 5102 p.ApplyFn = testApplyFn 5103 p.DiffFn = testDiffFn 5104 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5105 val, ok := c.Config["command"] 5106 if !ok || val != "bar" { 5107 t.Fatalf("bad value for command: %v %#v", val, c) 5108 } 5109 5110 return nil 5111 } 5112 5113 var state *State 5114 { 5115 ctx := testContext2(t, &ContextOpts{ 5116 Module: m, 5117 Providers: map[string]ResourceProviderFactory{ 5118 "aws": testProviderFuncFixed(p), 5119 }, 5120 Provisioners: map[string]ResourceProvisionerFactory{ 5121 "shell": testProvisionerFuncFixed(pr), 5122 }, 5123 }) 5124 5125 _, err := ctx.Plan() 5126 if err != nil { 5127 t.Fatalf("err: %s", err) 5128 } 5129 5130 state, err = ctx.Apply() 5131 if err != nil { 5132 t.Fatalf("err: %s", err) 5133 } 5134 5135 // Verify apply was invoked 5136 if !pr.ApplyCalled { 5137 t.Fatalf("provisioner not invoked") 5138 } 5139 } 5140 5141 { 5142 ctx := testContext2(t, &ContextOpts{ 5143 Module: m, 5144 Destroy: true, 5145 State: state, 5146 Providers: map[string]ResourceProviderFactory{ 5147 "aws": testProviderFuncFixed(p), 5148 }, 5149 Provisioners: map[string]ResourceProvisionerFactory{ 5150 "shell": testProvisionerFuncFixed(pr), 5151 }, 5152 }) 5153 5154 _, err := ctx.Plan() 5155 if err != nil { 5156 t.Fatalf("err: %s", err) 5157 } 5158 5159 state, err = ctx.Apply() 5160 if err != nil { 5161 t.Fatalf("err: %s", err) 5162 } 5163 5164 checkStateString(t, state, `<no state>`) 5165 } 5166 } 5167 5168 // Provisioner should NOT run on a diff, only create 5169 func TestContext2Apply_Provisioner_Diff(t *testing.T) { 5170 m := testModule(t, "apply-provisioner-diff") 5171 p := testProvider("aws") 5172 pr := testProvisioner() 5173 p.ApplyFn = testApplyFn 5174 p.DiffFn = testDiffFn 5175 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5176 return nil 5177 } 5178 ctx := testContext2(t, &ContextOpts{ 5179 Module: m, 5180 Providers: map[string]ResourceProviderFactory{ 5181 "aws": testProviderFuncFixed(p), 5182 }, 5183 Provisioners: map[string]ResourceProvisionerFactory{ 5184 "shell": testProvisionerFuncFixed(pr), 5185 }, 5186 }) 5187 5188 if _, err := ctx.Plan(); err != nil { 5189 t.Fatalf("err: %s", err) 5190 } 5191 5192 state, err := ctx.Apply() 5193 if err != nil { 5194 t.Fatalf("err: %s", err) 5195 } 5196 5197 actual := strings.TrimSpace(state.String()) 5198 expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr) 5199 if actual != expected { 5200 t.Fatalf("bad: \n%s", actual) 5201 } 5202 5203 // Verify apply was invoked 5204 if !pr.ApplyCalled { 5205 t.Fatalf("provisioner not invoked") 5206 } 5207 pr.ApplyCalled = false 5208 5209 // Change the state to force a diff 5210 mod := state.RootModule() 5211 mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz" 5212 5213 // Re-create context with state 5214 ctx = testContext2(t, &ContextOpts{ 5215 Module: m, 5216 Providers: map[string]ResourceProviderFactory{ 5217 "aws": testProviderFuncFixed(p), 5218 }, 5219 Provisioners: map[string]ResourceProvisionerFactory{ 5220 "shell": testProvisionerFuncFixed(pr), 5221 }, 5222 State: state, 5223 }) 5224 5225 if _, err := ctx.Plan(); err != nil { 5226 t.Fatalf("err: %s", err) 5227 } 5228 5229 state2, err := ctx.Apply() 5230 if err != nil { 5231 t.Fatalf("err: %s", err) 5232 } 5233 5234 actual = strings.TrimSpace(state2.String()) 5235 if actual != expected { 5236 t.Fatalf("bad: \n%s", actual) 5237 } 5238 5239 // Verify apply was NOT invoked 5240 if pr.ApplyCalled { 5241 t.Fatalf("provisioner invoked") 5242 } 5243 } 5244 5245 func TestContext2Apply_outputDiffVars(t *testing.T) { 5246 m := testModule(t, "apply-good") 5247 p := testProvider("aws") 5248 s := &State{ 5249 Modules: []*ModuleState{ 5250 &ModuleState{ 5251 Path: rootModulePath, 5252 Resources: map[string]*ResourceState{ 5253 "aws_instance.baz": &ResourceState{ 5254 Type: "aws_instance", 5255 Primary: &InstanceState{ 5256 ID: "bar", 5257 }, 5258 }, 5259 }, 5260 }, 5261 }, 5262 } 5263 ctx := testContext2(t, &ContextOpts{ 5264 Module: m, 5265 Providers: map[string]ResourceProviderFactory{ 5266 "aws": testProviderFuncFixed(p), 5267 }, 5268 State: s, 5269 }) 5270 5271 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5272 for k, ad := range d.Attributes { 5273 if ad.NewComputed { 5274 return nil, fmt.Errorf("%s: computed", k) 5275 } 5276 } 5277 5278 result := s.MergeDiff(d) 5279 result.ID = "foo" 5280 return result, nil 5281 } 5282 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5283 return &InstanceDiff{ 5284 Attributes: map[string]*ResourceAttrDiff{ 5285 "foo": &ResourceAttrDiff{ 5286 NewComputed: true, 5287 Type: DiffAttrOutput, 5288 }, 5289 "bar": &ResourceAttrDiff{ 5290 New: "baz", 5291 }, 5292 }, 5293 }, nil 5294 } 5295 5296 if _, err := ctx.Plan(); err != nil { 5297 t.Fatalf("err: %s", err) 5298 } 5299 if _, err := ctx.Apply(); err != nil { 5300 t.Fatalf("err: %s", err) 5301 } 5302 } 5303 5304 func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { 5305 m := testModule(t, "apply-provisioner-conninfo") 5306 p := testProvider("aws") 5307 pr := testProvisioner() 5308 5309 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5310 if s.Ephemeral.ConnInfo == nil { 5311 t.Fatalf("ConnInfo not initialized") 5312 } 5313 5314 result, _ := testApplyFn(info, s, d) 5315 result.Ephemeral.ConnInfo = map[string]string{ 5316 "type": "ssh", 5317 "host": "127.0.0.1", 5318 "port": "22", 5319 } 5320 return result, nil 5321 } 5322 p.DiffFn = testDiffFn 5323 5324 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5325 conn := rs.Ephemeral.ConnInfo 5326 if conn["type"] != "telnet" { 5327 t.Fatalf("Bad: %#v", conn) 5328 } 5329 if conn["host"] != "127.0.0.1" { 5330 t.Fatalf("Bad: %#v", conn) 5331 } 5332 if conn["port"] != "2222" { 5333 t.Fatalf("Bad: %#v", conn) 5334 } 5335 if conn["user"] != "superuser" { 5336 t.Fatalf("Bad: %#v", conn) 5337 } 5338 if conn["pass"] != "test" { 5339 t.Fatalf("Bad: %#v", conn) 5340 } 5341 5342 return nil 5343 } 5344 5345 ctx := testContext2(t, &ContextOpts{ 5346 Module: m, 5347 Providers: map[string]ResourceProviderFactory{ 5348 "aws": testProviderFuncFixed(p), 5349 }, 5350 Provisioners: map[string]ResourceProvisionerFactory{ 5351 "shell": testProvisionerFuncFixed(pr), 5352 }, 5353 Variables: map[string]interface{}{ 5354 "value": "1", 5355 "pass": "test", 5356 }, 5357 }) 5358 5359 if _, err := ctx.Plan(); err != nil { 5360 t.Fatalf("err: %s", err) 5361 } 5362 5363 state, err := ctx.Apply() 5364 if err != nil { 5365 t.Fatalf("err: %s", err) 5366 } 5367 5368 actual := strings.TrimSpace(state.String()) 5369 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 5370 if actual != expected { 5371 t.Fatalf("bad: \n%s", actual) 5372 } 5373 5374 // Verify apply was invoked 5375 if !pr.ApplyCalled { 5376 t.Fatalf("provisioner not invoked") 5377 } 5378 } 5379 5380 func TestContext2Apply_destroyX(t *testing.T) { 5381 m := testModule(t, "apply-destroy") 5382 h := new(HookRecordApplyOrder) 5383 p := testProvider("aws") 5384 p.ApplyFn = testApplyFn 5385 p.DiffFn = testDiffFn 5386 ctx := testContext2(t, &ContextOpts{ 5387 Module: m, 5388 Hooks: []Hook{h}, 5389 Providers: map[string]ResourceProviderFactory{ 5390 "aws": testProviderFuncFixed(p), 5391 }, 5392 }) 5393 5394 // First plan and apply a create operation 5395 if _, err := ctx.Plan(); err != nil { 5396 t.Fatalf("err: %s", err) 5397 } 5398 5399 state, err := ctx.Apply() 5400 if err != nil { 5401 t.Fatalf("err: %s", err) 5402 } 5403 5404 // Next, plan and apply a destroy operation 5405 h.Active = true 5406 ctx = testContext2(t, &ContextOpts{ 5407 Destroy: true, 5408 State: state, 5409 Module: m, 5410 Hooks: []Hook{h}, 5411 Providers: map[string]ResourceProviderFactory{ 5412 "aws": testProviderFuncFixed(p), 5413 }, 5414 }) 5415 5416 if _, err := ctx.Plan(); err != nil { 5417 t.Fatalf("err: %s", err) 5418 } 5419 5420 state, err = ctx.Apply() 5421 if err != nil { 5422 t.Fatalf("err: %s", err) 5423 } 5424 5425 // Test that things were destroyed 5426 actual := strings.TrimSpace(state.String()) 5427 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5428 if actual != expected { 5429 t.Fatalf("bad: \n%s", actual) 5430 } 5431 5432 // Test that things were destroyed _in the right order_ 5433 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 5434 actual2 := h.IDs 5435 if !reflect.DeepEqual(actual2, expected2) { 5436 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 5437 } 5438 } 5439 5440 func TestContext2Apply_destroyOrder(t *testing.T) { 5441 m := testModule(t, "apply-destroy") 5442 h := new(HookRecordApplyOrder) 5443 p := testProvider("aws") 5444 p.ApplyFn = testApplyFn 5445 p.DiffFn = testDiffFn 5446 ctx := testContext2(t, &ContextOpts{ 5447 Module: m, 5448 Hooks: []Hook{h}, 5449 Providers: map[string]ResourceProviderFactory{ 5450 "aws": testProviderFuncFixed(p), 5451 }, 5452 }) 5453 5454 // First plan and apply a create operation 5455 if _, err := ctx.Plan(); err != nil { 5456 t.Fatalf("err: %s", err) 5457 } 5458 5459 state, err := ctx.Apply() 5460 if err != nil { 5461 t.Fatalf("err: %s", err) 5462 } 5463 5464 t.Logf("State 1: %s", state) 5465 5466 // Next, plan and apply config-less to force a destroy with "apply" 5467 h.Active = true 5468 ctx = testContext2(t, &ContextOpts{ 5469 State: state, 5470 Module: module.NewEmptyTree(), 5471 Hooks: []Hook{h}, 5472 Providers: map[string]ResourceProviderFactory{ 5473 "aws": testProviderFuncFixed(p), 5474 }, 5475 }) 5476 5477 if _, err := ctx.Plan(); err != nil { 5478 t.Fatalf("err: %s", err) 5479 } 5480 5481 state, err = ctx.Apply() 5482 if err != nil { 5483 t.Fatalf("err: %s", err) 5484 } 5485 5486 // Test that things were destroyed 5487 actual := strings.TrimSpace(state.String()) 5488 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5489 if actual != expected { 5490 t.Fatalf("bad: \n%s", actual) 5491 } 5492 5493 // Test that things were destroyed _in the right order_ 5494 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 5495 actual2 := h.IDs 5496 if !reflect.DeepEqual(actual2, expected2) { 5497 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 5498 } 5499 } 5500 5501 // https://github.com/hashicorp/terraform/issues/2767 5502 func TestContext2Apply_destroyModulePrefix(t *testing.T) { 5503 m := testModule(t, "apply-destroy-module-resource-prefix") 5504 h := new(MockHook) 5505 p := testProvider("aws") 5506 p.ApplyFn = testApplyFn 5507 p.DiffFn = testDiffFn 5508 ctx := testContext2(t, &ContextOpts{ 5509 Module: m, 5510 Hooks: []Hook{h}, 5511 Providers: map[string]ResourceProviderFactory{ 5512 "aws": testProviderFuncFixed(p), 5513 }, 5514 }) 5515 5516 // First plan and apply a create operation 5517 if _, err := ctx.Plan(); err != nil { 5518 t.Fatalf("err: %s", err) 5519 } 5520 5521 state, err := ctx.Apply() 5522 if err != nil { 5523 t.Fatalf("err: %s", err) 5524 } 5525 5526 // Verify that we got the apply info correct 5527 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 5528 t.Fatalf("bad: %s", v) 5529 } 5530 5531 // Next, plan and apply a destroy operation and reset the hook 5532 h = new(MockHook) 5533 ctx = testContext2(t, &ContextOpts{ 5534 Destroy: true, 5535 State: state, 5536 Module: m, 5537 Hooks: []Hook{h}, 5538 Providers: map[string]ResourceProviderFactory{ 5539 "aws": testProviderFuncFixed(p), 5540 }, 5541 }) 5542 5543 if _, err := ctx.Plan(); err != nil { 5544 t.Fatalf("err: %s", err) 5545 } 5546 5547 state, err = ctx.Apply() 5548 if err != nil { 5549 t.Fatalf("err: %s", err) 5550 } 5551 5552 // Test that things were destroyed 5553 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 5554 t.Fatalf("bad: %s", v) 5555 } 5556 } 5557 5558 func TestContext2Apply_destroyNestedModule(t *testing.T) { 5559 m := testModule(t, "apply-destroy-nested-module") 5560 p := testProvider("aws") 5561 p.ApplyFn = testApplyFn 5562 p.DiffFn = testDiffFn 5563 5564 s := &State{ 5565 Modules: []*ModuleState{ 5566 &ModuleState{ 5567 Path: []string{"root", "child", "subchild"}, 5568 Resources: map[string]*ResourceState{ 5569 "aws_instance.bar": &ResourceState{ 5570 Type: "aws_instance", 5571 Primary: &InstanceState{ 5572 ID: "bar", 5573 }, 5574 }, 5575 }, 5576 }, 5577 }, 5578 } 5579 5580 ctx := testContext2(t, &ContextOpts{ 5581 Module: m, 5582 Providers: map[string]ResourceProviderFactory{ 5583 "aws": testProviderFuncFixed(p), 5584 }, 5585 State: s, 5586 }) 5587 5588 // First plan and apply a create operation 5589 if _, err := ctx.Plan(); err != nil { 5590 t.Fatalf("err: %s", err) 5591 } 5592 5593 state, err := ctx.Apply() 5594 if err != nil { 5595 t.Fatalf("err: %s", err) 5596 } 5597 5598 // Test that things were destroyed 5599 actual := strings.TrimSpace(state.String()) 5600 expected := strings.TrimSpace(testTerraformApplyDestroyNestedModuleStr) 5601 if actual != expected { 5602 t.Fatalf("bad: \n%s", actual) 5603 } 5604 } 5605 5606 func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) { 5607 m := testModule(t, "apply-destroy-deeply-nested-module") 5608 p := testProvider("aws") 5609 p.ApplyFn = testApplyFn 5610 p.DiffFn = testDiffFn 5611 5612 s := &State{ 5613 Modules: []*ModuleState{ 5614 &ModuleState{ 5615 Path: []string{"root", "child", "subchild", "subsubchild"}, 5616 Resources: map[string]*ResourceState{ 5617 "aws_instance.bar": &ResourceState{ 5618 Type: "aws_instance", 5619 Primary: &InstanceState{ 5620 ID: "bar", 5621 }, 5622 }, 5623 }, 5624 }, 5625 }, 5626 } 5627 5628 ctx := testContext2(t, &ContextOpts{ 5629 Module: m, 5630 Providers: map[string]ResourceProviderFactory{ 5631 "aws": testProviderFuncFixed(p), 5632 }, 5633 State: s, 5634 }) 5635 5636 // First plan and apply a create operation 5637 if _, err := ctx.Plan(); err != nil { 5638 t.Fatalf("err: %s", err) 5639 } 5640 5641 state, err := ctx.Apply() 5642 if err != nil { 5643 t.Fatalf("err: %s", err) 5644 } 5645 5646 // Test that things were destroyed 5647 actual := strings.TrimSpace(state.String()) 5648 expected := strings.TrimSpace(` 5649 module.child.subchild.subsubchild: 5650 <no state> 5651 `) 5652 if actual != expected { 5653 t.Fatalf("bad: \n%s", actual) 5654 } 5655 } 5656 5657 // https://github.com/hashicorp/terraform/issues/5440 5658 func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) { 5659 m := testModule(t, "apply-destroy-module-with-attrs") 5660 p := testProvider("aws") 5661 p.ApplyFn = testApplyFn 5662 p.DiffFn = testDiffFn 5663 5664 var state *State 5665 var err error 5666 { 5667 ctx := testContext2(t, &ContextOpts{ 5668 Module: m, 5669 Providers: map[string]ResourceProviderFactory{ 5670 "aws": testProviderFuncFixed(p), 5671 }, 5672 }) 5673 5674 // First plan and apply a create operation 5675 if p, err := ctx.Plan(); err != nil { 5676 t.Fatalf("plan err: %s", err) 5677 } else { 5678 t.Logf("Step 1 plan: %s", p) 5679 } 5680 5681 state, err = ctx.Apply() 5682 if err != nil { 5683 t.Fatalf("apply err: %s", err) 5684 } 5685 5686 t.Logf("Step 1 state: %s", state) 5687 } 5688 5689 h := new(HookRecordApplyOrder) 5690 h.Active = true 5691 5692 { 5693 ctx := testContext2(t, &ContextOpts{ 5694 Destroy: true, 5695 Module: m, 5696 State: state, 5697 Hooks: []Hook{h}, 5698 Providers: map[string]ResourceProviderFactory{ 5699 "aws": testProviderFuncFixed(p), 5700 }, 5701 Variables: map[string]interface{}{ 5702 "key_name": "foobarkey", 5703 }, 5704 }) 5705 5706 // First plan and apply a create operation 5707 plan, err := ctx.Plan() 5708 if err != nil { 5709 t.Fatalf("destroy plan err: %s", err) 5710 } 5711 5712 t.Logf("Step 2 plan: %s", plan) 5713 5714 var buf bytes.Buffer 5715 if err := WritePlan(plan, &buf); err != nil { 5716 t.Fatalf("plan write err: %s", err) 5717 } 5718 5719 planFromFile, err := ReadPlan(&buf) 5720 if err != nil { 5721 t.Fatalf("plan read err: %s", err) 5722 } 5723 5724 ctx, err = planFromFile.Context(&ContextOpts{ 5725 Providers: map[string]ResourceProviderFactory{ 5726 "aws": testProviderFuncFixed(p), 5727 }, 5728 }) 5729 if err != nil { 5730 t.Fatalf("err: %s", err) 5731 } 5732 5733 state, err = ctx.Apply() 5734 if err != nil { 5735 t.Fatalf("destroy apply err: %s", err) 5736 } 5737 5738 t.Logf("Step 2 state: %s", state) 5739 } 5740 5741 //Test that things were destroyed 5742 actual := strings.TrimSpace(state.String()) 5743 expected := strings.TrimSpace(` 5744 <no state> 5745 module.child: 5746 <no state> 5747 `) 5748 if actual != expected { 5749 t.Fatalf("expected:\n\n%s\n\nactual:\n\n%s", expected, actual) 5750 } 5751 } 5752 5753 func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) { 5754 m := testModule(t, "apply-destroy-mod-var-and-count") 5755 p := testProvider("aws") 5756 p.ApplyFn = testApplyFn 5757 p.DiffFn = testDiffFn 5758 5759 var state *State 5760 var err error 5761 { 5762 ctx := testContext2(t, &ContextOpts{ 5763 Module: m, 5764 Providers: map[string]ResourceProviderFactory{ 5765 "aws": testProviderFuncFixed(p), 5766 }, 5767 }) 5768 5769 // First plan and apply a create operation 5770 if _, err := ctx.Plan(); err != nil { 5771 t.Fatalf("plan err: %s", err) 5772 } 5773 5774 state, err = ctx.Apply() 5775 if err != nil { 5776 t.Fatalf("apply err: %s", err) 5777 } 5778 } 5779 5780 h := new(HookRecordApplyOrder) 5781 h.Active = true 5782 5783 { 5784 ctx := testContext2(t, &ContextOpts{ 5785 Destroy: true, 5786 Module: m, 5787 State: state, 5788 Hooks: []Hook{h}, 5789 Providers: map[string]ResourceProviderFactory{ 5790 "aws": testProviderFuncFixed(p), 5791 }, 5792 }) 5793 5794 // First plan and apply a create operation 5795 plan, err := ctx.Plan() 5796 if err != nil { 5797 t.Fatalf("destroy plan err: %s", err) 5798 } 5799 5800 var buf bytes.Buffer 5801 if err := WritePlan(plan, &buf); err != nil { 5802 t.Fatalf("plan write err: %s", err) 5803 } 5804 5805 planFromFile, err := ReadPlan(&buf) 5806 if err != nil { 5807 t.Fatalf("plan read err: %s", err) 5808 } 5809 5810 ctx, err = planFromFile.Context(&ContextOpts{ 5811 Providers: map[string]ResourceProviderFactory{ 5812 "aws": testProviderFuncFixed(p), 5813 }, 5814 }) 5815 if err != nil { 5816 t.Fatalf("err: %s", err) 5817 } 5818 5819 state, err = ctx.Apply() 5820 if err != nil { 5821 t.Fatalf("destroy apply err: %s", err) 5822 } 5823 } 5824 5825 //Test that things were destroyed 5826 actual := strings.TrimSpace(state.String()) 5827 expected := strings.TrimSpace(` 5828 <no state> 5829 module.child: 5830 <no state> 5831 `) 5832 if actual != expected { 5833 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5834 } 5835 } 5836 5837 func TestContext2Apply_destroyTargetWithModuleVariableAndCount(t *testing.T) { 5838 m := testModule(t, "apply-destroy-mod-var-and-count") 5839 p := testProvider("aws") 5840 p.ApplyFn = testApplyFn 5841 p.DiffFn = testDiffFn 5842 5843 var state *State 5844 var err error 5845 { 5846 ctx := testContext2(t, &ContextOpts{ 5847 Module: m, 5848 Providers: map[string]ResourceProviderFactory{ 5849 "aws": testProviderFuncFixed(p), 5850 }, 5851 }) 5852 5853 // First plan and apply a create operation 5854 if _, err := ctx.Plan(); err != nil { 5855 t.Fatalf("plan err: %s", err) 5856 } 5857 5858 state, err = ctx.Apply() 5859 if err != nil { 5860 t.Fatalf("apply err: %s", err) 5861 } 5862 } 5863 5864 { 5865 ctx := testContext2(t, &ContextOpts{ 5866 Destroy: true, 5867 Module: m, 5868 State: state, 5869 Providers: map[string]ResourceProviderFactory{ 5870 "aws": testProviderFuncFixed(p), 5871 }, 5872 Targets: []string{"module.child"}, 5873 }) 5874 5875 _, err := ctx.Plan() 5876 if err != nil { 5877 t.Fatalf("plan err: %s", err) 5878 } 5879 5880 // Destroy, targeting the module explicitly 5881 state, err = ctx.Apply() 5882 if err != nil { 5883 t.Fatalf("destroy apply err: %s", err) 5884 } 5885 } 5886 5887 //Test that things were destroyed 5888 actual := strings.TrimSpace(state.String()) 5889 expected := strings.TrimSpace(` 5890 <no state> 5891 module.child: 5892 <no state> 5893 `) 5894 if actual != expected { 5895 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5896 } 5897 } 5898 5899 func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) { 5900 m := testModule(t, "apply-destroy-mod-var-and-count-nested") 5901 p := testProvider("aws") 5902 p.ApplyFn = testApplyFn 5903 p.DiffFn = testDiffFn 5904 5905 var state *State 5906 var err error 5907 { 5908 ctx := testContext2(t, &ContextOpts{ 5909 Module: m, 5910 Providers: map[string]ResourceProviderFactory{ 5911 "aws": testProviderFuncFixed(p), 5912 }, 5913 }) 5914 5915 // First plan and apply a create operation 5916 if _, err := ctx.Plan(); err != nil { 5917 t.Fatalf("plan err: %s", err) 5918 } 5919 5920 state, err = ctx.Apply() 5921 if err != nil { 5922 t.Fatalf("apply err: %s", err) 5923 } 5924 } 5925 5926 h := new(HookRecordApplyOrder) 5927 h.Active = true 5928 5929 { 5930 ctx := testContext2(t, &ContextOpts{ 5931 Destroy: true, 5932 Module: m, 5933 State: state, 5934 Hooks: []Hook{h}, 5935 Providers: map[string]ResourceProviderFactory{ 5936 "aws": testProviderFuncFixed(p), 5937 }, 5938 }) 5939 5940 // First plan and apply a create operation 5941 plan, err := ctx.Plan() 5942 if err != nil { 5943 t.Fatalf("destroy plan err: %s", err) 5944 } 5945 5946 var buf bytes.Buffer 5947 if err := WritePlan(plan, &buf); err != nil { 5948 t.Fatalf("plan write err: %s", err) 5949 } 5950 5951 planFromFile, err := ReadPlan(&buf) 5952 if err != nil { 5953 t.Fatalf("plan read err: %s", err) 5954 } 5955 5956 ctx, err = planFromFile.Context(&ContextOpts{ 5957 Providers: map[string]ResourceProviderFactory{ 5958 "aws": testProviderFuncFixed(p), 5959 }, 5960 }) 5961 if err != nil { 5962 t.Fatalf("err: %s", err) 5963 } 5964 5965 state, err = ctx.Apply() 5966 if err != nil { 5967 t.Fatalf("destroy apply err: %s", err) 5968 } 5969 } 5970 5971 //Test that things were destroyed 5972 actual := strings.TrimSpace(state.String()) 5973 expected := strings.TrimSpace(` 5974 <no state> 5975 module.child: 5976 <no state> 5977 module.child.child2: 5978 <no state> 5979 `) 5980 if actual != expected { 5981 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5982 } 5983 } 5984 5985 func TestContext2Apply_destroyOutputs(t *testing.T) { 5986 m := testModule(t, "apply-destroy-outputs") 5987 h := new(HookRecordApplyOrder) 5988 p := testProvider("aws") 5989 p.ApplyFn = testApplyFn 5990 p.DiffFn = testDiffFn 5991 ctx := testContext2(t, &ContextOpts{ 5992 Module: m, 5993 Hooks: []Hook{h}, 5994 Providers: map[string]ResourceProviderFactory{ 5995 "aws": testProviderFuncFixed(p), 5996 }, 5997 }) 5998 5999 // First plan and apply a create operation 6000 if _, err := ctx.Plan(); err != nil { 6001 t.Fatalf("err: %s", err) 6002 } 6003 6004 state, err := ctx.Apply() 6005 6006 if err != nil { 6007 t.Fatalf("err: %s", err) 6008 } 6009 6010 // Next, plan and apply a destroy operation 6011 h.Active = true 6012 ctx = testContext2(t, &ContextOpts{ 6013 Destroy: true, 6014 State: state, 6015 Module: m, 6016 Hooks: []Hook{h}, 6017 Providers: map[string]ResourceProviderFactory{ 6018 "aws": testProviderFuncFixed(p), 6019 }, 6020 }) 6021 6022 if _, err := ctx.Plan(); err != nil { 6023 t.Fatalf("err: %s", err) 6024 } 6025 6026 state, err = ctx.Apply() 6027 if err != nil { 6028 t.Fatalf("err: %s", err) 6029 } 6030 6031 mod := state.RootModule() 6032 if len(mod.Resources) > 0 { 6033 t.Fatalf("bad: %#v", mod) 6034 } 6035 } 6036 6037 func TestContext2Apply_destroyOrphan(t *testing.T) { 6038 m := testModule(t, "apply-error") 6039 p := testProvider("aws") 6040 s := &State{ 6041 Modules: []*ModuleState{ 6042 &ModuleState{ 6043 Path: rootModulePath, 6044 Resources: map[string]*ResourceState{ 6045 "aws_instance.baz": &ResourceState{ 6046 Type: "aws_instance", 6047 Primary: &InstanceState{ 6048 ID: "bar", 6049 }, 6050 }, 6051 }, 6052 }, 6053 }, 6054 } 6055 ctx := testContext2(t, &ContextOpts{ 6056 Module: m, 6057 Providers: map[string]ResourceProviderFactory{ 6058 "aws": testProviderFuncFixed(p), 6059 }, 6060 State: s, 6061 }) 6062 6063 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6064 if d.Destroy { 6065 return nil, nil 6066 } 6067 6068 result := s.MergeDiff(d) 6069 result.ID = "foo" 6070 return result, nil 6071 } 6072 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6073 return &InstanceDiff{ 6074 Attributes: map[string]*ResourceAttrDiff{ 6075 "num": &ResourceAttrDiff{ 6076 New: "bar", 6077 }, 6078 }, 6079 }, nil 6080 } 6081 6082 if _, err := ctx.Plan(); err != nil { 6083 t.Fatalf("err: %s", err) 6084 } 6085 6086 state, err := ctx.Apply() 6087 if err != nil { 6088 t.Fatalf("err: %s", err) 6089 } 6090 6091 mod := state.RootModule() 6092 if _, ok := mod.Resources["aws_instance.baz"]; ok { 6093 t.Fatalf("bad: %#v", mod.Resources) 6094 } 6095 } 6096 6097 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 6098 m := testModule(t, "apply-destroy-provisioner") 6099 p := testProvider("aws") 6100 pr := testProvisioner() 6101 p.ApplyFn = testApplyFn 6102 p.DiffFn = testDiffFn 6103 6104 called := false 6105 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 6106 called = true 6107 return nil 6108 } 6109 6110 s := &State{ 6111 Modules: []*ModuleState{ 6112 &ModuleState{ 6113 Path: rootModulePath, 6114 Resources: map[string]*ResourceState{ 6115 "aws_instance.foo": &ResourceState{ 6116 Type: "aws_instance", 6117 Primary: &InstanceState{ 6118 ID: "bar", 6119 Attributes: map[string]string{ 6120 "id": "bar", 6121 }, 6122 Tainted: true, 6123 }, 6124 }, 6125 }, 6126 }, 6127 }, 6128 } 6129 6130 ctx := testContext2(t, &ContextOpts{ 6131 Module: m, 6132 Providers: map[string]ResourceProviderFactory{ 6133 "aws": testProviderFuncFixed(p), 6134 }, 6135 Provisioners: map[string]ResourceProvisionerFactory{ 6136 "shell": testProvisionerFuncFixed(pr), 6137 }, 6138 State: s, 6139 Destroy: true, 6140 }) 6141 6142 if _, err := ctx.Plan(); err != nil { 6143 t.Fatalf("err: %s", err) 6144 } 6145 6146 state, err := ctx.Apply() 6147 if err != nil { 6148 t.Fatalf("err: %s", err) 6149 } 6150 6151 if called { 6152 t.Fatal("provisioner should not be called") 6153 } 6154 6155 actual := strings.TrimSpace(state.String()) 6156 expected := strings.TrimSpace("<no state>") 6157 if actual != expected { 6158 t.Fatalf("bad: \n%s", actual) 6159 } 6160 } 6161 6162 func TestContext2Apply_error(t *testing.T) { 6163 errored := false 6164 6165 m := testModule(t, "apply-error") 6166 p := testProvider("aws") 6167 ctx := testContext2(t, &ContextOpts{ 6168 Module: m, 6169 Providers: map[string]ResourceProviderFactory{ 6170 "aws": testProviderFuncFixed(p), 6171 }, 6172 }) 6173 6174 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 6175 if errored { 6176 state := &InstanceState{ 6177 ID: "bar", 6178 } 6179 return state, fmt.Errorf("error") 6180 } 6181 errored = true 6182 6183 return &InstanceState{ 6184 ID: "foo", 6185 Attributes: map[string]string{ 6186 "num": "2", 6187 }, 6188 }, nil 6189 } 6190 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6191 return &InstanceDiff{ 6192 Attributes: map[string]*ResourceAttrDiff{ 6193 "num": &ResourceAttrDiff{ 6194 New: "bar", 6195 }, 6196 }, 6197 }, nil 6198 } 6199 6200 if _, err := ctx.Plan(); err != nil { 6201 t.Fatalf("err: %s", err) 6202 } 6203 6204 state, err := ctx.Apply() 6205 if err == nil { 6206 t.Fatal("should have error") 6207 } 6208 6209 actual := strings.TrimSpace(state.String()) 6210 expected := strings.TrimSpace(testTerraformApplyErrorStr) 6211 if actual != expected { 6212 t.Fatalf("bad: \n%s", actual) 6213 } 6214 } 6215 6216 func TestContext2Apply_errorPartial(t *testing.T) { 6217 errored := false 6218 6219 m := testModule(t, "apply-error") 6220 p := testProvider("aws") 6221 s := &State{ 6222 Modules: []*ModuleState{ 6223 &ModuleState{ 6224 Path: rootModulePath, 6225 Resources: map[string]*ResourceState{ 6226 "aws_instance.bar": &ResourceState{ 6227 Type: "aws_instance", 6228 Primary: &InstanceState{ 6229 ID: "bar", 6230 }, 6231 }, 6232 }, 6233 }, 6234 }, 6235 } 6236 ctx := testContext2(t, &ContextOpts{ 6237 Module: m, 6238 Providers: map[string]ResourceProviderFactory{ 6239 "aws": testProviderFuncFixed(p), 6240 }, 6241 State: s, 6242 }) 6243 6244 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6245 if errored { 6246 return s, fmt.Errorf("error") 6247 } 6248 errored = true 6249 6250 return &InstanceState{ 6251 ID: "foo", 6252 Attributes: map[string]string{ 6253 "num": "2", 6254 }, 6255 }, nil 6256 } 6257 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6258 return &InstanceDiff{ 6259 Attributes: map[string]*ResourceAttrDiff{ 6260 "num": &ResourceAttrDiff{ 6261 New: "bar", 6262 }, 6263 }, 6264 }, nil 6265 } 6266 6267 if _, err := ctx.Plan(); err != nil { 6268 t.Fatalf("err: %s", err) 6269 } 6270 6271 state, err := ctx.Apply() 6272 if err == nil { 6273 t.Fatal("should have error") 6274 } 6275 6276 mod := state.RootModule() 6277 if len(mod.Resources) != 2 { 6278 t.Fatalf("bad: %#v", mod.Resources) 6279 } 6280 6281 actual := strings.TrimSpace(state.String()) 6282 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 6283 if actual != expected { 6284 t.Fatalf("bad: \n%s", actual) 6285 } 6286 } 6287 6288 func TestContext2Apply_hook(t *testing.T) { 6289 m := testModule(t, "apply-good") 6290 h := new(MockHook) 6291 p := testProvider("aws") 6292 p.ApplyFn = testApplyFn 6293 p.DiffFn = testDiffFn 6294 ctx := testContext2(t, &ContextOpts{ 6295 Module: m, 6296 Hooks: []Hook{h}, 6297 Providers: map[string]ResourceProviderFactory{ 6298 "aws": testProviderFuncFixed(p), 6299 }, 6300 }) 6301 6302 if _, err := ctx.Plan(); err != nil { 6303 t.Fatalf("err: %s", err) 6304 } 6305 6306 if _, err := ctx.Apply(); err != nil { 6307 t.Fatalf("err: %s", err) 6308 } 6309 6310 if !h.PreApplyCalled { 6311 t.Fatal("should be called") 6312 } 6313 if !h.PostApplyCalled { 6314 t.Fatal("should be called") 6315 } 6316 if !h.PostStateUpdateCalled { 6317 t.Fatalf("should call post state update") 6318 } 6319 } 6320 6321 func TestContext2Apply_hookOrphan(t *testing.T) { 6322 m := testModule(t, "apply-blank") 6323 h := new(MockHook) 6324 p := testProvider("aws") 6325 p.ApplyFn = testApplyFn 6326 p.DiffFn = testDiffFn 6327 6328 state := &State{ 6329 Modules: []*ModuleState{ 6330 &ModuleState{ 6331 Path: rootModulePath, 6332 Resources: map[string]*ResourceState{ 6333 "aws_instance.bar": &ResourceState{ 6334 Type: "aws_instance", 6335 Primary: &InstanceState{ 6336 ID: "bar", 6337 }, 6338 }, 6339 }, 6340 }, 6341 }, 6342 } 6343 6344 ctx := testContext2(t, &ContextOpts{ 6345 Module: m, 6346 State: state, 6347 Hooks: []Hook{h}, 6348 Providers: map[string]ResourceProviderFactory{ 6349 "aws": testProviderFuncFixed(p), 6350 }, 6351 }) 6352 6353 if _, err := ctx.Plan(); err != nil { 6354 t.Fatalf("err: %s", err) 6355 } 6356 6357 if _, err := ctx.Apply(); err != nil { 6358 t.Fatalf("err: %s", err) 6359 } 6360 6361 if !h.PreApplyCalled { 6362 t.Fatal("should be called") 6363 } 6364 if !h.PostApplyCalled { 6365 t.Fatal("should be called") 6366 } 6367 if !h.PostStateUpdateCalled { 6368 t.Fatalf("should call post state update") 6369 } 6370 } 6371 6372 func TestContext2Apply_idAttr(t *testing.T) { 6373 m := testModule(t, "apply-idattr") 6374 p := testProvider("aws") 6375 ctx := testContext2(t, &ContextOpts{ 6376 Module: m, 6377 Providers: map[string]ResourceProviderFactory{ 6378 "aws": testProviderFuncFixed(p), 6379 }, 6380 }) 6381 6382 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6383 result := s.MergeDiff(d) 6384 result.ID = "foo" 6385 result.Attributes = map[string]string{ 6386 "id": "bar", 6387 } 6388 6389 return result, nil 6390 } 6391 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6392 return &InstanceDiff{ 6393 Attributes: map[string]*ResourceAttrDiff{ 6394 "num": &ResourceAttrDiff{ 6395 New: "bar", 6396 }, 6397 }, 6398 }, nil 6399 } 6400 6401 if _, err := ctx.Plan(); err != nil { 6402 t.Fatalf("err: %s", err) 6403 } 6404 6405 state, err := ctx.Apply() 6406 if err != nil { 6407 t.Fatalf("err: %s", err) 6408 } 6409 6410 mod := state.RootModule() 6411 rs, ok := mod.Resources["aws_instance.foo"] 6412 if !ok { 6413 t.Fatal("not in state") 6414 } 6415 if rs.Primary.ID != "foo" { 6416 t.Fatalf("bad: %#v", rs.Primary.ID) 6417 } 6418 if rs.Primary.Attributes["id"] != "foo" { 6419 t.Fatalf("bad: %#v", rs.Primary.Attributes) 6420 } 6421 } 6422 6423 func TestContext2Apply_outputBasic(t *testing.T) { 6424 m := testModule(t, "apply-output") 6425 p := testProvider("aws") 6426 p.ApplyFn = testApplyFn 6427 p.DiffFn = testDiffFn 6428 ctx := testContext2(t, &ContextOpts{ 6429 Module: m, 6430 Providers: map[string]ResourceProviderFactory{ 6431 "aws": testProviderFuncFixed(p), 6432 }, 6433 }) 6434 6435 if _, err := ctx.Plan(); err != nil { 6436 t.Fatalf("err: %s", err) 6437 } 6438 6439 state, err := ctx.Apply() 6440 if err != nil { 6441 t.Fatalf("err: %s", err) 6442 } 6443 6444 actual := strings.TrimSpace(state.String()) 6445 expected := strings.TrimSpace(testTerraformApplyOutputStr) 6446 if actual != expected { 6447 t.Fatalf("bad: \n%s", actual) 6448 } 6449 } 6450 6451 func TestContext2Apply_outputInvalid(t *testing.T) { 6452 m := testModule(t, "apply-output-invalid") 6453 p := testProvider("aws") 6454 p.ApplyFn = testApplyFn 6455 p.DiffFn = testDiffFn 6456 ctx := testContext2(t, &ContextOpts{ 6457 Module: m, 6458 Providers: map[string]ResourceProviderFactory{ 6459 "aws": testProviderFuncFixed(p), 6460 }, 6461 }) 6462 6463 _, err := ctx.Plan() 6464 if err == nil { 6465 t.Fatalf("err: %s", err) 6466 } 6467 if !strings.Contains(err.Error(), "is not a valid type") { 6468 t.Fatalf("err: %s", err) 6469 } 6470 } 6471 6472 func TestContext2Apply_outputAdd(t *testing.T) { 6473 m1 := testModule(t, "apply-output-add-before") 6474 p1 := testProvider("aws") 6475 p1.ApplyFn = testApplyFn 6476 p1.DiffFn = testDiffFn 6477 ctx1 := testContext2(t, &ContextOpts{ 6478 Module: m1, 6479 Providers: map[string]ResourceProviderFactory{ 6480 "aws": testProviderFuncFixed(p1), 6481 }, 6482 }) 6483 6484 if _, err := ctx1.Plan(); err != nil { 6485 t.Fatalf("err: %s", err) 6486 } 6487 6488 state1, err := ctx1.Apply() 6489 if err != nil { 6490 t.Fatalf("err: %s", err) 6491 } 6492 6493 m2 := testModule(t, "apply-output-add-after") 6494 p2 := testProvider("aws") 6495 p2.ApplyFn = testApplyFn 6496 p2.DiffFn = testDiffFn 6497 ctx2 := testContext2(t, &ContextOpts{ 6498 Module: m2, 6499 Providers: map[string]ResourceProviderFactory{ 6500 "aws": testProviderFuncFixed(p2), 6501 }, 6502 State: state1, 6503 }) 6504 6505 if _, err := ctx2.Plan(); err != nil { 6506 t.Fatalf("err: %s", err) 6507 } 6508 6509 state2, err := ctx2.Apply() 6510 if err != nil { 6511 t.Fatalf("err: %s", err) 6512 } 6513 6514 actual := strings.TrimSpace(state2.String()) 6515 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 6516 if actual != expected { 6517 t.Fatalf("bad: \n%s", actual) 6518 } 6519 } 6520 6521 func TestContext2Apply_outputList(t *testing.T) { 6522 m := testModule(t, "apply-output-list") 6523 p := testProvider("aws") 6524 p.ApplyFn = testApplyFn 6525 p.DiffFn = testDiffFn 6526 ctx := testContext2(t, &ContextOpts{ 6527 Module: m, 6528 Providers: map[string]ResourceProviderFactory{ 6529 "aws": testProviderFuncFixed(p), 6530 }, 6531 }) 6532 6533 if _, err := ctx.Plan(); err != nil { 6534 t.Fatalf("err: %s", err) 6535 } 6536 6537 state, err := ctx.Apply() 6538 if err != nil { 6539 t.Fatalf("err: %s", err) 6540 } 6541 6542 actual := strings.TrimSpace(state.String()) 6543 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 6544 if actual != expected { 6545 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 6546 } 6547 } 6548 6549 func TestContext2Apply_outputMulti(t *testing.T) { 6550 m := testModule(t, "apply-output-multi") 6551 p := testProvider("aws") 6552 p.ApplyFn = testApplyFn 6553 p.DiffFn = testDiffFn 6554 ctx := testContext2(t, &ContextOpts{ 6555 Module: m, 6556 Providers: map[string]ResourceProviderFactory{ 6557 "aws": testProviderFuncFixed(p), 6558 }, 6559 }) 6560 6561 if _, err := ctx.Plan(); err != nil { 6562 t.Fatalf("err: %s", err) 6563 } 6564 6565 state, err := ctx.Apply() 6566 if err != nil { 6567 t.Fatalf("err: %s", err) 6568 } 6569 6570 actual := strings.TrimSpace(state.String()) 6571 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 6572 if actual != expected { 6573 t.Fatalf("bad: \n%s", actual) 6574 } 6575 } 6576 6577 func TestContext2Apply_outputMultiIndex(t *testing.T) { 6578 m := testModule(t, "apply-output-multi-index") 6579 p := testProvider("aws") 6580 p.ApplyFn = testApplyFn 6581 p.DiffFn = testDiffFn 6582 ctx := testContext2(t, &ContextOpts{ 6583 Module: m, 6584 Providers: map[string]ResourceProviderFactory{ 6585 "aws": testProviderFuncFixed(p), 6586 }, 6587 }) 6588 6589 if _, err := ctx.Plan(); err != nil { 6590 t.Fatalf("err: %s", err) 6591 } 6592 6593 state, err := ctx.Apply() 6594 if err != nil { 6595 t.Fatalf("err: %s", err) 6596 } 6597 6598 actual := strings.TrimSpace(state.String()) 6599 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 6600 if actual != expected { 6601 t.Fatalf("bad: \n%s", actual) 6602 } 6603 } 6604 6605 func TestContext2Apply_taintX(t *testing.T) { 6606 m := testModule(t, "apply-taint") 6607 p := testProvider("aws") 6608 6609 // destroyCount tests against regression of 6610 // https://github.com/hashicorp/terraform/issues/1056 6611 var destroyCount = int32(0) 6612 var once sync.Once 6613 simulateProviderDelay := func() { 6614 time.Sleep(10 * time.Millisecond) 6615 } 6616 6617 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6618 once.Do(simulateProviderDelay) 6619 if d.Destroy { 6620 atomic.AddInt32(&destroyCount, 1) 6621 } 6622 return testApplyFn(info, s, d) 6623 } 6624 p.DiffFn = testDiffFn 6625 s := &State{ 6626 Modules: []*ModuleState{ 6627 &ModuleState{ 6628 Path: rootModulePath, 6629 Resources: map[string]*ResourceState{ 6630 "aws_instance.bar": &ResourceState{ 6631 Type: "aws_instance", 6632 Primary: &InstanceState{ 6633 ID: "baz", 6634 Attributes: map[string]string{ 6635 "num": "2", 6636 "type": "aws_instance", 6637 }, 6638 Tainted: true, 6639 }, 6640 }, 6641 }, 6642 }, 6643 }, 6644 } 6645 ctx := testContext2(t, &ContextOpts{ 6646 Module: m, 6647 Providers: map[string]ResourceProviderFactory{ 6648 "aws": testProviderFuncFixed(p), 6649 }, 6650 State: s, 6651 }) 6652 6653 if p, err := ctx.Plan(); err != nil { 6654 t.Fatalf("err: %s", err) 6655 } else { 6656 t.Logf("plan: %s", p) 6657 } 6658 6659 state, err := ctx.Apply() 6660 if err != nil { 6661 t.Fatalf("err: %s", err) 6662 } 6663 6664 actual := strings.TrimSpace(state.String()) 6665 expected := strings.TrimSpace(testTerraformApplyTaintStr) 6666 if actual != expected { 6667 t.Fatalf("bad:\n%s", actual) 6668 } 6669 6670 if destroyCount != 1 { 6671 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 6672 } 6673 } 6674 6675 func TestContext2Apply_taintDep(t *testing.T) { 6676 m := testModule(t, "apply-taint-dep") 6677 p := testProvider("aws") 6678 p.ApplyFn = testApplyFn 6679 p.DiffFn = testDiffFn 6680 s := &State{ 6681 Modules: []*ModuleState{ 6682 &ModuleState{ 6683 Path: rootModulePath, 6684 Resources: map[string]*ResourceState{ 6685 "aws_instance.foo": &ResourceState{ 6686 Type: "aws_instance", 6687 Primary: &InstanceState{ 6688 ID: "baz", 6689 Attributes: map[string]string{ 6690 "num": "2", 6691 "type": "aws_instance", 6692 }, 6693 Tainted: true, 6694 }, 6695 }, 6696 "aws_instance.bar": &ResourceState{ 6697 Type: "aws_instance", 6698 Primary: &InstanceState{ 6699 ID: "bar", 6700 Attributes: map[string]string{ 6701 "foo": "baz", 6702 "num": "2", 6703 "type": "aws_instance", 6704 }, 6705 }, 6706 }, 6707 }, 6708 }, 6709 }, 6710 } 6711 ctx := testContext2(t, &ContextOpts{ 6712 Module: m, 6713 Providers: map[string]ResourceProviderFactory{ 6714 "aws": testProviderFuncFixed(p), 6715 }, 6716 State: s, 6717 }) 6718 6719 if p, err := ctx.Plan(); err != nil { 6720 t.Fatalf("err: %s", err) 6721 } else { 6722 t.Logf("plan: %s", p) 6723 } 6724 6725 state, err := ctx.Apply() 6726 if err != nil { 6727 t.Fatalf("err: %s", err) 6728 } 6729 6730 actual := strings.TrimSpace(state.String()) 6731 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 6732 if actual != expected { 6733 t.Fatalf("bad:\n%s", actual) 6734 } 6735 } 6736 6737 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 6738 m := testModule(t, "apply-taint-dep-requires-new") 6739 p := testProvider("aws") 6740 p.ApplyFn = testApplyFn 6741 p.DiffFn = testDiffFn 6742 s := &State{ 6743 Modules: []*ModuleState{ 6744 &ModuleState{ 6745 Path: rootModulePath, 6746 Resources: map[string]*ResourceState{ 6747 "aws_instance.foo": &ResourceState{ 6748 Type: "aws_instance", 6749 Primary: &InstanceState{ 6750 ID: "baz", 6751 Attributes: map[string]string{ 6752 "num": "2", 6753 "type": "aws_instance", 6754 }, 6755 Tainted: true, 6756 }, 6757 }, 6758 "aws_instance.bar": &ResourceState{ 6759 Type: "aws_instance", 6760 Primary: &InstanceState{ 6761 ID: "bar", 6762 Attributes: map[string]string{ 6763 "foo": "baz", 6764 "num": "2", 6765 "type": "aws_instance", 6766 }, 6767 }, 6768 }, 6769 }, 6770 }, 6771 }, 6772 } 6773 ctx := testContext2(t, &ContextOpts{ 6774 Module: m, 6775 Providers: map[string]ResourceProviderFactory{ 6776 "aws": testProviderFuncFixed(p), 6777 }, 6778 State: s, 6779 }) 6780 6781 if p, err := ctx.Plan(); err != nil { 6782 t.Fatalf("err: %s", err) 6783 } else { 6784 t.Logf("plan: %s", p) 6785 } 6786 6787 state, err := ctx.Apply() 6788 if err != nil { 6789 t.Fatalf("err: %s", err) 6790 } 6791 6792 actual := strings.TrimSpace(state.String()) 6793 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 6794 if actual != expected { 6795 t.Fatalf("bad:\n%s", actual) 6796 } 6797 } 6798 6799 func TestContext2Apply_targeted(t *testing.T) { 6800 m := testModule(t, "apply-targeted") 6801 p := testProvider("aws") 6802 p.ApplyFn = testApplyFn 6803 p.DiffFn = testDiffFn 6804 ctx := testContext2(t, &ContextOpts{ 6805 Module: m, 6806 Providers: map[string]ResourceProviderFactory{ 6807 "aws": testProviderFuncFixed(p), 6808 }, 6809 Targets: []string{"aws_instance.foo"}, 6810 }) 6811 6812 if _, err := ctx.Plan(); err != nil { 6813 t.Fatalf("err: %s", err) 6814 } 6815 6816 state, err := ctx.Apply() 6817 if err != nil { 6818 t.Fatalf("err: %s", err) 6819 } 6820 6821 mod := state.RootModule() 6822 if len(mod.Resources) != 1 { 6823 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6824 } 6825 6826 checkStateString(t, state, ` 6827 aws_instance.foo: 6828 ID = foo 6829 num = 2 6830 type = aws_instance 6831 `) 6832 } 6833 6834 func TestContext2Apply_targetedCount(t *testing.T) { 6835 m := testModule(t, "apply-targeted-count") 6836 p := testProvider("aws") 6837 p.ApplyFn = testApplyFn 6838 p.DiffFn = testDiffFn 6839 ctx := testContext2(t, &ContextOpts{ 6840 Module: m, 6841 Providers: map[string]ResourceProviderFactory{ 6842 "aws": testProviderFuncFixed(p), 6843 }, 6844 Targets: []string{"aws_instance.foo"}, 6845 }) 6846 6847 if _, err := ctx.Plan(); err != nil { 6848 t.Fatalf("err: %s", err) 6849 } 6850 6851 state, err := ctx.Apply() 6852 if err != nil { 6853 t.Fatalf("err: %s", err) 6854 } 6855 6856 checkStateString(t, state, ` 6857 aws_instance.foo.0: 6858 ID = foo 6859 aws_instance.foo.1: 6860 ID = foo 6861 aws_instance.foo.2: 6862 ID = foo 6863 `) 6864 } 6865 6866 func TestContext2Apply_targetedCountIndex(t *testing.T) { 6867 m := testModule(t, "apply-targeted-count") 6868 p := testProvider("aws") 6869 p.ApplyFn = testApplyFn 6870 p.DiffFn = testDiffFn 6871 ctx := testContext2(t, &ContextOpts{ 6872 Module: m, 6873 Providers: map[string]ResourceProviderFactory{ 6874 "aws": testProviderFuncFixed(p), 6875 }, 6876 Targets: []string{"aws_instance.foo[1]"}, 6877 }) 6878 6879 if _, err := ctx.Plan(); err != nil { 6880 t.Fatalf("err: %s", err) 6881 } 6882 6883 state, err := ctx.Apply() 6884 if err != nil { 6885 t.Fatalf("err: %s", err) 6886 } 6887 6888 checkStateString(t, state, ` 6889 aws_instance.foo.1: 6890 ID = foo 6891 `) 6892 } 6893 6894 func TestContext2Apply_targetedDestroy(t *testing.T) { 6895 m := testModule(t, "apply-targeted") 6896 p := testProvider("aws") 6897 p.ApplyFn = testApplyFn 6898 p.DiffFn = testDiffFn 6899 ctx := testContext2(t, &ContextOpts{ 6900 Module: m, 6901 Providers: map[string]ResourceProviderFactory{ 6902 "aws": testProviderFuncFixed(p), 6903 }, 6904 State: &State{ 6905 Modules: []*ModuleState{ 6906 &ModuleState{ 6907 Path: rootModulePath, 6908 Resources: map[string]*ResourceState{ 6909 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6910 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6911 }, 6912 }, 6913 }, 6914 }, 6915 Targets: []string{"aws_instance.foo"}, 6916 Destroy: true, 6917 }) 6918 6919 if _, err := ctx.Plan(); err != nil { 6920 t.Fatalf("err: %s", err) 6921 } 6922 6923 state, err := ctx.Apply() 6924 if err != nil { 6925 t.Fatalf("err: %s", err) 6926 } 6927 6928 mod := state.RootModule() 6929 if len(mod.Resources) != 1 { 6930 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6931 } 6932 6933 checkStateString(t, state, ` 6934 aws_instance.bar: 6935 ID = i-abc123 6936 `) 6937 } 6938 6939 func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) { 6940 m := testModule(t, "apply-destroy-targeted-count") 6941 p := testProvider("aws") 6942 p.ApplyFn = testApplyFn 6943 p.DiffFn = testDiffFn 6944 ctx := testContext2(t, &ContextOpts{ 6945 Module: m, 6946 Providers: map[string]ResourceProviderFactory{ 6947 "aws": testProviderFuncFixed(p), 6948 }, 6949 State: &State{ 6950 Modules: []*ModuleState{ 6951 &ModuleState{ 6952 Path: rootModulePath, 6953 Resources: map[string]*ResourceState{ 6954 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6955 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6956 }, 6957 }, 6958 }, 6959 }, 6960 Targets: []string{"aws_instance.foo"}, 6961 Destroy: true, 6962 }) 6963 6964 if _, err := ctx.Plan(); err != nil { 6965 t.Fatalf("err: %s", err) 6966 } 6967 6968 state, err := ctx.Apply() 6969 if err != nil { 6970 t.Fatalf("err: %s", err) 6971 } 6972 6973 checkStateString(t, state, `<no state>`) 6974 } 6975 6976 // https://github.com/hashicorp/terraform/issues/4462 6977 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 6978 m := testModule(t, "apply-targeted-module") 6979 p := testProvider("aws") 6980 p.ApplyFn = testApplyFn 6981 p.DiffFn = testDiffFn 6982 ctx := testContext2(t, &ContextOpts{ 6983 Module: m, 6984 Providers: map[string]ResourceProviderFactory{ 6985 "aws": testProviderFuncFixed(p), 6986 }, 6987 State: &State{ 6988 Modules: []*ModuleState{ 6989 &ModuleState{ 6990 Path: rootModulePath, 6991 Resources: map[string]*ResourceState{ 6992 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6993 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6994 }, 6995 }, 6996 &ModuleState{ 6997 Path: []string{"root", "child"}, 6998 Resources: map[string]*ResourceState{ 6999 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 7000 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7001 }, 7002 }, 7003 }, 7004 }, 7005 Targets: []string{"module.child.aws_instance.foo"}, 7006 Destroy: true, 7007 }) 7008 7009 if _, err := ctx.Plan(); err != nil { 7010 t.Fatalf("err: %s", err) 7011 } 7012 7013 state, err := ctx.Apply() 7014 if err != nil { 7015 t.Fatalf("err: %s", err) 7016 } 7017 7018 checkStateString(t, state, ` 7019 aws_instance.bar: 7020 ID = i-abc123 7021 aws_instance.foo: 7022 ID = i-bcd345 7023 7024 module.child: 7025 aws_instance.bar: 7026 ID = i-abc123 7027 `) 7028 } 7029 7030 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 7031 m := testModule(t, "apply-targeted-count") 7032 p := testProvider("aws") 7033 p.ApplyFn = testApplyFn 7034 p.DiffFn = testDiffFn 7035 ctx := testContext2(t, &ContextOpts{ 7036 Module: m, 7037 Providers: map[string]ResourceProviderFactory{ 7038 "aws": testProviderFuncFixed(p), 7039 }, 7040 State: &State{ 7041 Modules: []*ModuleState{ 7042 &ModuleState{ 7043 Path: rootModulePath, 7044 Resources: map[string]*ResourceState{ 7045 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 7046 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 7047 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 7048 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 7049 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 7050 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 7051 }, 7052 }, 7053 }, 7054 }, 7055 Targets: []string{ 7056 "aws_instance.foo[2]", 7057 "aws_instance.bar[1]", 7058 }, 7059 Destroy: true, 7060 }) 7061 7062 if _, err := ctx.Plan(); err != nil { 7063 t.Fatalf("err: %s", err) 7064 } 7065 7066 state, err := ctx.Apply() 7067 if err != nil { 7068 t.Fatalf("err: %s", err) 7069 } 7070 7071 checkStateString(t, state, ` 7072 aws_instance.bar.0: 7073 ID = i-abc123 7074 aws_instance.bar.2: 7075 ID = i-abc123 7076 aws_instance.foo.0: 7077 ID = i-bcd345 7078 aws_instance.foo.1: 7079 ID = i-bcd345 7080 `) 7081 } 7082 7083 func TestContext2Apply_targetedModule(t *testing.T) { 7084 m := testModule(t, "apply-targeted-module") 7085 p := testProvider("aws") 7086 p.ApplyFn = testApplyFn 7087 p.DiffFn = testDiffFn 7088 ctx := testContext2(t, &ContextOpts{ 7089 Module: m, 7090 Providers: map[string]ResourceProviderFactory{ 7091 "aws": testProviderFuncFixed(p), 7092 }, 7093 Targets: []string{"module.child"}, 7094 }) 7095 7096 if _, err := ctx.Plan(); err != nil { 7097 t.Fatalf("err: %s", err) 7098 } 7099 7100 state, err := ctx.Apply() 7101 if err != nil { 7102 t.Fatalf("err: %s", err) 7103 } 7104 7105 mod := state.ModuleByPath([]string{"root", "child"}) 7106 if mod == nil { 7107 t.Fatalf("no child module found in the state!\n\n%#v", state) 7108 } 7109 if len(mod.Resources) != 2 { 7110 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 7111 } 7112 7113 checkStateString(t, state, ` 7114 <no state> 7115 module.child: 7116 aws_instance.bar: 7117 ID = foo 7118 num = 2 7119 type = aws_instance 7120 aws_instance.foo: 7121 ID = foo 7122 num = 2 7123 type = aws_instance 7124 `) 7125 } 7126 7127 // GH-1858 7128 func TestContext2Apply_targetedModuleDep(t *testing.T) { 7129 m := testModule(t, "apply-targeted-module-dep") 7130 p := testProvider("aws") 7131 p.ApplyFn = testApplyFn 7132 p.DiffFn = testDiffFn 7133 ctx := testContext2(t, &ContextOpts{ 7134 Module: m, 7135 Providers: map[string]ResourceProviderFactory{ 7136 "aws": testProviderFuncFixed(p), 7137 }, 7138 Targets: []string{"aws_instance.foo"}, 7139 }) 7140 7141 if p, err := ctx.Plan(); err != nil { 7142 t.Fatalf("err: %s", err) 7143 } else { 7144 t.Logf("Diff: %s", p) 7145 } 7146 7147 state, err := ctx.Apply() 7148 if err != nil { 7149 t.Fatalf("err: %s", err) 7150 } 7151 7152 checkStateString(t, state, ` 7153 aws_instance.foo: 7154 ID = foo 7155 foo = foo 7156 type = aws_instance 7157 7158 Dependencies: 7159 module.child 7160 7161 module.child: 7162 aws_instance.mod: 7163 ID = foo 7164 7165 Outputs: 7166 7167 output = foo 7168 `) 7169 } 7170 7171 // GH-10911 untargeted outputs should not be in the graph, and therefore 7172 // not execute. 7173 func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) { 7174 m := testModule(t, "apply-targeted-module-unrelated-outputs") 7175 p := testProvider("aws") 7176 p.ApplyFn = testApplyFn 7177 p.DiffFn = testDiffFn 7178 ctx := testContext2(t, &ContextOpts{ 7179 Module: m, 7180 Providers: map[string]ResourceProviderFactory{ 7181 "aws": testProviderFuncFixed(p), 7182 }, 7183 Targets: []string{"module.child2"}, 7184 }) 7185 7186 if _, err := ctx.Plan(); err != nil { 7187 t.Fatalf("err: %s", err) 7188 } 7189 7190 state, err := ctx.Apply() 7191 if err != nil { 7192 t.Fatalf("err: %s", err) 7193 } 7194 7195 checkStateString(t, state, ` 7196 <no state> 7197 module.child2: 7198 aws_instance.foo: 7199 ID = foo 7200 `) 7201 } 7202 7203 func TestContext2Apply_targetedModuleResource(t *testing.T) { 7204 m := testModule(t, "apply-targeted-module-resource") 7205 p := testProvider("aws") 7206 p.ApplyFn = testApplyFn 7207 p.DiffFn = testDiffFn 7208 ctx := testContext2(t, &ContextOpts{ 7209 Module: m, 7210 Providers: map[string]ResourceProviderFactory{ 7211 "aws": testProviderFuncFixed(p), 7212 }, 7213 Targets: []string{"module.child.aws_instance.foo"}, 7214 }) 7215 7216 if _, err := ctx.Plan(); err != nil { 7217 t.Fatalf("err: %s", err) 7218 } 7219 7220 state, err := ctx.Apply() 7221 if err != nil { 7222 t.Fatalf("err: %s", err) 7223 } 7224 7225 mod := state.ModuleByPath([]string{"root", "child"}) 7226 if mod == nil || len(mod.Resources) != 1 { 7227 t.Fatalf("expected 1 resource, got: %#v", mod) 7228 } 7229 7230 checkStateString(t, state, ` 7231 <no state> 7232 module.child: 7233 aws_instance.foo: 7234 ID = foo 7235 num = 2 7236 type = aws_instance 7237 `) 7238 } 7239 7240 func TestContext2Apply_unknownAttribute(t *testing.T) { 7241 m := testModule(t, "apply-unknown") 7242 p := testProvider("aws") 7243 p.ApplyFn = testApplyFn 7244 p.DiffFn = testDiffFn 7245 ctx := testContext2(t, &ContextOpts{ 7246 Module: m, 7247 Providers: map[string]ResourceProviderFactory{ 7248 "aws": testProviderFuncFixed(p), 7249 }, 7250 }) 7251 7252 if _, err := ctx.Plan(); err != nil { 7253 t.Fatalf("err: %s", err) 7254 } 7255 7256 state, err := ctx.Apply() 7257 if err == nil { 7258 t.Fatal("should error") 7259 } 7260 7261 actual := strings.TrimSpace(state.String()) 7262 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 7263 if actual != expected { 7264 t.Fatalf("bad: \n%s", actual) 7265 } 7266 } 7267 7268 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 7269 m := testModule(t, "apply-unknown-interpolate") 7270 p := testProvider("aws") 7271 p.ApplyFn = testApplyFn 7272 p.DiffFn = testDiffFn 7273 ctx := testContext2(t, &ContextOpts{ 7274 Module: m, 7275 Providers: map[string]ResourceProviderFactory{ 7276 "aws": testProviderFuncFixed(p), 7277 }, 7278 }) 7279 7280 if _, err := ctx.Plan(); err == nil { 7281 t.Fatal("should error") 7282 } 7283 } 7284 7285 func TestContext2Apply_vars(t *testing.T) { 7286 m := testModule(t, "apply-vars") 7287 p := testProvider("aws") 7288 p.ApplyFn = testApplyFn 7289 p.DiffFn = testDiffFn 7290 ctx := testContext2(t, &ContextOpts{ 7291 Module: m, 7292 Providers: map[string]ResourceProviderFactory{ 7293 "aws": testProviderFuncFixed(p), 7294 }, 7295 Variables: map[string]interface{}{ 7296 "foo": "us-west-2", 7297 "test_list": []interface{}{"Hello", "World"}, 7298 "test_map": map[string]interface{}{ 7299 "Hello": "World", 7300 "Foo": "Bar", 7301 "Baz": "Foo", 7302 }, 7303 "amis": []map[string]interface{}{ 7304 map[string]interface{}{ 7305 "us-east-1": "override", 7306 }, 7307 }, 7308 }, 7309 }) 7310 7311 w, e := ctx.Validate() 7312 if len(w) > 0 { 7313 t.Fatalf("bad: %#v", w) 7314 } 7315 if len(e) > 0 { 7316 t.Fatalf("bad: %s", e) 7317 } 7318 7319 if _, err := ctx.Plan(); err != nil { 7320 t.Fatalf("err: %s", err) 7321 } 7322 7323 state, err := ctx.Apply() 7324 if err != nil { 7325 t.Fatalf("err: %s", err) 7326 } 7327 7328 actual := strings.TrimSpace(state.String()) 7329 expected := strings.TrimSpace(testTerraformApplyVarsStr) 7330 if actual != expected { 7331 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 7332 } 7333 } 7334 7335 func TestContext2Apply_varsEnv(t *testing.T) { 7336 // Set the env var 7337 defer tempEnv(t, "TF_VAR_ami", "baz")() 7338 defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() 7339 defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() 7340 7341 m := testModule(t, "apply-vars-env") 7342 p := testProvider("aws") 7343 p.ApplyFn = testApplyFn 7344 p.DiffFn = testDiffFn 7345 ctx := testContext2(t, &ContextOpts{ 7346 Module: m, 7347 Providers: map[string]ResourceProviderFactory{ 7348 "aws": testProviderFuncFixed(p), 7349 }, 7350 }) 7351 7352 w, e := ctx.Validate() 7353 if len(w) > 0 { 7354 t.Fatalf("bad: %#v", w) 7355 } 7356 if len(e) > 0 { 7357 t.Fatalf("bad: %s", e) 7358 } 7359 7360 if _, err := ctx.Plan(); err != nil { 7361 t.Fatalf("err: %s", err) 7362 } 7363 7364 state, err := ctx.Apply() 7365 if err != nil { 7366 t.Fatalf("err: %s", err) 7367 } 7368 7369 actual := strings.TrimSpace(state.String()) 7370 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 7371 if actual != expected { 7372 t.Fatalf("bad: \n%s", actual) 7373 } 7374 } 7375 7376 func TestContext2Apply_createBefore_depends(t *testing.T) { 7377 m := testModule(t, "apply-depends-create-before") 7378 h := new(HookRecordApplyOrder) 7379 p := testProvider("aws") 7380 p.ApplyFn = testApplyFn 7381 p.DiffFn = testDiffFn 7382 state := &State{ 7383 Modules: []*ModuleState{ 7384 &ModuleState{ 7385 Path: rootModulePath, 7386 Resources: map[string]*ResourceState{ 7387 "aws_instance.web": &ResourceState{ 7388 Type: "aws_instance", 7389 Primary: &InstanceState{ 7390 ID: "bar", 7391 Attributes: map[string]string{ 7392 "require_new": "ami-old", 7393 }, 7394 }, 7395 }, 7396 "aws_instance.lb": &ResourceState{ 7397 Type: "aws_instance", 7398 Primary: &InstanceState{ 7399 ID: "baz", 7400 Attributes: map[string]string{ 7401 "instance": "bar", 7402 }, 7403 }, 7404 }, 7405 }, 7406 }, 7407 }, 7408 } 7409 ctx := testContext2(t, &ContextOpts{ 7410 Module: m, 7411 Hooks: []Hook{h}, 7412 Providers: map[string]ResourceProviderFactory{ 7413 "aws": testProviderFuncFixed(p), 7414 }, 7415 State: state, 7416 }) 7417 7418 if p, err := ctx.Plan(); err != nil { 7419 t.Fatalf("err: %s", err) 7420 } else { 7421 t.Logf("plan: %s", p) 7422 } 7423 7424 h.Active = true 7425 state, err := ctx.Apply() 7426 if err != nil { 7427 t.Fatalf("err: %s", err) 7428 } 7429 7430 mod := state.RootModule() 7431 if len(mod.Resources) < 2 { 7432 t.Fatalf("bad: %#v", mod.Resources) 7433 } 7434 7435 actual := strings.TrimSpace(state.String()) 7436 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 7437 if actual != expected { 7438 t.Fatalf("bad: \n%s\n\n%s", actual, expected) 7439 } 7440 7441 // Test that things were managed _in the right order_ 7442 order := h.States 7443 diffs := h.Diffs 7444 if order[0].ID != "" || diffs[0].Destroy { 7445 t.Fatalf("should create new instance first: %#v", order) 7446 } 7447 7448 if order[1].ID != "baz" { 7449 t.Fatalf("update must happen after create: %#v", order) 7450 } 7451 7452 if order[2].ID != "bar" || !diffs[2].Destroy { 7453 t.Fatalf("destroy must happen after update: %#v", order) 7454 } 7455 } 7456 7457 func TestContext2Apply_singleDestroy(t *testing.T) { 7458 m := testModule(t, "apply-depends-create-before") 7459 h := new(HookRecordApplyOrder) 7460 p := testProvider("aws") 7461 7462 invokeCount := 0 7463 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 7464 invokeCount++ 7465 switch invokeCount { 7466 case 1: 7467 if d.Destroy { 7468 t.Fatalf("should not destroy") 7469 } 7470 if s.ID != "" { 7471 t.Fatalf("should not have ID") 7472 } 7473 case 2: 7474 if d.Destroy { 7475 t.Fatalf("should not destroy") 7476 } 7477 if s.ID != "baz" { 7478 t.Fatalf("should have id") 7479 } 7480 case 3: 7481 if !d.Destroy { 7482 t.Fatalf("should destroy") 7483 } 7484 if s.ID == "" { 7485 t.Fatalf("should have ID") 7486 } 7487 default: 7488 t.Fatalf("bad invoke count %d", invokeCount) 7489 } 7490 return testApplyFn(info, s, d) 7491 } 7492 p.DiffFn = testDiffFn 7493 state := &State{ 7494 Modules: []*ModuleState{ 7495 &ModuleState{ 7496 Path: rootModulePath, 7497 Resources: map[string]*ResourceState{ 7498 "aws_instance.web": &ResourceState{ 7499 Type: "aws_instance", 7500 Primary: &InstanceState{ 7501 ID: "bar", 7502 Attributes: map[string]string{ 7503 "require_new": "ami-old", 7504 }, 7505 }, 7506 }, 7507 "aws_instance.lb": &ResourceState{ 7508 Type: "aws_instance", 7509 Primary: &InstanceState{ 7510 ID: "baz", 7511 Attributes: map[string]string{ 7512 "instance": "bar", 7513 }, 7514 }, 7515 }, 7516 }, 7517 }, 7518 }, 7519 } 7520 ctx := testContext2(t, &ContextOpts{ 7521 Module: m, 7522 Hooks: []Hook{h}, 7523 Providers: map[string]ResourceProviderFactory{ 7524 "aws": testProviderFuncFixed(p), 7525 }, 7526 State: state, 7527 }) 7528 7529 if _, err := ctx.Plan(); err != nil { 7530 t.Fatalf("err: %s", err) 7531 } 7532 7533 h.Active = true 7534 state, err := ctx.Apply() 7535 if err != nil { 7536 t.Fatalf("err: %s", err) 7537 } 7538 7539 if invokeCount != 3 { 7540 t.Fatalf("bad: %d", invokeCount) 7541 } 7542 } 7543 7544 // GH-7824 7545 func TestContext2Apply_issue7824(t *testing.T) { 7546 p := testProvider("template") 7547 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 7548 Name: "template_file", 7549 }) 7550 7551 p.ApplyFn = testApplyFn 7552 p.DiffFn = testDiffFn 7553 7554 // Apply cleanly step 0 7555 ctx := testContext2(t, &ContextOpts{ 7556 Module: testModule(t, "issue-7824"), 7557 Providers: map[string]ResourceProviderFactory{ 7558 "template": testProviderFuncFixed(p), 7559 }, 7560 }) 7561 7562 plan, err := ctx.Plan() 7563 if err != nil { 7564 t.Fatalf("err: %s", err) 7565 } 7566 7567 // Write / Read plan to simulate running it through a Plan file 7568 var buf bytes.Buffer 7569 if err := WritePlan(plan, &buf); err != nil { 7570 t.Fatalf("err: %s", err) 7571 } 7572 7573 planFromFile, err := ReadPlan(&buf) 7574 if err != nil { 7575 t.Fatalf("err: %s", err) 7576 } 7577 7578 ctx, err = planFromFile.Context(&ContextOpts{ 7579 Providers: map[string]ResourceProviderFactory{ 7580 "template": testProviderFuncFixed(p), 7581 }, 7582 }) 7583 if err != nil { 7584 t.Fatalf("err: %s", err) 7585 } 7586 7587 _, err = ctx.Apply() 7588 if err != nil { 7589 t.Fatalf("err: %s", err) 7590 } 7591 } 7592 7593 // GH-5254 7594 func TestContext2Apply_issue5254(t *testing.T) { 7595 // Create a provider. We use "template" here just to match the repro 7596 // we got from the issue itself. 7597 p := testProvider("template") 7598 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 7599 Name: "template_file", 7600 }) 7601 7602 p.ApplyFn = testApplyFn 7603 p.DiffFn = testDiffFn 7604 7605 // Apply cleanly step 0 7606 ctx := testContext2(t, &ContextOpts{ 7607 Module: testModule(t, "issue-5254/step-0"), 7608 Providers: map[string]ResourceProviderFactory{ 7609 "template": testProviderFuncFixed(p), 7610 }, 7611 }) 7612 7613 plan, err := ctx.Plan() 7614 if err != nil { 7615 t.Fatalf("err: %s", err) 7616 } 7617 7618 state, err := ctx.Apply() 7619 if err != nil { 7620 t.Fatalf("err: %s", err) 7621 } 7622 7623 // Application success. Now make the modification and store a plan 7624 ctx = testContext2(t, &ContextOpts{ 7625 Module: testModule(t, "issue-5254/step-1"), 7626 State: state, 7627 Providers: map[string]ResourceProviderFactory{ 7628 "template": testProviderFuncFixed(p), 7629 }, 7630 }) 7631 7632 plan, err = ctx.Plan() 7633 if err != nil { 7634 t.Fatalf("err: %s", err) 7635 } 7636 7637 // Write / Read plan to simulate running it through a Plan file 7638 var buf bytes.Buffer 7639 if err := WritePlan(plan, &buf); err != nil { 7640 t.Fatalf("err: %s", err) 7641 } 7642 7643 planFromFile, err := ReadPlan(&buf) 7644 if err != nil { 7645 t.Fatalf("err: %s", err) 7646 } 7647 7648 ctx, err = planFromFile.Context(&ContextOpts{ 7649 Providers: map[string]ResourceProviderFactory{ 7650 "template": testProviderFuncFixed(p), 7651 }, 7652 }) 7653 if err != nil { 7654 t.Fatalf("err: %s", err) 7655 } 7656 7657 state, err = ctx.Apply() 7658 if err != nil { 7659 t.Fatalf("err: %s", err) 7660 } 7661 7662 actual := strings.TrimSpace(state.String()) 7663 expected := strings.TrimSpace(` 7664 template_file.child: 7665 ID = foo 7666 template = Hi 7667 type = template_file 7668 7669 Dependencies: 7670 template_file.parent.* 7671 template_file.parent: 7672 ID = foo 7673 template = Hi 7674 type = template_file 7675 `) 7676 if actual != expected { 7677 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 7678 } 7679 } 7680 7681 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 7682 p := testProvider("aws") 7683 p.DiffFn = testDiffFn 7684 p.ApplyFn = testApplyFn 7685 ctx := testContext2(t, &ContextOpts{ 7686 Module: testModule(t, "apply-tainted-targets"), 7687 Providers: map[string]ResourceProviderFactory{ 7688 "aws": testProviderFuncFixed(p), 7689 }, 7690 Targets: []string{"aws_instance.iambeingadded"}, 7691 State: &State{ 7692 Modules: []*ModuleState{ 7693 &ModuleState{ 7694 Path: rootModulePath, 7695 Resources: map[string]*ResourceState{ 7696 "aws_instance.ifailedprovisioners": &ResourceState{ 7697 Primary: &InstanceState{ 7698 ID: "ifailedprovisioners", 7699 Tainted: true, 7700 }, 7701 }, 7702 }, 7703 }, 7704 }, 7705 }, 7706 }) 7707 7708 plan, err := ctx.Plan() 7709 if err != nil { 7710 t.Fatalf("err: %s", err) 7711 } 7712 7713 // Write / Read plan to simulate running it through a Plan file 7714 var buf bytes.Buffer 7715 if err := WritePlan(plan, &buf); err != nil { 7716 t.Fatalf("err: %s", err) 7717 } 7718 7719 planFromFile, err := ReadPlan(&buf) 7720 if err != nil { 7721 t.Fatalf("err: %s", err) 7722 } 7723 7724 ctx, err = planFromFile.Context(&ContextOpts{ 7725 Module: testModule(t, "apply-tainted-targets"), 7726 Providers: map[string]ResourceProviderFactory{ 7727 "aws": testProviderFuncFixed(p), 7728 }, 7729 }) 7730 if err != nil { 7731 t.Fatalf("err: %s", err) 7732 } 7733 7734 state, err := ctx.Apply() 7735 if err != nil { 7736 t.Fatalf("err: %s", err) 7737 } 7738 7739 actual := strings.TrimSpace(state.String()) 7740 expected := strings.TrimSpace(` 7741 aws_instance.iambeingadded: 7742 ID = foo 7743 aws_instance.ifailedprovisioners: (tainted) 7744 ID = ifailedprovisioners 7745 `) 7746 if actual != expected { 7747 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 7748 } 7749 } 7750 7751 // Higher level test exposing the bug this covers in 7752 // TestResource_ignoreChangesRequired 7753 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 7754 m := testModule(t, "apply-ignore-changes-create") 7755 p := testProvider("aws") 7756 p.ApplyFn = testApplyFn 7757 p.DiffFn = testDiffFn 7758 ctx := testContext2(t, &ContextOpts{ 7759 Module: m, 7760 Providers: map[string]ResourceProviderFactory{ 7761 "aws": testProviderFuncFixed(p), 7762 }, 7763 }) 7764 7765 if p, err := ctx.Plan(); err != nil { 7766 t.Fatalf("err: %s", err) 7767 } else { 7768 t.Logf(p.String()) 7769 } 7770 7771 state, err := ctx.Apply() 7772 if err != nil { 7773 t.Fatalf("err: %s", err) 7774 } 7775 7776 mod := state.RootModule() 7777 if len(mod.Resources) != 1 { 7778 t.Fatalf("bad: %s", state) 7779 } 7780 7781 actual := strings.TrimSpace(state.String()) 7782 // Expect no changes from original state 7783 expected := strings.TrimSpace(` 7784 aws_instance.foo: 7785 ID = foo 7786 required_field = set 7787 type = aws_instance 7788 `) 7789 if actual != expected { 7790 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 7791 } 7792 } 7793 7794 func TestContext2Apply_ignoreChangesWithDep(t *testing.T) { 7795 m := testModule(t, "apply-ignore-changes-dep") 7796 p := testProvider("aws") 7797 p.ApplyFn = testApplyFn 7798 p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 7799 switch i.Type { 7800 case "aws_instance": 7801 newAmi, _ := c.Get("ami") 7802 return &InstanceDiff{ 7803 Attributes: map[string]*ResourceAttrDiff{ 7804 "ami": &ResourceAttrDiff{ 7805 Old: s.Attributes["ami"], 7806 New: newAmi.(string), 7807 RequiresNew: true, 7808 }, 7809 }, 7810 }, nil 7811 case "aws_eip": 7812 return testDiffFn(i, s, c) 7813 default: 7814 t.Fatalf("Unexpected type: %s", i.Type) 7815 return nil, nil 7816 } 7817 } 7818 s := &State{ 7819 Modules: []*ModuleState{ 7820 &ModuleState{ 7821 Path: rootModulePath, 7822 Resources: map[string]*ResourceState{ 7823 "aws_instance.foo.0": &ResourceState{ 7824 Primary: &InstanceState{ 7825 ID: "i-abc123", 7826 Attributes: map[string]string{ 7827 "ami": "ami-abcd1234", 7828 "id": "i-abc123", 7829 }, 7830 }, 7831 }, 7832 "aws_instance.foo.1": &ResourceState{ 7833 Primary: &InstanceState{ 7834 ID: "i-bcd234", 7835 Attributes: map[string]string{ 7836 "ami": "ami-abcd1234", 7837 "id": "i-bcd234", 7838 }, 7839 }, 7840 }, 7841 "aws_eip.foo.0": &ResourceState{ 7842 Primary: &InstanceState{ 7843 ID: "eip-abc123", 7844 Attributes: map[string]string{ 7845 "id": "eip-abc123", 7846 "instance": "i-abc123", 7847 }, 7848 }, 7849 }, 7850 "aws_eip.foo.1": &ResourceState{ 7851 Primary: &InstanceState{ 7852 ID: "eip-bcd234", 7853 Attributes: map[string]string{ 7854 "id": "eip-bcd234", 7855 "instance": "i-bcd234", 7856 }, 7857 }, 7858 }, 7859 }, 7860 }, 7861 }, 7862 } 7863 ctx := testContext2(t, &ContextOpts{ 7864 Module: m, 7865 Providers: map[string]ResourceProviderFactory{ 7866 "aws": testProviderFuncFixed(p), 7867 }, 7868 State: s, 7869 }) 7870 7871 if p, err := ctx.Plan(); err != nil { 7872 t.Fatalf("err: %s", err) 7873 } else { 7874 t.Logf(p.String()) 7875 } 7876 7877 state, err := ctx.Apply() 7878 if err != nil { 7879 t.Fatalf("err: %s", err) 7880 } 7881 7882 actual := strings.TrimSpace(state.String()) 7883 expected := strings.TrimSpace(s.String()) 7884 if actual != expected { 7885 t.Fatalf("bad: \n%s", actual) 7886 } 7887 } 7888 7889 func TestContext2Apply_ignoreChangesWildcard(t *testing.T) { 7890 m := testModule(t, "apply-ignore-changes-wildcard") 7891 p := testProvider("aws") 7892 p.ApplyFn = testApplyFn 7893 p.DiffFn = testDiffFn 7894 ctx := testContext2(t, &ContextOpts{ 7895 Module: m, 7896 Providers: map[string]ResourceProviderFactory{ 7897 "aws": testProviderFuncFixed(p), 7898 }, 7899 }) 7900 7901 if p, err := ctx.Plan(); err != nil { 7902 t.Fatalf("err: %s", err) 7903 } else { 7904 t.Logf(p.String()) 7905 } 7906 7907 state, err := ctx.Apply() 7908 if err != nil { 7909 t.Fatalf("err: %s", err) 7910 } 7911 7912 mod := state.RootModule() 7913 if len(mod.Resources) != 1 { 7914 t.Fatalf("bad: %s", state) 7915 } 7916 7917 actual := strings.TrimSpace(state.String()) 7918 // Expect no changes from original state 7919 expected := strings.TrimSpace(` 7920 aws_instance.foo: 7921 ID = foo 7922 required_field = set 7923 type = aws_instance 7924 `) 7925 if actual != expected { 7926 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 7927 } 7928 } 7929 7930 // https://github.com/hashicorp/terraform/issues/7378 7931 func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) { 7932 m := testModule(t, "apply-destroy-nested-module-with-attrs") 7933 p := testProvider("null") 7934 p.ApplyFn = testApplyFn 7935 p.DiffFn = testDiffFn 7936 7937 var state *State 7938 var err error 7939 { 7940 ctx := testContext2(t, &ContextOpts{ 7941 Module: m, 7942 Providers: map[string]ResourceProviderFactory{ 7943 "null": testProviderFuncFixed(p), 7944 }, 7945 }) 7946 7947 // First plan and apply a create operation 7948 if _, err := ctx.Plan(); err != nil { 7949 t.Fatalf("plan err: %s", err) 7950 } 7951 7952 state, err = ctx.Apply() 7953 if err != nil { 7954 t.Fatalf("apply err: %s", err) 7955 } 7956 } 7957 7958 { 7959 ctx := testContext2(t, &ContextOpts{ 7960 Destroy: true, 7961 Module: m, 7962 State: state, 7963 Providers: map[string]ResourceProviderFactory{ 7964 "null": testProviderFuncFixed(p), 7965 }, 7966 }) 7967 7968 plan, err := ctx.Plan() 7969 if err != nil { 7970 t.Fatalf("destroy plan err: %s", err) 7971 } 7972 7973 var buf bytes.Buffer 7974 if err := WritePlan(plan, &buf); err != nil { 7975 t.Fatalf("plan write err: %s", err) 7976 } 7977 7978 planFromFile, err := ReadPlan(&buf) 7979 if err != nil { 7980 t.Fatalf("plan read err: %s", err) 7981 } 7982 7983 ctx, err = planFromFile.Context(&ContextOpts{ 7984 Providers: map[string]ResourceProviderFactory{ 7985 "null": testProviderFuncFixed(p), 7986 }, 7987 }) 7988 if err != nil { 7989 t.Fatalf("err: %s", err) 7990 } 7991 7992 state, err = ctx.Apply() 7993 if err != nil { 7994 t.Fatalf("destroy apply err: %s", err) 7995 } 7996 } 7997 7998 //Test that things were destroyed 7999 actual := strings.TrimSpace(state.String()) 8000 expected := strings.TrimSpace(` 8001 <no state> 8002 module.middle: 8003 <no state> 8004 module.middle.bottom: 8005 <no state> 8006 `) 8007 if actual != expected { 8008 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 8009 } 8010 } 8011 8012 // If a data source explicitly depends on another resource, it's because we need 8013 // that resource to be applied first. 8014 func TestContext2Apply_dataDependsOn(t *testing.T) { 8015 p := testProvider("null") 8016 m := testModule(t, "apply-data-depends-on") 8017 8018 ctx := testContext2(t, &ContextOpts{ 8019 Module: m, 8020 Providers: map[string]ResourceProviderFactory{ 8021 "null": testProviderFuncFixed(p), 8022 }, 8023 }) 8024 8025 // the "provisioner" here writes to this variable, because the intent is to 8026 // create a dependency which can't be viewed through the graph, and depends 8027 // solely on the configuration providing "depends_on" 8028 provisionerOutput := "" 8029 8030 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 8031 // the side effect of the resource being applied 8032 provisionerOutput = "APPLIED" 8033 return testApplyFn(info, s, d) 8034 } 8035 8036 p.DiffFn = testDiffFn 8037 p.ReadDataDiffFn = testDataDiffFn 8038 8039 p.ReadDataApplyFn = func(*InstanceInfo, *InstanceDiff) (*InstanceState, error) { 8040 // Read the artifact created by our dependency being applied. 8041 // Without any "depends_on", this would be skipped as it's assumed the 8042 // initial diff during refresh was all that's needed. 8043 return &InstanceState{ 8044 ID: "read", 8045 Attributes: map[string]string{ 8046 "foo": provisionerOutput, 8047 }, 8048 }, nil 8049 } 8050 8051 _, err := ctx.Refresh() 8052 if err != nil { 8053 t.Fatalf("err: %s", err) 8054 } 8055 8056 if _, err := ctx.Plan(); err != nil { 8057 t.Fatalf("err: %s", err) 8058 } 8059 8060 state, err := ctx.Apply() 8061 if err != nil { 8062 t.Fatalf("err: %s", err) 8063 } 8064 8065 root := state.ModuleByPath(RootModulePath) 8066 actual := root.Resources["data.null_data_source.read"].Primary.Attributes["foo"] 8067 8068 expected := "APPLIED" 8069 if actual != expected { 8070 t.Fatalf("bad:\n%s", strings.TrimSpace(state.String())) 8071 } 8072 } 8073 8074 func TestContext2Apply_terraformEnv(t *testing.T) { 8075 m := testModule(t, "apply-terraform-env") 8076 p := testProvider("aws") 8077 p.ApplyFn = testApplyFn 8078 p.DiffFn = testDiffFn 8079 8080 ctx := testContext2(t, &ContextOpts{ 8081 Meta: &ContextMeta{Env: "foo"}, 8082 Module: m, 8083 Providers: map[string]ResourceProviderFactory{ 8084 "aws": testProviderFuncFixed(p), 8085 }, 8086 }) 8087 8088 if _, err := ctx.Plan(); err != nil { 8089 t.Fatalf("err: %s", err) 8090 } 8091 8092 state, err := ctx.Apply() 8093 if err != nil { 8094 t.Fatalf("err: %s", err) 8095 } 8096 8097 actual := state.RootModule().Outputs["output"] 8098 expected := "foo" 8099 if actual == nil || actual.Value != expected { 8100 t.Fatalf("bad: \n%s", actual) 8101 } 8102 }