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