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