github.com/simonswine/terraform@v0.9.0-beta2/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 } 1744 } 1745 1746 return &InstanceState{ 1747 ID: "foo", 1748 Attributes: map[string]string{ 1749 "num": "2", 1750 }, 1751 }, nil 1752 } 1753 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 1754 return &InstanceDiff{ 1755 Attributes: map[string]*ResourceAttrDiff{ 1756 "num": &ResourceAttrDiff{ 1757 New: "bar", 1758 }, 1759 }, 1760 }, nil 1761 } 1762 1763 if _, err := ctx.Plan(); err != nil { 1764 t.Fatalf("err: %s", err) 1765 } 1766 1767 // Start the Apply in a goroutine 1768 var applyErr error 1769 stateCh := make(chan *State) 1770 go func() { 1771 state, err := ctx.Apply() 1772 if err != nil { 1773 applyErr = err 1774 } 1775 1776 stateCh <- state 1777 }() 1778 1779 state := <-stateCh 1780 if applyErr != nil { 1781 t.Fatalf("err: %s", applyErr) 1782 } 1783 1784 mod := state.RootModule() 1785 if len(mod.Resources) != 1 { 1786 t.Fatalf("bad: %s", state.String()) 1787 } 1788 1789 actual := strings.TrimSpace(state.String()) 1790 expected := strings.TrimSpace(testTerraformApplyCancelStr) 1791 if actual != expected { 1792 t.Fatalf("bad: \n%s", actual) 1793 } 1794 1795 if !p.StopCalled { 1796 t.Fatal("stop should be called") 1797 } 1798 } 1799 1800 func TestContext2Apply_cancelBlock(t *testing.T) { 1801 m := testModule(t, "apply-cancel-block") 1802 p := testProvider("aws") 1803 ctx := testContext2(t, &ContextOpts{ 1804 Module: m, 1805 Providers: map[string]ResourceProviderFactory{ 1806 "aws": testProviderFuncFixed(p), 1807 }, 1808 }) 1809 1810 applyCh := make(chan struct{}) 1811 p.DiffFn = testDiffFn 1812 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 1813 close(applyCh) 1814 1815 for !ctx.sh.Stopped() { 1816 // Wait for stop to be called. We call Gosched here so that 1817 // the other goroutines can always be scheduled to set Stopped. 1818 runtime.Gosched() 1819 } 1820 1821 // Sleep 1822 time.Sleep(100 * time.Millisecond) 1823 1824 return &InstanceState{ 1825 ID: "foo", 1826 }, nil 1827 } 1828 1829 if _, err := ctx.Plan(); err != nil { 1830 t.Fatalf("err: %s", err) 1831 } 1832 1833 // Start the Apply in a goroutine 1834 var applyErr error 1835 stateCh := make(chan *State) 1836 go func() { 1837 state, err := ctx.Apply() 1838 if err != nil { 1839 applyErr = err 1840 } 1841 1842 stateCh <- state 1843 }() 1844 1845 stopDone := make(chan struct{}) 1846 go func() { 1847 defer close(stopDone) 1848 <-applyCh 1849 ctx.Stop() 1850 }() 1851 1852 // Make sure that stop blocks 1853 select { 1854 case <-stopDone: 1855 t.Fatal("stop should block") 1856 case <-time.After(10 * time.Millisecond): 1857 } 1858 1859 // Wait for stop 1860 select { 1861 case <-stopDone: 1862 case <-time.After(500 * time.Millisecond): 1863 t.Fatal("stop should be done") 1864 } 1865 1866 // Wait for apply to complete 1867 state := <-stateCh 1868 if applyErr != nil { 1869 t.Fatalf("err: %s", applyErr) 1870 } 1871 1872 checkStateString(t, state, ` 1873 aws_instance.foo: 1874 ID = foo 1875 `) 1876 } 1877 1878 func TestContext2Apply_cancelProvisioner(t *testing.T) { 1879 m := testModule(t, "apply-cancel-provisioner") 1880 p := testProvider("aws") 1881 p.ApplyFn = testApplyFn 1882 p.DiffFn = testDiffFn 1883 pr := testProvisioner() 1884 ctx := testContext2(t, &ContextOpts{ 1885 Module: m, 1886 Providers: map[string]ResourceProviderFactory{ 1887 "aws": testProviderFuncFixed(p), 1888 }, 1889 Provisioners: map[string]ResourceProvisionerFactory{ 1890 "shell": testProvisionerFuncFixed(pr), 1891 }, 1892 }) 1893 1894 prStopped := make(chan struct{}) 1895 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 1896 // Start the stop process 1897 go ctx.Stop() 1898 1899 <-prStopped 1900 return nil 1901 } 1902 pr.StopFn = func() error { 1903 close(prStopped) 1904 return nil 1905 } 1906 1907 if _, err := ctx.Plan(); err != nil { 1908 t.Fatalf("err: %s", err) 1909 } 1910 1911 // Start the Apply in a goroutine 1912 var applyErr error 1913 stateCh := make(chan *State) 1914 go func() { 1915 state, err := ctx.Apply() 1916 if err != nil { 1917 applyErr = err 1918 } 1919 1920 stateCh <- state 1921 }() 1922 1923 // Wait for completion 1924 state := <-stateCh 1925 if applyErr != nil { 1926 t.Fatalf("err: %s", applyErr) 1927 } 1928 1929 checkStateString(t, state, ` 1930 aws_instance.foo: (tainted) 1931 ID = foo 1932 num = 2 1933 type = aws_instance 1934 `) 1935 1936 if !pr.StopCalled { 1937 t.Fatal("stop should be called") 1938 } 1939 } 1940 1941 func TestContext2Apply_compute(t *testing.T) { 1942 m := testModule(t, "apply-compute") 1943 p := testProvider("aws") 1944 p.ApplyFn = testApplyFn 1945 p.DiffFn = testDiffFn 1946 ctx := testContext2(t, &ContextOpts{ 1947 Module: m, 1948 Providers: map[string]ResourceProviderFactory{ 1949 "aws": testProviderFuncFixed(p), 1950 }, 1951 }) 1952 1953 if _, err := ctx.Plan(); err != nil { 1954 t.Fatalf("err: %s", err) 1955 } 1956 1957 ctx.variables = map[string]interface{}{"value": "1"} 1958 1959 state, err := ctx.Apply() 1960 if err != nil { 1961 t.Fatalf("err: %s", err) 1962 } 1963 1964 actual := strings.TrimSpace(state.String()) 1965 expected := strings.TrimSpace(testTerraformApplyComputeStr) 1966 if actual != expected { 1967 t.Fatalf("bad: \n%s", actual) 1968 } 1969 } 1970 1971 func TestContext2Apply_countDecrease(t *testing.T) { 1972 m := testModule(t, "apply-count-dec") 1973 p := testProvider("aws") 1974 p.DiffFn = testDiffFn 1975 s := &State{ 1976 Modules: []*ModuleState{ 1977 &ModuleState{ 1978 Path: rootModulePath, 1979 Resources: map[string]*ResourceState{ 1980 "aws_instance.foo.0": &ResourceState{ 1981 Type: "aws_instance", 1982 Primary: &InstanceState{ 1983 ID: "bar", 1984 Attributes: map[string]string{ 1985 "foo": "foo", 1986 "type": "aws_instance", 1987 }, 1988 }, 1989 }, 1990 "aws_instance.foo.1": &ResourceState{ 1991 Type: "aws_instance", 1992 Primary: &InstanceState{ 1993 ID: "bar", 1994 Attributes: map[string]string{ 1995 "foo": "foo", 1996 "type": "aws_instance", 1997 }, 1998 }, 1999 }, 2000 "aws_instance.foo.2": &ResourceState{ 2001 Type: "aws_instance", 2002 Primary: &InstanceState{ 2003 ID: "bar", 2004 Attributes: map[string]string{ 2005 "foo": "foo", 2006 "type": "aws_instance", 2007 }, 2008 }, 2009 }, 2010 }, 2011 }, 2012 }, 2013 } 2014 ctx := testContext2(t, &ContextOpts{ 2015 Module: m, 2016 Providers: map[string]ResourceProviderFactory{ 2017 "aws": testProviderFuncFixed(p), 2018 }, 2019 State: s, 2020 }) 2021 2022 if _, err := ctx.Plan(); err != nil { 2023 t.Fatalf("err: %s", err) 2024 } 2025 2026 state, err := ctx.Apply() 2027 if err != nil { 2028 t.Fatalf("err: %s", err) 2029 } 2030 2031 actual := strings.TrimSpace(state.String()) 2032 expected := strings.TrimSpace(testTerraformApplyCountDecStr) 2033 if actual != expected { 2034 t.Fatalf("bad: \n%s", actual) 2035 } 2036 } 2037 2038 func TestContext2Apply_countDecreaseToOneX(t *testing.T) { 2039 m := testModule(t, "apply-count-dec-one") 2040 p := testProvider("aws") 2041 p.ApplyFn = testApplyFn 2042 p.DiffFn = testDiffFn 2043 s := &State{ 2044 Modules: []*ModuleState{ 2045 &ModuleState{ 2046 Path: rootModulePath, 2047 Resources: map[string]*ResourceState{ 2048 "aws_instance.foo.0": &ResourceState{ 2049 Type: "aws_instance", 2050 Primary: &InstanceState{ 2051 ID: "bar", 2052 Attributes: map[string]string{ 2053 "foo": "foo", 2054 "type": "aws_instance", 2055 }, 2056 }, 2057 }, 2058 "aws_instance.foo.1": &ResourceState{ 2059 Type: "aws_instance", 2060 Primary: &InstanceState{ 2061 ID: "bar", 2062 }, 2063 }, 2064 "aws_instance.foo.2": &ResourceState{ 2065 Type: "aws_instance", 2066 Primary: &InstanceState{ 2067 ID: "bar", 2068 }, 2069 }, 2070 }, 2071 }, 2072 }, 2073 } 2074 ctx := testContext2(t, &ContextOpts{ 2075 Module: m, 2076 Providers: map[string]ResourceProviderFactory{ 2077 "aws": testProviderFuncFixed(p), 2078 }, 2079 State: s, 2080 }) 2081 2082 if _, err := ctx.Plan(); err != nil { 2083 t.Fatalf("err: %s", err) 2084 } 2085 2086 state, err := ctx.Apply() 2087 if err != nil { 2088 t.Fatalf("err: %s", err) 2089 } 2090 2091 actual := strings.TrimSpace(state.String()) 2092 expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr) 2093 if actual != expected { 2094 t.Fatalf("bad: \n%s", actual) 2095 } 2096 } 2097 2098 // https://github.com/PeoplePerHour/terraform/pull/11 2099 // 2100 // This tests a case where both a "resource" and "resource.0" are in 2101 // the state file, which apparently is a reasonable backwards compatibility 2102 // concern found in the above 3rd party repo. 2103 func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) { 2104 m := testModule(t, "apply-count-dec-one") 2105 p := testProvider("aws") 2106 p.ApplyFn = testApplyFn 2107 p.DiffFn = testDiffFn 2108 s := &State{ 2109 Modules: []*ModuleState{ 2110 &ModuleState{ 2111 Path: rootModulePath, 2112 Resources: map[string]*ResourceState{ 2113 "aws_instance.foo": &ResourceState{ 2114 Type: "aws_instance", 2115 Primary: &InstanceState{ 2116 ID: "bar", 2117 Attributes: map[string]string{ 2118 "foo": "foo", 2119 "type": "aws_instance", 2120 }, 2121 }, 2122 }, 2123 "aws_instance.foo.0": &ResourceState{ 2124 Type: "aws_instance", 2125 Primary: &InstanceState{ 2126 ID: "baz", 2127 Attributes: map[string]string{ 2128 "type": "aws_instance", 2129 }, 2130 }, 2131 }, 2132 }, 2133 }, 2134 }, 2135 } 2136 ctx := testContext2(t, &ContextOpts{ 2137 Module: m, 2138 Providers: map[string]ResourceProviderFactory{ 2139 "aws": testProviderFuncFixed(p), 2140 }, 2141 State: s, 2142 }) 2143 2144 if p, err := ctx.Plan(); err != nil { 2145 t.Fatalf("err: %s", err) 2146 } else { 2147 testStringMatch(t, p, testTerraformApplyCountDecToOneCorruptedPlanStr) 2148 } 2149 2150 state, err := ctx.Apply() 2151 if err != nil { 2152 t.Fatalf("err: %s", err) 2153 } 2154 2155 actual := strings.TrimSpace(state.String()) 2156 expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr) 2157 if actual != expected { 2158 t.Fatalf("bad: \n%s", actual) 2159 } 2160 } 2161 2162 func TestContext2Apply_countTainted(t *testing.T) { 2163 m := testModule(t, "apply-count-tainted") 2164 p := testProvider("aws") 2165 p.DiffFn = testDiffFn 2166 s := &State{ 2167 Modules: []*ModuleState{ 2168 &ModuleState{ 2169 Path: rootModulePath, 2170 Resources: map[string]*ResourceState{ 2171 "aws_instance.foo.0": &ResourceState{ 2172 Type: "aws_instance", 2173 Primary: &InstanceState{ 2174 ID: "bar", 2175 Attributes: map[string]string{ 2176 "foo": "foo", 2177 "type": "aws_instance", 2178 }, 2179 Tainted: true, 2180 }, 2181 }, 2182 }, 2183 }, 2184 }, 2185 } 2186 ctx := testContext2(t, &ContextOpts{ 2187 Module: m, 2188 Providers: map[string]ResourceProviderFactory{ 2189 "aws": testProviderFuncFixed(p), 2190 }, 2191 State: s, 2192 }) 2193 2194 if _, err := ctx.Plan(); err != nil { 2195 t.Fatalf("err: %s", err) 2196 } 2197 2198 state, err := ctx.Apply() 2199 if err != nil { 2200 t.Fatalf("err: %s", err) 2201 } 2202 2203 actual := strings.TrimSpace(state.String()) 2204 expected := strings.TrimSpace(testTerraformApplyCountTaintedStr) 2205 if actual != expected { 2206 t.Fatalf("bad: \n%s", actual) 2207 } 2208 } 2209 2210 func TestContext2Apply_countVariable(t *testing.T) { 2211 m := testModule(t, "apply-count-variable") 2212 p := testProvider("aws") 2213 p.ApplyFn = testApplyFn 2214 p.DiffFn = testDiffFn 2215 ctx := testContext2(t, &ContextOpts{ 2216 Module: m, 2217 Providers: map[string]ResourceProviderFactory{ 2218 "aws": testProviderFuncFixed(p), 2219 }, 2220 }) 2221 2222 if _, err := ctx.Plan(); err != nil { 2223 t.Fatalf("err: %s", err) 2224 } 2225 2226 state, err := ctx.Apply() 2227 if err != nil { 2228 t.Fatalf("err: %s", err) 2229 } 2230 2231 actual := strings.TrimSpace(state.String()) 2232 expected := strings.TrimSpace(testTerraformApplyCountVariableStr) 2233 if actual != expected { 2234 t.Fatalf("bad: \n%s", actual) 2235 } 2236 } 2237 2238 func TestContext2Apply_countVariableRef(t *testing.T) { 2239 m := testModule(t, "apply-count-variable-ref") 2240 p := testProvider("aws") 2241 p.ApplyFn = testApplyFn 2242 p.DiffFn = testDiffFn 2243 ctx := testContext2(t, &ContextOpts{ 2244 Module: m, 2245 Providers: map[string]ResourceProviderFactory{ 2246 "aws": testProviderFuncFixed(p), 2247 }, 2248 }) 2249 2250 if _, err := ctx.Plan(); err != nil { 2251 t.Fatalf("err: %s", err) 2252 } 2253 2254 state, err := ctx.Apply() 2255 if err != nil { 2256 t.Fatalf("err: %s", err) 2257 } 2258 2259 actual := strings.TrimSpace(state.String()) 2260 expected := strings.TrimSpace(testTerraformApplyCountVariableRefStr) 2261 if actual != expected { 2262 t.Fatalf("bad: \n%s", actual) 2263 } 2264 } 2265 2266 func TestContext2Apply_mapVariableOverride(t *testing.T) { 2267 m := testModule(t, "apply-map-var-override") 2268 p := testProvider("aws") 2269 p.ApplyFn = testApplyFn 2270 p.DiffFn = testDiffFn 2271 ctx := testContext2(t, &ContextOpts{ 2272 Module: m, 2273 Providers: map[string]ResourceProviderFactory{ 2274 "aws": testProviderFuncFixed(p), 2275 }, 2276 Variables: map[string]interface{}{ 2277 "images": []map[string]interface{}{ 2278 map[string]interface{}{ 2279 "us-west-2": "overridden", 2280 }, 2281 }, 2282 }, 2283 }) 2284 2285 if _, err := ctx.Plan(); err != nil { 2286 t.Fatalf("err: %s", err) 2287 } 2288 2289 state, err := ctx.Apply() 2290 if err != nil { 2291 t.Fatalf("err: %s", err) 2292 } 2293 2294 actual := strings.TrimSpace(state.String()) 2295 expected := strings.TrimSpace(` 2296 aws_instance.bar: 2297 ID = foo 2298 ami = overridden 2299 type = aws_instance 2300 aws_instance.foo: 2301 ID = foo 2302 ami = image-1234 2303 type = aws_instance 2304 `) 2305 if actual != expected { 2306 t.Fatalf("got: \n%s\nexpected: \n%s", actual, expected) 2307 } 2308 } 2309 2310 func TestContext2Apply_moduleBasic(t *testing.T) { 2311 m := testModule(t, "apply-module") 2312 p := testProvider("aws") 2313 p.ApplyFn = testApplyFn 2314 p.DiffFn = testDiffFn 2315 ctx := testContext2(t, &ContextOpts{ 2316 Module: m, 2317 Providers: map[string]ResourceProviderFactory{ 2318 "aws": testProviderFuncFixed(p), 2319 }, 2320 }) 2321 2322 if _, err := ctx.Plan(); err != nil { 2323 t.Fatalf("err: %s", err) 2324 } 2325 2326 state, err := ctx.Apply() 2327 if err != nil { 2328 t.Fatalf("err: %s", err) 2329 } 2330 2331 actual := strings.TrimSpace(state.String()) 2332 expected := strings.TrimSpace(testTerraformApplyModuleStr) 2333 if actual != expected { 2334 t.Fatalf("bad, expected:\n%s\n\nactual:\n%s", expected, actual) 2335 } 2336 } 2337 2338 func TestContext2Apply_moduleDestroyOrder(t *testing.T) { 2339 m := testModule(t, "apply-module-destroy-order") 2340 p := testProvider("aws") 2341 p.DiffFn = testDiffFn 2342 2343 // Create a custom apply function to track the order they were destroyed 2344 var order []string 2345 var orderLock sync.Mutex 2346 p.ApplyFn = func( 2347 info *InstanceInfo, 2348 is *InstanceState, 2349 id *InstanceDiff) (*InstanceState, error) { 2350 orderLock.Lock() 2351 defer orderLock.Unlock() 2352 2353 order = append(order, is.ID) 2354 return nil, nil 2355 } 2356 2357 state := &State{ 2358 Modules: []*ModuleState{ 2359 &ModuleState{ 2360 Path: rootModulePath, 2361 Resources: map[string]*ResourceState{ 2362 "aws_instance.b": &ResourceState{ 2363 Type: "aws_instance", 2364 Primary: &InstanceState{ 2365 ID: "b", 2366 }, 2367 }, 2368 }, 2369 }, 2370 2371 &ModuleState{ 2372 Path: []string{"root", "child"}, 2373 Resources: map[string]*ResourceState{ 2374 "aws_instance.a": &ResourceState{ 2375 Type: "aws_instance", 2376 Primary: &InstanceState{ 2377 ID: "a", 2378 }, 2379 }, 2380 }, 2381 Outputs: map[string]*OutputState{ 2382 "a_output": &OutputState{ 2383 Type: "string", 2384 Sensitive: false, 2385 Value: "a", 2386 }, 2387 }, 2388 }, 2389 }, 2390 } 2391 2392 ctx := testContext2(t, &ContextOpts{ 2393 Module: m, 2394 Providers: map[string]ResourceProviderFactory{ 2395 "aws": testProviderFuncFixed(p), 2396 }, 2397 State: state, 2398 Destroy: true, 2399 }) 2400 2401 if _, err := ctx.Plan(); err != nil { 2402 t.Fatalf("err: %s", err) 2403 } 2404 2405 state, err := ctx.Apply() 2406 if err != nil { 2407 t.Fatalf("err: %s", err) 2408 } 2409 2410 expected := []string{"b", "a"} 2411 if !reflect.DeepEqual(order, expected) { 2412 t.Fatalf("bad: %#v", order) 2413 } 2414 2415 { 2416 actual := strings.TrimSpace(state.String()) 2417 expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr) 2418 if actual != expected { 2419 t.Fatalf("bad: \n%s", actual) 2420 } 2421 } 2422 } 2423 2424 func TestContext2Apply_moduleInheritAlias(t *testing.T) { 2425 m := testModule(t, "apply-module-provider-inherit-alias") 2426 p := testProvider("aws") 2427 p.ApplyFn = testApplyFn 2428 p.DiffFn = testDiffFn 2429 2430 p.ConfigureFn = func(c *ResourceConfig) error { 2431 if _, ok := c.Get("child"); !ok { 2432 return nil 2433 } 2434 2435 if _, ok := c.Get("root"); ok { 2436 return fmt.Errorf("child should not get root") 2437 } 2438 2439 return nil 2440 } 2441 2442 ctx := testContext2(t, &ContextOpts{ 2443 Module: m, 2444 Providers: map[string]ResourceProviderFactory{ 2445 "aws": testProviderFuncFixed(p), 2446 }, 2447 }) 2448 2449 if _, err := ctx.Plan(); err != nil { 2450 t.Fatalf("err: %s", err) 2451 } 2452 2453 state, err := ctx.Apply() 2454 if err != nil { 2455 t.Fatalf("err: %s", err) 2456 } 2457 2458 checkStateString(t, state, ` 2459 <no state> 2460 module.child: 2461 aws_instance.foo: 2462 ID = foo 2463 provider = aws.eu 2464 `) 2465 } 2466 2467 func TestContext2Apply_moduleOrphanInheritAlias(t *testing.T) { 2468 m := testModule(t, "apply-module-provider-inherit-alias-orphan") 2469 p := testProvider("aws") 2470 p.ApplyFn = testApplyFn 2471 p.DiffFn = testDiffFn 2472 2473 called := false 2474 p.ConfigureFn = func(c *ResourceConfig) error { 2475 called = true 2476 2477 if _, ok := c.Get("child"); !ok { 2478 return nil 2479 } 2480 2481 if _, ok := c.Get("root"); ok { 2482 return fmt.Errorf("child should not get root") 2483 } 2484 2485 return nil 2486 } 2487 2488 // Create a state with an orphan module 2489 state := &State{ 2490 Modules: []*ModuleState{ 2491 &ModuleState{ 2492 Path: []string{"root", "child"}, 2493 Resources: map[string]*ResourceState{ 2494 "aws_instance.bar": &ResourceState{ 2495 Type: "aws_instance", 2496 Primary: &InstanceState{ 2497 ID: "bar", 2498 }, 2499 Provider: "aws.eu", 2500 }, 2501 }, 2502 }, 2503 }, 2504 } 2505 2506 ctx := testContext2(t, &ContextOpts{ 2507 Module: m, 2508 State: state, 2509 Providers: map[string]ResourceProviderFactory{ 2510 "aws": testProviderFuncFixed(p), 2511 }, 2512 }) 2513 2514 if _, err := ctx.Plan(); err != nil { 2515 t.Fatalf("err: %s", err) 2516 } 2517 2518 state, err := ctx.Apply() 2519 if err != nil { 2520 t.Fatalf("err: %s", err) 2521 } 2522 2523 if !called { 2524 t.Fatal("must call configure") 2525 } 2526 2527 checkStateString(t, state, ` 2528 module.child: 2529 <no state> 2530 `) 2531 } 2532 2533 func TestContext2Apply_moduleOrphanProvider(t *testing.T) { 2534 m := testModule(t, "apply-module-orphan-provider-inherit") 2535 p := testProvider("aws") 2536 p.ApplyFn = testApplyFn 2537 p.DiffFn = testDiffFn 2538 2539 p.ConfigureFn = func(c *ResourceConfig) error { 2540 if _, ok := c.Get("value"); !ok { 2541 return fmt.Errorf("value is not found") 2542 } 2543 2544 return nil 2545 } 2546 2547 // Create a state with an orphan module 2548 state := &State{ 2549 Modules: []*ModuleState{ 2550 &ModuleState{ 2551 Path: []string{"root", "child"}, 2552 Resources: map[string]*ResourceState{ 2553 "aws_instance.bar": &ResourceState{ 2554 Type: "aws_instance", 2555 Primary: &InstanceState{ 2556 ID: "bar", 2557 }, 2558 }, 2559 }, 2560 }, 2561 }, 2562 } 2563 2564 ctx := testContext2(t, &ContextOpts{ 2565 Module: m, 2566 State: state, 2567 Providers: map[string]ResourceProviderFactory{ 2568 "aws": testProviderFuncFixed(p), 2569 }, 2570 }) 2571 2572 if _, err := ctx.Plan(); err != nil { 2573 t.Fatalf("err: %s", err) 2574 } 2575 2576 if _, err := ctx.Apply(); err != nil { 2577 t.Fatalf("err: %s", err) 2578 } 2579 } 2580 2581 func TestContext2Apply_moduleOrphanGrandchildProvider(t *testing.T) { 2582 m := testModule(t, "apply-module-orphan-provider-inherit") 2583 p := testProvider("aws") 2584 p.ApplyFn = testApplyFn 2585 p.DiffFn = testDiffFn 2586 2587 p.ConfigureFn = func(c *ResourceConfig) error { 2588 if _, ok := c.Get("value"); !ok { 2589 return fmt.Errorf("value is not found") 2590 } 2591 2592 return nil 2593 } 2594 2595 // Create a state with an orphan module that is nested (grandchild) 2596 state := &State{ 2597 Modules: []*ModuleState{ 2598 &ModuleState{ 2599 Path: []string{"root", "parent", "child"}, 2600 Resources: map[string]*ResourceState{ 2601 "aws_instance.bar": &ResourceState{ 2602 Type: "aws_instance", 2603 Primary: &InstanceState{ 2604 ID: "bar", 2605 }, 2606 }, 2607 }, 2608 }, 2609 }, 2610 } 2611 2612 ctx := testContext2(t, &ContextOpts{ 2613 Module: m, 2614 State: state, 2615 Providers: map[string]ResourceProviderFactory{ 2616 "aws": testProviderFuncFixed(p), 2617 }, 2618 }) 2619 2620 if _, err := ctx.Plan(); err != nil { 2621 t.Fatalf("err: %s", err) 2622 } 2623 2624 if _, err := ctx.Apply(); err != nil { 2625 t.Fatalf("err: %s", err) 2626 } 2627 } 2628 2629 func TestContext2Apply_moduleGrandchildProvider(t *testing.T) { 2630 m := testModule(t, "apply-module-grandchild-provider-inherit") 2631 p := testProvider("aws") 2632 p.ApplyFn = testApplyFn 2633 p.DiffFn = testDiffFn 2634 2635 var callLock sync.Mutex 2636 called := false 2637 p.ConfigureFn = func(c *ResourceConfig) error { 2638 if _, ok := c.Get("value"); !ok { 2639 return fmt.Errorf("value is not found") 2640 } 2641 callLock.Lock() 2642 called = true 2643 callLock.Unlock() 2644 2645 return nil 2646 } 2647 2648 ctx := testContext2(t, &ContextOpts{ 2649 Module: m, 2650 Providers: map[string]ResourceProviderFactory{ 2651 "aws": testProviderFuncFixed(p), 2652 }, 2653 }) 2654 2655 if _, err := ctx.Plan(); err != nil { 2656 t.Fatalf("err: %s", err) 2657 } 2658 2659 if _, err := ctx.Apply(); err != nil { 2660 t.Fatalf("err: %s", err) 2661 } 2662 2663 callLock.Lock() 2664 defer callLock.Unlock() 2665 if called != true { 2666 t.Fatalf("err: configure never called") 2667 } 2668 } 2669 2670 // This tests an issue where all the providers in a module but not 2671 // in the root weren't being added to the root properly. In this test 2672 // case: aws is explicitly added to root, but "test" should be added to. 2673 // With the bug, it wasn't. 2674 func TestContext2Apply_moduleOnlyProvider(t *testing.T) { 2675 m := testModule(t, "apply-module-only-provider") 2676 p := testProvider("aws") 2677 p.ApplyFn = testApplyFn 2678 p.DiffFn = testDiffFn 2679 pTest := testProvider("test") 2680 pTest.ApplyFn = testApplyFn 2681 pTest.DiffFn = testDiffFn 2682 2683 ctx := testContext2(t, &ContextOpts{ 2684 Module: m, 2685 Providers: map[string]ResourceProviderFactory{ 2686 "aws": testProviderFuncFixed(p), 2687 "test": testProviderFuncFixed(pTest), 2688 }, 2689 }) 2690 2691 if _, err := ctx.Plan(); err != nil { 2692 t.Fatalf("err: %s", err) 2693 } 2694 2695 state, err := ctx.Apply() 2696 if err != nil { 2697 t.Fatalf("err: %s", err) 2698 } 2699 2700 actual := strings.TrimSpace(state.String()) 2701 expected := strings.TrimSpace(testTerraformApplyModuleOnlyProviderStr) 2702 if actual != expected { 2703 t.Fatalf("bad: \n%s", actual) 2704 } 2705 } 2706 2707 func TestContext2Apply_moduleProviderAlias(t *testing.T) { 2708 m := testModule(t, "apply-module-provider-alias") 2709 p := testProvider("aws") 2710 p.ApplyFn = testApplyFn 2711 p.DiffFn = testDiffFn 2712 ctx := testContext2(t, &ContextOpts{ 2713 Module: m, 2714 Providers: map[string]ResourceProviderFactory{ 2715 "aws": testProviderFuncFixed(p), 2716 }, 2717 }) 2718 2719 if _, err := ctx.Plan(); err != nil { 2720 t.Fatalf("err: %s", err) 2721 } 2722 2723 state, err := ctx.Apply() 2724 if err != nil { 2725 t.Fatalf("err: %s", err) 2726 } 2727 2728 actual := strings.TrimSpace(state.String()) 2729 expected := strings.TrimSpace(testTerraformApplyModuleProviderAliasStr) 2730 if actual != expected { 2731 t.Fatalf("bad: \n%s", actual) 2732 } 2733 } 2734 2735 func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) { 2736 m := testModule(t, "apply-module-provider-alias") 2737 p := testProvider("aws") 2738 p.ApplyFn = testApplyFn 2739 p.DiffFn = testDiffFn 2740 ctx := testContext2(t, &ContextOpts{ 2741 Module: m, 2742 Providers: map[string]ResourceProviderFactory{ 2743 "aws": testProviderFuncFixed(p), 2744 }, 2745 Targets: []string{"no.thing"}, 2746 }) 2747 2748 if _, err := ctx.Plan(); err != nil { 2749 t.Fatalf("err: %s", err) 2750 } 2751 2752 state, err := ctx.Apply() 2753 if err != nil { 2754 t.Fatalf("err: %s", err) 2755 } 2756 2757 actual := strings.TrimSpace(state.String()) 2758 expected := strings.TrimSpace(` 2759 <no state> 2760 `) 2761 if actual != expected { 2762 t.Fatalf("bad: \n%s", actual) 2763 } 2764 } 2765 2766 func TestContext2Apply_moduleProviderCloseNested(t *testing.T) { 2767 m := testModule(t, "apply-module-provider-close-nested") 2768 p := testProvider("aws") 2769 p.ApplyFn = testApplyFn 2770 p.DiffFn = testDiffFn 2771 ctx := testContext2(t, &ContextOpts{ 2772 Module: m, 2773 Providers: map[string]ResourceProviderFactory{ 2774 "aws": testProviderFuncFixed(p), 2775 }, 2776 State: &State{ 2777 Modules: []*ModuleState{ 2778 &ModuleState{ 2779 Path: []string{"root", "child", "subchild"}, 2780 Resources: map[string]*ResourceState{ 2781 "aws_instance.foo": &ResourceState{ 2782 Type: "aws_instance", 2783 Primary: &InstanceState{ 2784 ID: "bar", 2785 }, 2786 }, 2787 }, 2788 }, 2789 }, 2790 }, 2791 Destroy: true, 2792 }) 2793 2794 if _, err := ctx.Plan(); err != nil { 2795 t.Fatalf("err: %s", err) 2796 } 2797 2798 if _, err := ctx.Apply(); err != nil { 2799 t.Fatalf("err: %s", err) 2800 } 2801 } 2802 2803 // Tests that variables used as module vars that reference data that 2804 // already exists in the state and requires no diff works properly. This 2805 // fixes an issue faced where module variables were pruned because they were 2806 // accessing "non-existent" resources (they existed, just not in the graph 2807 // cause they weren't in the diff). 2808 func TestContext2Apply_moduleVarRefExisting(t *testing.T) { 2809 m := testModule(t, "apply-ref-existing") 2810 p := testProvider("aws") 2811 p.ApplyFn = testApplyFn 2812 p.DiffFn = testDiffFn 2813 2814 state := &State{ 2815 Modules: []*ModuleState{ 2816 &ModuleState{ 2817 Path: rootModulePath, 2818 Resources: map[string]*ResourceState{ 2819 "aws_instance.foo": &ResourceState{ 2820 Type: "aws_instance", 2821 Primary: &InstanceState{ 2822 ID: "foo", 2823 Attributes: map[string]string{ 2824 "foo": "bar", 2825 }, 2826 }, 2827 }, 2828 }, 2829 }, 2830 }, 2831 } 2832 2833 ctx := testContext2(t, &ContextOpts{ 2834 Module: m, 2835 Providers: map[string]ResourceProviderFactory{ 2836 "aws": testProviderFuncFixed(p), 2837 }, 2838 State: state, 2839 }) 2840 2841 if _, err := ctx.Plan(); err != nil { 2842 t.Fatalf("err: %s", err) 2843 } 2844 2845 state, err := ctx.Apply() 2846 if err != nil { 2847 t.Fatalf("err: %s", err) 2848 } 2849 2850 actual := strings.TrimSpace(state.String()) 2851 expected := strings.TrimSpace(testTerraformApplyModuleVarRefExistingStr) 2852 if actual != expected { 2853 t.Fatalf("bad: \n%s", actual) 2854 } 2855 } 2856 2857 func TestContext2Apply_moduleVarResourceCount(t *testing.T) { 2858 m := testModule(t, "apply-module-var-resource-count") 2859 p := testProvider("aws") 2860 p.ApplyFn = testApplyFn 2861 p.DiffFn = testDiffFn 2862 ctx := testContext2(t, &ContextOpts{ 2863 Module: m, 2864 Providers: map[string]ResourceProviderFactory{ 2865 "aws": testProviderFuncFixed(p), 2866 }, 2867 Variables: map[string]interface{}{ 2868 "count": "2", 2869 }, 2870 Destroy: true, 2871 }) 2872 2873 if _, err := ctx.Plan(); err != nil { 2874 t.Fatalf("err: %s", err) 2875 } 2876 2877 if _, err := ctx.Apply(); err != nil { 2878 t.Fatalf("err: %s", err) 2879 } 2880 2881 ctx = testContext2(t, &ContextOpts{ 2882 Module: m, 2883 Providers: map[string]ResourceProviderFactory{ 2884 "aws": testProviderFuncFixed(p), 2885 }, 2886 Variables: map[string]interface{}{ 2887 "count": "5", 2888 }, 2889 }) 2890 2891 if _, err := ctx.Plan(); err != nil { 2892 t.Fatalf("err: %s", err) 2893 } 2894 2895 if _, err := ctx.Apply(); err != nil { 2896 t.Fatalf("err: %s", err) 2897 } 2898 } 2899 2900 // GH-819 2901 func TestContext2Apply_moduleBool(t *testing.T) { 2902 m := testModule(t, "apply-module-bool") 2903 p := testProvider("aws") 2904 p.ApplyFn = testApplyFn 2905 p.DiffFn = testDiffFn 2906 ctx := testContext2(t, &ContextOpts{ 2907 Module: m, 2908 Providers: map[string]ResourceProviderFactory{ 2909 "aws": testProviderFuncFixed(p), 2910 }, 2911 }) 2912 2913 if _, err := ctx.Plan(); err != nil { 2914 t.Fatalf("err: %s", err) 2915 } 2916 2917 state, err := ctx.Apply() 2918 if err != nil { 2919 t.Fatalf("err: %s", err) 2920 } 2921 2922 actual := strings.TrimSpace(state.String()) 2923 expected := strings.TrimSpace(testTerraformApplyModuleBoolStr) 2924 if actual != expected { 2925 t.Fatalf("bad: \n%s", actual) 2926 } 2927 } 2928 2929 // Tests that a module can be targeted and everything is properly created. 2930 // This adds to the plan test to also just verify that apply works. 2931 func TestContext2Apply_moduleTarget(t *testing.T) { 2932 m := testModule(t, "plan-targeted-cross-module") 2933 p := testProvider("aws") 2934 p.ApplyFn = testApplyFn 2935 p.DiffFn = testDiffFn 2936 ctx := testContext2(t, &ContextOpts{ 2937 Module: m, 2938 Providers: map[string]ResourceProviderFactory{ 2939 "aws": testProviderFuncFixed(p), 2940 }, 2941 Targets: []string{"module.B"}, 2942 }) 2943 2944 if _, err := ctx.Plan(); err != nil { 2945 t.Fatalf("err: %s", err) 2946 } 2947 2948 state, err := ctx.Apply() 2949 if err != nil { 2950 t.Fatalf("err: %s", err) 2951 } 2952 2953 checkStateString(t, state, ` 2954 <no state> 2955 module.A: 2956 aws_instance.foo: 2957 ID = foo 2958 foo = bar 2959 type = aws_instance 2960 2961 Outputs: 2962 2963 value = foo 2964 module.B: 2965 aws_instance.bar: 2966 ID = foo 2967 foo = foo 2968 type = aws_instance 2969 `) 2970 } 2971 2972 func TestContext2Apply_multiProvider(t *testing.T) { 2973 m := testModule(t, "apply-multi-provider") 2974 p := testProvider("aws") 2975 p.ApplyFn = testApplyFn 2976 p.DiffFn = testDiffFn 2977 2978 pDO := testProvider("do") 2979 pDO.ApplyFn = testApplyFn 2980 pDO.DiffFn = testDiffFn 2981 2982 ctx := testContext2(t, &ContextOpts{ 2983 Module: m, 2984 Providers: map[string]ResourceProviderFactory{ 2985 "aws": testProviderFuncFixed(p), 2986 "do": testProviderFuncFixed(pDO), 2987 }, 2988 }) 2989 2990 if _, err := ctx.Plan(); err != nil { 2991 t.Fatalf("err: %s", err) 2992 } 2993 2994 state, err := ctx.Apply() 2995 if err != nil { 2996 t.Fatalf("err: %s", err) 2997 } 2998 2999 mod := state.RootModule() 3000 if len(mod.Resources) < 2 { 3001 t.Fatalf("bad: %#v", mod.Resources) 3002 } 3003 3004 actual := strings.TrimSpace(state.String()) 3005 expected := strings.TrimSpace(testTerraformApplyMultiProviderStr) 3006 if actual != expected { 3007 t.Fatalf("bad: \n%s", actual) 3008 } 3009 } 3010 3011 func TestContext2Apply_multiProviderDestroy(t *testing.T) { 3012 m := testModule(t, "apply-multi-provider-destroy") 3013 p := testProvider("aws") 3014 p.ApplyFn = testApplyFn 3015 p.DiffFn = testDiffFn 3016 3017 p2 := testProvider("do") 3018 p2.ApplyFn = testApplyFn 3019 p2.DiffFn = testDiffFn 3020 3021 var state *State 3022 3023 // First, create the instances 3024 { 3025 ctx := testContext2(t, &ContextOpts{ 3026 Module: m, 3027 Providers: map[string]ResourceProviderFactory{ 3028 "aws": testProviderFuncFixed(p), 3029 "vault": testProviderFuncFixed(p2), 3030 }, 3031 }) 3032 3033 if _, err := ctx.Plan(); err != nil { 3034 t.Fatalf("err: %s", err) 3035 } 3036 3037 s, err := ctx.Apply() 3038 if err != nil { 3039 t.Fatalf("err: %s", err) 3040 } 3041 3042 state = s 3043 } 3044 3045 // Destroy them 3046 { 3047 // Verify that aws_instance.bar is destroyed first 3048 var checked bool 3049 var called int32 3050 var lock sync.Mutex 3051 applyFn := func( 3052 info *InstanceInfo, 3053 is *InstanceState, 3054 id *InstanceDiff) (*InstanceState, error) { 3055 lock.Lock() 3056 defer lock.Unlock() 3057 3058 if info.HumanId() == "aws_instance.bar" { 3059 checked = true 3060 3061 // Sleep to allow parallel execution 3062 time.Sleep(50 * time.Millisecond) 3063 3064 // Verify that called is 0 (dep not called) 3065 if atomic.LoadInt32(&called) != 0 { 3066 return nil, fmt.Errorf("nothing else should be called") 3067 } 3068 } 3069 3070 atomic.AddInt32(&called, 1) 3071 return testApplyFn(info, is, id) 3072 } 3073 3074 // Set the apply functions 3075 p.ApplyFn = applyFn 3076 p2.ApplyFn = applyFn 3077 3078 ctx := testContext2(t, &ContextOpts{ 3079 Destroy: true, 3080 State: state, 3081 Module: m, 3082 Providers: map[string]ResourceProviderFactory{ 3083 "aws": testProviderFuncFixed(p), 3084 "vault": testProviderFuncFixed(p2), 3085 }, 3086 }) 3087 3088 if _, err := ctx.Plan(); err != nil { 3089 t.Fatalf("err: %s", err) 3090 } 3091 3092 s, err := ctx.Apply() 3093 if err != nil { 3094 t.Fatalf("err: %s", err) 3095 } 3096 3097 if !checked { 3098 t.Fatal("should be checked") 3099 } 3100 3101 state = s 3102 } 3103 3104 checkStateString(t, state, `<no state>`) 3105 } 3106 3107 // This is like the multiProviderDestroy test except it tests that 3108 // dependent resources within a child module that inherit provider 3109 // configuration are still destroyed first. 3110 func TestContext2Apply_multiProviderDestroyChild(t *testing.T) { 3111 m := testModule(t, "apply-multi-provider-destroy-child") 3112 p := testProvider("aws") 3113 p.ApplyFn = testApplyFn 3114 p.DiffFn = testDiffFn 3115 3116 p2 := testProvider("do") 3117 p2.ApplyFn = testApplyFn 3118 p2.DiffFn = testDiffFn 3119 3120 var state *State 3121 3122 // First, create the instances 3123 { 3124 ctx := testContext2(t, &ContextOpts{ 3125 Module: m, 3126 Providers: map[string]ResourceProviderFactory{ 3127 "aws": testProviderFuncFixed(p), 3128 "vault": testProviderFuncFixed(p2), 3129 }, 3130 }) 3131 3132 if _, err := ctx.Plan(); err != nil { 3133 t.Fatalf("err: %s", err) 3134 } 3135 3136 s, err := ctx.Apply() 3137 if err != nil { 3138 t.Fatalf("err: %s", err) 3139 } 3140 3141 state = s 3142 } 3143 3144 // Destroy them 3145 { 3146 // Verify that aws_instance.bar is destroyed first 3147 var checked bool 3148 var called int32 3149 var lock sync.Mutex 3150 applyFn := func( 3151 info *InstanceInfo, 3152 is *InstanceState, 3153 id *InstanceDiff) (*InstanceState, error) { 3154 lock.Lock() 3155 defer lock.Unlock() 3156 3157 if info.HumanId() == "module.child.aws_instance.bar" { 3158 checked = true 3159 3160 // Sleep to allow parallel execution 3161 time.Sleep(50 * time.Millisecond) 3162 3163 // Verify that called is 0 (dep not called) 3164 if atomic.LoadInt32(&called) != 0 { 3165 return nil, fmt.Errorf("nothing else should be called") 3166 } 3167 } 3168 3169 atomic.AddInt32(&called, 1) 3170 return testApplyFn(info, is, id) 3171 } 3172 3173 // Set the apply functions 3174 p.ApplyFn = applyFn 3175 p2.ApplyFn = applyFn 3176 3177 ctx := testContext2(t, &ContextOpts{ 3178 Destroy: true, 3179 State: state, 3180 Module: m, 3181 Providers: map[string]ResourceProviderFactory{ 3182 "aws": testProviderFuncFixed(p), 3183 "vault": testProviderFuncFixed(p2), 3184 }, 3185 }) 3186 3187 if _, err := ctx.Plan(); err != nil { 3188 t.Fatalf("err: %s", err) 3189 } 3190 3191 s, err := ctx.Apply() 3192 if err != nil { 3193 t.Fatalf("err: %s", err) 3194 } 3195 3196 if !checked { 3197 t.Fatal("should be checked") 3198 } 3199 3200 state = s 3201 } 3202 3203 checkStateString(t, state, ` 3204 <no state> 3205 module.child: 3206 <no state> 3207 `) 3208 } 3209 3210 func TestContext2Apply_multiVar(t *testing.T) { 3211 m := testModule(t, "apply-multi-var") 3212 p := testProvider("aws") 3213 p.ApplyFn = testApplyFn 3214 p.DiffFn = testDiffFn 3215 3216 // First, apply with a count of 3 3217 ctx := testContext2(t, &ContextOpts{ 3218 Module: m, 3219 Providers: map[string]ResourceProviderFactory{ 3220 "aws": testProviderFuncFixed(p), 3221 }, 3222 Variables: map[string]interface{}{ 3223 "count": "3", 3224 }, 3225 }) 3226 3227 if _, err := ctx.Plan(); err != nil { 3228 t.Fatalf("err: %s", err) 3229 } 3230 3231 state, err := ctx.Apply() 3232 if err != nil { 3233 t.Fatalf("err: %s", err) 3234 } 3235 3236 actual := state.RootModule().Outputs["output"] 3237 expected := "bar0,bar1,bar2" 3238 if actual == nil || actual.Value != expected { 3239 t.Fatalf("bad: \n%s", actual) 3240 } 3241 3242 t.Logf("Initial state: %s", state.String()) 3243 3244 // Apply again, reduce the count to 1 3245 { 3246 ctx := testContext2(t, &ContextOpts{ 3247 Module: m, 3248 State: state, 3249 Providers: map[string]ResourceProviderFactory{ 3250 "aws": testProviderFuncFixed(p), 3251 }, 3252 Variables: map[string]interface{}{ 3253 "count": "1", 3254 }, 3255 }) 3256 3257 if _, err := ctx.Plan(); err != nil { 3258 t.Fatalf("err: %s", err) 3259 } 3260 3261 state, err := ctx.Apply() 3262 if err != nil { 3263 t.Fatalf("err: %s", err) 3264 } 3265 3266 t.Logf("End state: %s", state.String()) 3267 3268 actual := state.RootModule().Outputs["output"] 3269 if actual == nil { 3270 t.Fatal("missing output") 3271 } 3272 3273 expected := "bar0" 3274 if actual.Value != expected { 3275 t.Fatalf("bad: \n%s", actual) 3276 } 3277 } 3278 } 3279 3280 // Test that multi-var (splat) access is ordered by count, not by 3281 // value. 3282 func TestContext2Apply_multiVarOrder(t *testing.T) { 3283 m := testModule(t, "apply-multi-var-order") 3284 p := testProvider("aws") 3285 p.ApplyFn = testApplyFn 3286 p.DiffFn = testDiffFn 3287 3288 // First, apply with a count of 3 3289 ctx := testContext2(t, &ContextOpts{ 3290 Module: m, 3291 Providers: map[string]ResourceProviderFactory{ 3292 "aws": testProviderFuncFixed(p), 3293 }, 3294 }) 3295 3296 if _, err := ctx.Plan(); err != nil { 3297 t.Fatalf("err: %s", err) 3298 } 3299 3300 state, err := ctx.Apply() 3301 if err != nil { 3302 t.Fatalf("err: %s", err) 3303 } 3304 3305 t.Logf("State: %s", state.String()) 3306 3307 actual := state.RootModule().Outputs["should-be-11"] 3308 expected := "index-11" 3309 if actual == nil || actual.Value != expected { 3310 t.Fatalf("bad: \n%s", actual) 3311 } 3312 } 3313 3314 // Test that multi-var (splat) access is ordered by count, not by 3315 // value, through interpolations. 3316 func TestContext2Apply_multiVarOrderInterp(t *testing.T) { 3317 m := testModule(t, "apply-multi-var-order-interp") 3318 p := testProvider("aws") 3319 p.ApplyFn = testApplyFn 3320 p.DiffFn = testDiffFn 3321 3322 // First, apply with a count of 3 3323 ctx := testContext2(t, &ContextOpts{ 3324 Module: m, 3325 Providers: map[string]ResourceProviderFactory{ 3326 "aws": testProviderFuncFixed(p), 3327 }, 3328 }) 3329 3330 if _, err := ctx.Plan(); err != nil { 3331 t.Fatalf("err: %s", err) 3332 } 3333 3334 state, err := ctx.Apply() 3335 if err != nil { 3336 t.Fatalf("err: %s", err) 3337 } 3338 3339 t.Logf("State: %s", state.String()) 3340 3341 actual := state.RootModule().Outputs["should-be-11"] 3342 expected := "baz-index-11" 3343 if actual == nil || actual.Value != expected { 3344 t.Fatalf("bad: \n%s", actual) 3345 } 3346 } 3347 3348 // Based on GH-10440 where a graph edge wasn't properly being created 3349 // between a modified resource and a count instance being destroyed. 3350 func TestContext2Apply_multiVarCountDec(t *testing.T) { 3351 var s *State 3352 3353 // First create resources. Nothing sneaky here. 3354 { 3355 m := testModule(t, "apply-multi-var-count-dec") 3356 p := testProvider("aws") 3357 p.ApplyFn = testApplyFn 3358 p.DiffFn = testDiffFn 3359 ctx := testContext2(t, &ContextOpts{ 3360 Module: m, 3361 Providers: map[string]ResourceProviderFactory{ 3362 "aws": testProviderFuncFixed(p), 3363 }, 3364 Variables: map[string]interface{}{ 3365 "count": "2", 3366 }, 3367 }) 3368 3369 if _, err := ctx.Plan(); err != nil { 3370 t.Fatalf("err: %s", err) 3371 } 3372 3373 state, err := ctx.Apply() 3374 if err != nil { 3375 t.Fatalf("err: %s", err) 3376 } 3377 3378 t.Logf("Step 1 state: %s", state) 3379 3380 s = state 3381 } 3382 3383 // Decrease the count by 1 and verify that everything happens in the 3384 // right order. 3385 { 3386 m := testModule(t, "apply-multi-var-count-dec") 3387 p := testProvider("aws") 3388 p.ApplyFn = testApplyFn 3389 p.DiffFn = testDiffFn 3390 3391 // Verify that aws_instance.bar is modified first and nothing 3392 // else happens at the same time. 3393 var checked bool 3394 var called int32 3395 var lock sync.Mutex 3396 p.ApplyFn = func( 3397 info *InstanceInfo, 3398 is *InstanceState, 3399 id *InstanceDiff) (*InstanceState, error) { 3400 lock.Lock() 3401 defer lock.Unlock() 3402 3403 if info.HumanId() == "aws_instance.bar" { 3404 checked = true 3405 3406 // Sleep to allow parallel execution 3407 time.Sleep(50 * time.Millisecond) 3408 3409 // Verify that called is 0 (dep not called) 3410 if atomic.LoadInt32(&called) != 1 { 3411 return nil, fmt.Errorf("nothing else should be called") 3412 } 3413 } 3414 3415 atomic.AddInt32(&called, 1) 3416 return testApplyFn(info, is, id) 3417 } 3418 3419 ctx := testContext2(t, &ContextOpts{ 3420 State: s, 3421 Module: m, 3422 Providers: map[string]ResourceProviderFactory{ 3423 "aws": testProviderFuncFixed(p), 3424 }, 3425 Variables: map[string]interface{}{ 3426 "count": "1", 3427 }, 3428 }) 3429 3430 if _, err := ctx.Plan(); err != nil { 3431 t.Fatalf("err: %s", err) 3432 } 3433 3434 state, err := ctx.Apply() 3435 if err != nil { 3436 t.Fatalf("err: %s", err) 3437 } 3438 3439 if !checked { 3440 t.Fatal("apply never called") 3441 } 3442 3443 t.Logf("Step 2 state: %s", state) 3444 3445 s = state 3446 } 3447 } 3448 3449 func TestContext2Apply_nilDiff(t *testing.T) { 3450 m := testModule(t, "apply-good") 3451 p := testProvider("aws") 3452 p.ApplyFn = testApplyFn 3453 p.DiffFn = testDiffFn 3454 ctx := testContext2(t, &ContextOpts{ 3455 Module: m, 3456 Providers: map[string]ResourceProviderFactory{ 3457 "aws": testProviderFuncFixed(p), 3458 }, 3459 }) 3460 3461 if _, err := ctx.Plan(); err != nil { 3462 t.Fatalf("err: %s", err) 3463 } 3464 3465 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3466 return nil, nil 3467 } 3468 3469 if _, err := ctx.Apply(); err == nil { 3470 t.Fatal("should error") 3471 } 3472 } 3473 3474 func TestContext2Apply_outputDependsOn(t *testing.T) { 3475 m := testModule(t, "apply-output-depends-on") 3476 p := testProvider("aws") 3477 p.DiffFn = testDiffFn 3478 3479 { 3480 // Create a custom apply function that sleeps a bit (to allow parallel 3481 // graph execution) and then returns an error to force a partial state 3482 // return. We then verify the output is NOT there. 3483 p.ApplyFn = func( 3484 info *InstanceInfo, 3485 is *InstanceState, 3486 id *InstanceDiff) (*InstanceState, error) { 3487 3488 // Sleep to allow parallel execution 3489 time.Sleep(50 * time.Millisecond) 3490 3491 // Return error to force partial state 3492 return nil, fmt.Errorf("abcd") 3493 } 3494 3495 ctx := testContext2(t, &ContextOpts{ 3496 Module: m, 3497 Providers: map[string]ResourceProviderFactory{ 3498 "aws": testProviderFuncFixed(p), 3499 }, 3500 }) 3501 3502 if _, err := ctx.Plan(); err != nil { 3503 t.Fatalf("err: %s", err) 3504 } 3505 3506 state, err := ctx.Apply() 3507 if err == nil || !strings.Contains(err.Error(), "abcd") { 3508 t.Fatalf("err: %s", err) 3509 } 3510 3511 checkStateString(t, state, `<no state>`) 3512 } 3513 3514 { 3515 // Create the standard apply function and verify we get the output 3516 p.ApplyFn = testApplyFn 3517 3518 ctx := testContext2(t, &ContextOpts{ 3519 Module: m, 3520 Providers: map[string]ResourceProviderFactory{ 3521 "aws": testProviderFuncFixed(p), 3522 }, 3523 }) 3524 3525 if _, err := ctx.Plan(); err != nil { 3526 t.Fatalf("err: %s", err) 3527 } 3528 3529 state, err := ctx.Apply() 3530 if err != nil { 3531 t.Fatalf("err: %s", err) 3532 } 3533 3534 checkStateString(t, state, ` 3535 aws_instance.foo: 3536 ID = foo 3537 3538 Outputs: 3539 3540 value = result 3541 `) 3542 } 3543 } 3544 3545 func TestContext2Apply_outputOrphan(t *testing.T) { 3546 m := testModule(t, "apply-output-orphan") 3547 p := testProvider("aws") 3548 p.ApplyFn = testApplyFn 3549 p.DiffFn = testDiffFn 3550 3551 state := &State{ 3552 Modules: []*ModuleState{ 3553 &ModuleState{ 3554 Path: rootModulePath, 3555 Outputs: map[string]*OutputState{ 3556 "foo": &OutputState{ 3557 Type: "string", 3558 Sensitive: false, 3559 Value: "bar", 3560 }, 3561 "bar": &OutputState{ 3562 Type: "string", 3563 Sensitive: false, 3564 Value: "baz", 3565 }, 3566 }, 3567 }, 3568 }, 3569 } 3570 3571 ctx := testContext2(t, &ContextOpts{ 3572 Module: m, 3573 Providers: map[string]ResourceProviderFactory{ 3574 "aws": testProviderFuncFixed(p), 3575 }, 3576 State: state, 3577 }) 3578 3579 if _, err := ctx.Plan(); err != nil { 3580 t.Fatalf("err: %s", err) 3581 } 3582 3583 state, err := ctx.Apply() 3584 if err != nil { 3585 t.Fatalf("err: %s", err) 3586 } 3587 3588 actual := strings.TrimSpace(state.String()) 3589 expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr) 3590 if actual != expected { 3591 t.Fatalf("bad: \n%s", actual) 3592 } 3593 } 3594 3595 func TestContext2Apply_outputOrphanModule(t *testing.T) { 3596 m := testModule(t, "apply-output-orphan-module") 3597 p := testProvider("aws") 3598 p.ApplyFn = testApplyFn 3599 p.DiffFn = testDiffFn 3600 3601 state := &State{ 3602 Modules: []*ModuleState{ 3603 &ModuleState{ 3604 Path: []string{"root", "child"}, 3605 Outputs: map[string]*OutputState{ 3606 "foo": &OutputState{ 3607 Type: "string", 3608 Value: "bar", 3609 }, 3610 "bar": &OutputState{ 3611 Type: "string", 3612 Value: "baz", 3613 }, 3614 }, 3615 }, 3616 }, 3617 } 3618 3619 ctx := testContext2(t, &ContextOpts{ 3620 Module: m, 3621 Providers: map[string]ResourceProviderFactory{ 3622 "aws": testProviderFuncFixed(p), 3623 }, 3624 State: state, 3625 }) 3626 3627 if _, err := ctx.Plan(); err != nil { 3628 t.Fatalf("err: %s", err) 3629 } 3630 3631 state, err := ctx.Apply() 3632 if err != nil { 3633 t.Fatalf("err: %s", err) 3634 } 3635 3636 actual := strings.TrimSpace(state.String()) 3637 expected := strings.TrimSpace(testTerraformApplyOutputOrphanModuleStr) 3638 if actual != expected { 3639 t.Fatalf("bad: \n%s", actual) 3640 } 3641 } 3642 3643 func TestContext2Apply_providerComputedVar(t *testing.T) { 3644 m := testModule(t, "apply-provider-computed") 3645 p := testProvider("aws") 3646 p.ApplyFn = testApplyFn 3647 p.DiffFn = testDiffFn 3648 3649 pTest := testProvider("test") 3650 pTest.ApplyFn = testApplyFn 3651 pTest.DiffFn = testDiffFn 3652 3653 ctx := testContext2(t, &ContextOpts{ 3654 Module: m, 3655 Providers: map[string]ResourceProviderFactory{ 3656 "aws": testProviderFuncFixed(p), 3657 "test": testProviderFuncFixed(pTest), 3658 }, 3659 }) 3660 3661 p.ConfigureFn = func(c *ResourceConfig) error { 3662 if c.IsComputed("value") { 3663 return fmt.Errorf("value is computed") 3664 } 3665 3666 v, ok := c.Get("value") 3667 if !ok { 3668 return fmt.Errorf("value is not found") 3669 } 3670 if v != "yes" { 3671 return fmt.Errorf("value is not 'yes': %v", v) 3672 } 3673 3674 return nil 3675 } 3676 3677 if _, err := ctx.Plan(); err != nil { 3678 t.Fatalf("err: %s", err) 3679 } 3680 3681 if _, err := ctx.Apply(); err != nil { 3682 t.Fatalf("err: %s", err) 3683 } 3684 } 3685 3686 func TestContext2Apply_providerConfigureDisabled(t *testing.T) { 3687 m := testModule(t, "apply-provider-configure-disabled") 3688 p := testProvider("aws") 3689 p.ApplyFn = testApplyFn 3690 p.DiffFn = testDiffFn 3691 3692 called := false 3693 p.ConfigureFn = func(c *ResourceConfig) error { 3694 called = true 3695 3696 if _, ok := c.Get("value"); !ok { 3697 return fmt.Errorf("value is not found") 3698 } 3699 3700 return nil 3701 } 3702 3703 ctx := testContext2(t, &ContextOpts{ 3704 Module: m, 3705 Providers: map[string]ResourceProviderFactory{ 3706 "aws": testProviderFuncFixed(p), 3707 }, 3708 }) 3709 3710 if _, err := ctx.Plan(); err != nil { 3711 t.Fatalf("err: %s", err) 3712 } 3713 3714 if _, err := ctx.Apply(); err != nil { 3715 t.Fatalf("err: %s", err) 3716 } 3717 3718 if !called { 3719 t.Fatal("configure never called") 3720 } 3721 } 3722 3723 func TestContext2Apply_provisionerModule(t *testing.T) { 3724 m := testModule(t, "apply-provisioner-module") 3725 p := testProvider("aws") 3726 pr := testProvisioner() 3727 p.ApplyFn = testApplyFn 3728 p.DiffFn = testDiffFn 3729 ctx := testContext2(t, &ContextOpts{ 3730 Module: m, 3731 Providers: map[string]ResourceProviderFactory{ 3732 "aws": testProviderFuncFixed(p), 3733 }, 3734 Provisioners: map[string]ResourceProvisionerFactory{ 3735 "shell": testProvisionerFuncFixed(pr), 3736 }, 3737 }) 3738 3739 if _, err := ctx.Plan(); err != nil { 3740 t.Fatalf("err: %s", err) 3741 } 3742 3743 state, err := ctx.Apply() 3744 if err != nil { 3745 t.Fatalf("err: %s", err) 3746 } 3747 3748 actual := strings.TrimSpace(state.String()) 3749 expected := strings.TrimSpace(testTerraformApplyProvisionerModuleStr) 3750 if actual != expected { 3751 t.Fatalf("bad: \n%s", actual) 3752 } 3753 3754 // Verify apply was invoked 3755 if !pr.ApplyCalled { 3756 t.Fatalf("provisioner not invoked") 3757 } 3758 } 3759 3760 func TestContext2Apply_Provisioner_compute(t *testing.T) { 3761 m := testModule(t, "apply-provisioner-compute") 3762 p := testProvider("aws") 3763 pr := testProvisioner() 3764 p.ApplyFn = testApplyFn 3765 p.DiffFn = testDiffFn 3766 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 3767 val, ok := c.Config["foo"] 3768 if !ok || val != "computed_dynamical" { 3769 t.Fatalf("bad value for foo: %v %#v", val, c) 3770 } 3771 3772 return nil 3773 } 3774 ctx := testContext2(t, &ContextOpts{ 3775 Module: m, 3776 Providers: map[string]ResourceProviderFactory{ 3777 "aws": testProviderFuncFixed(p), 3778 }, 3779 Provisioners: map[string]ResourceProvisionerFactory{ 3780 "shell": testProvisionerFuncFixed(pr), 3781 }, 3782 Variables: map[string]interface{}{ 3783 "value": "1", 3784 }, 3785 }) 3786 3787 if _, err := ctx.Plan(); err != nil { 3788 t.Fatalf("err: %s", err) 3789 } 3790 3791 state, err := ctx.Apply() 3792 if err != nil { 3793 t.Fatalf("err: %s", err) 3794 } 3795 3796 actual := strings.TrimSpace(state.String()) 3797 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 3798 if actual != expected { 3799 t.Fatalf("bad: \n%s", actual) 3800 } 3801 3802 // Verify apply was invoked 3803 if !pr.ApplyCalled { 3804 t.Fatalf("provisioner not invoked") 3805 } 3806 } 3807 3808 func TestContext2Apply_provisionerCreateFail(t *testing.T) { 3809 m := testModule(t, "apply-provisioner-fail-create") 3810 p := testProvider("aws") 3811 pr := testProvisioner() 3812 p.DiffFn = testDiffFn 3813 3814 p.ApplyFn = func( 3815 info *InstanceInfo, 3816 is *InstanceState, 3817 id *InstanceDiff) (*InstanceState, error) { 3818 is.ID = "foo" 3819 return is, fmt.Errorf("error") 3820 } 3821 3822 ctx := testContext2(t, &ContextOpts{ 3823 Module: m, 3824 Providers: map[string]ResourceProviderFactory{ 3825 "aws": testProviderFuncFixed(p), 3826 }, 3827 Provisioners: map[string]ResourceProvisionerFactory{ 3828 "shell": testProvisionerFuncFixed(pr), 3829 }, 3830 }) 3831 3832 if _, err := ctx.Plan(); err != nil { 3833 t.Fatalf("err: %s", err) 3834 } 3835 3836 state, err := ctx.Apply() 3837 if err == nil { 3838 t.Fatal("should error") 3839 } 3840 3841 actual := strings.TrimSpace(state.String()) 3842 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr) 3843 if actual != expected { 3844 t.Fatalf("bad: \n%s", actual) 3845 } 3846 } 3847 3848 func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) { 3849 m := testModule(t, "apply-provisioner-fail-create") 3850 p := testProvider("aws") 3851 pr := testProvisioner() 3852 p.DiffFn = testDiffFn 3853 3854 p.ApplyFn = func( 3855 info *InstanceInfo, 3856 is *InstanceState, 3857 id *InstanceDiff) (*InstanceState, error) { 3858 return nil, fmt.Errorf("error") 3859 } 3860 3861 ctx := testContext2(t, &ContextOpts{ 3862 Module: m, 3863 Providers: map[string]ResourceProviderFactory{ 3864 "aws": testProviderFuncFixed(p), 3865 }, 3866 Provisioners: map[string]ResourceProvisionerFactory{ 3867 "shell": testProvisionerFuncFixed(pr), 3868 }, 3869 }) 3870 3871 if _, err := ctx.Plan(); err != nil { 3872 t.Fatalf("err: %s", err) 3873 } 3874 3875 state, err := ctx.Apply() 3876 if err == nil { 3877 t.Fatal("should error") 3878 } 3879 3880 actual := strings.TrimSpace(state.String()) 3881 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr) 3882 if actual != expected { 3883 t.Fatalf("bad: \n%s", actual) 3884 } 3885 } 3886 3887 func TestContext2Apply_provisionerFail(t *testing.T) { 3888 m := testModule(t, "apply-provisioner-fail") 3889 p := testProvider("aws") 3890 pr := testProvisioner() 3891 p.ApplyFn = testApplyFn 3892 p.DiffFn = testDiffFn 3893 3894 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 3895 return fmt.Errorf("EXPLOSION") 3896 } 3897 3898 ctx := testContext2(t, &ContextOpts{ 3899 Module: m, 3900 Providers: map[string]ResourceProviderFactory{ 3901 "aws": testProviderFuncFixed(p), 3902 }, 3903 Provisioners: map[string]ResourceProvisionerFactory{ 3904 "shell": testProvisionerFuncFixed(pr), 3905 }, 3906 Variables: map[string]interface{}{ 3907 "value": "1", 3908 }, 3909 }) 3910 3911 if _, err := ctx.Plan(); err != nil { 3912 t.Fatalf("err: %s", err) 3913 } 3914 3915 state, err := ctx.Apply() 3916 if err == nil { 3917 t.Fatal("should error") 3918 } 3919 3920 actual := strings.TrimSpace(state.String()) 3921 expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr) 3922 if actual != expected { 3923 t.Fatalf("bad: \n%s", actual) 3924 } 3925 } 3926 3927 func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) { 3928 m := testModule(t, "apply-provisioner-fail-create-before") 3929 p := testProvider("aws") 3930 pr := testProvisioner() 3931 p.ApplyFn = testApplyFn 3932 p.DiffFn = testDiffFn 3933 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 3934 return fmt.Errorf("EXPLOSION") 3935 } 3936 3937 state := &State{ 3938 Modules: []*ModuleState{ 3939 &ModuleState{ 3940 Path: rootModulePath, 3941 Resources: map[string]*ResourceState{ 3942 "aws_instance.bar": &ResourceState{ 3943 Type: "aws_instance", 3944 Primary: &InstanceState{ 3945 ID: "bar", 3946 Attributes: map[string]string{ 3947 "require_new": "abc", 3948 }, 3949 }, 3950 }, 3951 }, 3952 }, 3953 }, 3954 } 3955 ctx := testContext2(t, &ContextOpts{ 3956 Module: m, 3957 Providers: map[string]ResourceProviderFactory{ 3958 "aws": testProviderFuncFixed(p), 3959 }, 3960 Provisioners: map[string]ResourceProvisionerFactory{ 3961 "shell": testProvisionerFuncFixed(pr), 3962 }, 3963 State: state, 3964 }) 3965 3966 if _, err := ctx.Plan(); err != nil { 3967 t.Fatalf("err: %s", err) 3968 } 3969 3970 state, err := ctx.Apply() 3971 if err == nil { 3972 t.Fatal("should error") 3973 } 3974 3975 actual := strings.TrimSpace(state.String()) 3976 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr) 3977 if actual != expected { 3978 t.Fatalf("bad: \n%s", actual) 3979 } 3980 } 3981 3982 func TestContext2Apply_error_createBeforeDestroy(t *testing.T) { 3983 m := testModule(t, "apply-error-create-before") 3984 p := testProvider("aws") 3985 state := &State{ 3986 Modules: []*ModuleState{ 3987 &ModuleState{ 3988 Path: rootModulePath, 3989 Resources: map[string]*ResourceState{ 3990 "aws_instance.bar": &ResourceState{ 3991 Type: "aws_instance", 3992 Primary: &InstanceState{ 3993 ID: "bar", 3994 Attributes: map[string]string{ 3995 "require_new": "abc", 3996 }, 3997 }, 3998 }, 3999 }, 4000 }, 4001 }, 4002 } 4003 ctx := testContext2(t, &ContextOpts{ 4004 Module: m, 4005 Providers: map[string]ResourceProviderFactory{ 4006 "aws": testProviderFuncFixed(p), 4007 }, 4008 State: state, 4009 }) 4010 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4011 return nil, fmt.Errorf("error") 4012 } 4013 p.DiffFn = testDiffFn 4014 4015 if _, err := ctx.Plan(); err != nil { 4016 t.Fatalf("err: %s", err) 4017 } 4018 4019 state, err := ctx.Apply() 4020 if err == nil { 4021 t.Fatal("should have error") 4022 } 4023 4024 actual := strings.TrimSpace(state.String()) 4025 expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr) 4026 if actual != expected { 4027 t.Fatalf("bad: \n%s\n\nExpected:\n\n%s", actual, expected) 4028 } 4029 } 4030 4031 func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) { 4032 m := testModule(t, "apply-error-create-before") 4033 p := testProvider("aws") 4034 state := &State{ 4035 Modules: []*ModuleState{ 4036 &ModuleState{ 4037 Path: rootModulePath, 4038 Resources: map[string]*ResourceState{ 4039 "aws_instance.bar": &ResourceState{ 4040 Type: "aws_instance", 4041 Primary: &InstanceState{ 4042 ID: "bar", 4043 Attributes: map[string]string{ 4044 "require_new": "abc", 4045 }, 4046 }, 4047 }, 4048 }, 4049 }, 4050 }, 4051 } 4052 ctx := testContext2(t, &ContextOpts{ 4053 Module: m, 4054 Providers: map[string]ResourceProviderFactory{ 4055 "aws": testProviderFuncFixed(p), 4056 }, 4057 State: state, 4058 }) 4059 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4060 // Fail the destroy! 4061 if id.Destroy { 4062 return is, fmt.Errorf("error") 4063 } 4064 4065 // Create should work 4066 is = &InstanceState{ 4067 ID: "foo", 4068 } 4069 return is, nil 4070 } 4071 p.DiffFn = testDiffFn 4072 4073 if _, err := ctx.Plan(); err != nil { 4074 t.Fatalf("err: %s", err) 4075 } 4076 4077 state, err := ctx.Apply() 4078 if err == nil { 4079 t.Fatal("should have error") 4080 } 4081 4082 actual := strings.TrimSpace(state.String()) 4083 expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr) 4084 if actual != expected { 4085 t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected) 4086 } 4087 } 4088 4089 func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) { 4090 m := testModule(t, "apply-multi-depose-create-before-destroy") 4091 p := testProvider("aws") 4092 p.DiffFn = testDiffFn 4093 ps := map[string]ResourceProviderFactory{"aws": testProviderFuncFixed(p)} 4094 state := &State{ 4095 Modules: []*ModuleState{ 4096 &ModuleState{ 4097 Path: rootModulePath, 4098 Resources: map[string]*ResourceState{ 4099 "aws_instance.web": &ResourceState{ 4100 Type: "aws_instance", 4101 Primary: &InstanceState{ID: "foo"}, 4102 }, 4103 }, 4104 }, 4105 }, 4106 } 4107 4108 ctx := testContext2(t, &ContextOpts{ 4109 Module: m, 4110 Providers: ps, 4111 State: state, 4112 }) 4113 createdInstanceId := "bar" 4114 // Create works 4115 createFunc := func(is *InstanceState) (*InstanceState, error) { 4116 return &InstanceState{ID: createdInstanceId}, nil 4117 } 4118 // Destroy starts broken 4119 destroyFunc := func(is *InstanceState) (*InstanceState, error) { 4120 return is, fmt.Errorf("destroy failed") 4121 } 4122 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 4123 if id.Destroy { 4124 return destroyFunc(is) 4125 } else { 4126 return createFunc(is) 4127 } 4128 } 4129 4130 if _, err := ctx.Plan(); err != nil { 4131 t.Fatalf("err: %s", err) 4132 } 4133 4134 // Destroy is broken, so even though CBD successfully replaces the instance, 4135 // we'll have to save the Deposed instance to destroy later 4136 state, err := ctx.Apply() 4137 if err == nil { 4138 t.Fatal("should have error") 4139 } 4140 4141 checkStateString(t, state, ` 4142 aws_instance.web: (1 deposed) 4143 ID = bar 4144 Deposed ID 1 = foo 4145 `) 4146 4147 createdInstanceId = "baz" 4148 ctx = testContext2(t, &ContextOpts{ 4149 Module: m, 4150 Providers: ps, 4151 State: state, 4152 }) 4153 4154 if _, err := ctx.Plan(); err != nil { 4155 t.Fatalf("err: %s", err) 4156 } 4157 4158 // We're replacing the primary instance once again. Destroy is _still_ 4159 // broken, so the Deposed list gets longer 4160 state, err = ctx.Apply() 4161 if err == nil { 4162 t.Fatal("should have error") 4163 } 4164 4165 checkStateString(t, state, ` 4166 aws_instance.web: (2 deposed) 4167 ID = baz 4168 Deposed ID 1 = foo 4169 Deposed ID 2 = bar 4170 `) 4171 4172 // Destroy partially fixed! 4173 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4174 if is.ID == "foo" || is.ID == "baz" { 4175 return nil, nil 4176 } else { 4177 return is, fmt.Errorf("destroy partially failed") 4178 } 4179 } 4180 4181 createdInstanceId = "qux" 4182 if _, err := ctx.Plan(); err != nil { 4183 t.Fatalf("err: %s", err) 4184 } 4185 state, err = ctx.Apply() 4186 // Expect error because 1/2 of Deposed destroys failed 4187 if err == nil { 4188 t.Fatal("should have error") 4189 } 4190 4191 // foo and baz are now gone, bar sticks around 4192 checkStateString(t, state, ` 4193 aws_instance.web: (1 deposed) 4194 ID = qux 4195 Deposed ID 1 = bar 4196 `) 4197 4198 // Destroy working fully! 4199 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 4200 return nil, nil 4201 } 4202 4203 createdInstanceId = "quux" 4204 if _, err := ctx.Plan(); err != nil { 4205 t.Fatalf("err: %s", err) 4206 } 4207 state, err = ctx.Apply() 4208 if err != nil { 4209 t.Fatal("should not have error:", err) 4210 } 4211 4212 // And finally the state is clean 4213 checkStateString(t, state, ` 4214 aws_instance.web: 4215 ID = quux 4216 `) 4217 } 4218 4219 // Verify that a normal provisioner with on_failure "continue" set won't 4220 // taint the resource and continues executing. 4221 func TestContext2Apply_provisionerFailContinue(t *testing.T) { 4222 m := testModule(t, "apply-provisioner-fail-continue") 4223 p := testProvider("aws") 4224 pr := testProvisioner() 4225 p.ApplyFn = testApplyFn 4226 p.DiffFn = testDiffFn 4227 4228 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4229 return fmt.Errorf("provisioner error") 4230 } 4231 4232 ctx := testContext2(t, &ContextOpts{ 4233 Module: m, 4234 Providers: map[string]ResourceProviderFactory{ 4235 "aws": testProviderFuncFixed(p), 4236 }, 4237 Provisioners: map[string]ResourceProvisionerFactory{ 4238 "shell": testProvisionerFuncFixed(pr), 4239 }, 4240 }) 4241 4242 if _, err := ctx.Plan(); err != nil { 4243 t.Fatalf("err: %s", err) 4244 } 4245 4246 state, err := ctx.Apply() 4247 if err != nil { 4248 t.Fatalf("err: %s", err) 4249 } 4250 4251 checkStateString(t, state, ` 4252 aws_instance.foo: 4253 ID = foo 4254 foo = bar 4255 type = aws_instance 4256 `) 4257 4258 // Verify apply was invoked 4259 if !pr.ApplyCalled { 4260 t.Fatalf("provisioner not invoked") 4261 } 4262 } 4263 4264 // Verify that a normal provisioner with on_failure "continue" records 4265 // the error with the hook. 4266 func TestContext2Apply_provisionerFailContinueHook(t *testing.T) { 4267 h := new(MockHook) 4268 m := testModule(t, "apply-provisioner-fail-continue") 4269 p := testProvider("aws") 4270 pr := testProvisioner() 4271 p.ApplyFn = testApplyFn 4272 p.DiffFn = testDiffFn 4273 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4274 return fmt.Errorf("provisioner error") 4275 } 4276 4277 ctx := testContext2(t, &ContextOpts{ 4278 Module: m, 4279 Hooks: []Hook{h}, 4280 Providers: map[string]ResourceProviderFactory{ 4281 "aws": testProviderFuncFixed(p), 4282 }, 4283 Provisioners: map[string]ResourceProvisionerFactory{ 4284 "shell": testProvisionerFuncFixed(pr), 4285 }, 4286 }) 4287 4288 if _, err := ctx.Plan(); err != nil { 4289 t.Fatalf("err: %s", err) 4290 } 4291 4292 if _, err := ctx.Apply(); err != nil { 4293 t.Fatalf("err: %s", err) 4294 } 4295 4296 if !h.PostProvisionCalled { 4297 t.Fatal("PostProvision not called") 4298 } 4299 if h.PostProvisionErrorArg == nil { 4300 t.Fatal("should have error") 4301 } 4302 } 4303 4304 func TestContext2Apply_provisionerDestroy(t *testing.T) { 4305 m := testModule(t, "apply-provisioner-destroy") 4306 p := testProvider("aws") 4307 pr := testProvisioner() 4308 p.ApplyFn = testApplyFn 4309 p.DiffFn = testDiffFn 4310 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4311 val, ok := c.Config["foo"] 4312 if !ok || val != "destroy" { 4313 t.Fatalf("bad value for foo: %v %#v", val, c) 4314 } 4315 4316 return nil 4317 } 4318 4319 state := &State{ 4320 Modules: []*ModuleState{ 4321 &ModuleState{ 4322 Path: rootModulePath, 4323 Resources: map[string]*ResourceState{ 4324 "aws_instance.foo": &ResourceState{ 4325 Type: "aws_instance", 4326 Primary: &InstanceState{ 4327 ID: "bar", 4328 }, 4329 }, 4330 }, 4331 }, 4332 }, 4333 } 4334 4335 ctx := testContext2(t, &ContextOpts{ 4336 Module: m, 4337 State: state, 4338 Destroy: true, 4339 Providers: map[string]ResourceProviderFactory{ 4340 "aws": testProviderFuncFixed(p), 4341 }, 4342 Provisioners: map[string]ResourceProvisionerFactory{ 4343 "shell": testProvisionerFuncFixed(pr), 4344 }, 4345 }) 4346 4347 if _, err := ctx.Plan(); err != nil { 4348 t.Fatalf("err: %s", err) 4349 } 4350 4351 state, err := ctx.Apply() 4352 if err != nil { 4353 t.Fatalf("err: %s", err) 4354 } 4355 4356 checkStateString(t, state, `<no state>`) 4357 4358 // Verify apply was invoked 4359 if !pr.ApplyCalled { 4360 t.Fatalf("provisioner not invoked") 4361 } 4362 } 4363 4364 // Verify that on destroy provisioner failure, nothing happens to the instance 4365 func TestContext2Apply_provisionerDestroyFail(t *testing.T) { 4366 m := testModule(t, "apply-provisioner-destroy") 4367 p := testProvider("aws") 4368 pr := testProvisioner() 4369 p.ApplyFn = testApplyFn 4370 p.DiffFn = testDiffFn 4371 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4372 return fmt.Errorf("provisioner error") 4373 } 4374 4375 state := &State{ 4376 Modules: []*ModuleState{ 4377 &ModuleState{ 4378 Path: rootModulePath, 4379 Resources: map[string]*ResourceState{ 4380 "aws_instance.foo": &ResourceState{ 4381 Type: "aws_instance", 4382 Primary: &InstanceState{ 4383 ID: "bar", 4384 }, 4385 }, 4386 }, 4387 }, 4388 }, 4389 } 4390 4391 ctx := testContext2(t, &ContextOpts{ 4392 Module: m, 4393 State: state, 4394 Destroy: true, 4395 Providers: map[string]ResourceProviderFactory{ 4396 "aws": testProviderFuncFixed(p), 4397 }, 4398 Provisioners: map[string]ResourceProvisionerFactory{ 4399 "shell": testProvisionerFuncFixed(pr), 4400 }, 4401 }) 4402 4403 if _, err := ctx.Plan(); err != nil { 4404 t.Fatalf("err: %s", err) 4405 } 4406 4407 state, err := ctx.Apply() 4408 if err == nil { 4409 t.Fatal("should error") 4410 } 4411 4412 checkStateString(t, state, ` 4413 aws_instance.foo: 4414 ID = bar 4415 `) 4416 4417 // Verify apply was invoked 4418 if !pr.ApplyCalled { 4419 t.Fatalf("provisioner not invoked") 4420 } 4421 } 4422 4423 // Verify that on destroy provisioner failure with "continue" that 4424 // we continue to the next provisioner. 4425 func TestContext2Apply_provisionerDestroyFailContinue(t *testing.T) { 4426 m := testModule(t, "apply-provisioner-destroy-continue") 4427 p := testProvider("aws") 4428 pr := testProvisioner() 4429 p.ApplyFn = testApplyFn 4430 p.DiffFn = testDiffFn 4431 4432 var calls []string 4433 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4434 val, ok := c.Config["foo"] 4435 if !ok { 4436 t.Fatalf("bad value for foo: %v %#v", val, c) 4437 } 4438 4439 calls = append(calls, val.(string)) 4440 return fmt.Errorf("provisioner error") 4441 } 4442 4443 state := &State{ 4444 Modules: []*ModuleState{ 4445 &ModuleState{ 4446 Path: rootModulePath, 4447 Resources: map[string]*ResourceState{ 4448 "aws_instance.foo": &ResourceState{ 4449 Type: "aws_instance", 4450 Primary: &InstanceState{ 4451 ID: "bar", 4452 }, 4453 }, 4454 }, 4455 }, 4456 }, 4457 } 4458 4459 ctx := testContext2(t, &ContextOpts{ 4460 Module: m, 4461 State: state, 4462 Destroy: true, 4463 Providers: map[string]ResourceProviderFactory{ 4464 "aws": testProviderFuncFixed(p), 4465 }, 4466 Provisioners: map[string]ResourceProvisionerFactory{ 4467 "shell": testProvisionerFuncFixed(pr), 4468 }, 4469 }) 4470 4471 if _, err := ctx.Plan(); err != nil { 4472 t.Fatalf("err: %s", err) 4473 } 4474 4475 state, err := ctx.Apply() 4476 if err != nil { 4477 t.Fatalf("err: %s", err) 4478 } 4479 4480 checkStateString(t, state, `<no state>`) 4481 4482 // Verify apply was invoked 4483 if !pr.ApplyCalled { 4484 t.Fatalf("provisioner not invoked") 4485 } 4486 4487 expected := []string{"one", "two"} 4488 if !reflect.DeepEqual(calls, expected) { 4489 t.Fatalf("bad: %#v", calls) 4490 } 4491 } 4492 4493 // Verify that on destroy provisioner failure with "continue" that 4494 // we continue to the next provisioner. But if the next provisioner defines 4495 // to fail, then we fail after running it. 4496 func TestContext2Apply_provisionerDestroyFailContinueFail(t *testing.T) { 4497 m := testModule(t, "apply-provisioner-destroy-fail") 4498 p := testProvider("aws") 4499 pr := testProvisioner() 4500 p.ApplyFn = testApplyFn 4501 p.DiffFn = testDiffFn 4502 4503 var calls []string 4504 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4505 val, ok := c.Config["foo"] 4506 if !ok { 4507 t.Fatalf("bad value for foo: %v %#v", val, c) 4508 } 4509 4510 calls = append(calls, val.(string)) 4511 return fmt.Errorf("provisioner error") 4512 } 4513 4514 state := &State{ 4515 Modules: []*ModuleState{ 4516 &ModuleState{ 4517 Path: rootModulePath, 4518 Resources: map[string]*ResourceState{ 4519 "aws_instance.foo": &ResourceState{ 4520 Type: "aws_instance", 4521 Primary: &InstanceState{ 4522 ID: "bar", 4523 }, 4524 }, 4525 }, 4526 }, 4527 }, 4528 } 4529 4530 ctx := testContext2(t, &ContextOpts{ 4531 Module: m, 4532 State: state, 4533 Destroy: true, 4534 Providers: map[string]ResourceProviderFactory{ 4535 "aws": testProviderFuncFixed(p), 4536 }, 4537 Provisioners: map[string]ResourceProvisionerFactory{ 4538 "shell": testProvisionerFuncFixed(pr), 4539 }, 4540 }) 4541 4542 if _, err := ctx.Plan(); err != nil { 4543 t.Fatalf("err: %s", err) 4544 } 4545 4546 state, err := ctx.Apply() 4547 if err == nil { 4548 t.Fatal("should error") 4549 } 4550 4551 checkStateString(t, state, ` 4552 aws_instance.foo: 4553 ID = bar 4554 `) 4555 4556 // Verify apply was invoked 4557 if !pr.ApplyCalled { 4558 t.Fatalf("provisioner not invoked") 4559 } 4560 4561 expected := []string{"one", "two"} 4562 if !reflect.DeepEqual(calls, expected) { 4563 t.Fatalf("bad: %#v", calls) 4564 } 4565 } 4566 4567 // Verify destroy provisioners are not run for tainted instances. 4568 func TestContext2Apply_provisionerDestroyTainted(t *testing.T) { 4569 m := testModule(t, "apply-provisioner-destroy") 4570 p := testProvider("aws") 4571 pr := testProvisioner() 4572 p.ApplyFn = testApplyFn 4573 p.DiffFn = testDiffFn 4574 4575 destroyCalled := false 4576 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4577 expected := "create" 4578 if rs.ID == "bar" { 4579 destroyCalled = true 4580 return nil 4581 } 4582 4583 val, ok := c.Config["foo"] 4584 if !ok || val != expected { 4585 t.Fatalf("bad value for foo: %v %#v", val, c) 4586 } 4587 4588 return nil 4589 } 4590 4591 state := &State{ 4592 Modules: []*ModuleState{ 4593 &ModuleState{ 4594 Path: rootModulePath, 4595 Resources: map[string]*ResourceState{ 4596 "aws_instance.foo": &ResourceState{ 4597 Type: "aws_instance", 4598 Primary: &InstanceState{ 4599 ID: "bar", 4600 Tainted: true, 4601 }, 4602 }, 4603 }, 4604 }, 4605 }, 4606 } 4607 4608 ctx := testContext2(t, &ContextOpts{ 4609 Module: m, 4610 State: state, 4611 Providers: map[string]ResourceProviderFactory{ 4612 "aws": testProviderFuncFixed(p), 4613 }, 4614 Provisioners: map[string]ResourceProvisionerFactory{ 4615 "shell": testProvisionerFuncFixed(pr), 4616 }, 4617 }) 4618 4619 if _, err := ctx.Plan(); err != nil { 4620 t.Fatalf("err: %s", err) 4621 } 4622 4623 state, err := ctx.Apply() 4624 if err != nil { 4625 t.Fatalf("err: %s", err) 4626 } 4627 4628 checkStateString(t, state, ` 4629 aws_instance.foo: 4630 ID = foo 4631 foo = bar 4632 type = aws_instance 4633 `) 4634 4635 // Verify apply was invoked 4636 if !pr.ApplyCalled { 4637 t.Fatalf("provisioner not invoked") 4638 } 4639 4640 if destroyCalled { 4641 t.Fatal("destroy should not be called") 4642 } 4643 } 4644 4645 func TestContext2Apply_provisionerDestroyModule(t *testing.T) { 4646 m := testModule(t, "apply-provisioner-destroy-module") 4647 p := testProvider("aws") 4648 pr := testProvisioner() 4649 p.ApplyFn = testApplyFn 4650 p.DiffFn = testDiffFn 4651 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4652 val, ok := c.Config["foo"] 4653 if !ok || val != "value" { 4654 t.Fatalf("bad value for foo: %v %#v", val, c) 4655 } 4656 4657 return nil 4658 } 4659 4660 state := &State{ 4661 Modules: []*ModuleState{ 4662 &ModuleState{ 4663 Path: []string{"root", "child"}, 4664 Resources: map[string]*ResourceState{ 4665 "aws_instance.foo": &ResourceState{ 4666 Type: "aws_instance", 4667 Primary: &InstanceState{ 4668 ID: "bar", 4669 }, 4670 }, 4671 }, 4672 }, 4673 }, 4674 } 4675 4676 ctx := testContext2(t, &ContextOpts{ 4677 Module: m, 4678 State: state, 4679 Destroy: true, 4680 Providers: map[string]ResourceProviderFactory{ 4681 "aws": testProviderFuncFixed(p), 4682 }, 4683 Provisioners: map[string]ResourceProvisionerFactory{ 4684 "shell": testProvisionerFuncFixed(pr), 4685 }, 4686 }) 4687 4688 if _, err := ctx.Plan(); err != nil { 4689 t.Fatalf("err: %s", err) 4690 } 4691 4692 state, err := ctx.Apply() 4693 if err != nil { 4694 t.Fatalf("err: %s", err) 4695 } 4696 4697 checkStateString(t, state, ` 4698 module.child: 4699 <no state>`) 4700 4701 // Verify apply was invoked 4702 if !pr.ApplyCalled { 4703 t.Fatalf("provisioner not invoked") 4704 } 4705 } 4706 4707 func TestContext2Apply_provisionerDestroyRef(t *testing.T) { 4708 m := testModule(t, "apply-provisioner-destroy-ref") 4709 p := testProvider("aws") 4710 pr := testProvisioner() 4711 p.ApplyFn = testApplyFn 4712 p.DiffFn = testDiffFn 4713 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4714 val, ok := c.Config["foo"] 4715 if !ok || val != "hello" { 4716 return fmt.Errorf("bad value for foo: %v %#v", val, c) 4717 } 4718 4719 return nil 4720 } 4721 4722 state := &State{ 4723 Modules: []*ModuleState{ 4724 &ModuleState{ 4725 Path: rootModulePath, 4726 Resources: map[string]*ResourceState{ 4727 "aws_instance.bar": &ResourceState{ 4728 Type: "aws_instance", 4729 Primary: &InstanceState{ 4730 ID: "bar", 4731 Attributes: map[string]string{ 4732 "key": "hello", 4733 }, 4734 }, 4735 }, 4736 4737 "aws_instance.foo": &ResourceState{ 4738 Type: "aws_instance", 4739 Primary: &InstanceState{ 4740 ID: "bar", 4741 }, 4742 }, 4743 }, 4744 }, 4745 }, 4746 } 4747 4748 ctx := testContext2(t, &ContextOpts{ 4749 Module: m, 4750 State: state, 4751 Destroy: true, 4752 Providers: map[string]ResourceProviderFactory{ 4753 "aws": testProviderFuncFixed(p), 4754 }, 4755 Provisioners: map[string]ResourceProvisionerFactory{ 4756 "shell": testProvisionerFuncFixed(pr), 4757 }, 4758 }) 4759 4760 if _, err := ctx.Plan(); err != nil { 4761 t.Fatalf("err: %s", err) 4762 } 4763 4764 state, err := ctx.Apply() 4765 if err != nil { 4766 t.Fatalf("err: %s", err) 4767 } 4768 4769 checkStateString(t, state, `<no state>`) 4770 4771 // Verify apply was invoked 4772 if !pr.ApplyCalled { 4773 t.Fatalf("provisioner not invoked") 4774 } 4775 } 4776 4777 // Test that a destroy provisioner referencing an invalid key errors. 4778 func TestContext2Apply_provisionerDestroyRefInvalid(t *testing.T) { 4779 m := testModule(t, "apply-provisioner-destroy-ref") 4780 p := testProvider("aws") 4781 pr := testProvisioner() 4782 p.ApplyFn = testApplyFn 4783 p.DiffFn = testDiffFn 4784 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4785 return nil 4786 } 4787 4788 state := &State{ 4789 Modules: []*ModuleState{ 4790 &ModuleState{ 4791 Path: rootModulePath, 4792 Resources: map[string]*ResourceState{ 4793 "aws_instance.bar": &ResourceState{ 4794 Type: "aws_instance", 4795 Primary: &InstanceState{ 4796 ID: "bar", 4797 }, 4798 }, 4799 4800 "aws_instance.foo": &ResourceState{ 4801 Type: "aws_instance", 4802 Primary: &InstanceState{ 4803 ID: "bar", 4804 }, 4805 }, 4806 }, 4807 }, 4808 }, 4809 } 4810 4811 ctx := testContext2(t, &ContextOpts{ 4812 Module: m, 4813 State: state, 4814 Destroy: true, 4815 Providers: map[string]ResourceProviderFactory{ 4816 "aws": testProviderFuncFixed(p), 4817 }, 4818 Provisioners: map[string]ResourceProvisionerFactory{ 4819 "shell": testProvisionerFuncFixed(pr), 4820 }, 4821 }) 4822 4823 if _, err := ctx.Plan(); err != nil { 4824 t.Fatalf("err: %s", err) 4825 } 4826 4827 if _, err := ctx.Apply(); err == nil { 4828 t.Fatal("expected error") 4829 } 4830 } 4831 4832 func TestContext2Apply_provisionerResourceRef(t *testing.T) { 4833 m := testModule(t, "apply-provisioner-resource-ref") 4834 p := testProvider("aws") 4835 pr := testProvisioner() 4836 p.ApplyFn = testApplyFn 4837 p.DiffFn = testDiffFn 4838 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4839 val, ok := c.Config["foo"] 4840 if !ok || val != "2" { 4841 t.Fatalf("bad value for foo: %v %#v", val, c) 4842 } 4843 4844 return nil 4845 } 4846 4847 ctx := testContext2(t, &ContextOpts{ 4848 Module: m, 4849 Providers: map[string]ResourceProviderFactory{ 4850 "aws": testProviderFuncFixed(p), 4851 }, 4852 Provisioners: map[string]ResourceProvisionerFactory{ 4853 "shell": testProvisionerFuncFixed(pr), 4854 }, 4855 }) 4856 4857 if _, err := ctx.Plan(); err != nil { 4858 t.Fatalf("err: %s", err) 4859 } 4860 4861 state, err := ctx.Apply() 4862 if err != nil { 4863 t.Fatalf("err: %s", err) 4864 } 4865 4866 actual := strings.TrimSpace(state.String()) 4867 expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr) 4868 if actual != expected { 4869 t.Fatalf("bad: \n%s", actual) 4870 } 4871 4872 // Verify apply was invoked 4873 if !pr.ApplyCalled { 4874 t.Fatalf("provisioner not invoked") 4875 } 4876 } 4877 4878 func TestContext2Apply_provisionerSelfRef(t *testing.T) { 4879 m := testModule(t, "apply-provisioner-self-ref") 4880 p := testProvider("aws") 4881 pr := testProvisioner() 4882 p.ApplyFn = testApplyFn 4883 p.DiffFn = testDiffFn 4884 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4885 val, ok := c.Config["command"] 4886 if !ok || val != "bar" { 4887 t.Fatalf("bad value for command: %v %#v", val, c) 4888 } 4889 4890 return nil 4891 } 4892 4893 ctx := testContext2(t, &ContextOpts{ 4894 Module: m, 4895 Providers: map[string]ResourceProviderFactory{ 4896 "aws": testProviderFuncFixed(p), 4897 }, 4898 Provisioners: map[string]ResourceProvisionerFactory{ 4899 "shell": testProvisionerFuncFixed(pr), 4900 }, 4901 }) 4902 4903 if _, err := ctx.Plan(); err != nil { 4904 t.Fatalf("err: %s", err) 4905 } 4906 4907 state, err := ctx.Apply() 4908 if err != nil { 4909 t.Fatalf("err: %s", err) 4910 } 4911 4912 actual := strings.TrimSpace(state.String()) 4913 expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) 4914 if actual != expected { 4915 t.Fatalf("bad: \n%s", actual) 4916 } 4917 4918 // Verify apply was invoked 4919 if !pr.ApplyCalled { 4920 t.Fatalf("provisioner not invoked") 4921 } 4922 } 4923 4924 func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { 4925 var lock sync.Mutex 4926 commands := make([]string, 0, 5) 4927 4928 m := testModule(t, "apply-provisioner-multi-self-ref") 4929 p := testProvider("aws") 4930 pr := testProvisioner() 4931 p.ApplyFn = testApplyFn 4932 p.DiffFn = testDiffFn 4933 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4934 lock.Lock() 4935 defer lock.Unlock() 4936 4937 val, ok := c.Config["command"] 4938 if !ok { 4939 t.Fatalf("bad value for command: %v %#v", val, c) 4940 } 4941 4942 commands = append(commands, val.(string)) 4943 return nil 4944 } 4945 4946 ctx := testContext2(t, &ContextOpts{ 4947 Module: m, 4948 Providers: map[string]ResourceProviderFactory{ 4949 "aws": testProviderFuncFixed(p), 4950 }, 4951 Provisioners: map[string]ResourceProvisionerFactory{ 4952 "shell": testProvisionerFuncFixed(pr), 4953 }, 4954 }) 4955 4956 if _, err := ctx.Plan(); err != nil { 4957 t.Fatalf("err: %s", err) 4958 } 4959 4960 state, err := ctx.Apply() 4961 if err != nil { 4962 t.Fatalf("err: %s", err) 4963 } 4964 4965 actual := strings.TrimSpace(state.String()) 4966 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr) 4967 if actual != expected { 4968 t.Fatalf("bad: \n%s", actual) 4969 } 4970 4971 // Verify apply was invoked 4972 if !pr.ApplyCalled { 4973 t.Fatalf("provisioner not invoked") 4974 } 4975 4976 // Verify our result 4977 sort.Strings(commands) 4978 expectedCommands := []string{"number 0", "number 1", "number 2"} 4979 if !reflect.DeepEqual(commands, expectedCommands) { 4980 t.Fatalf("bad: %#v", commands) 4981 } 4982 } 4983 4984 func TestContext2Apply_provisionerMultiSelfRefSingle(t *testing.T) { 4985 var lock sync.Mutex 4986 order := make([]string, 0, 5) 4987 4988 m := testModule(t, "apply-provisioner-multi-self-ref-single") 4989 p := testProvider("aws") 4990 pr := testProvisioner() 4991 p.ApplyFn = testApplyFn 4992 p.DiffFn = testDiffFn 4993 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 4994 lock.Lock() 4995 defer lock.Unlock() 4996 4997 val, ok := c.Config["order"] 4998 if !ok { 4999 t.Fatalf("bad value for order: %v %#v", val, c) 5000 } 5001 5002 order = append(order, val.(string)) 5003 return nil 5004 } 5005 5006 ctx := testContext2(t, &ContextOpts{ 5007 Module: m, 5008 Providers: map[string]ResourceProviderFactory{ 5009 "aws": testProviderFuncFixed(p), 5010 }, 5011 Provisioners: map[string]ResourceProvisionerFactory{ 5012 "shell": testProvisionerFuncFixed(pr), 5013 }, 5014 }) 5015 5016 if _, err := ctx.Plan(); err != nil { 5017 t.Fatalf("err: %s", err) 5018 } 5019 5020 state, err := ctx.Apply() 5021 if err != nil { 5022 t.Fatalf("err: %s", err) 5023 } 5024 5025 actual := strings.TrimSpace(state.String()) 5026 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefSingleStr) 5027 if actual != expected { 5028 t.Fatalf("bad: \n%s", actual) 5029 } 5030 5031 // Verify apply was invoked 5032 if !pr.ApplyCalled { 5033 t.Fatalf("provisioner not invoked") 5034 } 5035 5036 // Verify our result 5037 sort.Strings(order) 5038 expectedOrder := []string{"0", "1", "2"} 5039 if !reflect.DeepEqual(order, expectedOrder) { 5040 t.Fatalf("bad: %#v", order) 5041 } 5042 } 5043 5044 func TestContext2Apply_provisionerMultiSelfRefCount(t *testing.T) { 5045 var lock sync.Mutex 5046 commands := make([]string, 0, 5) 5047 5048 m := testModule(t, "apply-provisioner-multi-self-ref-count") 5049 p := testProvider("aws") 5050 pr := testProvisioner() 5051 p.ApplyFn = testApplyFn 5052 p.DiffFn = testDiffFn 5053 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5054 lock.Lock() 5055 defer lock.Unlock() 5056 5057 val, ok := c.Config["command"] 5058 if !ok { 5059 t.Fatalf("bad value for command: %v %#v", val, c) 5060 } 5061 5062 commands = append(commands, val.(string)) 5063 return nil 5064 } 5065 5066 ctx := testContext2(t, &ContextOpts{ 5067 Module: m, 5068 Providers: map[string]ResourceProviderFactory{ 5069 "aws": testProviderFuncFixed(p), 5070 }, 5071 Provisioners: map[string]ResourceProvisionerFactory{ 5072 "shell": testProvisionerFuncFixed(pr), 5073 }, 5074 }) 5075 5076 if _, err := ctx.Plan(); err != nil { 5077 t.Fatalf("err: %s", err) 5078 } 5079 5080 if _, err := ctx.Apply(); err != nil { 5081 t.Fatalf("err: %s", err) 5082 } 5083 5084 // Verify apply was invoked 5085 if !pr.ApplyCalled { 5086 t.Fatalf("provisioner not invoked") 5087 } 5088 5089 // Verify our result 5090 sort.Strings(commands) 5091 expectedCommands := []string{"3", "3", "3"} 5092 if !reflect.DeepEqual(commands, expectedCommands) { 5093 t.Fatalf("bad: %#v", commands) 5094 } 5095 } 5096 5097 func TestContext2Apply_provisionerExplicitSelfRef(t *testing.T) { 5098 m := testModule(t, "apply-provisioner-explicit-self-ref") 5099 p := testProvider("aws") 5100 pr := testProvisioner() 5101 p.ApplyFn = testApplyFn 5102 p.DiffFn = testDiffFn 5103 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5104 val, ok := c.Config["command"] 5105 if !ok || val != "bar" { 5106 t.Fatalf("bad value for command: %v %#v", val, c) 5107 } 5108 5109 return nil 5110 } 5111 5112 var state *State 5113 { 5114 ctx := testContext2(t, &ContextOpts{ 5115 Module: m, 5116 Providers: map[string]ResourceProviderFactory{ 5117 "aws": testProviderFuncFixed(p), 5118 }, 5119 Provisioners: map[string]ResourceProvisionerFactory{ 5120 "shell": testProvisionerFuncFixed(pr), 5121 }, 5122 }) 5123 5124 _, err := ctx.Plan() 5125 if err != nil { 5126 t.Fatalf("err: %s", err) 5127 } 5128 5129 state, err = ctx.Apply() 5130 if err != nil { 5131 t.Fatalf("err: %s", err) 5132 } 5133 5134 // Verify apply was invoked 5135 if !pr.ApplyCalled { 5136 t.Fatalf("provisioner not invoked") 5137 } 5138 } 5139 5140 { 5141 ctx := testContext2(t, &ContextOpts{ 5142 Module: m, 5143 Destroy: true, 5144 State: state, 5145 Providers: map[string]ResourceProviderFactory{ 5146 "aws": testProviderFuncFixed(p), 5147 }, 5148 Provisioners: map[string]ResourceProvisionerFactory{ 5149 "shell": testProvisionerFuncFixed(pr), 5150 }, 5151 }) 5152 5153 _, err := ctx.Plan() 5154 if err != nil { 5155 t.Fatalf("err: %s", err) 5156 } 5157 5158 state, err = ctx.Apply() 5159 if err != nil { 5160 t.Fatalf("err: %s", err) 5161 } 5162 5163 checkStateString(t, state, `<no state>`) 5164 } 5165 } 5166 5167 // Provisioner should NOT run on a diff, only create 5168 func TestContext2Apply_Provisioner_Diff(t *testing.T) { 5169 m := testModule(t, "apply-provisioner-diff") 5170 p := testProvider("aws") 5171 pr := testProvisioner() 5172 p.ApplyFn = testApplyFn 5173 p.DiffFn = testDiffFn 5174 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5175 return nil 5176 } 5177 ctx := testContext2(t, &ContextOpts{ 5178 Module: m, 5179 Providers: map[string]ResourceProviderFactory{ 5180 "aws": testProviderFuncFixed(p), 5181 }, 5182 Provisioners: map[string]ResourceProvisionerFactory{ 5183 "shell": testProvisionerFuncFixed(pr), 5184 }, 5185 }) 5186 5187 if _, err := ctx.Plan(); err != nil { 5188 t.Fatalf("err: %s", err) 5189 } 5190 5191 state, err := ctx.Apply() 5192 if err != nil { 5193 t.Fatalf("err: %s", err) 5194 } 5195 5196 actual := strings.TrimSpace(state.String()) 5197 expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr) 5198 if actual != expected { 5199 t.Fatalf("bad: \n%s", actual) 5200 } 5201 5202 // Verify apply was invoked 5203 if !pr.ApplyCalled { 5204 t.Fatalf("provisioner not invoked") 5205 } 5206 pr.ApplyCalled = false 5207 5208 // Change the state to force a diff 5209 mod := state.RootModule() 5210 mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz" 5211 5212 // Re-create context with state 5213 ctx = testContext2(t, &ContextOpts{ 5214 Module: m, 5215 Providers: map[string]ResourceProviderFactory{ 5216 "aws": testProviderFuncFixed(p), 5217 }, 5218 Provisioners: map[string]ResourceProvisionerFactory{ 5219 "shell": testProvisionerFuncFixed(pr), 5220 }, 5221 State: state, 5222 }) 5223 5224 if _, err := ctx.Plan(); err != nil { 5225 t.Fatalf("err: %s", err) 5226 } 5227 5228 state2, err := ctx.Apply() 5229 if err != nil { 5230 t.Fatalf("err: %s", err) 5231 } 5232 5233 actual = strings.TrimSpace(state2.String()) 5234 if actual != expected { 5235 t.Fatalf("bad: \n%s", actual) 5236 } 5237 5238 // Verify apply was NOT invoked 5239 if pr.ApplyCalled { 5240 t.Fatalf("provisioner invoked") 5241 } 5242 } 5243 5244 func TestContext2Apply_outputDiffVars(t *testing.T) { 5245 m := testModule(t, "apply-good") 5246 p := testProvider("aws") 5247 s := &State{ 5248 Modules: []*ModuleState{ 5249 &ModuleState{ 5250 Path: rootModulePath, 5251 Resources: map[string]*ResourceState{ 5252 "aws_instance.baz": &ResourceState{ 5253 Type: "aws_instance", 5254 Primary: &InstanceState{ 5255 ID: "bar", 5256 }, 5257 }, 5258 }, 5259 }, 5260 }, 5261 } 5262 ctx := testContext2(t, &ContextOpts{ 5263 Module: m, 5264 Providers: map[string]ResourceProviderFactory{ 5265 "aws": testProviderFuncFixed(p), 5266 }, 5267 State: s, 5268 }) 5269 5270 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5271 for k, ad := range d.Attributes { 5272 if ad.NewComputed { 5273 return nil, fmt.Errorf("%s: computed", k) 5274 } 5275 } 5276 5277 result := s.MergeDiff(d) 5278 result.ID = "foo" 5279 return result, nil 5280 } 5281 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 5282 return &InstanceDiff{ 5283 Attributes: map[string]*ResourceAttrDiff{ 5284 "foo": &ResourceAttrDiff{ 5285 NewComputed: true, 5286 Type: DiffAttrOutput, 5287 }, 5288 "bar": &ResourceAttrDiff{ 5289 New: "baz", 5290 }, 5291 }, 5292 }, nil 5293 } 5294 5295 if _, err := ctx.Plan(); err != nil { 5296 t.Fatalf("err: %s", err) 5297 } 5298 if _, err := ctx.Apply(); err != nil { 5299 t.Fatalf("err: %s", err) 5300 } 5301 } 5302 5303 func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { 5304 m := testModule(t, "apply-provisioner-conninfo") 5305 p := testProvider("aws") 5306 pr := testProvisioner() 5307 5308 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 5309 if s.Ephemeral.ConnInfo == nil { 5310 t.Fatalf("ConnInfo not initialized") 5311 } 5312 5313 result, _ := testApplyFn(info, s, d) 5314 result.Ephemeral.ConnInfo = map[string]string{ 5315 "type": "ssh", 5316 "host": "127.0.0.1", 5317 "port": "22", 5318 } 5319 return result, nil 5320 } 5321 p.DiffFn = testDiffFn 5322 5323 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 5324 conn := rs.Ephemeral.ConnInfo 5325 if conn["type"] != "telnet" { 5326 t.Fatalf("Bad: %#v", conn) 5327 } 5328 if conn["host"] != "127.0.0.1" { 5329 t.Fatalf("Bad: %#v", conn) 5330 } 5331 if conn["port"] != "2222" { 5332 t.Fatalf("Bad: %#v", conn) 5333 } 5334 if conn["user"] != "superuser" { 5335 t.Fatalf("Bad: %#v", conn) 5336 } 5337 if conn["pass"] != "test" { 5338 t.Fatalf("Bad: %#v", conn) 5339 } 5340 5341 return nil 5342 } 5343 5344 ctx := testContext2(t, &ContextOpts{ 5345 Module: m, 5346 Providers: map[string]ResourceProviderFactory{ 5347 "aws": testProviderFuncFixed(p), 5348 }, 5349 Provisioners: map[string]ResourceProvisionerFactory{ 5350 "shell": testProvisionerFuncFixed(pr), 5351 }, 5352 Variables: map[string]interface{}{ 5353 "value": "1", 5354 "pass": "test", 5355 }, 5356 }) 5357 5358 if _, err := ctx.Plan(); err != nil { 5359 t.Fatalf("err: %s", err) 5360 } 5361 5362 state, err := ctx.Apply() 5363 if err != nil { 5364 t.Fatalf("err: %s", err) 5365 } 5366 5367 actual := strings.TrimSpace(state.String()) 5368 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 5369 if actual != expected { 5370 t.Fatalf("bad: \n%s", actual) 5371 } 5372 5373 // Verify apply was invoked 5374 if !pr.ApplyCalled { 5375 t.Fatalf("provisioner not invoked") 5376 } 5377 } 5378 5379 func TestContext2Apply_destroyX(t *testing.T) { 5380 m := testModule(t, "apply-destroy") 5381 h := new(HookRecordApplyOrder) 5382 p := testProvider("aws") 5383 p.ApplyFn = testApplyFn 5384 p.DiffFn = testDiffFn 5385 ctx := testContext2(t, &ContextOpts{ 5386 Module: m, 5387 Hooks: []Hook{h}, 5388 Providers: map[string]ResourceProviderFactory{ 5389 "aws": testProviderFuncFixed(p), 5390 }, 5391 }) 5392 5393 // First plan and apply a create operation 5394 if _, err := ctx.Plan(); err != nil { 5395 t.Fatalf("err: %s", err) 5396 } 5397 5398 state, err := ctx.Apply() 5399 if err != nil { 5400 t.Fatalf("err: %s", err) 5401 } 5402 5403 // Next, plan and apply a destroy operation 5404 h.Active = true 5405 ctx = testContext2(t, &ContextOpts{ 5406 Destroy: true, 5407 State: state, 5408 Module: m, 5409 Hooks: []Hook{h}, 5410 Providers: map[string]ResourceProviderFactory{ 5411 "aws": testProviderFuncFixed(p), 5412 }, 5413 }) 5414 5415 if _, err := ctx.Plan(); err != nil { 5416 t.Fatalf("err: %s", err) 5417 } 5418 5419 state, err = ctx.Apply() 5420 if err != nil { 5421 t.Fatalf("err: %s", err) 5422 } 5423 5424 // Test that things were destroyed 5425 actual := strings.TrimSpace(state.String()) 5426 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5427 if actual != expected { 5428 t.Fatalf("bad: \n%s", actual) 5429 } 5430 5431 // Test that things were destroyed _in the right order_ 5432 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 5433 actual2 := h.IDs 5434 if !reflect.DeepEqual(actual2, expected2) { 5435 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 5436 } 5437 } 5438 5439 func TestContext2Apply_destroyOrder(t *testing.T) { 5440 m := testModule(t, "apply-destroy") 5441 h := new(HookRecordApplyOrder) 5442 p := testProvider("aws") 5443 p.ApplyFn = testApplyFn 5444 p.DiffFn = testDiffFn 5445 ctx := testContext2(t, &ContextOpts{ 5446 Module: m, 5447 Hooks: []Hook{h}, 5448 Providers: map[string]ResourceProviderFactory{ 5449 "aws": testProviderFuncFixed(p), 5450 }, 5451 }) 5452 5453 // First plan and apply a create operation 5454 if _, err := ctx.Plan(); err != nil { 5455 t.Fatalf("err: %s", err) 5456 } 5457 5458 state, err := ctx.Apply() 5459 if err != nil { 5460 t.Fatalf("err: %s", err) 5461 } 5462 5463 t.Logf("State 1: %s", state) 5464 5465 // Next, plan and apply config-less to force a destroy with "apply" 5466 h.Active = true 5467 ctx = testContext2(t, &ContextOpts{ 5468 State: state, 5469 Module: module.NewEmptyTree(), 5470 Hooks: []Hook{h}, 5471 Providers: map[string]ResourceProviderFactory{ 5472 "aws": testProviderFuncFixed(p), 5473 }, 5474 }) 5475 5476 if _, err := ctx.Plan(); err != nil { 5477 t.Fatalf("err: %s", err) 5478 } 5479 5480 state, err = ctx.Apply() 5481 if err != nil { 5482 t.Fatalf("err: %s", err) 5483 } 5484 5485 // Test that things were destroyed 5486 actual := strings.TrimSpace(state.String()) 5487 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 5488 if actual != expected { 5489 t.Fatalf("bad: \n%s", actual) 5490 } 5491 5492 // Test that things were destroyed _in the right order_ 5493 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 5494 actual2 := h.IDs 5495 if !reflect.DeepEqual(actual2, expected2) { 5496 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 5497 } 5498 } 5499 5500 // https://github.com/hashicorp/terraform/issues/2767 5501 func TestContext2Apply_destroyModulePrefix(t *testing.T) { 5502 m := testModule(t, "apply-destroy-module-resource-prefix") 5503 h := new(MockHook) 5504 p := testProvider("aws") 5505 p.ApplyFn = testApplyFn 5506 p.DiffFn = testDiffFn 5507 ctx := testContext2(t, &ContextOpts{ 5508 Module: m, 5509 Hooks: []Hook{h}, 5510 Providers: map[string]ResourceProviderFactory{ 5511 "aws": testProviderFuncFixed(p), 5512 }, 5513 }) 5514 5515 // First plan and apply a create operation 5516 if _, err := ctx.Plan(); err != nil { 5517 t.Fatalf("err: %s", err) 5518 } 5519 5520 state, err := ctx.Apply() 5521 if err != nil { 5522 t.Fatalf("err: %s", err) 5523 } 5524 5525 // Verify that we got the apply info correct 5526 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 5527 t.Fatalf("bad: %s", v) 5528 } 5529 5530 // Next, plan and apply a destroy operation and reset the hook 5531 h = new(MockHook) 5532 ctx = testContext2(t, &ContextOpts{ 5533 Destroy: true, 5534 State: state, 5535 Module: m, 5536 Hooks: []Hook{h}, 5537 Providers: map[string]ResourceProviderFactory{ 5538 "aws": testProviderFuncFixed(p), 5539 }, 5540 }) 5541 5542 if _, err := ctx.Plan(); err != nil { 5543 t.Fatalf("err: %s", err) 5544 } 5545 5546 state, err = ctx.Apply() 5547 if err != nil { 5548 t.Fatalf("err: %s", err) 5549 } 5550 5551 // Test that things were destroyed 5552 if v := h.PreApplyInfo.HumanId(); v != "module.child.aws_instance.foo" { 5553 t.Fatalf("bad: %s", v) 5554 } 5555 } 5556 5557 func TestContext2Apply_destroyNestedModule(t *testing.T) { 5558 m := testModule(t, "apply-destroy-nested-module") 5559 p := testProvider("aws") 5560 p.ApplyFn = testApplyFn 5561 p.DiffFn = testDiffFn 5562 5563 s := &State{ 5564 Modules: []*ModuleState{ 5565 &ModuleState{ 5566 Path: []string{"root", "child", "subchild"}, 5567 Resources: map[string]*ResourceState{ 5568 "aws_instance.bar": &ResourceState{ 5569 Type: "aws_instance", 5570 Primary: &InstanceState{ 5571 ID: "bar", 5572 }, 5573 }, 5574 }, 5575 }, 5576 }, 5577 } 5578 5579 ctx := testContext2(t, &ContextOpts{ 5580 Module: m, 5581 Providers: map[string]ResourceProviderFactory{ 5582 "aws": testProviderFuncFixed(p), 5583 }, 5584 State: s, 5585 }) 5586 5587 // First plan and apply a create operation 5588 if _, err := ctx.Plan(); err != nil { 5589 t.Fatalf("err: %s", err) 5590 } 5591 5592 state, err := ctx.Apply() 5593 if err != nil { 5594 t.Fatalf("err: %s", err) 5595 } 5596 5597 // Test that things were destroyed 5598 actual := strings.TrimSpace(state.String()) 5599 expected := strings.TrimSpace(testTerraformApplyDestroyNestedModuleStr) 5600 if actual != expected { 5601 t.Fatalf("bad: \n%s", actual) 5602 } 5603 } 5604 5605 func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) { 5606 m := testModule(t, "apply-destroy-deeply-nested-module") 5607 p := testProvider("aws") 5608 p.ApplyFn = testApplyFn 5609 p.DiffFn = testDiffFn 5610 5611 s := &State{ 5612 Modules: []*ModuleState{ 5613 &ModuleState{ 5614 Path: []string{"root", "child", "subchild", "subsubchild"}, 5615 Resources: map[string]*ResourceState{ 5616 "aws_instance.bar": &ResourceState{ 5617 Type: "aws_instance", 5618 Primary: &InstanceState{ 5619 ID: "bar", 5620 }, 5621 }, 5622 }, 5623 }, 5624 }, 5625 } 5626 5627 ctx := testContext2(t, &ContextOpts{ 5628 Module: m, 5629 Providers: map[string]ResourceProviderFactory{ 5630 "aws": testProviderFuncFixed(p), 5631 }, 5632 State: s, 5633 }) 5634 5635 // First plan and apply a create operation 5636 if _, err := ctx.Plan(); err != nil { 5637 t.Fatalf("err: %s", err) 5638 } 5639 5640 state, err := ctx.Apply() 5641 if err != nil { 5642 t.Fatalf("err: %s", err) 5643 } 5644 5645 // Test that things were destroyed 5646 actual := strings.TrimSpace(state.String()) 5647 expected := strings.TrimSpace(` 5648 module.child.subchild.subsubchild: 5649 <no state> 5650 `) 5651 if actual != expected { 5652 t.Fatalf("bad: \n%s", actual) 5653 } 5654 } 5655 5656 // https://github.com/hashicorp/terraform/issues/5440 5657 func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) { 5658 m := testModule(t, "apply-destroy-module-with-attrs") 5659 p := testProvider("aws") 5660 p.ApplyFn = testApplyFn 5661 p.DiffFn = testDiffFn 5662 5663 var state *State 5664 var err error 5665 { 5666 ctx := testContext2(t, &ContextOpts{ 5667 Module: m, 5668 Providers: map[string]ResourceProviderFactory{ 5669 "aws": testProviderFuncFixed(p), 5670 }, 5671 }) 5672 5673 // First plan and apply a create operation 5674 if p, err := ctx.Plan(); err != nil { 5675 t.Fatalf("plan err: %s", err) 5676 } else { 5677 t.Logf("Step 1 plan: %s", p) 5678 } 5679 5680 state, err = ctx.Apply() 5681 if err != nil { 5682 t.Fatalf("apply err: %s", err) 5683 } 5684 5685 t.Logf("Step 1 state: %s", state) 5686 } 5687 5688 h := new(HookRecordApplyOrder) 5689 h.Active = true 5690 5691 { 5692 ctx := testContext2(t, &ContextOpts{ 5693 Destroy: true, 5694 Module: m, 5695 State: state, 5696 Hooks: []Hook{h}, 5697 Providers: map[string]ResourceProviderFactory{ 5698 "aws": testProviderFuncFixed(p), 5699 }, 5700 Variables: map[string]interface{}{ 5701 "key_name": "foobarkey", 5702 }, 5703 }) 5704 5705 // First plan and apply a create operation 5706 plan, err := ctx.Plan() 5707 if err != nil { 5708 t.Fatalf("destroy plan err: %s", err) 5709 } 5710 5711 t.Logf("Step 2 plan: %s", plan) 5712 5713 var buf bytes.Buffer 5714 if err := WritePlan(plan, &buf); err != nil { 5715 t.Fatalf("plan write err: %s", err) 5716 } 5717 5718 planFromFile, err := ReadPlan(&buf) 5719 if err != nil { 5720 t.Fatalf("plan read err: %s", err) 5721 } 5722 5723 ctx, err = planFromFile.Context(&ContextOpts{ 5724 Providers: map[string]ResourceProviderFactory{ 5725 "aws": testProviderFuncFixed(p), 5726 }, 5727 }) 5728 if err != nil { 5729 t.Fatalf("err: %s", err) 5730 } 5731 5732 state, err = ctx.Apply() 5733 if err != nil { 5734 t.Fatalf("destroy apply err: %s", err) 5735 } 5736 5737 t.Logf("Step 2 state: %s", state) 5738 } 5739 5740 //Test that things were destroyed 5741 actual := strings.TrimSpace(state.String()) 5742 expected := strings.TrimSpace(` 5743 <no state> 5744 module.child: 5745 <no state> 5746 `) 5747 if actual != expected { 5748 t.Fatalf("expected:\n\n%s\n\nactual:\n\n%s", expected, actual) 5749 } 5750 } 5751 5752 func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) { 5753 m := testModule(t, "apply-destroy-mod-var-and-count") 5754 p := testProvider("aws") 5755 p.ApplyFn = testApplyFn 5756 p.DiffFn = testDiffFn 5757 5758 var state *State 5759 var err error 5760 { 5761 ctx := testContext2(t, &ContextOpts{ 5762 Module: m, 5763 Providers: map[string]ResourceProviderFactory{ 5764 "aws": testProviderFuncFixed(p), 5765 }, 5766 }) 5767 5768 // First plan and apply a create operation 5769 if _, err := ctx.Plan(); err != nil { 5770 t.Fatalf("plan err: %s", err) 5771 } 5772 5773 state, err = ctx.Apply() 5774 if err != nil { 5775 t.Fatalf("apply err: %s", err) 5776 } 5777 } 5778 5779 h := new(HookRecordApplyOrder) 5780 h.Active = true 5781 5782 { 5783 ctx := testContext2(t, &ContextOpts{ 5784 Destroy: true, 5785 Module: m, 5786 State: state, 5787 Hooks: []Hook{h}, 5788 Providers: map[string]ResourceProviderFactory{ 5789 "aws": testProviderFuncFixed(p), 5790 }, 5791 }) 5792 5793 // First plan and apply a create operation 5794 plan, err := ctx.Plan() 5795 if err != nil { 5796 t.Fatalf("destroy plan err: %s", err) 5797 } 5798 5799 var buf bytes.Buffer 5800 if err := WritePlan(plan, &buf); err != nil { 5801 t.Fatalf("plan write err: %s", err) 5802 } 5803 5804 planFromFile, err := ReadPlan(&buf) 5805 if err != nil { 5806 t.Fatalf("plan read err: %s", err) 5807 } 5808 5809 ctx, err = planFromFile.Context(&ContextOpts{ 5810 Providers: map[string]ResourceProviderFactory{ 5811 "aws": testProviderFuncFixed(p), 5812 }, 5813 }) 5814 if err != nil { 5815 t.Fatalf("err: %s", err) 5816 } 5817 5818 state, err = ctx.Apply() 5819 if err != nil { 5820 t.Fatalf("destroy apply err: %s", err) 5821 } 5822 } 5823 5824 //Test that things were destroyed 5825 actual := strings.TrimSpace(state.String()) 5826 expected := strings.TrimSpace(` 5827 <no state> 5828 module.child: 5829 <no state> 5830 `) 5831 if actual != expected { 5832 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5833 } 5834 } 5835 5836 func TestContext2Apply_destroyTargetWithModuleVariableAndCount(t *testing.T) { 5837 m := testModule(t, "apply-destroy-mod-var-and-count") 5838 p := testProvider("aws") 5839 p.ApplyFn = testApplyFn 5840 p.DiffFn = testDiffFn 5841 5842 var state *State 5843 var err error 5844 { 5845 ctx := testContext2(t, &ContextOpts{ 5846 Module: m, 5847 Providers: map[string]ResourceProviderFactory{ 5848 "aws": testProviderFuncFixed(p), 5849 }, 5850 }) 5851 5852 // First plan and apply a create operation 5853 if _, err := ctx.Plan(); err != nil { 5854 t.Fatalf("plan err: %s", err) 5855 } 5856 5857 state, err = ctx.Apply() 5858 if err != nil { 5859 t.Fatalf("apply err: %s", err) 5860 } 5861 } 5862 5863 { 5864 ctx := testContext2(t, &ContextOpts{ 5865 Destroy: true, 5866 Module: m, 5867 State: state, 5868 Providers: map[string]ResourceProviderFactory{ 5869 "aws": testProviderFuncFixed(p), 5870 }, 5871 Targets: []string{"module.child"}, 5872 }) 5873 5874 _, err := ctx.Plan() 5875 if err != nil { 5876 t.Fatalf("plan err: %s", err) 5877 } 5878 5879 // Destroy, targeting the module explicitly 5880 state, err = ctx.Apply() 5881 if err != nil { 5882 t.Fatalf("destroy apply err: %s", err) 5883 } 5884 } 5885 5886 //Test that things were destroyed 5887 actual := strings.TrimSpace(state.String()) 5888 expected := strings.TrimSpace(` 5889 <no state> 5890 module.child: 5891 <no state> 5892 `) 5893 if actual != expected { 5894 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5895 } 5896 } 5897 5898 func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) { 5899 m := testModule(t, "apply-destroy-mod-var-and-count-nested") 5900 p := testProvider("aws") 5901 p.ApplyFn = testApplyFn 5902 p.DiffFn = testDiffFn 5903 5904 var state *State 5905 var err error 5906 { 5907 ctx := testContext2(t, &ContextOpts{ 5908 Module: m, 5909 Providers: map[string]ResourceProviderFactory{ 5910 "aws": testProviderFuncFixed(p), 5911 }, 5912 }) 5913 5914 // First plan and apply a create operation 5915 if _, err := ctx.Plan(); err != nil { 5916 t.Fatalf("plan err: %s", err) 5917 } 5918 5919 state, err = ctx.Apply() 5920 if err != nil { 5921 t.Fatalf("apply err: %s", err) 5922 } 5923 } 5924 5925 h := new(HookRecordApplyOrder) 5926 h.Active = true 5927 5928 { 5929 ctx := testContext2(t, &ContextOpts{ 5930 Destroy: true, 5931 Module: m, 5932 State: state, 5933 Hooks: []Hook{h}, 5934 Providers: map[string]ResourceProviderFactory{ 5935 "aws": testProviderFuncFixed(p), 5936 }, 5937 }) 5938 5939 // First plan and apply a create operation 5940 plan, err := ctx.Plan() 5941 if err != nil { 5942 t.Fatalf("destroy plan err: %s", err) 5943 } 5944 5945 var buf bytes.Buffer 5946 if err := WritePlan(plan, &buf); err != nil { 5947 t.Fatalf("plan write err: %s", err) 5948 } 5949 5950 planFromFile, err := ReadPlan(&buf) 5951 if err != nil { 5952 t.Fatalf("plan read err: %s", err) 5953 } 5954 5955 ctx, err = planFromFile.Context(&ContextOpts{ 5956 Providers: map[string]ResourceProviderFactory{ 5957 "aws": testProviderFuncFixed(p), 5958 }, 5959 }) 5960 if err != nil { 5961 t.Fatalf("err: %s", err) 5962 } 5963 5964 state, err = ctx.Apply() 5965 if err != nil { 5966 t.Fatalf("destroy apply err: %s", err) 5967 } 5968 } 5969 5970 //Test that things were destroyed 5971 actual := strings.TrimSpace(state.String()) 5972 expected := strings.TrimSpace(` 5973 <no state> 5974 module.child: 5975 <no state> 5976 module.child.child2: 5977 <no state> 5978 `) 5979 if actual != expected { 5980 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5981 } 5982 } 5983 5984 func TestContext2Apply_destroyOutputs(t *testing.T) { 5985 m := testModule(t, "apply-destroy-outputs") 5986 h := new(HookRecordApplyOrder) 5987 p := testProvider("aws") 5988 p.ApplyFn = testApplyFn 5989 p.DiffFn = testDiffFn 5990 ctx := testContext2(t, &ContextOpts{ 5991 Module: m, 5992 Hooks: []Hook{h}, 5993 Providers: map[string]ResourceProviderFactory{ 5994 "aws": testProviderFuncFixed(p), 5995 }, 5996 }) 5997 5998 // First plan and apply a create operation 5999 if _, err := ctx.Plan(); err != nil { 6000 t.Fatalf("err: %s", err) 6001 } 6002 6003 state, err := ctx.Apply() 6004 6005 if err != nil { 6006 t.Fatalf("err: %s", err) 6007 } 6008 6009 // Next, plan and apply a destroy operation 6010 h.Active = true 6011 ctx = testContext2(t, &ContextOpts{ 6012 Destroy: true, 6013 State: state, 6014 Module: m, 6015 Hooks: []Hook{h}, 6016 Providers: map[string]ResourceProviderFactory{ 6017 "aws": testProviderFuncFixed(p), 6018 }, 6019 }) 6020 6021 if _, err := ctx.Plan(); err != nil { 6022 t.Fatalf("err: %s", err) 6023 } 6024 6025 state, err = ctx.Apply() 6026 if err != nil { 6027 t.Fatalf("err: %s", err) 6028 } 6029 6030 mod := state.RootModule() 6031 if len(mod.Resources) > 0 { 6032 t.Fatalf("bad: %#v", mod) 6033 } 6034 } 6035 6036 func TestContext2Apply_destroyOrphan(t *testing.T) { 6037 m := testModule(t, "apply-error") 6038 p := testProvider("aws") 6039 s := &State{ 6040 Modules: []*ModuleState{ 6041 &ModuleState{ 6042 Path: rootModulePath, 6043 Resources: map[string]*ResourceState{ 6044 "aws_instance.baz": &ResourceState{ 6045 Type: "aws_instance", 6046 Primary: &InstanceState{ 6047 ID: "bar", 6048 }, 6049 }, 6050 }, 6051 }, 6052 }, 6053 } 6054 ctx := testContext2(t, &ContextOpts{ 6055 Module: m, 6056 Providers: map[string]ResourceProviderFactory{ 6057 "aws": testProviderFuncFixed(p), 6058 }, 6059 State: s, 6060 }) 6061 6062 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6063 if d.Destroy { 6064 return nil, nil 6065 } 6066 6067 result := s.MergeDiff(d) 6068 result.ID = "foo" 6069 return result, nil 6070 } 6071 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6072 return &InstanceDiff{ 6073 Attributes: map[string]*ResourceAttrDiff{ 6074 "num": &ResourceAttrDiff{ 6075 New: "bar", 6076 }, 6077 }, 6078 }, nil 6079 } 6080 6081 if _, err := ctx.Plan(); err != nil { 6082 t.Fatalf("err: %s", err) 6083 } 6084 6085 state, err := ctx.Apply() 6086 if err != nil { 6087 t.Fatalf("err: %s", err) 6088 } 6089 6090 mod := state.RootModule() 6091 if _, ok := mod.Resources["aws_instance.baz"]; ok { 6092 t.Fatalf("bad: %#v", mod.Resources) 6093 } 6094 } 6095 6096 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 6097 m := testModule(t, "apply-destroy-provisioner") 6098 p := testProvider("aws") 6099 pr := testProvisioner() 6100 p.ApplyFn = testApplyFn 6101 p.DiffFn = testDiffFn 6102 6103 called := false 6104 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 6105 called = true 6106 return nil 6107 } 6108 6109 s := &State{ 6110 Modules: []*ModuleState{ 6111 &ModuleState{ 6112 Path: rootModulePath, 6113 Resources: map[string]*ResourceState{ 6114 "aws_instance.foo": &ResourceState{ 6115 Type: "aws_instance", 6116 Primary: &InstanceState{ 6117 ID: "bar", 6118 Attributes: map[string]string{ 6119 "id": "bar", 6120 }, 6121 Tainted: true, 6122 }, 6123 }, 6124 }, 6125 }, 6126 }, 6127 } 6128 6129 ctx := testContext2(t, &ContextOpts{ 6130 Module: m, 6131 Providers: map[string]ResourceProviderFactory{ 6132 "aws": testProviderFuncFixed(p), 6133 }, 6134 Provisioners: map[string]ResourceProvisionerFactory{ 6135 "shell": testProvisionerFuncFixed(pr), 6136 }, 6137 State: s, 6138 Destroy: true, 6139 }) 6140 6141 if _, err := ctx.Plan(); err != nil { 6142 t.Fatalf("err: %s", err) 6143 } 6144 6145 state, err := ctx.Apply() 6146 if err != nil { 6147 t.Fatalf("err: %s", err) 6148 } 6149 6150 if called { 6151 t.Fatal("provisioner should not be called") 6152 } 6153 6154 actual := strings.TrimSpace(state.String()) 6155 expected := strings.TrimSpace("<no state>") 6156 if actual != expected { 6157 t.Fatalf("bad: \n%s", actual) 6158 } 6159 } 6160 6161 func TestContext2Apply_error(t *testing.T) { 6162 errored := false 6163 6164 m := testModule(t, "apply-error") 6165 p := testProvider("aws") 6166 ctx := testContext2(t, &ContextOpts{ 6167 Module: m, 6168 Providers: map[string]ResourceProviderFactory{ 6169 "aws": testProviderFuncFixed(p), 6170 }, 6171 }) 6172 6173 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 6174 if errored { 6175 state := &InstanceState{ 6176 ID: "bar", 6177 } 6178 return state, fmt.Errorf("error") 6179 } 6180 errored = true 6181 6182 return &InstanceState{ 6183 ID: "foo", 6184 Attributes: map[string]string{ 6185 "num": "2", 6186 }, 6187 }, nil 6188 } 6189 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6190 return &InstanceDiff{ 6191 Attributes: map[string]*ResourceAttrDiff{ 6192 "num": &ResourceAttrDiff{ 6193 New: "bar", 6194 }, 6195 }, 6196 }, nil 6197 } 6198 6199 if _, err := ctx.Plan(); err != nil { 6200 t.Fatalf("err: %s", err) 6201 } 6202 6203 state, err := ctx.Apply() 6204 if err == nil { 6205 t.Fatal("should have error") 6206 } 6207 6208 actual := strings.TrimSpace(state.String()) 6209 expected := strings.TrimSpace(testTerraformApplyErrorStr) 6210 if actual != expected { 6211 t.Fatalf("bad: \n%s", actual) 6212 } 6213 } 6214 6215 func TestContext2Apply_errorPartial(t *testing.T) { 6216 errored := false 6217 6218 m := testModule(t, "apply-error") 6219 p := testProvider("aws") 6220 s := &State{ 6221 Modules: []*ModuleState{ 6222 &ModuleState{ 6223 Path: rootModulePath, 6224 Resources: map[string]*ResourceState{ 6225 "aws_instance.bar": &ResourceState{ 6226 Type: "aws_instance", 6227 Primary: &InstanceState{ 6228 ID: "bar", 6229 }, 6230 }, 6231 }, 6232 }, 6233 }, 6234 } 6235 ctx := testContext2(t, &ContextOpts{ 6236 Module: m, 6237 Providers: map[string]ResourceProviderFactory{ 6238 "aws": testProviderFuncFixed(p), 6239 }, 6240 State: s, 6241 }) 6242 6243 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6244 if errored { 6245 return s, fmt.Errorf("error") 6246 } 6247 errored = true 6248 6249 return &InstanceState{ 6250 ID: "foo", 6251 Attributes: map[string]string{ 6252 "num": "2", 6253 }, 6254 }, nil 6255 } 6256 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6257 return &InstanceDiff{ 6258 Attributes: map[string]*ResourceAttrDiff{ 6259 "num": &ResourceAttrDiff{ 6260 New: "bar", 6261 }, 6262 }, 6263 }, nil 6264 } 6265 6266 if _, err := ctx.Plan(); err != nil { 6267 t.Fatalf("err: %s", err) 6268 } 6269 6270 state, err := ctx.Apply() 6271 if err == nil { 6272 t.Fatal("should have error") 6273 } 6274 6275 mod := state.RootModule() 6276 if len(mod.Resources) != 2 { 6277 t.Fatalf("bad: %#v", mod.Resources) 6278 } 6279 6280 actual := strings.TrimSpace(state.String()) 6281 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 6282 if actual != expected { 6283 t.Fatalf("bad: \n%s", actual) 6284 } 6285 } 6286 6287 func TestContext2Apply_hook(t *testing.T) { 6288 m := testModule(t, "apply-good") 6289 h := new(MockHook) 6290 p := testProvider("aws") 6291 p.ApplyFn = testApplyFn 6292 p.DiffFn = testDiffFn 6293 ctx := testContext2(t, &ContextOpts{ 6294 Module: m, 6295 Hooks: []Hook{h}, 6296 Providers: map[string]ResourceProviderFactory{ 6297 "aws": testProviderFuncFixed(p), 6298 }, 6299 }) 6300 6301 if _, err := ctx.Plan(); err != nil { 6302 t.Fatalf("err: %s", err) 6303 } 6304 6305 if _, err := ctx.Apply(); err != nil { 6306 t.Fatalf("err: %s", err) 6307 } 6308 6309 if !h.PreApplyCalled { 6310 t.Fatal("should be called") 6311 } 6312 if !h.PostApplyCalled { 6313 t.Fatal("should be called") 6314 } 6315 if !h.PostStateUpdateCalled { 6316 t.Fatalf("should call post state update") 6317 } 6318 } 6319 6320 func TestContext2Apply_hookOrphan(t *testing.T) { 6321 m := testModule(t, "apply-blank") 6322 h := new(MockHook) 6323 p := testProvider("aws") 6324 p.ApplyFn = testApplyFn 6325 p.DiffFn = testDiffFn 6326 6327 state := &State{ 6328 Modules: []*ModuleState{ 6329 &ModuleState{ 6330 Path: rootModulePath, 6331 Resources: map[string]*ResourceState{ 6332 "aws_instance.bar": &ResourceState{ 6333 Type: "aws_instance", 6334 Primary: &InstanceState{ 6335 ID: "bar", 6336 }, 6337 }, 6338 }, 6339 }, 6340 }, 6341 } 6342 6343 ctx := testContext2(t, &ContextOpts{ 6344 Module: m, 6345 State: state, 6346 Hooks: []Hook{h}, 6347 Providers: map[string]ResourceProviderFactory{ 6348 "aws": testProviderFuncFixed(p), 6349 }, 6350 }) 6351 6352 if _, err := ctx.Plan(); err != nil { 6353 t.Fatalf("err: %s", err) 6354 } 6355 6356 if _, err := ctx.Apply(); err != nil { 6357 t.Fatalf("err: %s", err) 6358 } 6359 6360 if !h.PreApplyCalled { 6361 t.Fatal("should be called") 6362 } 6363 if !h.PostApplyCalled { 6364 t.Fatal("should be called") 6365 } 6366 if !h.PostStateUpdateCalled { 6367 t.Fatalf("should call post state update") 6368 } 6369 } 6370 6371 func TestContext2Apply_idAttr(t *testing.T) { 6372 m := testModule(t, "apply-idattr") 6373 p := testProvider("aws") 6374 ctx := testContext2(t, &ContextOpts{ 6375 Module: m, 6376 Providers: map[string]ResourceProviderFactory{ 6377 "aws": testProviderFuncFixed(p), 6378 }, 6379 }) 6380 6381 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6382 result := s.MergeDiff(d) 6383 result.ID = "foo" 6384 result.Attributes = map[string]string{ 6385 "id": "bar", 6386 } 6387 6388 return result, nil 6389 } 6390 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 6391 return &InstanceDiff{ 6392 Attributes: map[string]*ResourceAttrDiff{ 6393 "num": &ResourceAttrDiff{ 6394 New: "bar", 6395 }, 6396 }, 6397 }, nil 6398 } 6399 6400 if _, err := ctx.Plan(); err != nil { 6401 t.Fatalf("err: %s", err) 6402 } 6403 6404 state, err := ctx.Apply() 6405 if err != nil { 6406 t.Fatalf("err: %s", err) 6407 } 6408 6409 mod := state.RootModule() 6410 rs, ok := mod.Resources["aws_instance.foo"] 6411 if !ok { 6412 t.Fatal("not in state") 6413 } 6414 if rs.Primary.ID != "foo" { 6415 t.Fatalf("bad: %#v", rs.Primary.ID) 6416 } 6417 if rs.Primary.Attributes["id"] != "foo" { 6418 t.Fatalf("bad: %#v", rs.Primary.Attributes) 6419 } 6420 } 6421 6422 func TestContext2Apply_outputBasic(t *testing.T) { 6423 m := testModule(t, "apply-output") 6424 p := testProvider("aws") 6425 p.ApplyFn = testApplyFn 6426 p.DiffFn = testDiffFn 6427 ctx := testContext2(t, &ContextOpts{ 6428 Module: m, 6429 Providers: map[string]ResourceProviderFactory{ 6430 "aws": testProviderFuncFixed(p), 6431 }, 6432 }) 6433 6434 if _, err := ctx.Plan(); err != nil { 6435 t.Fatalf("err: %s", err) 6436 } 6437 6438 state, err := ctx.Apply() 6439 if err != nil { 6440 t.Fatalf("err: %s", err) 6441 } 6442 6443 actual := strings.TrimSpace(state.String()) 6444 expected := strings.TrimSpace(testTerraformApplyOutputStr) 6445 if actual != expected { 6446 t.Fatalf("bad: \n%s", actual) 6447 } 6448 } 6449 6450 func TestContext2Apply_outputInvalid(t *testing.T) { 6451 m := testModule(t, "apply-output-invalid") 6452 p := testProvider("aws") 6453 p.ApplyFn = testApplyFn 6454 p.DiffFn = testDiffFn 6455 ctx := testContext2(t, &ContextOpts{ 6456 Module: m, 6457 Providers: map[string]ResourceProviderFactory{ 6458 "aws": testProviderFuncFixed(p), 6459 }, 6460 }) 6461 6462 _, err := ctx.Plan() 6463 if err == nil { 6464 t.Fatalf("err: %s", err) 6465 } 6466 if !strings.Contains(err.Error(), "is not a valid type") { 6467 t.Fatalf("err: %s", err) 6468 } 6469 } 6470 6471 func TestContext2Apply_outputAdd(t *testing.T) { 6472 m1 := testModule(t, "apply-output-add-before") 6473 p1 := testProvider("aws") 6474 p1.ApplyFn = testApplyFn 6475 p1.DiffFn = testDiffFn 6476 ctx1 := testContext2(t, &ContextOpts{ 6477 Module: m1, 6478 Providers: map[string]ResourceProviderFactory{ 6479 "aws": testProviderFuncFixed(p1), 6480 }, 6481 }) 6482 6483 if _, err := ctx1.Plan(); err != nil { 6484 t.Fatalf("err: %s", err) 6485 } 6486 6487 state1, err := ctx1.Apply() 6488 if err != nil { 6489 t.Fatalf("err: %s", err) 6490 } 6491 6492 m2 := testModule(t, "apply-output-add-after") 6493 p2 := testProvider("aws") 6494 p2.ApplyFn = testApplyFn 6495 p2.DiffFn = testDiffFn 6496 ctx2 := testContext2(t, &ContextOpts{ 6497 Module: m2, 6498 Providers: map[string]ResourceProviderFactory{ 6499 "aws": testProviderFuncFixed(p2), 6500 }, 6501 State: state1, 6502 }) 6503 6504 if _, err := ctx2.Plan(); err != nil { 6505 t.Fatalf("err: %s", err) 6506 } 6507 6508 state2, err := ctx2.Apply() 6509 if err != nil { 6510 t.Fatalf("err: %s", err) 6511 } 6512 6513 actual := strings.TrimSpace(state2.String()) 6514 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 6515 if actual != expected { 6516 t.Fatalf("bad: \n%s", actual) 6517 } 6518 } 6519 6520 func TestContext2Apply_outputList(t *testing.T) { 6521 m := testModule(t, "apply-output-list") 6522 p := testProvider("aws") 6523 p.ApplyFn = testApplyFn 6524 p.DiffFn = testDiffFn 6525 ctx := testContext2(t, &ContextOpts{ 6526 Module: m, 6527 Providers: map[string]ResourceProviderFactory{ 6528 "aws": testProviderFuncFixed(p), 6529 }, 6530 }) 6531 6532 if _, err := ctx.Plan(); err != nil { 6533 t.Fatalf("err: %s", err) 6534 } 6535 6536 state, err := ctx.Apply() 6537 if err != nil { 6538 t.Fatalf("err: %s", err) 6539 } 6540 6541 actual := strings.TrimSpace(state.String()) 6542 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 6543 if actual != expected { 6544 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 6545 } 6546 } 6547 6548 func TestContext2Apply_outputMulti(t *testing.T) { 6549 m := testModule(t, "apply-output-multi") 6550 p := testProvider("aws") 6551 p.ApplyFn = testApplyFn 6552 p.DiffFn = testDiffFn 6553 ctx := testContext2(t, &ContextOpts{ 6554 Module: m, 6555 Providers: map[string]ResourceProviderFactory{ 6556 "aws": testProviderFuncFixed(p), 6557 }, 6558 }) 6559 6560 if _, err := ctx.Plan(); err != nil { 6561 t.Fatalf("err: %s", err) 6562 } 6563 6564 state, err := ctx.Apply() 6565 if err != nil { 6566 t.Fatalf("err: %s", err) 6567 } 6568 6569 actual := strings.TrimSpace(state.String()) 6570 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 6571 if actual != expected { 6572 t.Fatalf("bad: \n%s", actual) 6573 } 6574 } 6575 6576 func TestContext2Apply_outputMultiIndex(t *testing.T) { 6577 m := testModule(t, "apply-output-multi-index") 6578 p := testProvider("aws") 6579 p.ApplyFn = testApplyFn 6580 p.DiffFn = testDiffFn 6581 ctx := testContext2(t, &ContextOpts{ 6582 Module: m, 6583 Providers: map[string]ResourceProviderFactory{ 6584 "aws": testProviderFuncFixed(p), 6585 }, 6586 }) 6587 6588 if _, err := ctx.Plan(); err != nil { 6589 t.Fatalf("err: %s", err) 6590 } 6591 6592 state, err := ctx.Apply() 6593 if err != nil { 6594 t.Fatalf("err: %s", err) 6595 } 6596 6597 actual := strings.TrimSpace(state.String()) 6598 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 6599 if actual != expected { 6600 t.Fatalf("bad: \n%s", actual) 6601 } 6602 } 6603 6604 func TestContext2Apply_taintX(t *testing.T) { 6605 m := testModule(t, "apply-taint") 6606 p := testProvider("aws") 6607 6608 // destroyCount tests against regression of 6609 // https://github.com/hashicorp/terraform/issues/1056 6610 var destroyCount = int32(0) 6611 var once sync.Once 6612 simulateProviderDelay := func() { 6613 time.Sleep(10 * time.Millisecond) 6614 } 6615 6616 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 6617 once.Do(simulateProviderDelay) 6618 if d.Destroy { 6619 atomic.AddInt32(&destroyCount, 1) 6620 } 6621 return testApplyFn(info, s, d) 6622 } 6623 p.DiffFn = testDiffFn 6624 s := &State{ 6625 Modules: []*ModuleState{ 6626 &ModuleState{ 6627 Path: rootModulePath, 6628 Resources: map[string]*ResourceState{ 6629 "aws_instance.bar": &ResourceState{ 6630 Type: "aws_instance", 6631 Primary: &InstanceState{ 6632 ID: "baz", 6633 Attributes: map[string]string{ 6634 "num": "2", 6635 "type": "aws_instance", 6636 }, 6637 Tainted: true, 6638 }, 6639 }, 6640 }, 6641 }, 6642 }, 6643 } 6644 ctx := testContext2(t, &ContextOpts{ 6645 Module: m, 6646 Providers: map[string]ResourceProviderFactory{ 6647 "aws": testProviderFuncFixed(p), 6648 }, 6649 State: s, 6650 }) 6651 6652 if p, err := ctx.Plan(); err != nil { 6653 t.Fatalf("err: %s", err) 6654 } else { 6655 t.Logf("plan: %s", p) 6656 } 6657 6658 state, err := ctx.Apply() 6659 if err != nil { 6660 t.Fatalf("err: %s", err) 6661 } 6662 6663 actual := strings.TrimSpace(state.String()) 6664 expected := strings.TrimSpace(testTerraformApplyTaintStr) 6665 if actual != expected { 6666 t.Fatalf("bad:\n%s", actual) 6667 } 6668 6669 if destroyCount != 1 { 6670 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 6671 } 6672 } 6673 6674 func TestContext2Apply_taintDep(t *testing.T) { 6675 m := testModule(t, "apply-taint-dep") 6676 p := testProvider("aws") 6677 p.ApplyFn = testApplyFn 6678 p.DiffFn = testDiffFn 6679 s := &State{ 6680 Modules: []*ModuleState{ 6681 &ModuleState{ 6682 Path: rootModulePath, 6683 Resources: map[string]*ResourceState{ 6684 "aws_instance.foo": &ResourceState{ 6685 Type: "aws_instance", 6686 Primary: &InstanceState{ 6687 ID: "baz", 6688 Attributes: map[string]string{ 6689 "num": "2", 6690 "type": "aws_instance", 6691 }, 6692 Tainted: true, 6693 }, 6694 }, 6695 "aws_instance.bar": &ResourceState{ 6696 Type: "aws_instance", 6697 Primary: &InstanceState{ 6698 ID: "bar", 6699 Attributes: map[string]string{ 6700 "foo": "baz", 6701 "num": "2", 6702 "type": "aws_instance", 6703 }, 6704 }, 6705 }, 6706 }, 6707 }, 6708 }, 6709 } 6710 ctx := testContext2(t, &ContextOpts{ 6711 Module: m, 6712 Providers: map[string]ResourceProviderFactory{ 6713 "aws": testProviderFuncFixed(p), 6714 }, 6715 State: s, 6716 }) 6717 6718 if p, err := ctx.Plan(); err != nil { 6719 t.Fatalf("err: %s", err) 6720 } else { 6721 t.Logf("plan: %s", p) 6722 } 6723 6724 state, err := ctx.Apply() 6725 if err != nil { 6726 t.Fatalf("err: %s", err) 6727 } 6728 6729 actual := strings.TrimSpace(state.String()) 6730 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 6731 if actual != expected { 6732 t.Fatalf("bad:\n%s", actual) 6733 } 6734 } 6735 6736 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 6737 m := testModule(t, "apply-taint-dep-requires-new") 6738 p := testProvider("aws") 6739 p.ApplyFn = testApplyFn 6740 p.DiffFn = testDiffFn 6741 s := &State{ 6742 Modules: []*ModuleState{ 6743 &ModuleState{ 6744 Path: rootModulePath, 6745 Resources: map[string]*ResourceState{ 6746 "aws_instance.foo": &ResourceState{ 6747 Type: "aws_instance", 6748 Primary: &InstanceState{ 6749 ID: "baz", 6750 Attributes: map[string]string{ 6751 "num": "2", 6752 "type": "aws_instance", 6753 }, 6754 Tainted: true, 6755 }, 6756 }, 6757 "aws_instance.bar": &ResourceState{ 6758 Type: "aws_instance", 6759 Primary: &InstanceState{ 6760 ID: "bar", 6761 Attributes: map[string]string{ 6762 "foo": "baz", 6763 "num": "2", 6764 "type": "aws_instance", 6765 }, 6766 }, 6767 }, 6768 }, 6769 }, 6770 }, 6771 } 6772 ctx := testContext2(t, &ContextOpts{ 6773 Module: m, 6774 Providers: map[string]ResourceProviderFactory{ 6775 "aws": testProviderFuncFixed(p), 6776 }, 6777 State: s, 6778 }) 6779 6780 if p, err := ctx.Plan(); err != nil { 6781 t.Fatalf("err: %s", err) 6782 } else { 6783 t.Logf("plan: %s", p) 6784 } 6785 6786 state, err := ctx.Apply() 6787 if err != nil { 6788 t.Fatalf("err: %s", err) 6789 } 6790 6791 actual := strings.TrimSpace(state.String()) 6792 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 6793 if actual != expected { 6794 t.Fatalf("bad:\n%s", actual) 6795 } 6796 } 6797 6798 func TestContext2Apply_targeted(t *testing.T) { 6799 m := testModule(t, "apply-targeted") 6800 p := testProvider("aws") 6801 p.ApplyFn = testApplyFn 6802 p.DiffFn = testDiffFn 6803 ctx := testContext2(t, &ContextOpts{ 6804 Module: m, 6805 Providers: map[string]ResourceProviderFactory{ 6806 "aws": testProviderFuncFixed(p), 6807 }, 6808 Targets: []string{"aws_instance.foo"}, 6809 }) 6810 6811 if _, err := ctx.Plan(); err != nil { 6812 t.Fatalf("err: %s", err) 6813 } 6814 6815 state, err := ctx.Apply() 6816 if err != nil { 6817 t.Fatalf("err: %s", err) 6818 } 6819 6820 mod := state.RootModule() 6821 if len(mod.Resources) != 1 { 6822 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6823 } 6824 6825 checkStateString(t, state, ` 6826 aws_instance.foo: 6827 ID = foo 6828 num = 2 6829 type = aws_instance 6830 `) 6831 } 6832 6833 func TestContext2Apply_targetedCount(t *testing.T) { 6834 m := testModule(t, "apply-targeted-count") 6835 p := testProvider("aws") 6836 p.ApplyFn = testApplyFn 6837 p.DiffFn = testDiffFn 6838 ctx := testContext2(t, &ContextOpts{ 6839 Module: m, 6840 Providers: map[string]ResourceProviderFactory{ 6841 "aws": testProviderFuncFixed(p), 6842 }, 6843 Targets: []string{"aws_instance.foo"}, 6844 }) 6845 6846 if _, err := ctx.Plan(); err != nil { 6847 t.Fatalf("err: %s", err) 6848 } 6849 6850 state, err := ctx.Apply() 6851 if err != nil { 6852 t.Fatalf("err: %s", err) 6853 } 6854 6855 checkStateString(t, state, ` 6856 aws_instance.foo.0: 6857 ID = foo 6858 aws_instance.foo.1: 6859 ID = foo 6860 aws_instance.foo.2: 6861 ID = foo 6862 `) 6863 } 6864 6865 func TestContext2Apply_targetedCountIndex(t *testing.T) { 6866 m := testModule(t, "apply-targeted-count") 6867 p := testProvider("aws") 6868 p.ApplyFn = testApplyFn 6869 p.DiffFn = testDiffFn 6870 ctx := testContext2(t, &ContextOpts{ 6871 Module: m, 6872 Providers: map[string]ResourceProviderFactory{ 6873 "aws": testProviderFuncFixed(p), 6874 }, 6875 Targets: []string{"aws_instance.foo[1]"}, 6876 }) 6877 6878 if _, err := ctx.Plan(); err != nil { 6879 t.Fatalf("err: %s", err) 6880 } 6881 6882 state, err := ctx.Apply() 6883 if err != nil { 6884 t.Fatalf("err: %s", err) 6885 } 6886 6887 checkStateString(t, state, ` 6888 aws_instance.foo.1: 6889 ID = foo 6890 `) 6891 } 6892 6893 func TestContext2Apply_targetedDestroy(t *testing.T) { 6894 m := testModule(t, "apply-targeted") 6895 p := testProvider("aws") 6896 p.ApplyFn = testApplyFn 6897 p.DiffFn = testDiffFn 6898 ctx := testContext2(t, &ContextOpts{ 6899 Module: m, 6900 Providers: map[string]ResourceProviderFactory{ 6901 "aws": testProviderFuncFixed(p), 6902 }, 6903 State: &State{ 6904 Modules: []*ModuleState{ 6905 &ModuleState{ 6906 Path: rootModulePath, 6907 Resources: map[string]*ResourceState{ 6908 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6909 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6910 }, 6911 }, 6912 }, 6913 }, 6914 Targets: []string{"aws_instance.foo"}, 6915 Destroy: true, 6916 }) 6917 6918 if _, err := ctx.Plan(); err != nil { 6919 t.Fatalf("err: %s", err) 6920 } 6921 6922 state, err := ctx.Apply() 6923 if err != nil { 6924 t.Fatalf("err: %s", err) 6925 } 6926 6927 mod := state.RootModule() 6928 if len(mod.Resources) != 1 { 6929 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 6930 } 6931 6932 checkStateString(t, state, ` 6933 aws_instance.bar: 6934 ID = i-abc123 6935 `) 6936 } 6937 6938 func TestContext2Apply_targetedDestroyCountDeps(t *testing.T) { 6939 m := testModule(t, "apply-destroy-targeted-count") 6940 p := testProvider("aws") 6941 p.ApplyFn = testApplyFn 6942 p.DiffFn = testDiffFn 6943 ctx := testContext2(t, &ContextOpts{ 6944 Module: m, 6945 Providers: map[string]ResourceProviderFactory{ 6946 "aws": testProviderFuncFixed(p), 6947 }, 6948 State: &State{ 6949 Modules: []*ModuleState{ 6950 &ModuleState{ 6951 Path: rootModulePath, 6952 Resources: map[string]*ResourceState{ 6953 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6954 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6955 }, 6956 }, 6957 }, 6958 }, 6959 Targets: []string{"aws_instance.foo"}, 6960 Destroy: true, 6961 }) 6962 6963 if _, err := ctx.Plan(); err != nil { 6964 t.Fatalf("err: %s", err) 6965 } 6966 6967 state, err := ctx.Apply() 6968 if err != nil { 6969 t.Fatalf("err: %s", err) 6970 } 6971 6972 checkStateString(t, state, `<no state>`) 6973 } 6974 6975 // https://github.com/hashicorp/terraform/issues/4462 6976 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 6977 m := testModule(t, "apply-targeted-module") 6978 p := testProvider("aws") 6979 p.ApplyFn = testApplyFn 6980 p.DiffFn = testDiffFn 6981 ctx := testContext2(t, &ContextOpts{ 6982 Module: m, 6983 Providers: map[string]ResourceProviderFactory{ 6984 "aws": testProviderFuncFixed(p), 6985 }, 6986 State: &State{ 6987 Modules: []*ModuleState{ 6988 &ModuleState{ 6989 Path: rootModulePath, 6990 Resources: map[string]*ResourceState{ 6991 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6992 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 6993 }, 6994 }, 6995 &ModuleState{ 6996 Path: []string{"root", "child"}, 6997 Resources: map[string]*ResourceState{ 6998 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 6999 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 7000 }, 7001 }, 7002 }, 7003 }, 7004 Targets: []string{"module.child.aws_instance.foo"}, 7005 Destroy: true, 7006 }) 7007 7008 if _, err := ctx.Plan(); err != nil { 7009 t.Fatalf("err: %s", err) 7010 } 7011 7012 state, err := ctx.Apply() 7013 if err != nil { 7014 t.Fatalf("err: %s", err) 7015 } 7016 7017 checkStateString(t, state, ` 7018 aws_instance.bar: 7019 ID = i-abc123 7020 aws_instance.foo: 7021 ID = i-bcd345 7022 7023 module.child: 7024 aws_instance.bar: 7025 ID = i-abc123 7026 `) 7027 } 7028 7029 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 7030 m := testModule(t, "apply-targeted-count") 7031 p := testProvider("aws") 7032 p.ApplyFn = testApplyFn 7033 p.DiffFn = testDiffFn 7034 ctx := testContext2(t, &ContextOpts{ 7035 Module: m, 7036 Providers: map[string]ResourceProviderFactory{ 7037 "aws": testProviderFuncFixed(p), 7038 }, 7039 State: &State{ 7040 Modules: []*ModuleState{ 7041 &ModuleState{ 7042 Path: rootModulePath, 7043 Resources: map[string]*ResourceState{ 7044 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 7045 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 7046 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 7047 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 7048 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 7049 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 7050 }, 7051 }, 7052 }, 7053 }, 7054 Targets: []string{ 7055 "aws_instance.foo[2]", 7056 "aws_instance.bar[1]", 7057 }, 7058 Destroy: true, 7059 }) 7060 7061 if _, err := ctx.Plan(); err != nil { 7062 t.Fatalf("err: %s", err) 7063 } 7064 7065 state, err := ctx.Apply() 7066 if err != nil { 7067 t.Fatalf("err: %s", err) 7068 } 7069 7070 checkStateString(t, state, ` 7071 aws_instance.bar.0: 7072 ID = i-abc123 7073 aws_instance.bar.2: 7074 ID = i-abc123 7075 aws_instance.foo.0: 7076 ID = i-bcd345 7077 aws_instance.foo.1: 7078 ID = i-bcd345 7079 `) 7080 } 7081 7082 func TestContext2Apply_targetedModule(t *testing.T) { 7083 m := testModule(t, "apply-targeted-module") 7084 p := testProvider("aws") 7085 p.ApplyFn = testApplyFn 7086 p.DiffFn = testDiffFn 7087 ctx := testContext2(t, &ContextOpts{ 7088 Module: m, 7089 Providers: map[string]ResourceProviderFactory{ 7090 "aws": testProviderFuncFixed(p), 7091 }, 7092 Targets: []string{"module.child"}, 7093 }) 7094 7095 if _, err := ctx.Plan(); err != nil { 7096 t.Fatalf("err: %s", err) 7097 } 7098 7099 state, err := ctx.Apply() 7100 if err != nil { 7101 t.Fatalf("err: %s", err) 7102 } 7103 7104 mod := state.ModuleByPath([]string{"root", "child"}) 7105 if mod == nil { 7106 t.Fatalf("no child module found in the state!\n\n%#v", state) 7107 } 7108 if len(mod.Resources) != 2 { 7109 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 7110 } 7111 7112 checkStateString(t, state, ` 7113 <no state> 7114 module.child: 7115 aws_instance.bar: 7116 ID = foo 7117 num = 2 7118 type = aws_instance 7119 aws_instance.foo: 7120 ID = foo 7121 num = 2 7122 type = aws_instance 7123 `) 7124 } 7125 7126 // GH-1858 7127 func TestContext2Apply_targetedModuleDep(t *testing.T) { 7128 m := testModule(t, "apply-targeted-module-dep") 7129 p := testProvider("aws") 7130 p.ApplyFn = testApplyFn 7131 p.DiffFn = testDiffFn 7132 ctx := testContext2(t, &ContextOpts{ 7133 Module: m, 7134 Providers: map[string]ResourceProviderFactory{ 7135 "aws": testProviderFuncFixed(p), 7136 }, 7137 Targets: []string{"aws_instance.foo"}, 7138 }) 7139 7140 if p, err := ctx.Plan(); err != nil { 7141 t.Fatalf("err: %s", err) 7142 } else { 7143 t.Logf("Diff: %s", p) 7144 } 7145 7146 state, err := ctx.Apply() 7147 if err != nil { 7148 t.Fatalf("err: %s", err) 7149 } 7150 7151 checkStateString(t, state, ` 7152 aws_instance.foo: 7153 ID = foo 7154 foo = foo 7155 type = aws_instance 7156 7157 Dependencies: 7158 module.child 7159 7160 module.child: 7161 aws_instance.mod: 7162 ID = foo 7163 7164 Outputs: 7165 7166 output = foo 7167 `) 7168 } 7169 7170 // GH-10911 untargeted outputs should not be in the graph, and therefore 7171 // not execute. 7172 func TestContext2Apply_targetedModuleUnrelatedOutputs(t *testing.T) { 7173 m := testModule(t, "apply-targeted-module-unrelated-outputs") 7174 p := testProvider("aws") 7175 p.ApplyFn = testApplyFn 7176 p.DiffFn = testDiffFn 7177 ctx := testContext2(t, &ContextOpts{ 7178 Module: m, 7179 Providers: map[string]ResourceProviderFactory{ 7180 "aws": testProviderFuncFixed(p), 7181 }, 7182 Targets: []string{"module.child2"}, 7183 }) 7184 7185 if _, err := ctx.Plan(); err != nil { 7186 t.Fatalf("err: %s", err) 7187 } 7188 7189 state, err := ctx.Apply() 7190 if err != nil { 7191 t.Fatalf("err: %s", err) 7192 } 7193 7194 checkStateString(t, state, ` 7195 <no state> 7196 module.child2: 7197 aws_instance.foo: 7198 ID = foo 7199 `) 7200 } 7201 7202 func TestContext2Apply_targetedModuleResource(t *testing.T) { 7203 m := testModule(t, "apply-targeted-module-resource") 7204 p := testProvider("aws") 7205 p.ApplyFn = testApplyFn 7206 p.DiffFn = testDiffFn 7207 ctx := testContext2(t, &ContextOpts{ 7208 Module: m, 7209 Providers: map[string]ResourceProviderFactory{ 7210 "aws": testProviderFuncFixed(p), 7211 }, 7212 Targets: []string{"module.child.aws_instance.foo"}, 7213 }) 7214 7215 if _, err := ctx.Plan(); err != nil { 7216 t.Fatalf("err: %s", err) 7217 } 7218 7219 state, err := ctx.Apply() 7220 if err != nil { 7221 t.Fatalf("err: %s", err) 7222 } 7223 7224 mod := state.ModuleByPath([]string{"root", "child"}) 7225 if mod == nil || len(mod.Resources) != 1 { 7226 t.Fatalf("expected 1 resource, got: %#v", mod) 7227 } 7228 7229 checkStateString(t, state, ` 7230 <no state> 7231 module.child: 7232 aws_instance.foo: 7233 ID = foo 7234 num = 2 7235 type = aws_instance 7236 `) 7237 } 7238 7239 func TestContext2Apply_unknownAttribute(t *testing.T) { 7240 m := testModule(t, "apply-unknown") 7241 p := testProvider("aws") 7242 p.ApplyFn = testApplyFn 7243 p.DiffFn = testDiffFn 7244 ctx := testContext2(t, &ContextOpts{ 7245 Module: m, 7246 Providers: map[string]ResourceProviderFactory{ 7247 "aws": testProviderFuncFixed(p), 7248 }, 7249 }) 7250 7251 if _, err := ctx.Plan(); err != nil { 7252 t.Fatalf("err: %s", err) 7253 } 7254 7255 state, err := ctx.Apply() 7256 if err == nil { 7257 t.Fatal("should error") 7258 } 7259 7260 actual := strings.TrimSpace(state.String()) 7261 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 7262 if actual != expected { 7263 t.Fatalf("bad: \n%s", actual) 7264 } 7265 } 7266 7267 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 7268 m := testModule(t, "apply-unknown-interpolate") 7269 p := testProvider("aws") 7270 p.ApplyFn = testApplyFn 7271 p.DiffFn = testDiffFn 7272 ctx := testContext2(t, &ContextOpts{ 7273 Module: m, 7274 Providers: map[string]ResourceProviderFactory{ 7275 "aws": testProviderFuncFixed(p), 7276 }, 7277 }) 7278 7279 if _, err := ctx.Plan(); err == nil { 7280 t.Fatal("should error") 7281 } 7282 } 7283 7284 func TestContext2Apply_vars(t *testing.T) { 7285 m := testModule(t, "apply-vars") 7286 p := testProvider("aws") 7287 p.ApplyFn = testApplyFn 7288 p.DiffFn = testDiffFn 7289 ctx := testContext2(t, &ContextOpts{ 7290 Module: m, 7291 Providers: map[string]ResourceProviderFactory{ 7292 "aws": testProviderFuncFixed(p), 7293 }, 7294 Variables: map[string]interface{}{ 7295 "foo": "us-west-2", 7296 "test_list": []interface{}{"Hello", "World"}, 7297 "test_map": map[string]interface{}{ 7298 "Hello": "World", 7299 "Foo": "Bar", 7300 "Baz": "Foo", 7301 }, 7302 "amis": []map[string]interface{}{ 7303 map[string]interface{}{ 7304 "us-east-1": "override", 7305 }, 7306 }, 7307 }, 7308 }) 7309 7310 w, e := ctx.Validate() 7311 if len(w) > 0 { 7312 t.Fatalf("bad: %#v", w) 7313 } 7314 if len(e) > 0 { 7315 t.Fatalf("bad: %s", e) 7316 } 7317 7318 if _, err := ctx.Plan(); err != nil { 7319 t.Fatalf("err: %s", err) 7320 } 7321 7322 state, err := ctx.Apply() 7323 if err != nil { 7324 t.Fatalf("err: %s", err) 7325 } 7326 7327 actual := strings.TrimSpace(state.String()) 7328 expected := strings.TrimSpace(testTerraformApplyVarsStr) 7329 if actual != expected { 7330 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 7331 } 7332 } 7333 7334 func TestContext2Apply_varsEnv(t *testing.T) { 7335 // Set the env var 7336 defer tempEnv(t, "TF_VAR_ami", "baz")() 7337 defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() 7338 defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() 7339 7340 m := testModule(t, "apply-vars-env") 7341 p := testProvider("aws") 7342 p.ApplyFn = testApplyFn 7343 p.DiffFn = testDiffFn 7344 ctx := testContext2(t, &ContextOpts{ 7345 Module: m, 7346 Providers: map[string]ResourceProviderFactory{ 7347 "aws": testProviderFuncFixed(p), 7348 }, 7349 }) 7350 7351 w, e := ctx.Validate() 7352 if len(w) > 0 { 7353 t.Fatalf("bad: %#v", w) 7354 } 7355 if len(e) > 0 { 7356 t.Fatalf("bad: %s", e) 7357 } 7358 7359 if _, err := ctx.Plan(); err != nil { 7360 t.Fatalf("err: %s", err) 7361 } 7362 7363 state, err := ctx.Apply() 7364 if err != nil { 7365 t.Fatalf("err: %s", err) 7366 } 7367 7368 actual := strings.TrimSpace(state.String()) 7369 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 7370 if actual != expected { 7371 t.Fatalf("bad: \n%s", actual) 7372 } 7373 } 7374 7375 func TestContext2Apply_createBefore_depends(t *testing.T) { 7376 m := testModule(t, "apply-depends-create-before") 7377 h := new(HookRecordApplyOrder) 7378 p := testProvider("aws") 7379 p.ApplyFn = testApplyFn 7380 p.DiffFn = testDiffFn 7381 state := &State{ 7382 Modules: []*ModuleState{ 7383 &ModuleState{ 7384 Path: rootModulePath, 7385 Resources: map[string]*ResourceState{ 7386 "aws_instance.web": &ResourceState{ 7387 Type: "aws_instance", 7388 Primary: &InstanceState{ 7389 ID: "bar", 7390 Attributes: map[string]string{ 7391 "require_new": "ami-old", 7392 }, 7393 }, 7394 }, 7395 "aws_instance.lb": &ResourceState{ 7396 Type: "aws_instance", 7397 Primary: &InstanceState{ 7398 ID: "baz", 7399 Attributes: map[string]string{ 7400 "instance": "bar", 7401 }, 7402 }, 7403 }, 7404 }, 7405 }, 7406 }, 7407 } 7408 ctx := testContext2(t, &ContextOpts{ 7409 Module: m, 7410 Hooks: []Hook{h}, 7411 Providers: map[string]ResourceProviderFactory{ 7412 "aws": testProviderFuncFixed(p), 7413 }, 7414 State: state, 7415 }) 7416 7417 if p, err := ctx.Plan(); err != nil { 7418 t.Fatalf("err: %s", err) 7419 } else { 7420 t.Logf("plan: %s", p) 7421 } 7422 7423 h.Active = true 7424 state, err := ctx.Apply() 7425 if err != nil { 7426 t.Fatalf("err: %s", err) 7427 } 7428 7429 mod := state.RootModule() 7430 if len(mod.Resources) < 2 { 7431 t.Fatalf("bad: %#v", mod.Resources) 7432 } 7433 7434 actual := strings.TrimSpace(state.String()) 7435 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 7436 if actual != expected { 7437 t.Fatalf("bad: \n%s\n\n%s", actual, expected) 7438 } 7439 7440 // Test that things were managed _in the right order_ 7441 order := h.States 7442 diffs := h.Diffs 7443 if order[0].ID != "" || diffs[0].Destroy { 7444 t.Fatalf("should create new instance first: %#v", order) 7445 } 7446 7447 if order[1].ID != "baz" { 7448 t.Fatalf("update must happen after create: %#v", order) 7449 } 7450 7451 if order[2].ID != "bar" || !diffs[2].Destroy { 7452 t.Fatalf("destroy must happen after update: %#v", order) 7453 } 7454 } 7455 7456 func TestContext2Apply_singleDestroy(t *testing.T) { 7457 m := testModule(t, "apply-depends-create-before") 7458 h := new(HookRecordApplyOrder) 7459 p := testProvider("aws") 7460 7461 invokeCount := 0 7462 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 7463 invokeCount++ 7464 switch invokeCount { 7465 case 1: 7466 if d.Destroy { 7467 t.Fatalf("should not destroy") 7468 } 7469 if s.ID != "" { 7470 t.Fatalf("should not have ID") 7471 } 7472 case 2: 7473 if d.Destroy { 7474 t.Fatalf("should not destroy") 7475 } 7476 if s.ID != "baz" { 7477 t.Fatalf("should have id") 7478 } 7479 case 3: 7480 if !d.Destroy { 7481 t.Fatalf("should destroy") 7482 } 7483 if s.ID == "" { 7484 t.Fatalf("should have ID") 7485 } 7486 default: 7487 t.Fatalf("bad invoke count %d", invokeCount) 7488 } 7489 return testApplyFn(info, s, d) 7490 } 7491 p.DiffFn = testDiffFn 7492 state := &State{ 7493 Modules: []*ModuleState{ 7494 &ModuleState{ 7495 Path: rootModulePath, 7496 Resources: map[string]*ResourceState{ 7497 "aws_instance.web": &ResourceState{ 7498 Type: "aws_instance", 7499 Primary: &InstanceState{ 7500 ID: "bar", 7501 Attributes: map[string]string{ 7502 "require_new": "ami-old", 7503 }, 7504 }, 7505 }, 7506 "aws_instance.lb": &ResourceState{ 7507 Type: "aws_instance", 7508 Primary: &InstanceState{ 7509 ID: "baz", 7510 Attributes: map[string]string{ 7511 "instance": "bar", 7512 }, 7513 }, 7514 }, 7515 }, 7516 }, 7517 }, 7518 } 7519 ctx := testContext2(t, &ContextOpts{ 7520 Module: m, 7521 Hooks: []Hook{h}, 7522 Providers: map[string]ResourceProviderFactory{ 7523 "aws": testProviderFuncFixed(p), 7524 }, 7525 State: state, 7526 }) 7527 7528 if _, err := ctx.Plan(); err != nil { 7529 t.Fatalf("err: %s", err) 7530 } 7531 7532 h.Active = true 7533 state, err := ctx.Apply() 7534 if err != nil { 7535 t.Fatalf("err: %s", err) 7536 } 7537 7538 if invokeCount != 3 { 7539 t.Fatalf("bad: %d", invokeCount) 7540 } 7541 } 7542 7543 // GH-7824 7544 func TestContext2Apply_issue7824(t *testing.T) { 7545 p := testProvider("template") 7546 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 7547 Name: "template_file", 7548 }) 7549 7550 p.ApplyFn = testApplyFn 7551 p.DiffFn = testDiffFn 7552 7553 // Apply cleanly step 0 7554 ctx := testContext2(t, &ContextOpts{ 7555 Module: testModule(t, "issue-7824"), 7556 Providers: map[string]ResourceProviderFactory{ 7557 "template": testProviderFuncFixed(p), 7558 }, 7559 }) 7560 7561 plan, err := ctx.Plan() 7562 if err != nil { 7563 t.Fatalf("err: %s", err) 7564 } 7565 7566 // Write / Read plan to simulate running it through a Plan file 7567 var buf bytes.Buffer 7568 if err := WritePlan(plan, &buf); err != nil { 7569 t.Fatalf("err: %s", err) 7570 } 7571 7572 planFromFile, err := ReadPlan(&buf) 7573 if err != nil { 7574 t.Fatalf("err: %s", err) 7575 } 7576 7577 ctx, err = planFromFile.Context(&ContextOpts{ 7578 Providers: map[string]ResourceProviderFactory{ 7579 "template": testProviderFuncFixed(p), 7580 }, 7581 }) 7582 if err != nil { 7583 t.Fatalf("err: %s", err) 7584 } 7585 7586 _, err = ctx.Apply() 7587 if err != nil { 7588 t.Fatalf("err: %s", err) 7589 } 7590 } 7591 7592 // GH-5254 7593 func TestContext2Apply_issue5254(t *testing.T) { 7594 // Create a provider. We use "template" here just to match the repro 7595 // we got from the issue itself. 7596 p := testProvider("template") 7597 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 7598 Name: "template_file", 7599 }) 7600 7601 p.ApplyFn = testApplyFn 7602 p.DiffFn = testDiffFn 7603 7604 // Apply cleanly step 0 7605 ctx := testContext2(t, &ContextOpts{ 7606 Module: testModule(t, "issue-5254/step-0"), 7607 Providers: map[string]ResourceProviderFactory{ 7608 "template": testProviderFuncFixed(p), 7609 }, 7610 }) 7611 7612 plan, err := ctx.Plan() 7613 if err != nil { 7614 t.Fatalf("err: %s", err) 7615 } 7616 7617 state, err := ctx.Apply() 7618 if err != nil { 7619 t.Fatalf("err: %s", err) 7620 } 7621 7622 // Application success. Now make the modification and store a plan 7623 ctx = testContext2(t, &ContextOpts{ 7624 Module: testModule(t, "issue-5254/step-1"), 7625 State: state, 7626 Providers: map[string]ResourceProviderFactory{ 7627 "template": testProviderFuncFixed(p), 7628 }, 7629 }) 7630 7631 plan, err = ctx.Plan() 7632 if err != nil { 7633 t.Fatalf("err: %s", err) 7634 } 7635 7636 // Write / Read plan to simulate running it through a Plan file 7637 var buf bytes.Buffer 7638 if err := WritePlan(plan, &buf); err != nil { 7639 t.Fatalf("err: %s", err) 7640 } 7641 7642 planFromFile, err := ReadPlan(&buf) 7643 if err != nil { 7644 t.Fatalf("err: %s", err) 7645 } 7646 7647 ctx, err = planFromFile.Context(&ContextOpts{ 7648 Providers: map[string]ResourceProviderFactory{ 7649 "template": testProviderFuncFixed(p), 7650 }, 7651 }) 7652 if err != nil { 7653 t.Fatalf("err: %s", err) 7654 } 7655 7656 state, err = ctx.Apply() 7657 if err != nil { 7658 t.Fatalf("err: %s", err) 7659 } 7660 7661 actual := strings.TrimSpace(state.String()) 7662 expected := strings.TrimSpace(` 7663 template_file.child: 7664 ID = foo 7665 template = Hi 7666 type = template_file 7667 7668 Dependencies: 7669 template_file.parent.* 7670 template_file.parent: 7671 ID = foo 7672 template = Hi 7673 type = template_file 7674 `) 7675 if actual != expected { 7676 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 7677 } 7678 } 7679 7680 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 7681 p := testProvider("aws") 7682 p.DiffFn = testDiffFn 7683 p.ApplyFn = testApplyFn 7684 ctx := testContext2(t, &ContextOpts{ 7685 Module: testModule(t, "apply-tainted-targets"), 7686 Providers: map[string]ResourceProviderFactory{ 7687 "aws": testProviderFuncFixed(p), 7688 }, 7689 Targets: []string{"aws_instance.iambeingadded"}, 7690 State: &State{ 7691 Modules: []*ModuleState{ 7692 &ModuleState{ 7693 Path: rootModulePath, 7694 Resources: map[string]*ResourceState{ 7695 "aws_instance.ifailedprovisioners": &ResourceState{ 7696 Primary: &InstanceState{ 7697 ID: "ifailedprovisioners", 7698 Tainted: true, 7699 }, 7700 }, 7701 }, 7702 }, 7703 }, 7704 }, 7705 }) 7706 7707 plan, err := ctx.Plan() 7708 if err != nil { 7709 t.Fatalf("err: %s", err) 7710 } 7711 7712 // Write / Read plan to simulate running it through a Plan file 7713 var buf bytes.Buffer 7714 if err := WritePlan(plan, &buf); err != nil { 7715 t.Fatalf("err: %s", err) 7716 } 7717 7718 planFromFile, err := ReadPlan(&buf) 7719 if err != nil { 7720 t.Fatalf("err: %s", err) 7721 } 7722 7723 ctx, err = planFromFile.Context(&ContextOpts{ 7724 Module: testModule(t, "apply-tainted-targets"), 7725 Providers: map[string]ResourceProviderFactory{ 7726 "aws": testProviderFuncFixed(p), 7727 }, 7728 }) 7729 if err != nil { 7730 t.Fatalf("err: %s", err) 7731 } 7732 7733 state, err := ctx.Apply() 7734 if err != nil { 7735 t.Fatalf("err: %s", err) 7736 } 7737 7738 actual := strings.TrimSpace(state.String()) 7739 expected := strings.TrimSpace(` 7740 aws_instance.iambeingadded: 7741 ID = foo 7742 aws_instance.ifailedprovisioners: (tainted) 7743 ID = ifailedprovisioners 7744 `) 7745 if actual != expected { 7746 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 7747 } 7748 } 7749 7750 // Higher level test exposing the bug this covers in 7751 // TestResource_ignoreChangesRequired 7752 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 7753 m := testModule(t, "apply-ignore-changes-create") 7754 p := testProvider("aws") 7755 p.ApplyFn = testApplyFn 7756 p.DiffFn = testDiffFn 7757 ctx := testContext2(t, &ContextOpts{ 7758 Module: m, 7759 Providers: map[string]ResourceProviderFactory{ 7760 "aws": testProviderFuncFixed(p), 7761 }, 7762 }) 7763 7764 if p, err := ctx.Plan(); err != nil { 7765 t.Fatalf("err: %s", err) 7766 } else { 7767 t.Logf(p.String()) 7768 } 7769 7770 state, err := ctx.Apply() 7771 if err != nil { 7772 t.Fatalf("err: %s", err) 7773 } 7774 7775 mod := state.RootModule() 7776 if len(mod.Resources) != 1 { 7777 t.Fatalf("bad: %s", state) 7778 } 7779 7780 actual := strings.TrimSpace(state.String()) 7781 // Expect no changes from original state 7782 expected := strings.TrimSpace(` 7783 aws_instance.foo: 7784 ID = foo 7785 required_field = set 7786 type = aws_instance 7787 `) 7788 if actual != expected { 7789 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 7790 } 7791 } 7792 7793 func TestContext2Apply_ignoreChangesWithDep(t *testing.T) { 7794 m := testModule(t, "apply-ignore-changes-dep") 7795 p := testProvider("aws") 7796 p.ApplyFn = testApplyFn 7797 p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 7798 switch i.Type { 7799 case "aws_instance": 7800 newAmi, _ := c.Get("ami") 7801 return &InstanceDiff{ 7802 Attributes: map[string]*ResourceAttrDiff{ 7803 "ami": &ResourceAttrDiff{ 7804 Old: s.Attributes["ami"], 7805 New: newAmi.(string), 7806 RequiresNew: true, 7807 }, 7808 }, 7809 }, nil 7810 case "aws_eip": 7811 return testDiffFn(i, s, c) 7812 default: 7813 t.Fatalf("Unexpected type: %s", i.Type) 7814 return nil, nil 7815 } 7816 } 7817 s := &State{ 7818 Modules: []*ModuleState{ 7819 &ModuleState{ 7820 Path: rootModulePath, 7821 Resources: map[string]*ResourceState{ 7822 "aws_instance.foo.0": &ResourceState{ 7823 Primary: &InstanceState{ 7824 ID: "i-abc123", 7825 Attributes: map[string]string{ 7826 "ami": "ami-abcd1234", 7827 "id": "i-abc123", 7828 }, 7829 }, 7830 }, 7831 "aws_instance.foo.1": &ResourceState{ 7832 Primary: &InstanceState{ 7833 ID: "i-bcd234", 7834 Attributes: map[string]string{ 7835 "ami": "ami-abcd1234", 7836 "id": "i-bcd234", 7837 }, 7838 }, 7839 }, 7840 "aws_eip.foo.0": &ResourceState{ 7841 Primary: &InstanceState{ 7842 ID: "eip-abc123", 7843 Attributes: map[string]string{ 7844 "id": "eip-abc123", 7845 "instance": "i-abc123", 7846 }, 7847 }, 7848 }, 7849 "aws_eip.foo.1": &ResourceState{ 7850 Primary: &InstanceState{ 7851 ID: "eip-bcd234", 7852 Attributes: map[string]string{ 7853 "id": "eip-bcd234", 7854 "instance": "i-bcd234", 7855 }, 7856 }, 7857 }, 7858 }, 7859 }, 7860 }, 7861 } 7862 ctx := testContext2(t, &ContextOpts{ 7863 Module: m, 7864 Providers: map[string]ResourceProviderFactory{ 7865 "aws": testProviderFuncFixed(p), 7866 }, 7867 State: s, 7868 }) 7869 7870 if p, err := ctx.Plan(); err != nil { 7871 t.Fatalf("err: %s", err) 7872 } else { 7873 t.Logf(p.String()) 7874 } 7875 7876 state, err := ctx.Apply() 7877 if err != nil { 7878 t.Fatalf("err: %s", err) 7879 } 7880 7881 actual := strings.TrimSpace(state.String()) 7882 expected := strings.TrimSpace(s.String()) 7883 if actual != expected { 7884 t.Fatalf("bad: \n%s", actual) 7885 } 7886 } 7887 7888 func TestContext2Apply_ignoreChangesWildcard(t *testing.T) { 7889 m := testModule(t, "apply-ignore-changes-wildcard") 7890 p := testProvider("aws") 7891 p.ApplyFn = testApplyFn 7892 p.DiffFn = testDiffFn 7893 ctx := testContext2(t, &ContextOpts{ 7894 Module: m, 7895 Providers: map[string]ResourceProviderFactory{ 7896 "aws": testProviderFuncFixed(p), 7897 }, 7898 }) 7899 7900 if p, err := ctx.Plan(); err != nil { 7901 t.Fatalf("err: %s", err) 7902 } else { 7903 t.Logf(p.String()) 7904 } 7905 7906 state, err := ctx.Apply() 7907 if err != nil { 7908 t.Fatalf("err: %s", err) 7909 } 7910 7911 mod := state.RootModule() 7912 if len(mod.Resources) != 1 { 7913 t.Fatalf("bad: %s", state) 7914 } 7915 7916 actual := strings.TrimSpace(state.String()) 7917 // Expect no changes from original state 7918 expected := strings.TrimSpace(` 7919 aws_instance.foo: 7920 ID = foo 7921 required_field = set 7922 type = aws_instance 7923 `) 7924 if actual != expected { 7925 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 7926 } 7927 } 7928 7929 // https://github.com/hashicorp/terraform/issues/7378 7930 func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) { 7931 m := testModule(t, "apply-destroy-nested-module-with-attrs") 7932 p := testProvider("null") 7933 p.ApplyFn = testApplyFn 7934 p.DiffFn = testDiffFn 7935 7936 var state *State 7937 var err error 7938 { 7939 ctx := testContext2(t, &ContextOpts{ 7940 Module: m, 7941 Providers: map[string]ResourceProviderFactory{ 7942 "null": testProviderFuncFixed(p), 7943 }, 7944 }) 7945 7946 // First plan and apply a create operation 7947 if _, err := ctx.Plan(); err != nil { 7948 t.Fatalf("plan err: %s", err) 7949 } 7950 7951 state, err = ctx.Apply() 7952 if err != nil { 7953 t.Fatalf("apply err: %s", err) 7954 } 7955 } 7956 7957 { 7958 ctx := testContext2(t, &ContextOpts{ 7959 Destroy: true, 7960 Module: m, 7961 State: state, 7962 Providers: map[string]ResourceProviderFactory{ 7963 "null": testProviderFuncFixed(p), 7964 }, 7965 }) 7966 7967 plan, err := ctx.Plan() 7968 if err != nil { 7969 t.Fatalf("destroy plan err: %s", err) 7970 } 7971 7972 var buf bytes.Buffer 7973 if err := WritePlan(plan, &buf); err != nil { 7974 t.Fatalf("plan write err: %s", err) 7975 } 7976 7977 planFromFile, err := ReadPlan(&buf) 7978 if err != nil { 7979 t.Fatalf("plan read err: %s", err) 7980 } 7981 7982 ctx, err = planFromFile.Context(&ContextOpts{ 7983 Providers: map[string]ResourceProviderFactory{ 7984 "null": testProviderFuncFixed(p), 7985 }, 7986 }) 7987 if err != nil { 7988 t.Fatalf("err: %s", err) 7989 } 7990 7991 state, err = ctx.Apply() 7992 if err != nil { 7993 t.Fatalf("destroy apply err: %s", err) 7994 } 7995 } 7996 7997 //Test that things were destroyed 7998 actual := strings.TrimSpace(state.String()) 7999 expected := strings.TrimSpace(` 8000 <no state> 8001 module.middle: 8002 <no state> 8003 module.middle.bottom: 8004 <no state> 8005 `) 8006 if actual != expected { 8007 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 8008 } 8009 } 8010 8011 // If a data source explicitly depends on another resource, it's because we need 8012 // that resource to be applied first. 8013 func TestContext2Apply_dataDependsOn(t *testing.T) { 8014 p := testProvider("null") 8015 m := testModule(t, "apply-data-depends-on") 8016 8017 ctx := testContext2(t, &ContextOpts{ 8018 Module: m, 8019 Providers: map[string]ResourceProviderFactory{ 8020 "null": testProviderFuncFixed(p), 8021 }, 8022 }) 8023 8024 // the "provisioner" here writes to this variable, because the intent is to 8025 // create a dependency which can't be viewed through the graph, and depends 8026 // solely on the configuration providing "depends_on" 8027 provisionerOutput := "" 8028 8029 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 8030 // the side effect of the resource being applied 8031 provisionerOutput = "APPLIED" 8032 return testApplyFn(info, s, d) 8033 } 8034 8035 p.DiffFn = testDiffFn 8036 p.ReadDataDiffFn = testDataDiffFn 8037 8038 p.ReadDataApplyFn = func(*InstanceInfo, *InstanceDiff) (*InstanceState, error) { 8039 // Read the artifact created by our dependency being applied. 8040 // Without any "depends_on", this would be skipped as it's assumed the 8041 // initial diff during refresh was all that's needed. 8042 return &InstanceState{ 8043 ID: "read", 8044 Attributes: map[string]string{ 8045 "foo": provisionerOutput, 8046 }, 8047 }, nil 8048 } 8049 8050 _, err := ctx.Refresh() 8051 if err != nil { 8052 t.Fatalf("err: %s", err) 8053 } 8054 8055 if _, err := ctx.Plan(); err != nil { 8056 t.Fatalf("err: %s", err) 8057 } 8058 8059 state, err := ctx.Apply() 8060 if err != nil { 8061 t.Fatalf("err: %s", err) 8062 } 8063 8064 root := state.ModuleByPath(RootModulePath) 8065 actual := root.Resources["data.null_data_source.read"].Primary.Attributes["foo"] 8066 8067 expected := "APPLIED" 8068 if actual != expected { 8069 t.Fatalf("bad:\n%s", strings.TrimSpace(state.String())) 8070 } 8071 }