github.com/sarguru/terraform@v0.6.17-0.20160525232901-8fcdfd7e3dc9/terraform/context_apply_test.go (about) 1 package terraform 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "reflect" 8 "sort" 9 "strings" 10 "sync" 11 "sync/atomic" 12 "testing" 13 "time" 14 15 "github.com/hashicorp/terraform/config/module" 16 ) 17 18 func TestContext2Apply(t *testing.T) { 19 m := testModule(t, "apply-good") 20 p := testProvider("aws") 21 p.ApplyFn = testApplyFn 22 p.DiffFn = testDiffFn 23 ctx := testContext2(t, &ContextOpts{ 24 Module: m, 25 Providers: map[string]ResourceProviderFactory{ 26 "aws": testProviderFuncFixed(p), 27 }, 28 }) 29 30 if _, err := ctx.Plan(); err != nil { 31 t.Fatalf("err: %s", err) 32 } 33 34 state, err := ctx.Apply() 35 if err != nil { 36 t.Fatalf("err: %s", err) 37 } 38 39 mod := state.RootModule() 40 if len(mod.Resources) < 2 { 41 t.Fatalf("bad: %#v", mod.Resources) 42 } 43 44 actual := strings.TrimSpace(state.String()) 45 expected := strings.TrimSpace(testTerraformApplyStr) 46 if actual != expected { 47 t.Fatalf("bad: \n%s", actual) 48 } 49 } 50 51 func TestContext2Apply_mapVarBetweenModules(t *testing.T) { 52 m := testModule(t, "apply-map-var-through-module") 53 p := testProvider("null") 54 p.ApplyFn = testApplyFn 55 p.DiffFn = testDiffFn 56 ctx := testContext2(t, &ContextOpts{ 57 Module: m, 58 Providers: map[string]ResourceProviderFactory{ 59 "null": testProviderFuncFixed(p), 60 }, 61 }) 62 63 if _, err := ctx.Plan(); err != nil { 64 t.Fatalf("err: %s", err) 65 } 66 67 state, err := ctx.Apply() 68 if err != nil { 69 t.Fatalf("err: %s", err) 70 } 71 72 actual := strings.TrimSpace(state.String()) 73 expected := strings.TrimSpace(`<no state> 74 Outputs: 75 76 amis_from_module = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 } 77 78 module.test: 79 null_resource.noop: 80 ID = foo 81 82 Outputs: 83 84 amis_out = {eu-west-1:ami-789012 eu-west-2:ami-989484 us-west-1:ami-123456 us-west-2:ami-456789 }`) 85 if actual != expected { 86 t.Fatalf("expected: \n%s\n\ngot: \n%s\n", expected, actual) 87 } 88 } 89 90 func TestContext2Apply_providerAlias(t *testing.T) { 91 m := testModule(t, "apply-provider-alias") 92 p := testProvider("aws") 93 p.ApplyFn = testApplyFn 94 p.DiffFn = testDiffFn 95 ctx := testContext2(t, &ContextOpts{ 96 Module: m, 97 Providers: map[string]ResourceProviderFactory{ 98 "aws": testProviderFuncFixed(p), 99 }, 100 }) 101 102 if _, err := ctx.Plan(); err != nil { 103 t.Fatalf("err: %s", err) 104 } 105 106 state, err := ctx.Apply() 107 if err != nil { 108 t.Fatalf("err: %s", err) 109 } 110 111 mod := state.RootModule() 112 if len(mod.Resources) < 2 { 113 t.Fatalf("bad: %#v", mod.Resources) 114 } 115 116 actual := strings.TrimSpace(state.String()) 117 expected := strings.TrimSpace(testTerraformApplyProviderAliasStr) 118 if actual != expected { 119 t.Fatalf("bad: \n%s", actual) 120 } 121 } 122 123 // GH-2870 124 func TestContext2Apply_providerWarning(t *testing.T) { 125 m := testModule(t, "apply-provider-warning") 126 p := testProvider("aws") 127 p.ApplyFn = testApplyFn 128 p.DiffFn = testDiffFn 129 p.ValidateFn = func(c *ResourceConfig) (ws []string, es []error) { 130 ws = append(ws, "Just a warning") 131 return 132 } 133 ctx := testContext2(t, &ContextOpts{ 134 Module: m, 135 Providers: map[string]ResourceProviderFactory{ 136 "aws": testProviderFuncFixed(p), 137 }, 138 }) 139 140 if _, err := ctx.Plan(); err != nil { 141 t.Fatalf("err: %s", err) 142 } 143 144 state, err := ctx.Apply() 145 if err != nil { 146 t.Fatalf("err: %s", err) 147 } 148 149 actual := strings.TrimSpace(state.String()) 150 expected := strings.TrimSpace(` 151 aws_instance.foo: 152 ID = foo 153 `) 154 if actual != expected { 155 t.Fatalf("got: \n%s\n\nexpected:\n%s", actual, expected) 156 } 157 158 if !p.ConfigureCalled { 159 t.Fatalf("provider Configure() was never called!") 160 } 161 } 162 163 func TestContext2Apply_emptyModule(t *testing.T) { 164 m := testModule(t, "apply-empty-module") 165 p := testProvider("aws") 166 p.ApplyFn = testApplyFn 167 p.DiffFn = testDiffFn 168 ctx := testContext2(t, &ContextOpts{ 169 Module: m, 170 Providers: map[string]ResourceProviderFactory{ 171 "aws": testProviderFuncFixed(p), 172 }, 173 }) 174 175 if _, err := ctx.Plan(); err != nil { 176 t.Fatalf("err: %s", err) 177 } 178 179 state, err := ctx.Apply() 180 if err != nil { 181 t.Fatalf("err: %s", err) 182 } 183 184 actual := strings.TrimSpace(state.String()) 185 actual = strings.Replace(actual, " ", "", -1) 186 expected := strings.TrimSpace(testTerraformApplyEmptyModuleStr) 187 if actual != expected { 188 t.Fatalf("bad: \n%s\nexpect:\n%s", actual, expected) 189 } 190 } 191 192 func TestContext2Apply_createBeforeDestroy(t *testing.T) { 193 m := testModule(t, "apply-good-create-before") 194 p := testProvider("aws") 195 p.ApplyFn = testApplyFn 196 p.DiffFn = testDiffFn 197 state := &State{ 198 Modules: []*ModuleState{ 199 &ModuleState{ 200 Path: rootModulePath, 201 Resources: map[string]*ResourceState{ 202 "aws_instance.bar": &ResourceState{ 203 Type: "aws_instance", 204 Primary: &InstanceState{ 205 ID: "bar", 206 Attributes: map[string]string{ 207 "require_new": "abc", 208 }, 209 }, 210 }, 211 }, 212 }, 213 }, 214 } 215 ctx := testContext2(t, &ContextOpts{ 216 Module: m, 217 Providers: map[string]ResourceProviderFactory{ 218 "aws": testProviderFuncFixed(p), 219 }, 220 State: state, 221 }) 222 223 if p, err := ctx.Plan(); err != nil { 224 t.Fatalf("err: %s", err) 225 } else { 226 t.Logf(p.String()) 227 } 228 229 state, err := ctx.Apply() 230 if err != nil { 231 t.Fatalf("err: %s", err) 232 } 233 234 mod := state.RootModule() 235 if len(mod.Resources) != 1 { 236 t.Fatalf("bad: %s", state) 237 } 238 239 actual := strings.TrimSpace(state.String()) 240 expected := strings.TrimSpace(testTerraformApplyCreateBeforeStr) 241 if actual != expected { 242 t.Fatalf("bad: \n%s", actual) 243 } 244 } 245 246 func TestContext2Apply_createBeforeDestroyUpdate(t *testing.T) { 247 m := testModule(t, "apply-good-create-before-update") 248 p := testProvider("aws") 249 p.ApplyFn = testApplyFn 250 p.DiffFn = testDiffFn 251 state := &State{ 252 Modules: []*ModuleState{ 253 &ModuleState{ 254 Path: rootModulePath, 255 Resources: map[string]*ResourceState{ 256 "aws_instance.bar": &ResourceState{ 257 Type: "aws_instance", 258 Primary: &InstanceState{ 259 ID: "bar", 260 Attributes: map[string]string{ 261 "foo": "bar", 262 }, 263 }, 264 }, 265 }, 266 }, 267 }, 268 } 269 ctx := testContext2(t, &ContextOpts{ 270 Module: m, 271 Providers: map[string]ResourceProviderFactory{ 272 "aws": testProviderFuncFixed(p), 273 }, 274 State: state, 275 }) 276 277 if p, err := ctx.Plan(); err != nil { 278 t.Fatalf("err: %s", err) 279 } else { 280 t.Logf(p.String()) 281 } 282 283 state, err := ctx.Apply() 284 if err != nil { 285 t.Fatalf("err: %s", err) 286 } 287 288 mod := state.RootModule() 289 if len(mod.Resources) != 1 { 290 t.Fatalf("bad: %s", state) 291 } 292 293 actual := strings.TrimSpace(state.String()) 294 expected := strings.TrimSpace(testTerraformApplyCreateBeforeUpdateStr) 295 if actual != expected { 296 t.Fatalf("bad: \n%s", actual) 297 } 298 } 299 300 func TestContext2Apply_destroyComputed(t *testing.T) { 301 m := testModule(t, "apply-destroy-computed") 302 p := testProvider("aws") 303 p.ApplyFn = testApplyFn 304 p.DiffFn = testDiffFn 305 state := &State{ 306 Modules: []*ModuleState{ 307 &ModuleState{ 308 Path: rootModulePath, 309 Resources: map[string]*ResourceState{ 310 "aws_instance.foo": &ResourceState{ 311 Type: "aws_instance", 312 Primary: &InstanceState{ 313 ID: "foo", 314 Attributes: map[string]string{ 315 "output": "value", 316 }, 317 }, 318 }, 319 }, 320 }, 321 }, 322 } 323 ctx := testContext2(t, &ContextOpts{ 324 Module: m, 325 Providers: map[string]ResourceProviderFactory{ 326 "aws": testProviderFuncFixed(p), 327 }, 328 State: state, 329 Destroy: true, 330 }) 331 332 if p, err := ctx.Plan(); err != nil { 333 t.Fatalf("err: %s", err) 334 } else { 335 t.Logf(p.String()) 336 } 337 338 if _, err := ctx.Apply(); err != nil { 339 t.Fatalf("err: %s", err) 340 } 341 } 342 343 func TestContext2Apply_destroyData(t *testing.T) { 344 m := testModule(t, "apply-destroy-data-resource") 345 p := testProvider("null") 346 p.ApplyFn = testApplyFn 347 p.DiffFn = testDiffFn 348 state := &State{ 349 Modules: []*ModuleState{ 350 &ModuleState{ 351 Path: rootModulePath, 352 Resources: map[string]*ResourceState{ 353 "data.null_data_source.testing": &ResourceState{ 354 Type: "aws_instance", 355 Primary: &InstanceState{ 356 ID: "-", 357 Attributes: map[string]string{ 358 "inputs.#": "1", 359 "inputs.test": "yes", 360 }, 361 }, 362 }, 363 }, 364 }, 365 }, 366 } 367 ctx := testContext2(t, &ContextOpts{ 368 Module: m, 369 Providers: map[string]ResourceProviderFactory{ 370 "null": testProviderFuncFixed(p), 371 }, 372 State: state, 373 Destroy: true, 374 }) 375 376 if p, err := ctx.Plan(); err != nil { 377 t.Fatalf("err: %s", err) 378 } else { 379 t.Logf(p.String()) 380 } 381 382 newState, err := ctx.Apply() 383 if err != nil { 384 t.Fatalf("err: %s", err) 385 } 386 387 if got := len(newState.Modules); got != 1 { 388 t.Fatalf("state has %d modules after destroy; want 1", got) 389 } 390 391 if got := len(newState.Modules[0].Resources); got != 0 { 392 t.Fatalf("state has %d resources after destroy; want 0", got) 393 } 394 } 395 396 // https://github.com/hashicorp/terraform/pull/5096 397 func TestContext2Apply_destroySkipsCBD(t *testing.T) { 398 // Config contains CBD resource depending on non-CBD resource, which triggers 399 // a cycle if they are both replaced, but should _not_ trigger a cycle when 400 // just doing a `terraform destroy`. 401 m := testModule(t, "apply-destroy-cbd") 402 p := testProvider("aws") 403 p.ApplyFn = testApplyFn 404 p.DiffFn = testDiffFn 405 state := &State{ 406 Modules: []*ModuleState{ 407 &ModuleState{ 408 Path: rootModulePath, 409 Resources: map[string]*ResourceState{ 410 "aws_instance.foo": &ResourceState{ 411 Type: "aws_instance", 412 Primary: &InstanceState{ 413 ID: "foo", 414 }, 415 }, 416 "aws_instance.bar": &ResourceState{ 417 Type: "aws_instance", 418 Primary: &InstanceState{ 419 ID: "foo", 420 }, 421 }, 422 }, 423 }, 424 }, 425 } 426 ctx := testContext2(t, &ContextOpts{ 427 Module: m, 428 Providers: map[string]ResourceProviderFactory{ 429 "aws": testProviderFuncFixed(p), 430 }, 431 State: state, 432 Destroy: true, 433 }) 434 435 if p, err := ctx.Plan(); err != nil { 436 t.Fatalf("err: %s", err) 437 } else { 438 t.Logf(p.String()) 439 } 440 441 if _, err := ctx.Apply(); err != nil { 442 t.Fatalf("err: %s", err) 443 } 444 } 445 446 // https://github.com/hashicorp/terraform/issues/2892 447 func TestContext2Apply_destroyCrossProviders(t *testing.T) { 448 m := testModule(t, "apply-destroy-cross-providers") 449 450 p_aws := testProvider("aws") 451 p_aws.ApplyFn = testApplyFn 452 p_aws.DiffFn = testDiffFn 453 454 p_tf := testProvider("terraform") 455 p_tf.ApplyFn = testApplyFn 456 p_tf.DiffFn = testDiffFn 457 458 providers := map[string]ResourceProviderFactory{ 459 "aws": testProviderFuncFixed(p_aws), 460 "terraform": testProviderFuncFixed(p_tf), 461 } 462 463 // Bug only appears from time to time, 464 // so we run this test multiple times 465 // to check for the race-condition 466 for i := 0; i <= 10; i++ { 467 ctx := getContextForApply_destroyCrossProviders( 468 t, m, providers) 469 470 if p, err := ctx.Plan(); err != nil { 471 t.Fatalf("err: %s", err) 472 } else { 473 t.Logf(p.String()) 474 } 475 476 if _, err := ctx.Apply(); err != nil { 477 t.Fatalf("err: %s", err) 478 } 479 } 480 } 481 482 func getContextForApply_destroyCrossProviders( 483 t *testing.T, 484 m *module.Tree, 485 providers map[string]ResourceProviderFactory) *Context { 486 state := &State{ 487 Modules: []*ModuleState{ 488 &ModuleState{ 489 Path: rootModulePath, 490 Resources: map[string]*ResourceState{ 491 "terraform_remote_state.shared": &ResourceState{ 492 Type: "terraform_remote_state", 493 Primary: &InstanceState{ 494 ID: "remote-2652591293", 495 Attributes: map[string]string{ 496 "output.env_name": "test", 497 }, 498 }, 499 }, 500 }, 501 }, 502 &ModuleState{ 503 Path: []string{"root", "example"}, 504 Resources: map[string]*ResourceState{ 505 "aws_vpc.bar": &ResourceState{ 506 Type: "aws_vpc", 507 Primary: &InstanceState{ 508 ID: "vpc-aaabbb12", 509 Attributes: map[string]string{ 510 "value": "test", 511 }, 512 }, 513 }, 514 }, 515 }, 516 }, 517 } 518 ctx := testContext2(t, &ContextOpts{ 519 Module: m, 520 Providers: providers, 521 State: state, 522 Destroy: true, 523 }) 524 525 return ctx 526 } 527 528 func TestContext2Apply_minimal(t *testing.T) { 529 m := testModule(t, "apply-minimal") 530 p := testProvider("aws") 531 p.ApplyFn = testApplyFn 532 p.DiffFn = testDiffFn 533 ctx := testContext2(t, &ContextOpts{ 534 Module: m, 535 Providers: map[string]ResourceProviderFactory{ 536 "aws": testProviderFuncFixed(p), 537 }, 538 }) 539 540 if _, err := ctx.Plan(); err != nil { 541 t.Fatalf("err: %s", err) 542 } 543 544 state, err := ctx.Apply() 545 if err != nil { 546 t.Fatalf("err: %s", err) 547 } 548 549 actual := strings.TrimSpace(state.String()) 550 expected := strings.TrimSpace(testTerraformApplyMinimalStr) 551 if actual != expected { 552 t.Fatalf("bad: \n%s", actual) 553 } 554 } 555 556 func TestContext2Apply_badDiff(t *testing.T) { 557 m := testModule(t, "apply-good") 558 p := testProvider("aws") 559 p.ApplyFn = testApplyFn 560 p.DiffFn = testDiffFn 561 ctx := testContext2(t, &ContextOpts{ 562 Module: m, 563 Providers: map[string]ResourceProviderFactory{ 564 "aws": testProviderFuncFixed(p), 565 }, 566 }) 567 568 if _, err := ctx.Plan(); err != nil { 569 t.Fatalf("err: %s", err) 570 } 571 572 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 573 return &InstanceDiff{ 574 Attributes: map[string]*ResourceAttrDiff{ 575 "newp": nil, 576 }, 577 }, nil 578 } 579 580 if _, err := ctx.Apply(); err == nil { 581 t.Fatal("should error") 582 } 583 } 584 585 func TestContext2Apply_cancel(t *testing.T) { 586 stopped := false 587 588 m := testModule(t, "apply-cancel") 589 p := testProvider("aws") 590 ctx := testContext2(t, &ContextOpts{ 591 Module: m, 592 Providers: map[string]ResourceProviderFactory{ 593 "aws": testProviderFuncFixed(p), 594 }, 595 }) 596 597 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 598 if !stopped { 599 stopped = true 600 go ctx.Stop() 601 602 for { 603 if ctx.sh.Stopped() { 604 break 605 } 606 } 607 } 608 609 return &InstanceState{ 610 ID: "foo", 611 Attributes: map[string]string{ 612 "num": "2", 613 }, 614 }, nil 615 } 616 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 617 return &InstanceDiff{ 618 Attributes: map[string]*ResourceAttrDiff{ 619 "num": &ResourceAttrDiff{ 620 New: "bar", 621 }, 622 }, 623 }, nil 624 } 625 626 if _, err := ctx.Plan(); err != nil { 627 t.Fatalf("err: %s", err) 628 } 629 630 // Start the Apply in a goroutine 631 stateCh := make(chan *State) 632 go func() { 633 state, err := ctx.Apply() 634 if err != nil { 635 panic(err) 636 } 637 638 stateCh <- state 639 }() 640 641 state := <-stateCh 642 643 mod := state.RootModule() 644 if len(mod.Resources) != 1 { 645 t.Fatalf("bad: %s", state.String()) 646 } 647 648 actual := strings.TrimSpace(state.String()) 649 expected := strings.TrimSpace(testTerraformApplyCancelStr) 650 if actual != expected { 651 t.Fatalf("bad: \n%s", actual) 652 } 653 } 654 655 func TestContext2Apply_compute(t *testing.T) { 656 m := testModule(t, "apply-compute") 657 p := testProvider("aws") 658 p.ApplyFn = testApplyFn 659 p.DiffFn = testDiffFn 660 ctx := testContext2(t, &ContextOpts{ 661 Module: m, 662 Providers: map[string]ResourceProviderFactory{ 663 "aws": testProviderFuncFixed(p), 664 }, 665 }) 666 667 if _, err := ctx.Plan(); err != nil { 668 t.Fatalf("err: %s", err) 669 } 670 671 ctx.variables = map[string]string{"value": "1"} 672 673 state, err := ctx.Apply() 674 if err != nil { 675 t.Fatalf("err: %s", err) 676 } 677 678 actual := strings.TrimSpace(state.String()) 679 expected := strings.TrimSpace(testTerraformApplyComputeStr) 680 if actual != expected { 681 t.Fatalf("bad: \n%s", actual) 682 } 683 } 684 685 func TestContext2Apply_countDecrease(t *testing.T) { 686 m := testModule(t, "apply-count-dec") 687 p := testProvider("aws") 688 p.DiffFn = testDiffFn 689 s := &State{ 690 Modules: []*ModuleState{ 691 &ModuleState{ 692 Path: rootModulePath, 693 Resources: map[string]*ResourceState{ 694 "aws_instance.foo.0": &ResourceState{ 695 Type: "aws_instance", 696 Primary: &InstanceState{ 697 ID: "bar", 698 Attributes: map[string]string{ 699 "foo": "foo", 700 "type": "aws_instance", 701 }, 702 }, 703 }, 704 "aws_instance.foo.1": &ResourceState{ 705 Type: "aws_instance", 706 Primary: &InstanceState{ 707 ID: "bar", 708 Attributes: map[string]string{ 709 "foo": "foo", 710 "type": "aws_instance", 711 }, 712 }, 713 }, 714 "aws_instance.foo.2": &ResourceState{ 715 Type: "aws_instance", 716 Primary: &InstanceState{ 717 ID: "bar", 718 Attributes: map[string]string{ 719 "foo": "foo", 720 "type": "aws_instance", 721 }, 722 }, 723 }, 724 }, 725 }, 726 }, 727 } 728 ctx := testContext2(t, &ContextOpts{ 729 Module: m, 730 Providers: map[string]ResourceProviderFactory{ 731 "aws": testProviderFuncFixed(p), 732 }, 733 State: s, 734 }) 735 736 if _, err := ctx.Plan(); err != nil { 737 t.Fatalf("err: %s", err) 738 } 739 740 state, err := ctx.Apply() 741 if err != nil { 742 t.Fatalf("err: %s", err) 743 } 744 745 actual := strings.TrimSpace(state.String()) 746 expected := strings.TrimSpace(testTerraformApplyCountDecStr) 747 if actual != expected { 748 t.Fatalf("bad: \n%s", actual) 749 } 750 } 751 752 func TestContext2Apply_countDecreaseToOne(t *testing.T) { 753 m := testModule(t, "apply-count-dec-one") 754 p := testProvider("aws") 755 p.ApplyFn = testApplyFn 756 p.DiffFn = testDiffFn 757 s := &State{ 758 Modules: []*ModuleState{ 759 &ModuleState{ 760 Path: rootModulePath, 761 Resources: map[string]*ResourceState{ 762 "aws_instance.foo.0": &ResourceState{ 763 Type: "aws_instance", 764 Primary: &InstanceState{ 765 ID: "bar", 766 Attributes: map[string]string{ 767 "foo": "foo", 768 "type": "aws_instance", 769 }, 770 }, 771 }, 772 "aws_instance.foo.1": &ResourceState{ 773 Type: "aws_instance", 774 Primary: &InstanceState{ 775 ID: "bar", 776 }, 777 }, 778 "aws_instance.foo.2": &ResourceState{ 779 Type: "aws_instance", 780 Primary: &InstanceState{ 781 ID: "bar", 782 }, 783 }, 784 }, 785 }, 786 }, 787 } 788 ctx := testContext2(t, &ContextOpts{ 789 Module: m, 790 Providers: map[string]ResourceProviderFactory{ 791 "aws": testProviderFuncFixed(p), 792 }, 793 State: s, 794 }) 795 796 if _, err := ctx.Plan(); err != nil { 797 t.Fatalf("err: %s", err) 798 } 799 800 state, err := ctx.Apply() 801 if err != nil { 802 t.Fatalf("err: %s", err) 803 } 804 805 actual := strings.TrimSpace(state.String()) 806 expected := strings.TrimSpace(testTerraformApplyCountDecToOneStr) 807 if actual != expected { 808 t.Fatalf("bad: \n%s", actual) 809 } 810 } 811 812 // https://github.com/PeoplePerHour/terraform/pull/11 813 // 814 // This tests a case where both a "resource" and "resource.0" are in 815 // the state file, which apparently is a reasonable backwards compatibility 816 // concern found in the above 3rd party repo. 817 func TestContext2Apply_countDecreaseToOneCorrupted(t *testing.T) { 818 m := testModule(t, "apply-count-dec-one") 819 p := testProvider("aws") 820 p.ApplyFn = testApplyFn 821 p.DiffFn = testDiffFn 822 s := &State{ 823 Modules: []*ModuleState{ 824 &ModuleState{ 825 Path: rootModulePath, 826 Resources: map[string]*ResourceState{ 827 "aws_instance.foo": &ResourceState{ 828 Type: "aws_instance", 829 Primary: &InstanceState{ 830 ID: "bar", 831 Attributes: map[string]string{ 832 "foo": "foo", 833 "type": "aws_instance", 834 }, 835 }, 836 }, 837 "aws_instance.foo.0": &ResourceState{ 838 Type: "aws_instance", 839 Primary: &InstanceState{ 840 ID: "baz", 841 Attributes: map[string]string{ 842 "type": "aws_instance", 843 }, 844 }, 845 }, 846 }, 847 }, 848 }, 849 } 850 ctx := testContext2(t, &ContextOpts{ 851 Module: m, 852 Providers: map[string]ResourceProviderFactory{ 853 "aws": testProviderFuncFixed(p), 854 }, 855 State: s, 856 }) 857 858 if p, err := ctx.Plan(); err != nil { 859 t.Fatalf("err: %s", err) 860 } else { 861 testStringMatch(t, p, testTerraformApplyCountDecToOneCorruptedPlanStr) 862 } 863 864 state, err := ctx.Apply() 865 if err != nil { 866 t.Fatalf("err: %s", err) 867 } 868 869 actual := strings.TrimSpace(state.String()) 870 expected := strings.TrimSpace(testTerraformApplyCountDecToOneCorruptedStr) 871 if actual != expected { 872 t.Fatalf("bad: \n%s", actual) 873 } 874 } 875 876 func TestContext2Apply_countTainted(t *testing.T) { 877 m := testModule(t, "apply-count-tainted") 878 p := testProvider("aws") 879 p.DiffFn = testDiffFn 880 s := &State{ 881 Modules: []*ModuleState{ 882 &ModuleState{ 883 Path: rootModulePath, 884 Resources: map[string]*ResourceState{ 885 "aws_instance.foo.0": &ResourceState{ 886 Type: "aws_instance", 887 Tainted: []*InstanceState{ 888 &InstanceState{ 889 ID: "bar", 890 Attributes: map[string]string{ 891 "foo": "foo", 892 "type": "aws_instance", 893 }, 894 }, 895 }, 896 }, 897 }, 898 }, 899 }, 900 } 901 ctx := testContext2(t, &ContextOpts{ 902 Module: m, 903 Providers: map[string]ResourceProviderFactory{ 904 "aws": testProviderFuncFixed(p), 905 }, 906 State: s, 907 }) 908 909 if _, err := ctx.Plan(); err != nil { 910 t.Fatalf("err: %s", err) 911 } 912 913 state, err := ctx.Apply() 914 if err != nil { 915 t.Fatalf("err: %s", err) 916 } 917 918 actual := strings.TrimSpace(state.String()) 919 expected := strings.TrimSpace(testTerraformApplyCountTaintedStr) 920 if actual != expected { 921 t.Fatalf("bad: \n%s", actual) 922 } 923 } 924 925 func TestContext2Apply_countVariable(t *testing.T) { 926 m := testModule(t, "apply-count-variable") 927 p := testProvider("aws") 928 p.ApplyFn = testApplyFn 929 p.DiffFn = testDiffFn 930 ctx := testContext2(t, &ContextOpts{ 931 Module: m, 932 Providers: map[string]ResourceProviderFactory{ 933 "aws": testProviderFuncFixed(p), 934 }, 935 }) 936 937 if _, err := ctx.Plan(); err != nil { 938 t.Fatalf("err: %s", err) 939 } 940 941 state, err := ctx.Apply() 942 if err != nil { 943 t.Fatalf("err: %s", err) 944 } 945 946 actual := strings.TrimSpace(state.String()) 947 expected := strings.TrimSpace(testTerraformApplyCountVariableStr) 948 if actual != expected { 949 t.Fatalf("bad: \n%s", actual) 950 } 951 } 952 953 func TestContext2Apply_mapVariableOverride(t *testing.T) { 954 m := testModule(t, "apply-map-var-override") 955 p := testProvider("aws") 956 p.ApplyFn = testApplyFn 957 p.DiffFn = testDiffFn 958 ctx := testContext2(t, &ContextOpts{ 959 Module: m, 960 Providers: map[string]ResourceProviderFactory{ 961 "aws": testProviderFuncFixed(p), 962 }, 963 Variables: map[string]string{ 964 "images.us-west-2": "overridden", 965 }, 966 }) 967 968 if _, err := ctx.Plan(); err != nil { 969 t.Fatalf("err: %s", err) 970 } 971 972 state, err := ctx.Apply() 973 if err != nil { 974 t.Fatalf("err: %s", err) 975 } 976 977 actual := strings.TrimSpace(state.String()) 978 expected := strings.TrimSpace(` 979 aws_instance.bar: 980 ID = foo 981 ami = overridden 982 type = aws_instance 983 aws_instance.foo: 984 ID = foo 985 ami = image-1234 986 type = aws_instance 987 `) 988 if actual != expected { 989 t.Fatalf("got: \n%s\nexpected: \n%s", actual, expected) 990 } 991 } 992 993 func TestContext2Apply_module(t *testing.T) { 994 m := testModule(t, "apply-module") 995 p := testProvider("aws") 996 p.ApplyFn = testApplyFn 997 p.DiffFn = testDiffFn 998 ctx := testContext2(t, &ContextOpts{ 999 Module: m, 1000 Providers: map[string]ResourceProviderFactory{ 1001 "aws": testProviderFuncFixed(p), 1002 }, 1003 }) 1004 1005 if _, err := ctx.Plan(); err != nil { 1006 t.Fatalf("err: %s", err) 1007 } 1008 1009 state, err := ctx.Apply() 1010 if err != nil { 1011 t.Fatalf("err: %s", err) 1012 } 1013 1014 actual := strings.TrimSpace(state.String()) 1015 expected := strings.TrimSpace(testTerraformApplyModuleStr) 1016 if actual != expected { 1017 t.Fatalf("bad: \n%s", actual) 1018 } 1019 } 1020 1021 func TestContext2Apply_moduleDestroyOrder(t *testing.T) { 1022 m := testModule(t, "apply-module-destroy-order") 1023 p := testProvider("aws") 1024 p.DiffFn = testDiffFn 1025 1026 // Create a custom apply function to track the order they were destroyed 1027 var order []string 1028 var orderLock sync.Mutex 1029 p.ApplyFn = func( 1030 info *InstanceInfo, 1031 is *InstanceState, 1032 id *InstanceDiff) (*InstanceState, error) { 1033 orderLock.Lock() 1034 defer orderLock.Unlock() 1035 1036 order = append(order, is.ID) 1037 return nil, nil 1038 } 1039 1040 state := &State{ 1041 Modules: []*ModuleState{ 1042 &ModuleState{ 1043 Path: rootModulePath, 1044 Resources: map[string]*ResourceState{ 1045 "aws_instance.b": &ResourceState{ 1046 Type: "aws_instance", 1047 Primary: &InstanceState{ 1048 ID: "b", 1049 }, 1050 }, 1051 }, 1052 }, 1053 1054 &ModuleState{ 1055 Path: []string{"root", "child"}, 1056 Resources: map[string]*ResourceState{ 1057 "aws_instance.a": &ResourceState{ 1058 Type: "aws_instance", 1059 Primary: &InstanceState{ 1060 ID: "a", 1061 }, 1062 }, 1063 }, 1064 Outputs: map[string]*OutputState{ 1065 "a_output": &OutputState{ 1066 Type: "string", 1067 Sensitive: false, 1068 Value: "a", 1069 }, 1070 }, 1071 }, 1072 }, 1073 } 1074 1075 ctx := testContext2(t, &ContextOpts{ 1076 Module: m, 1077 Providers: map[string]ResourceProviderFactory{ 1078 "aws": testProviderFuncFixed(p), 1079 }, 1080 State: state, 1081 Destroy: true, 1082 }) 1083 1084 if _, err := ctx.Plan(); err != nil { 1085 t.Fatalf("err: %s", err) 1086 } 1087 1088 state, err := ctx.Apply() 1089 if err != nil { 1090 t.Fatalf("err: %s", err) 1091 } 1092 1093 expected := []string{"b", "a"} 1094 if !reflect.DeepEqual(order, expected) { 1095 t.Fatalf("bad: %#v", order) 1096 } 1097 1098 { 1099 actual := strings.TrimSpace(state.String()) 1100 expected := strings.TrimSpace(testTerraformApplyModuleDestroyOrderStr) 1101 if actual != expected { 1102 t.Fatalf("bad: \n%s", actual) 1103 } 1104 } 1105 } 1106 1107 func TestContext2Apply_moduleOrphanProvider(t *testing.T) { 1108 m := testModule(t, "apply-module-orphan-provider-inherit") 1109 p := testProvider("aws") 1110 p.ApplyFn = testApplyFn 1111 p.DiffFn = testDiffFn 1112 1113 p.ConfigureFn = func(c *ResourceConfig) error { 1114 if _, ok := c.Get("value"); !ok { 1115 return fmt.Errorf("value is not found") 1116 } 1117 1118 return nil 1119 } 1120 1121 // Create a state with an orphan module 1122 state := &State{ 1123 Modules: []*ModuleState{ 1124 &ModuleState{ 1125 Path: []string{"root", "child"}, 1126 Resources: map[string]*ResourceState{ 1127 "aws_instance.bar": &ResourceState{ 1128 Type: "aws_instance", 1129 Primary: &InstanceState{ 1130 ID: "bar", 1131 }, 1132 }, 1133 }, 1134 }, 1135 }, 1136 } 1137 1138 ctx := testContext2(t, &ContextOpts{ 1139 Module: m, 1140 State: state, 1141 Providers: map[string]ResourceProviderFactory{ 1142 "aws": testProviderFuncFixed(p), 1143 }, 1144 }) 1145 1146 if _, err := ctx.Plan(); err != nil { 1147 t.Fatalf("err: %s", err) 1148 } 1149 1150 if _, err := ctx.Apply(); err != nil { 1151 t.Fatalf("err: %s", err) 1152 } 1153 } 1154 1155 func TestContext2Apply_moduleGrandchildProvider(t *testing.T) { 1156 m := testModule(t, "apply-module-grandchild-provider-inherit") 1157 p := testProvider("aws") 1158 p.ApplyFn = testApplyFn 1159 p.DiffFn = testDiffFn 1160 1161 var callLock sync.Mutex 1162 called := false 1163 p.ConfigureFn = func(c *ResourceConfig) error { 1164 if _, ok := c.Get("value"); !ok { 1165 return fmt.Errorf("value is not found") 1166 } 1167 callLock.Lock() 1168 called = true 1169 callLock.Unlock() 1170 1171 return nil 1172 } 1173 1174 ctx := testContext2(t, &ContextOpts{ 1175 Module: m, 1176 Providers: map[string]ResourceProviderFactory{ 1177 "aws": testProviderFuncFixed(p), 1178 }, 1179 }) 1180 1181 if _, err := ctx.Plan(); err != nil { 1182 t.Fatalf("err: %s", err) 1183 } 1184 1185 if _, err := ctx.Apply(); err != nil { 1186 t.Fatalf("err: %s", err) 1187 } 1188 1189 callLock.Lock() 1190 defer callLock.Unlock() 1191 if called != true { 1192 t.Fatalf("err: configure never called") 1193 } 1194 } 1195 1196 // This tests an issue where all the providers in a module but not 1197 // in the root weren't being added to the root properly. In this test 1198 // case: aws is explicitly added to root, but "test" should be added to. 1199 // With the bug, it wasn't. 1200 func TestContext2Apply_moduleOnlyProvider(t *testing.T) { 1201 m := testModule(t, "apply-module-only-provider") 1202 p := testProvider("aws") 1203 p.ApplyFn = testApplyFn 1204 p.DiffFn = testDiffFn 1205 pTest := testProvider("test") 1206 pTest.ApplyFn = testApplyFn 1207 pTest.DiffFn = testDiffFn 1208 1209 ctx := testContext2(t, &ContextOpts{ 1210 Module: m, 1211 Providers: map[string]ResourceProviderFactory{ 1212 "aws": testProviderFuncFixed(p), 1213 "test": testProviderFuncFixed(pTest), 1214 }, 1215 }) 1216 1217 if _, err := ctx.Plan(); err != nil { 1218 t.Fatalf("err: %s", err) 1219 } 1220 1221 state, err := ctx.Apply() 1222 if err != nil { 1223 t.Fatalf("err: %s", err) 1224 } 1225 1226 actual := strings.TrimSpace(state.String()) 1227 expected := strings.TrimSpace(testTerraformApplyModuleOnlyProviderStr) 1228 if actual != expected { 1229 t.Fatalf("bad: \n%s", actual) 1230 } 1231 } 1232 1233 func TestContext2Apply_moduleProviderAlias(t *testing.T) { 1234 m := testModule(t, "apply-module-provider-alias") 1235 p := testProvider("aws") 1236 p.ApplyFn = testApplyFn 1237 p.DiffFn = testDiffFn 1238 ctx := testContext2(t, &ContextOpts{ 1239 Module: m, 1240 Providers: map[string]ResourceProviderFactory{ 1241 "aws": testProviderFuncFixed(p), 1242 }, 1243 }) 1244 1245 if _, err := ctx.Plan(); err != nil { 1246 t.Fatalf("err: %s", err) 1247 } 1248 1249 state, err := ctx.Apply() 1250 if err != nil { 1251 t.Fatalf("err: %s", err) 1252 } 1253 1254 actual := strings.TrimSpace(state.String()) 1255 expected := strings.TrimSpace(testTerraformApplyModuleProviderAliasStr) 1256 if actual != expected { 1257 t.Fatalf("bad: \n%s", actual) 1258 } 1259 } 1260 1261 func TestContext2Apply_moduleProviderAliasTargets(t *testing.T) { 1262 m := testModule(t, "apply-module-provider-alias") 1263 p := testProvider("aws") 1264 p.ApplyFn = testApplyFn 1265 p.DiffFn = testDiffFn 1266 ctx := testContext2(t, &ContextOpts{ 1267 Module: m, 1268 Providers: map[string]ResourceProviderFactory{ 1269 "aws": testProviderFuncFixed(p), 1270 }, 1271 Targets: []string{"no.thing"}, 1272 }) 1273 1274 if _, err := ctx.Plan(); err != nil { 1275 t.Fatalf("err: %s", err) 1276 } 1277 1278 state, err := ctx.Apply() 1279 if err != nil { 1280 t.Fatalf("err: %s", err) 1281 } 1282 1283 actual := strings.TrimSpace(state.String()) 1284 expected := strings.TrimSpace(` 1285 <no state> 1286 `) 1287 if actual != expected { 1288 t.Fatalf("bad: \n%s", actual) 1289 } 1290 } 1291 1292 func TestContext2Apply_moduleProviderCloseNested(t *testing.T) { 1293 m := testModule(t, "apply-module-provider-close-nested") 1294 p := testProvider("aws") 1295 p.ApplyFn = testApplyFn 1296 p.DiffFn = testDiffFn 1297 ctx := testContext2(t, &ContextOpts{ 1298 Module: m, 1299 Providers: map[string]ResourceProviderFactory{ 1300 "aws": testProviderFuncFixed(p), 1301 }, 1302 State: &State{ 1303 Modules: []*ModuleState{ 1304 &ModuleState{ 1305 Path: []string{"root", "child", "subchild"}, 1306 Resources: map[string]*ResourceState{ 1307 "aws_instance.foo": &ResourceState{ 1308 Type: "aws_instance", 1309 Primary: &InstanceState{ 1310 ID: "bar", 1311 }, 1312 }, 1313 }, 1314 }, 1315 }, 1316 }, 1317 Destroy: true, 1318 }) 1319 1320 if _, err := ctx.Plan(); err != nil { 1321 t.Fatalf("err: %s", err) 1322 } 1323 1324 if _, err := ctx.Apply(); err != nil { 1325 t.Fatalf("err: %s", err) 1326 } 1327 } 1328 1329 func TestContext2Apply_moduleVarResourceCount(t *testing.T) { 1330 m := testModule(t, "apply-module-var-resource-count") 1331 p := testProvider("aws") 1332 p.ApplyFn = testApplyFn 1333 p.DiffFn = testDiffFn 1334 ctx := testContext2(t, &ContextOpts{ 1335 Module: m, 1336 Providers: map[string]ResourceProviderFactory{ 1337 "aws": testProviderFuncFixed(p), 1338 }, 1339 Variables: map[string]string{ 1340 "count": "2", 1341 }, 1342 Destroy: true, 1343 }) 1344 1345 if _, err := ctx.Plan(); err != nil { 1346 t.Fatalf("err: %s", err) 1347 } 1348 1349 if _, err := ctx.Apply(); err != nil { 1350 t.Fatalf("err: %s", err) 1351 } 1352 1353 ctx = testContext2(t, &ContextOpts{ 1354 Module: m, 1355 Providers: map[string]ResourceProviderFactory{ 1356 "aws": testProviderFuncFixed(p), 1357 }, 1358 Variables: map[string]string{ 1359 "count": "5", 1360 }, 1361 }) 1362 1363 if _, err := ctx.Plan(); err != nil { 1364 t.Fatalf("err: %s", err) 1365 } 1366 1367 if _, err := ctx.Apply(); err != nil { 1368 t.Fatalf("err: %s", err) 1369 } 1370 } 1371 1372 // GH-819 1373 func TestContext2Apply_moduleBool(t *testing.T) { 1374 m := testModule(t, "apply-module-bool") 1375 p := testProvider("aws") 1376 p.ApplyFn = testApplyFn 1377 p.DiffFn = testDiffFn 1378 ctx := testContext2(t, &ContextOpts{ 1379 Module: m, 1380 Providers: map[string]ResourceProviderFactory{ 1381 "aws": testProviderFuncFixed(p), 1382 }, 1383 }) 1384 1385 if _, err := ctx.Plan(); err != nil { 1386 t.Fatalf("err: %s", err) 1387 } 1388 1389 state, err := ctx.Apply() 1390 if err != nil { 1391 t.Fatalf("err: %s", err) 1392 } 1393 1394 actual := strings.TrimSpace(state.String()) 1395 expected := strings.TrimSpace(testTerraformApplyModuleBoolStr) 1396 if actual != expected { 1397 t.Fatalf("bad: \n%s", actual) 1398 } 1399 } 1400 1401 func TestContext2Apply_multiProvider(t *testing.T) { 1402 m := testModule(t, "apply-multi-provider") 1403 p := testProvider("aws") 1404 p.ApplyFn = testApplyFn 1405 p.DiffFn = testDiffFn 1406 1407 pDO := testProvider("do") 1408 pDO.ApplyFn = testApplyFn 1409 pDO.DiffFn = testDiffFn 1410 1411 ctx := testContext2(t, &ContextOpts{ 1412 Module: m, 1413 Providers: map[string]ResourceProviderFactory{ 1414 "aws": testProviderFuncFixed(p), 1415 "do": testProviderFuncFixed(pDO), 1416 }, 1417 }) 1418 1419 if _, err := ctx.Plan(); err != nil { 1420 t.Fatalf("err: %s", err) 1421 } 1422 1423 state, err := ctx.Apply() 1424 if err != nil { 1425 t.Fatalf("err: %s", err) 1426 } 1427 1428 mod := state.RootModule() 1429 if len(mod.Resources) < 2 { 1430 t.Fatalf("bad: %#v", mod.Resources) 1431 } 1432 1433 actual := strings.TrimSpace(state.String()) 1434 expected := strings.TrimSpace(testTerraformApplyMultiProviderStr) 1435 if actual != expected { 1436 t.Fatalf("bad: \n%s", actual) 1437 } 1438 } 1439 1440 func TestContext2Apply_multiVar(t *testing.T) { 1441 m := testModule(t, "apply-multi-var") 1442 p := testProvider("aws") 1443 p.ApplyFn = testApplyFn 1444 p.DiffFn = testDiffFn 1445 1446 // First, apply with a count of 3 1447 ctx := testContext2(t, &ContextOpts{ 1448 Module: m, 1449 Providers: map[string]ResourceProviderFactory{ 1450 "aws": testProviderFuncFixed(p), 1451 }, 1452 Variables: map[string]string{ 1453 "count": "3", 1454 }, 1455 }) 1456 1457 if _, err := ctx.Plan(); err != nil { 1458 t.Fatalf("err: %s", err) 1459 } 1460 1461 state, err := ctx.Apply() 1462 if err != nil { 1463 t.Fatalf("err: %s", err) 1464 } 1465 1466 actual := state.RootModule().Outputs["output"] 1467 expected := "bar0,bar1,bar2" 1468 if actual.Value != expected { 1469 t.Fatalf("bad: \n%s", actual) 1470 } 1471 1472 // Apply again, reduce the count to 1 1473 { 1474 ctx := testContext2(t, &ContextOpts{ 1475 Module: m, 1476 State: state, 1477 Providers: map[string]ResourceProviderFactory{ 1478 "aws": testProviderFuncFixed(p), 1479 }, 1480 Variables: map[string]string{ 1481 "count": "1", 1482 }, 1483 }) 1484 1485 if _, err := ctx.Plan(); err != nil { 1486 t.Fatalf("err: %s", err) 1487 } 1488 1489 state, err := ctx.Apply() 1490 if err != nil { 1491 t.Fatalf("err: %s", err) 1492 } 1493 1494 actual := state.RootModule().Outputs["output"] 1495 expected := "bar0" 1496 if actual.Value != expected { 1497 t.Fatalf("bad: \n%s", actual) 1498 } 1499 } 1500 } 1501 1502 func TestContext2Apply_nilDiff(t *testing.T) { 1503 m := testModule(t, "apply-good") 1504 p := testProvider("aws") 1505 p.ApplyFn = testApplyFn 1506 p.DiffFn = testDiffFn 1507 ctx := testContext2(t, &ContextOpts{ 1508 Module: m, 1509 Providers: map[string]ResourceProviderFactory{ 1510 "aws": testProviderFuncFixed(p), 1511 }, 1512 }) 1513 1514 if _, err := ctx.Plan(); err != nil { 1515 t.Fatalf("err: %s", err) 1516 } 1517 1518 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 1519 return nil, nil 1520 } 1521 1522 if _, err := ctx.Apply(); err == nil { 1523 t.Fatal("should error") 1524 } 1525 } 1526 1527 func TestContext2Apply_outputOrphan(t *testing.T) { 1528 m := testModule(t, "apply-output-orphan") 1529 p := testProvider("aws") 1530 p.ApplyFn = testApplyFn 1531 p.DiffFn = testDiffFn 1532 1533 state := &State{ 1534 Modules: []*ModuleState{ 1535 &ModuleState{ 1536 Path: rootModulePath, 1537 Outputs: map[string]*OutputState{ 1538 "foo": &OutputState{ 1539 Type: "string", 1540 Sensitive: false, 1541 Value: "bar", 1542 }, 1543 "bar": &OutputState{ 1544 Type: "string", 1545 Sensitive: false, 1546 Value: "baz", 1547 }, 1548 }, 1549 }, 1550 }, 1551 } 1552 1553 ctx := testContext2(t, &ContextOpts{ 1554 Module: m, 1555 Providers: map[string]ResourceProviderFactory{ 1556 "aws": testProviderFuncFixed(p), 1557 }, 1558 State: state, 1559 }) 1560 1561 if _, err := ctx.Plan(); err != nil { 1562 t.Fatalf("err: %s", err) 1563 } 1564 1565 state, err := ctx.Apply() 1566 if err != nil { 1567 t.Fatalf("err: %s", err) 1568 } 1569 1570 actual := strings.TrimSpace(state.String()) 1571 expected := strings.TrimSpace(testTerraformApplyOutputOrphanStr) 1572 if actual != expected { 1573 t.Fatalf("bad: \n%s", actual) 1574 } 1575 } 1576 1577 func TestContext2Apply_providerComputedVar(t *testing.T) { 1578 m := testModule(t, "apply-provider-computed") 1579 p := testProvider("aws") 1580 p.ApplyFn = testApplyFn 1581 p.DiffFn = testDiffFn 1582 1583 pTest := testProvider("test") 1584 pTest.ApplyFn = testApplyFn 1585 pTest.DiffFn = testDiffFn 1586 1587 ctx := testContext2(t, &ContextOpts{ 1588 Module: m, 1589 Providers: map[string]ResourceProviderFactory{ 1590 "aws": testProviderFuncFixed(p), 1591 "test": testProviderFuncFixed(pTest), 1592 }, 1593 }) 1594 1595 p.ConfigureFn = func(c *ResourceConfig) error { 1596 if c.IsComputed("value") { 1597 return fmt.Errorf("value is computed") 1598 } 1599 1600 v, ok := c.Get("value") 1601 if !ok { 1602 return fmt.Errorf("value is not found") 1603 } 1604 if v != "yes" { 1605 return fmt.Errorf("value is not 'yes': %v", v) 1606 } 1607 1608 return nil 1609 } 1610 1611 if _, err := ctx.Plan(); err != nil { 1612 t.Fatalf("err: %s", err) 1613 } 1614 1615 if _, err := ctx.Apply(); err != nil { 1616 t.Fatalf("err: %s", err) 1617 } 1618 } 1619 1620 func TestContext2Apply_Provisioner_compute(t *testing.T) { 1621 m := testModule(t, "apply-provisioner-compute") 1622 p := testProvider("aws") 1623 pr := testProvisioner() 1624 p.ApplyFn = testApplyFn 1625 p.DiffFn = testDiffFn 1626 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 1627 val, ok := c.Config["foo"] 1628 if !ok || val != "computed_dynamical" { 1629 t.Fatalf("bad value for foo: %v %#v", val, c) 1630 } 1631 1632 return nil 1633 } 1634 ctx := testContext2(t, &ContextOpts{ 1635 Module: m, 1636 Providers: map[string]ResourceProviderFactory{ 1637 "aws": testProviderFuncFixed(p), 1638 }, 1639 Provisioners: map[string]ResourceProvisionerFactory{ 1640 "shell": testProvisionerFuncFixed(pr), 1641 }, 1642 Variables: map[string]string{ 1643 "value": "1", 1644 }, 1645 }) 1646 1647 if _, err := ctx.Plan(); err != nil { 1648 t.Fatalf("err: %s", err) 1649 } 1650 1651 state, err := ctx.Apply() 1652 if err != nil { 1653 t.Fatalf("err: %s", err) 1654 } 1655 1656 actual := strings.TrimSpace(state.String()) 1657 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 1658 if actual != expected { 1659 t.Fatalf("bad: \n%s", actual) 1660 } 1661 1662 // Verify apply was invoked 1663 if !pr.ApplyCalled { 1664 t.Fatalf("provisioner not invoked") 1665 } 1666 } 1667 1668 func TestContext2Apply_provisionerCreateFail(t *testing.T) { 1669 m := testModule(t, "apply-provisioner-fail-create") 1670 p := testProvider("aws") 1671 pr := testProvisioner() 1672 p.DiffFn = testDiffFn 1673 1674 p.ApplyFn = func( 1675 info *InstanceInfo, 1676 is *InstanceState, 1677 id *InstanceDiff) (*InstanceState, error) { 1678 is.ID = "foo" 1679 return is, fmt.Errorf("error") 1680 } 1681 1682 ctx := testContext2(t, &ContextOpts{ 1683 Module: m, 1684 Providers: map[string]ResourceProviderFactory{ 1685 "aws": testProviderFuncFixed(p), 1686 }, 1687 Provisioners: map[string]ResourceProvisionerFactory{ 1688 "shell": testProvisionerFuncFixed(pr), 1689 }, 1690 }) 1691 1692 if _, err := ctx.Plan(); err != nil { 1693 t.Fatalf("err: %s", err) 1694 } 1695 1696 state, err := ctx.Apply() 1697 if err == nil { 1698 t.Fatal("should error") 1699 } 1700 1701 actual := strings.TrimSpace(state.String()) 1702 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateStr) 1703 if actual != expected { 1704 t.Fatalf("bad: \n%s", actual) 1705 } 1706 } 1707 1708 func TestContext2Apply_provisionerCreateFailNoId(t *testing.T) { 1709 m := testModule(t, "apply-provisioner-fail-create") 1710 p := testProvider("aws") 1711 pr := testProvisioner() 1712 p.DiffFn = testDiffFn 1713 1714 p.ApplyFn = func( 1715 info *InstanceInfo, 1716 is *InstanceState, 1717 id *InstanceDiff) (*InstanceState, error) { 1718 return nil, fmt.Errorf("error") 1719 } 1720 1721 ctx := testContext2(t, &ContextOpts{ 1722 Module: m, 1723 Providers: map[string]ResourceProviderFactory{ 1724 "aws": testProviderFuncFixed(p), 1725 }, 1726 Provisioners: map[string]ResourceProvisionerFactory{ 1727 "shell": testProvisionerFuncFixed(pr), 1728 }, 1729 }) 1730 1731 if _, err := ctx.Plan(); err != nil { 1732 t.Fatalf("err: %s", err) 1733 } 1734 1735 state, err := ctx.Apply() 1736 if err == nil { 1737 t.Fatal("should error") 1738 } 1739 1740 actual := strings.TrimSpace(state.String()) 1741 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateNoIdStr) 1742 if actual != expected { 1743 t.Fatalf("bad: \n%s", actual) 1744 } 1745 } 1746 1747 func TestContext2Apply_provisionerFail(t *testing.T) { 1748 m := testModule(t, "apply-provisioner-fail") 1749 p := testProvider("aws") 1750 pr := testProvisioner() 1751 p.ApplyFn = testApplyFn 1752 p.DiffFn = testDiffFn 1753 1754 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 1755 return fmt.Errorf("EXPLOSION") 1756 } 1757 1758 ctx := testContext2(t, &ContextOpts{ 1759 Module: m, 1760 Providers: map[string]ResourceProviderFactory{ 1761 "aws": testProviderFuncFixed(p), 1762 }, 1763 Provisioners: map[string]ResourceProvisionerFactory{ 1764 "shell": testProvisionerFuncFixed(pr), 1765 }, 1766 Variables: map[string]string{ 1767 "value": "1", 1768 }, 1769 }) 1770 1771 if _, err := ctx.Plan(); err != nil { 1772 t.Fatalf("err: %s", err) 1773 } 1774 1775 state, err := ctx.Apply() 1776 if err == nil { 1777 t.Fatal("should error") 1778 } 1779 1780 actual := strings.TrimSpace(state.String()) 1781 expected := strings.TrimSpace(testTerraformApplyProvisionerFailStr) 1782 if actual != expected { 1783 t.Fatalf("bad: \n%s", actual) 1784 } 1785 } 1786 1787 func TestContext2Apply_provisionerFail_createBeforeDestroy(t *testing.T) { 1788 m := testModule(t, "apply-provisioner-fail-create-before") 1789 p := testProvider("aws") 1790 pr := testProvisioner() 1791 p.ApplyFn = testApplyFn 1792 p.DiffFn = testDiffFn 1793 pr.ApplyFn = func(*InstanceState, *ResourceConfig) error { 1794 return fmt.Errorf("EXPLOSION") 1795 } 1796 1797 state := &State{ 1798 Modules: []*ModuleState{ 1799 &ModuleState{ 1800 Path: rootModulePath, 1801 Resources: map[string]*ResourceState{ 1802 "aws_instance.bar": &ResourceState{ 1803 Type: "aws_instance", 1804 Primary: &InstanceState{ 1805 ID: "bar", 1806 Attributes: map[string]string{ 1807 "require_new": "abc", 1808 }, 1809 }, 1810 }, 1811 }, 1812 }, 1813 }, 1814 } 1815 ctx := testContext2(t, &ContextOpts{ 1816 Module: m, 1817 Providers: map[string]ResourceProviderFactory{ 1818 "aws": testProviderFuncFixed(p), 1819 }, 1820 Provisioners: map[string]ResourceProvisionerFactory{ 1821 "shell": testProvisionerFuncFixed(pr), 1822 }, 1823 State: state, 1824 }) 1825 1826 if _, err := ctx.Plan(); err != nil { 1827 t.Fatalf("err: %s", err) 1828 } 1829 1830 state, err := ctx.Apply() 1831 if err == nil { 1832 t.Fatal("should error") 1833 } 1834 1835 actual := strings.TrimSpace(state.String()) 1836 expected := strings.TrimSpace(testTerraformApplyProvisionerFailCreateBeforeDestroyStr) 1837 if actual != expected { 1838 t.Fatalf("bad: \n%s", actual) 1839 } 1840 } 1841 1842 func TestContext2Apply_error_createBeforeDestroy(t *testing.T) { 1843 m := testModule(t, "apply-error-create-before") 1844 p := testProvider("aws") 1845 state := &State{ 1846 Modules: []*ModuleState{ 1847 &ModuleState{ 1848 Path: rootModulePath, 1849 Resources: map[string]*ResourceState{ 1850 "aws_instance.bar": &ResourceState{ 1851 Type: "aws_instance", 1852 Primary: &InstanceState{ 1853 ID: "bar", 1854 Attributes: map[string]string{ 1855 "require_new": "abc", 1856 }, 1857 }, 1858 }, 1859 }, 1860 }, 1861 }, 1862 } 1863 ctx := testContext2(t, &ContextOpts{ 1864 Module: m, 1865 Providers: map[string]ResourceProviderFactory{ 1866 "aws": testProviderFuncFixed(p), 1867 }, 1868 State: state, 1869 }) 1870 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 1871 return nil, fmt.Errorf("error") 1872 } 1873 p.DiffFn = testDiffFn 1874 1875 if _, err := ctx.Plan(); err != nil { 1876 t.Fatalf("err: %s", err) 1877 } 1878 1879 state, err := ctx.Apply() 1880 if err == nil { 1881 t.Fatal("should have error") 1882 } 1883 1884 actual := strings.TrimSpace(state.String()) 1885 expected := strings.TrimSpace(testTerraformApplyErrorCreateBeforeDestroyStr) 1886 if actual != expected { 1887 t.Fatalf("bad: \n%s\n\nExpected:\n\n%s", actual, expected) 1888 } 1889 } 1890 1891 func TestContext2Apply_errorDestroy_createBeforeDestroy(t *testing.T) { 1892 m := testModule(t, "apply-error-create-before") 1893 p := testProvider("aws") 1894 state := &State{ 1895 Modules: []*ModuleState{ 1896 &ModuleState{ 1897 Path: rootModulePath, 1898 Resources: map[string]*ResourceState{ 1899 "aws_instance.bar": &ResourceState{ 1900 Type: "aws_instance", 1901 Primary: &InstanceState{ 1902 ID: "bar", 1903 Attributes: map[string]string{ 1904 "require_new": "abc", 1905 }, 1906 }, 1907 }, 1908 }, 1909 }, 1910 }, 1911 } 1912 ctx := testContext2(t, &ContextOpts{ 1913 Module: m, 1914 Providers: map[string]ResourceProviderFactory{ 1915 "aws": testProviderFuncFixed(p), 1916 }, 1917 State: state, 1918 }) 1919 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 1920 // Fail the destroy! 1921 if id.Destroy { 1922 return is, fmt.Errorf("error") 1923 } 1924 1925 // Create should work 1926 is = &InstanceState{ 1927 ID: "foo", 1928 } 1929 return is, nil 1930 } 1931 p.DiffFn = testDiffFn 1932 1933 if _, err := ctx.Plan(); err != nil { 1934 t.Fatalf("err: %s", err) 1935 } 1936 1937 state, err := ctx.Apply() 1938 if err == nil { 1939 t.Fatal("should have error") 1940 } 1941 1942 actual := strings.TrimSpace(state.String()) 1943 expected := strings.TrimSpace(testTerraformApplyErrorDestroyCreateBeforeDestroyStr) 1944 if actual != expected { 1945 t.Fatalf("bad: actual:\n%s\n\nexpected:\n%s", actual, expected) 1946 } 1947 } 1948 1949 func TestContext2Apply_multiDepose_createBeforeDestroy(t *testing.T) { 1950 m := testModule(t, "apply-multi-depose-create-before-destroy") 1951 p := testProvider("aws") 1952 p.DiffFn = testDiffFn 1953 ps := map[string]ResourceProviderFactory{"aws": testProviderFuncFixed(p)} 1954 state := &State{ 1955 Modules: []*ModuleState{ 1956 &ModuleState{ 1957 Path: rootModulePath, 1958 Resources: map[string]*ResourceState{ 1959 "aws_instance.web": &ResourceState{ 1960 Type: "aws_instance", 1961 Primary: &InstanceState{ID: "foo"}, 1962 }, 1963 }, 1964 }, 1965 }, 1966 } 1967 1968 ctx := testContext2(t, &ContextOpts{ 1969 Module: m, 1970 Providers: ps, 1971 State: state, 1972 }) 1973 createdInstanceId := "bar" 1974 // Create works 1975 createFunc := func(is *InstanceState) (*InstanceState, error) { 1976 return &InstanceState{ID: createdInstanceId}, nil 1977 } 1978 // Destroy starts broken 1979 destroyFunc := func(is *InstanceState) (*InstanceState, error) { 1980 return is, fmt.Errorf("destroy failed") 1981 } 1982 p.ApplyFn = func(info *InstanceInfo, is *InstanceState, id *InstanceDiff) (*InstanceState, error) { 1983 if id.Destroy { 1984 return destroyFunc(is) 1985 } else { 1986 return createFunc(is) 1987 } 1988 } 1989 1990 if _, err := ctx.Plan(); err != nil { 1991 t.Fatalf("err: %s", err) 1992 } 1993 1994 // Destroy is broken, so even though CBD successfully replaces the instance, 1995 // we'll have to save the Deposed instance to destroy later 1996 state, err := ctx.Apply() 1997 if err == nil { 1998 t.Fatal("should have error") 1999 } 2000 2001 checkStateString(t, state, ` 2002 aws_instance.web: (1 deposed) 2003 ID = bar 2004 Deposed ID 1 = foo 2005 `) 2006 2007 createdInstanceId = "baz" 2008 ctx = testContext2(t, &ContextOpts{ 2009 Module: m, 2010 Providers: ps, 2011 State: state, 2012 }) 2013 2014 if _, err := ctx.Plan(); err != nil { 2015 t.Fatalf("err: %s", err) 2016 } 2017 2018 // We're replacing the primary instance once again. Destroy is _still_ 2019 // broken, so the Deposed list gets longer 2020 state, err = ctx.Apply() 2021 if err == nil { 2022 t.Fatal("should have error") 2023 } 2024 2025 checkStateString(t, state, ` 2026 aws_instance.web: (2 deposed) 2027 ID = baz 2028 Deposed ID 1 = foo 2029 Deposed ID 2 = bar 2030 `) 2031 2032 // Destroy partially fixed! 2033 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 2034 if is.ID == "foo" || is.ID == "baz" { 2035 return nil, nil 2036 } else { 2037 return is, fmt.Errorf("destroy partially failed") 2038 } 2039 } 2040 2041 createdInstanceId = "qux" 2042 if _, err := ctx.Plan(); err != nil { 2043 t.Fatalf("err: %s", err) 2044 } 2045 state, err = ctx.Apply() 2046 // Expect error because 1/2 of Deposed destroys failed 2047 if err == nil { 2048 t.Fatal("should have error") 2049 } 2050 2051 // foo and baz are now gone, bar sticks around 2052 checkStateString(t, state, ` 2053 aws_instance.web: (1 deposed) 2054 ID = qux 2055 Deposed ID 1 = bar 2056 `) 2057 2058 // Destroy working fully! 2059 destroyFunc = func(is *InstanceState) (*InstanceState, error) { 2060 return nil, nil 2061 } 2062 2063 createdInstanceId = "quux" 2064 if _, err := ctx.Plan(); err != nil { 2065 t.Fatalf("err: %s", err) 2066 } 2067 state, err = ctx.Apply() 2068 if err != nil { 2069 t.Fatal("should not have error:", err) 2070 } 2071 2072 // And finally the state is clean 2073 checkStateString(t, state, ` 2074 aws_instance.web: 2075 ID = quux 2076 `) 2077 } 2078 2079 func TestContext2Apply_provisionerResourceRef(t *testing.T) { 2080 m := testModule(t, "apply-provisioner-resource-ref") 2081 p := testProvider("aws") 2082 pr := testProvisioner() 2083 p.ApplyFn = testApplyFn 2084 p.DiffFn = testDiffFn 2085 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2086 val, ok := c.Config["foo"] 2087 if !ok || val != "2" { 2088 t.Fatalf("bad value for foo: %v %#v", val, c) 2089 } 2090 2091 return nil 2092 } 2093 2094 ctx := testContext2(t, &ContextOpts{ 2095 Module: m, 2096 Providers: map[string]ResourceProviderFactory{ 2097 "aws": testProviderFuncFixed(p), 2098 }, 2099 Provisioners: map[string]ResourceProvisionerFactory{ 2100 "shell": testProvisionerFuncFixed(pr), 2101 }, 2102 }) 2103 2104 if _, err := ctx.Plan(); err != nil { 2105 t.Fatalf("err: %s", err) 2106 } 2107 2108 state, err := ctx.Apply() 2109 if err != nil { 2110 t.Fatalf("err: %s", err) 2111 } 2112 2113 actual := strings.TrimSpace(state.String()) 2114 expected := strings.TrimSpace(testTerraformApplyProvisionerResourceRefStr) 2115 if actual != expected { 2116 t.Fatalf("bad: \n%s", actual) 2117 } 2118 2119 // Verify apply was invoked 2120 if !pr.ApplyCalled { 2121 t.Fatalf("provisioner not invoked") 2122 } 2123 } 2124 2125 func TestContext2Apply_provisionerSelfRef(t *testing.T) { 2126 m := testModule(t, "apply-provisioner-self-ref") 2127 p := testProvider("aws") 2128 pr := testProvisioner() 2129 p.ApplyFn = testApplyFn 2130 p.DiffFn = testDiffFn 2131 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2132 val, ok := c.Config["command"] 2133 if !ok || val != "bar" { 2134 t.Fatalf("bad value for command: %v %#v", val, c) 2135 } 2136 2137 return nil 2138 } 2139 2140 ctx := testContext2(t, &ContextOpts{ 2141 Module: m, 2142 Providers: map[string]ResourceProviderFactory{ 2143 "aws": testProviderFuncFixed(p), 2144 }, 2145 Provisioners: map[string]ResourceProvisionerFactory{ 2146 "shell": testProvisionerFuncFixed(pr), 2147 }, 2148 }) 2149 2150 if _, err := ctx.Plan(); err != nil { 2151 t.Fatalf("err: %s", err) 2152 } 2153 2154 state, err := ctx.Apply() 2155 if err != nil { 2156 t.Fatalf("err: %s", err) 2157 } 2158 2159 actual := strings.TrimSpace(state.String()) 2160 expected := strings.TrimSpace(testTerraformApplyProvisionerSelfRefStr) 2161 if actual != expected { 2162 t.Fatalf("bad: \n%s", actual) 2163 } 2164 2165 // Verify apply was invoked 2166 if !pr.ApplyCalled { 2167 t.Fatalf("provisioner not invoked") 2168 } 2169 } 2170 2171 func TestContext2Apply_provisionerMultiSelfRef(t *testing.T) { 2172 var lock sync.Mutex 2173 commands := make([]string, 0, 5) 2174 2175 m := testModule(t, "apply-provisioner-multi-self-ref") 2176 p := testProvider("aws") 2177 pr := testProvisioner() 2178 p.ApplyFn = testApplyFn 2179 p.DiffFn = testDiffFn 2180 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2181 lock.Lock() 2182 defer lock.Unlock() 2183 2184 val, ok := c.Config["command"] 2185 if !ok { 2186 t.Fatalf("bad value for command: %v %#v", val, c) 2187 } 2188 2189 commands = append(commands, val.(string)) 2190 return nil 2191 } 2192 2193 ctx := testContext2(t, &ContextOpts{ 2194 Module: m, 2195 Providers: map[string]ResourceProviderFactory{ 2196 "aws": testProviderFuncFixed(p), 2197 }, 2198 Provisioners: map[string]ResourceProvisionerFactory{ 2199 "shell": testProvisionerFuncFixed(pr), 2200 }, 2201 }) 2202 2203 if _, err := ctx.Plan(); err != nil { 2204 t.Fatalf("err: %s", err) 2205 } 2206 2207 state, err := ctx.Apply() 2208 if err != nil { 2209 t.Fatalf("err: %s", err) 2210 } 2211 2212 actual := strings.TrimSpace(state.String()) 2213 expected := strings.TrimSpace(testTerraformApplyProvisionerMultiSelfRefStr) 2214 if actual != expected { 2215 t.Fatalf("bad: \n%s", actual) 2216 } 2217 2218 // Verify apply was invoked 2219 if !pr.ApplyCalled { 2220 t.Fatalf("provisioner not invoked") 2221 } 2222 2223 // Verify our result 2224 sort.Strings(commands) 2225 expectedCommands := []string{"number 0", "number 1", "number 2"} 2226 if !reflect.DeepEqual(commands, expectedCommands) { 2227 t.Fatalf("bad: %#v", commands) 2228 } 2229 } 2230 2231 // Provisioner should NOT run on a diff, only create 2232 func TestContext2Apply_Provisioner_Diff(t *testing.T) { 2233 m := testModule(t, "apply-provisioner-diff") 2234 p := testProvider("aws") 2235 pr := testProvisioner() 2236 p.ApplyFn = testApplyFn 2237 p.DiffFn = testDiffFn 2238 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2239 return nil 2240 } 2241 ctx := testContext2(t, &ContextOpts{ 2242 Module: m, 2243 Providers: map[string]ResourceProviderFactory{ 2244 "aws": testProviderFuncFixed(p), 2245 }, 2246 Provisioners: map[string]ResourceProvisionerFactory{ 2247 "shell": testProvisionerFuncFixed(pr), 2248 }, 2249 }) 2250 2251 if _, err := ctx.Plan(); err != nil { 2252 t.Fatalf("err: %s", err) 2253 } 2254 2255 state, err := ctx.Apply() 2256 if err != nil { 2257 t.Fatalf("err: %s", err) 2258 } 2259 2260 actual := strings.TrimSpace(state.String()) 2261 expected := strings.TrimSpace(testTerraformApplyProvisionerDiffStr) 2262 if actual != expected { 2263 t.Fatalf("bad: \n%s", actual) 2264 } 2265 2266 // Verify apply was invoked 2267 if !pr.ApplyCalled { 2268 t.Fatalf("provisioner not invoked") 2269 } 2270 pr.ApplyCalled = false 2271 2272 // Change the state to force a diff 2273 mod := state.RootModule() 2274 mod.Resources["aws_instance.bar"].Primary.Attributes["foo"] = "baz" 2275 2276 // Re-create context with state 2277 ctx = testContext2(t, &ContextOpts{ 2278 Module: m, 2279 Providers: map[string]ResourceProviderFactory{ 2280 "aws": testProviderFuncFixed(p), 2281 }, 2282 Provisioners: map[string]ResourceProvisionerFactory{ 2283 "shell": testProvisionerFuncFixed(pr), 2284 }, 2285 State: state, 2286 }) 2287 2288 if _, err := ctx.Plan(); err != nil { 2289 t.Fatalf("err: %s", err) 2290 } 2291 2292 state2, err := ctx.Apply() 2293 if err != nil { 2294 t.Fatalf("err: %s", err) 2295 } 2296 2297 actual = strings.TrimSpace(state2.String()) 2298 if actual != expected { 2299 t.Fatalf("bad: \n%s", actual) 2300 } 2301 2302 // Verify apply was NOT invoked 2303 if pr.ApplyCalled { 2304 t.Fatalf("provisioner invoked") 2305 } 2306 } 2307 2308 func TestContext2Apply_outputDiffVars(t *testing.T) { 2309 m := testModule(t, "apply-good") 2310 p := testProvider("aws") 2311 s := &State{ 2312 Modules: []*ModuleState{ 2313 &ModuleState{ 2314 Path: rootModulePath, 2315 Resources: map[string]*ResourceState{ 2316 "aws_instance.baz": &ResourceState{ 2317 Type: "aws_instance", 2318 Primary: &InstanceState{ 2319 ID: "bar", 2320 }, 2321 }, 2322 }, 2323 }, 2324 }, 2325 } 2326 ctx := testContext2(t, &ContextOpts{ 2327 Module: m, 2328 Providers: map[string]ResourceProviderFactory{ 2329 "aws": testProviderFuncFixed(p), 2330 }, 2331 State: s, 2332 }) 2333 2334 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 2335 for k, ad := range d.Attributes { 2336 if ad.NewComputed { 2337 return nil, fmt.Errorf("%s: computed", k) 2338 } 2339 } 2340 2341 result := s.MergeDiff(d) 2342 result.ID = "foo" 2343 return result, nil 2344 } 2345 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 2346 return &InstanceDiff{ 2347 Attributes: map[string]*ResourceAttrDiff{ 2348 "foo": &ResourceAttrDiff{ 2349 NewComputed: true, 2350 Type: DiffAttrOutput, 2351 }, 2352 "bar": &ResourceAttrDiff{ 2353 New: "baz", 2354 }, 2355 }, 2356 }, nil 2357 } 2358 2359 if _, err := ctx.Plan(); err != nil { 2360 t.Fatalf("err: %s", err) 2361 } 2362 if _, err := ctx.Apply(); err != nil { 2363 t.Fatalf("err: %s", err) 2364 } 2365 } 2366 2367 func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { 2368 m := testModule(t, "apply-provisioner-conninfo") 2369 p := testProvider("aws") 2370 pr := testProvisioner() 2371 2372 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 2373 if s.Ephemeral.ConnInfo == nil { 2374 t.Fatalf("ConnInfo not initialized") 2375 } 2376 2377 result, _ := testApplyFn(info, s, d) 2378 result.Ephemeral.ConnInfo = map[string]string{ 2379 "type": "ssh", 2380 "host": "127.0.0.1", 2381 "port": "22", 2382 } 2383 return result, nil 2384 } 2385 p.DiffFn = testDiffFn 2386 2387 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2388 conn := rs.Ephemeral.ConnInfo 2389 if conn["type"] != "telnet" { 2390 t.Fatalf("Bad: %#v", conn) 2391 } 2392 if conn["host"] != "127.0.0.1" { 2393 t.Fatalf("Bad: %#v", conn) 2394 } 2395 if conn["port"] != "2222" { 2396 t.Fatalf("Bad: %#v", conn) 2397 } 2398 if conn["user"] != "superuser" { 2399 t.Fatalf("Bad: %#v", conn) 2400 } 2401 if conn["pass"] != "test" { 2402 t.Fatalf("Bad: %#v", conn) 2403 } 2404 2405 return nil 2406 } 2407 2408 ctx := testContext2(t, &ContextOpts{ 2409 Module: m, 2410 Providers: map[string]ResourceProviderFactory{ 2411 "aws": testProviderFuncFixed(p), 2412 }, 2413 Provisioners: map[string]ResourceProvisionerFactory{ 2414 "shell": testProvisionerFuncFixed(pr), 2415 }, 2416 Variables: map[string]string{ 2417 "value": "1", 2418 "pass": "test", 2419 }, 2420 }) 2421 2422 if _, err := ctx.Plan(); err != nil { 2423 t.Fatalf("err: %s", err) 2424 } 2425 2426 state, err := ctx.Apply() 2427 if err != nil { 2428 t.Fatalf("err: %s", err) 2429 } 2430 2431 actual := strings.TrimSpace(state.String()) 2432 expected := strings.TrimSpace(testTerraformApplyProvisionerStr) 2433 if actual != expected { 2434 t.Fatalf("bad: \n%s", actual) 2435 } 2436 2437 // Verify apply was invoked 2438 if !pr.ApplyCalled { 2439 t.Fatalf("provisioner not invoked") 2440 } 2441 } 2442 2443 func TestContext2Apply_destroy(t *testing.T) { 2444 m := testModule(t, "apply-destroy") 2445 h := new(HookRecordApplyOrder) 2446 p := testProvider("aws") 2447 p.ApplyFn = testApplyFn 2448 p.DiffFn = testDiffFn 2449 ctx := testContext2(t, &ContextOpts{ 2450 Module: m, 2451 Hooks: []Hook{h}, 2452 Providers: map[string]ResourceProviderFactory{ 2453 "aws": testProviderFuncFixed(p), 2454 }, 2455 }) 2456 2457 // First plan and apply a create operation 2458 if _, err := ctx.Plan(); err != nil { 2459 t.Fatalf("err: %s", err) 2460 } 2461 2462 state, err := ctx.Apply() 2463 if err != nil { 2464 t.Fatalf("err: %s", err) 2465 } 2466 2467 // Next, plan and apply a destroy operation 2468 h.Active = true 2469 ctx = testContext2(t, &ContextOpts{ 2470 Destroy: true, 2471 State: state, 2472 Module: m, 2473 Hooks: []Hook{h}, 2474 Providers: map[string]ResourceProviderFactory{ 2475 "aws": testProviderFuncFixed(p), 2476 }, 2477 }) 2478 2479 if _, err := ctx.Plan(); err != nil { 2480 t.Fatalf("err: %s", err) 2481 } 2482 2483 state, err = ctx.Apply() 2484 if err != nil { 2485 t.Fatalf("err: %s", err) 2486 } 2487 2488 // Test that things were destroyed 2489 actual := strings.TrimSpace(state.String()) 2490 expected := strings.TrimSpace(testTerraformApplyDestroyStr) 2491 if actual != expected { 2492 t.Fatalf("bad: \n%s", actual) 2493 } 2494 2495 // Test that things were destroyed _in the right order_ 2496 expected2 := []string{"aws_instance.bar", "aws_instance.foo"} 2497 actual2 := h.IDs 2498 if !reflect.DeepEqual(actual2, expected2) { 2499 t.Fatalf("expected: %#v\n\ngot:%#v", expected2, actual2) 2500 } 2501 } 2502 2503 func TestContext2Apply_destroyNestedModule(t *testing.T) { 2504 m := testModule(t, "apply-destroy-nested-module") 2505 p := testProvider("aws") 2506 p.ApplyFn = testApplyFn 2507 p.DiffFn = testDiffFn 2508 2509 s := &State{ 2510 Modules: []*ModuleState{ 2511 &ModuleState{ 2512 Path: []string{"root", "child", "subchild"}, 2513 Resources: map[string]*ResourceState{ 2514 "aws_instance.bar": &ResourceState{ 2515 Type: "aws_instance", 2516 Primary: &InstanceState{ 2517 ID: "bar", 2518 }, 2519 }, 2520 }, 2521 }, 2522 }, 2523 } 2524 2525 ctx := testContext2(t, &ContextOpts{ 2526 Module: m, 2527 Providers: map[string]ResourceProviderFactory{ 2528 "aws": testProviderFuncFixed(p), 2529 }, 2530 State: s, 2531 }) 2532 2533 // First plan and apply a create operation 2534 if _, err := ctx.Plan(); err != nil { 2535 t.Fatalf("err: %s", err) 2536 } 2537 2538 state, err := ctx.Apply() 2539 if err != nil { 2540 t.Fatalf("err: %s", err) 2541 } 2542 2543 // Test that things were destroyed 2544 actual := strings.TrimSpace(state.String()) 2545 expected := strings.TrimSpace(testTerraformApplyDestroyNestedModuleStr) 2546 if actual != expected { 2547 t.Fatalf("bad: \n%s", actual) 2548 } 2549 } 2550 2551 func TestContext2Apply_destroyDeeplyNestedModule(t *testing.T) { 2552 m := testModule(t, "apply-destroy-deeply-nested-module") 2553 p := testProvider("aws") 2554 p.ApplyFn = testApplyFn 2555 p.DiffFn = testDiffFn 2556 2557 s := &State{ 2558 Modules: []*ModuleState{ 2559 &ModuleState{ 2560 Path: []string{"root", "child", "subchild", "subsubchild"}, 2561 Resources: map[string]*ResourceState{ 2562 "aws_instance.bar": &ResourceState{ 2563 Type: "aws_instance", 2564 Primary: &InstanceState{ 2565 ID: "bar", 2566 }, 2567 }, 2568 }, 2569 }, 2570 }, 2571 } 2572 2573 ctx := testContext2(t, &ContextOpts{ 2574 Module: m, 2575 Providers: map[string]ResourceProviderFactory{ 2576 "aws": testProviderFuncFixed(p), 2577 }, 2578 State: s, 2579 }) 2580 2581 // First plan and apply a create operation 2582 if _, err := ctx.Plan(); err != nil { 2583 t.Fatalf("err: %s", err) 2584 } 2585 2586 state, err := ctx.Apply() 2587 if err != nil { 2588 t.Fatalf("err: %s", err) 2589 } 2590 2591 // Test that things were destroyed 2592 actual := strings.TrimSpace(state.String()) 2593 expected := strings.TrimSpace(` 2594 module.child.subchild.subsubchild: 2595 <no state> 2596 `) 2597 if actual != expected { 2598 t.Fatalf("bad: \n%s", actual) 2599 } 2600 } 2601 2602 // https://github.com/hashicorp/terraform/issues/5440 2603 func TestContext2Apply_destroyModuleWithAttrsReferencingResource(t *testing.T) { 2604 m := testModule(t, "apply-destroy-module-with-attrs") 2605 p := testProvider("aws") 2606 p.ApplyFn = testApplyFn 2607 p.DiffFn = testDiffFn 2608 2609 var state *State 2610 var err error 2611 { 2612 ctx := testContext2(t, &ContextOpts{ 2613 Module: m, 2614 Providers: map[string]ResourceProviderFactory{ 2615 "aws": testProviderFuncFixed(p), 2616 }, 2617 }) 2618 2619 // First plan and apply a create operation 2620 if _, err := ctx.Plan(); err != nil { 2621 t.Fatalf("plan err: %s", err) 2622 } 2623 2624 state, err = ctx.Apply() 2625 if err != nil { 2626 t.Fatalf("apply err: %s", err) 2627 } 2628 } 2629 2630 h := new(HookRecordApplyOrder) 2631 h.Active = true 2632 2633 { 2634 ctx := testContext2(t, &ContextOpts{ 2635 Destroy: true, 2636 Module: m, 2637 State: state, 2638 Hooks: []Hook{h}, 2639 Providers: map[string]ResourceProviderFactory{ 2640 "aws": testProviderFuncFixed(p), 2641 }, 2642 Variables: map[string]string{ 2643 "key_name": "foobarkey", 2644 }, 2645 }) 2646 2647 // First plan and apply a create operation 2648 plan, err := ctx.Plan() 2649 if err != nil { 2650 t.Fatalf("destroy plan err: %s", err) 2651 } 2652 2653 var buf bytes.Buffer 2654 if err := WritePlan(plan, &buf); err != nil { 2655 t.Fatalf("plan write err: %s", err) 2656 } 2657 2658 planFromFile, err := ReadPlan(&buf) 2659 if err != nil { 2660 t.Fatalf("plan read err: %s", err) 2661 } 2662 2663 ctx, err = planFromFile.Context(&ContextOpts{ 2664 Providers: map[string]ResourceProviderFactory{ 2665 "aws": testProviderFuncFixed(p), 2666 }, 2667 }) 2668 if err != nil { 2669 t.Fatalf("err: %s", err) 2670 } 2671 2672 state, err = ctx.Apply() 2673 if err != nil { 2674 t.Fatalf("destroy apply err: %s", err) 2675 } 2676 } 2677 2678 //Test that things were destroyed 2679 actual := strings.TrimSpace(state.String()) 2680 expected := strings.TrimSpace(` 2681 <no state> 2682 module.child: 2683 <no state> 2684 `) 2685 if actual != expected { 2686 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 2687 } 2688 } 2689 2690 func TestContext2Apply_destroyWithModuleVariableAndCount(t *testing.T) { 2691 m := testModule(t, "apply-destroy-mod-var-and-count") 2692 p := testProvider("aws") 2693 p.ApplyFn = testApplyFn 2694 p.DiffFn = testDiffFn 2695 2696 var state *State 2697 var err error 2698 { 2699 ctx := testContext2(t, &ContextOpts{ 2700 Module: m, 2701 Providers: map[string]ResourceProviderFactory{ 2702 "aws": testProviderFuncFixed(p), 2703 }, 2704 }) 2705 2706 // First plan and apply a create operation 2707 if _, err := ctx.Plan(); err != nil { 2708 t.Fatalf("plan err: %s", err) 2709 } 2710 2711 state, err = ctx.Apply() 2712 if err != nil { 2713 t.Fatalf("apply err: %s", err) 2714 } 2715 } 2716 2717 h := new(HookRecordApplyOrder) 2718 h.Active = true 2719 2720 { 2721 ctx := testContext2(t, &ContextOpts{ 2722 Destroy: true, 2723 Module: m, 2724 State: state, 2725 Hooks: []Hook{h}, 2726 Providers: map[string]ResourceProviderFactory{ 2727 "aws": testProviderFuncFixed(p), 2728 }, 2729 }) 2730 2731 // First plan and apply a create operation 2732 plan, err := ctx.Plan() 2733 if err != nil { 2734 t.Fatalf("destroy plan err: %s", err) 2735 } 2736 2737 var buf bytes.Buffer 2738 if err := WritePlan(plan, &buf); err != nil { 2739 t.Fatalf("plan write err: %s", err) 2740 } 2741 2742 planFromFile, err := ReadPlan(&buf) 2743 if err != nil { 2744 t.Fatalf("plan read err: %s", err) 2745 } 2746 2747 ctx, err = planFromFile.Context(&ContextOpts{ 2748 Providers: map[string]ResourceProviderFactory{ 2749 "aws": testProviderFuncFixed(p), 2750 }, 2751 }) 2752 if err != nil { 2753 t.Fatalf("err: %s", err) 2754 } 2755 2756 state, err = ctx.Apply() 2757 if err != nil { 2758 t.Fatalf("destroy apply err: %s", err) 2759 } 2760 } 2761 2762 //Test that things were destroyed 2763 actual := strings.TrimSpace(state.String()) 2764 expected := strings.TrimSpace(` 2765 <no state> 2766 module.child: 2767 <no state> 2768 `) 2769 if actual != expected { 2770 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 2771 } 2772 } 2773 2774 func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) { 2775 m := testModule(t, "apply-destroy-mod-var-and-count-nested") 2776 p := testProvider("aws") 2777 p.ApplyFn = testApplyFn 2778 p.DiffFn = testDiffFn 2779 2780 var state *State 2781 var err error 2782 { 2783 ctx := testContext2(t, &ContextOpts{ 2784 Module: m, 2785 Providers: map[string]ResourceProviderFactory{ 2786 "aws": testProviderFuncFixed(p), 2787 }, 2788 }) 2789 2790 // First plan and apply a create operation 2791 if _, err := ctx.Plan(); err != nil { 2792 t.Fatalf("plan err: %s", err) 2793 } 2794 2795 state, err = ctx.Apply() 2796 if err != nil { 2797 t.Fatalf("apply err: %s", err) 2798 } 2799 } 2800 2801 h := new(HookRecordApplyOrder) 2802 h.Active = true 2803 2804 { 2805 ctx := testContext2(t, &ContextOpts{ 2806 Destroy: true, 2807 Module: m, 2808 State: state, 2809 Hooks: []Hook{h}, 2810 Providers: map[string]ResourceProviderFactory{ 2811 "aws": testProviderFuncFixed(p), 2812 }, 2813 }) 2814 2815 // First plan and apply a create operation 2816 plan, err := ctx.Plan() 2817 if err != nil { 2818 t.Fatalf("destroy plan err: %s", err) 2819 } 2820 2821 var buf bytes.Buffer 2822 if err := WritePlan(plan, &buf); err != nil { 2823 t.Fatalf("plan write err: %s", err) 2824 } 2825 2826 planFromFile, err := ReadPlan(&buf) 2827 if err != nil { 2828 t.Fatalf("plan read err: %s", err) 2829 } 2830 2831 ctx, err = planFromFile.Context(&ContextOpts{ 2832 Providers: map[string]ResourceProviderFactory{ 2833 "aws": testProviderFuncFixed(p), 2834 }, 2835 }) 2836 if err != nil { 2837 t.Fatalf("err: %s", err) 2838 } 2839 2840 state, err = ctx.Apply() 2841 if err != nil { 2842 t.Fatalf("destroy apply err: %s", err) 2843 } 2844 } 2845 2846 //Test that things were destroyed 2847 actual := strings.TrimSpace(state.String()) 2848 expected := strings.TrimSpace(` 2849 <no state> 2850 module.child: 2851 <no state> 2852 module.child.child2: 2853 <no state> 2854 `) 2855 if actual != expected { 2856 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 2857 } 2858 } 2859 2860 func TestContext2Apply_destroyOutputs(t *testing.T) { 2861 m := testModule(t, "apply-destroy-outputs") 2862 h := new(HookRecordApplyOrder) 2863 p := testProvider("aws") 2864 p.ApplyFn = testApplyFn 2865 p.DiffFn = testDiffFn 2866 ctx := testContext2(t, &ContextOpts{ 2867 Module: m, 2868 Hooks: []Hook{h}, 2869 Providers: map[string]ResourceProviderFactory{ 2870 "aws": testProviderFuncFixed(p), 2871 }, 2872 }) 2873 2874 // First plan and apply a create operation 2875 if _, err := ctx.Plan(); err != nil { 2876 t.Fatalf("err: %s", err) 2877 } 2878 2879 state, err := ctx.Apply() 2880 2881 if err != nil { 2882 t.Fatalf("err: %s", err) 2883 } 2884 2885 // Next, plan and apply a destroy operation 2886 h.Active = true 2887 ctx = testContext2(t, &ContextOpts{ 2888 Destroy: true, 2889 State: state, 2890 Module: m, 2891 Hooks: []Hook{h}, 2892 Providers: map[string]ResourceProviderFactory{ 2893 "aws": testProviderFuncFixed(p), 2894 }, 2895 }) 2896 2897 if _, err := ctx.Plan(); err != nil { 2898 t.Fatalf("err: %s", err) 2899 } 2900 2901 state, err = ctx.Apply() 2902 if err != nil { 2903 t.Fatalf("err: %s", err) 2904 } 2905 2906 mod := state.RootModule() 2907 if len(mod.Resources) > 0 { 2908 t.Fatalf("bad: %#v", mod) 2909 } 2910 } 2911 2912 func TestContext2Apply_destroyOrphan(t *testing.T) { 2913 m := testModule(t, "apply-error") 2914 p := testProvider("aws") 2915 s := &State{ 2916 Modules: []*ModuleState{ 2917 &ModuleState{ 2918 Path: rootModulePath, 2919 Resources: map[string]*ResourceState{ 2920 "aws_instance.baz": &ResourceState{ 2921 Type: "aws_instance", 2922 Primary: &InstanceState{ 2923 ID: "bar", 2924 }, 2925 }, 2926 }, 2927 }, 2928 }, 2929 } 2930 ctx := testContext2(t, &ContextOpts{ 2931 Module: m, 2932 Providers: map[string]ResourceProviderFactory{ 2933 "aws": testProviderFuncFixed(p), 2934 }, 2935 State: s, 2936 }) 2937 2938 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 2939 if d.Destroy { 2940 return nil, nil 2941 } 2942 2943 result := s.MergeDiff(d) 2944 result.ID = "foo" 2945 return result, nil 2946 } 2947 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 2948 return &InstanceDiff{ 2949 Attributes: map[string]*ResourceAttrDiff{ 2950 "num": &ResourceAttrDiff{ 2951 New: "bar", 2952 }, 2953 }, 2954 }, nil 2955 } 2956 2957 if _, err := ctx.Plan(); err != nil { 2958 t.Fatalf("err: %s", err) 2959 } 2960 2961 state, err := ctx.Apply() 2962 if err != nil { 2963 t.Fatalf("err: %s", err) 2964 } 2965 2966 mod := state.RootModule() 2967 if _, ok := mod.Resources["aws_instance.baz"]; ok { 2968 t.Fatalf("bad: %#v", mod.Resources) 2969 } 2970 } 2971 2972 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 2973 m := testModule(t, "apply-destroy-provisioner") 2974 p := testProvider("aws") 2975 pr := testProvisioner() 2976 p.ApplyFn = testApplyFn 2977 p.DiffFn = testDiffFn 2978 2979 called := false 2980 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 2981 called = true 2982 return nil 2983 } 2984 2985 s := &State{ 2986 Modules: []*ModuleState{ 2987 &ModuleState{ 2988 Path: rootModulePath, 2989 Resources: map[string]*ResourceState{ 2990 "aws_instance.foo": &ResourceState{ 2991 Type: "aws_instance", 2992 Tainted: []*InstanceState{ 2993 &InstanceState{ 2994 ID: "bar", 2995 Attributes: map[string]string{ 2996 "id": "bar", 2997 }, 2998 }, 2999 }, 3000 }, 3001 }, 3002 }, 3003 }, 3004 } 3005 3006 ctx := testContext2(t, &ContextOpts{ 3007 Module: m, 3008 Providers: map[string]ResourceProviderFactory{ 3009 "aws": testProviderFuncFixed(p), 3010 }, 3011 Provisioners: map[string]ResourceProvisionerFactory{ 3012 "shell": testProvisionerFuncFixed(pr), 3013 }, 3014 State: s, 3015 Destroy: true, 3016 }) 3017 3018 if _, err := ctx.Plan(); err != nil { 3019 t.Fatalf("err: %s", err) 3020 } 3021 3022 state, err := ctx.Apply() 3023 if err != nil { 3024 t.Fatalf("err: %s", err) 3025 } 3026 3027 if called { 3028 t.Fatal("provisioner should not be called") 3029 } 3030 3031 actual := strings.TrimSpace(state.String()) 3032 expected := strings.TrimSpace("<no state>") 3033 if actual != expected { 3034 t.Fatalf("bad: \n%s", actual) 3035 } 3036 } 3037 3038 func TestContext2Apply_error(t *testing.T) { 3039 errored := false 3040 3041 m := testModule(t, "apply-error") 3042 p := testProvider("aws") 3043 ctx := testContext2(t, &ContextOpts{ 3044 Module: m, 3045 Providers: map[string]ResourceProviderFactory{ 3046 "aws": testProviderFuncFixed(p), 3047 }, 3048 }) 3049 3050 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 3051 if errored { 3052 state := &InstanceState{ 3053 ID: "bar", 3054 } 3055 return state, fmt.Errorf("error") 3056 } 3057 errored = true 3058 3059 return &InstanceState{ 3060 ID: "foo", 3061 Attributes: map[string]string{ 3062 "num": "2", 3063 }, 3064 }, nil 3065 } 3066 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3067 return &InstanceDiff{ 3068 Attributes: map[string]*ResourceAttrDiff{ 3069 "num": &ResourceAttrDiff{ 3070 New: "bar", 3071 }, 3072 }, 3073 }, nil 3074 } 3075 3076 if _, err := ctx.Plan(); err != nil { 3077 t.Fatalf("err: %s", err) 3078 } 3079 3080 state, err := ctx.Apply() 3081 if err == nil { 3082 t.Fatal("should have error") 3083 } 3084 3085 actual := strings.TrimSpace(state.String()) 3086 expected := strings.TrimSpace(testTerraformApplyErrorStr) 3087 if actual != expected { 3088 t.Fatalf("bad: \n%s", actual) 3089 } 3090 } 3091 3092 func TestContext2Apply_errorPartial(t *testing.T) { 3093 errored := false 3094 3095 m := testModule(t, "apply-error") 3096 p := testProvider("aws") 3097 s := &State{ 3098 Modules: []*ModuleState{ 3099 &ModuleState{ 3100 Path: rootModulePath, 3101 Resources: map[string]*ResourceState{ 3102 "aws_instance.bar": &ResourceState{ 3103 Type: "aws_instance", 3104 Primary: &InstanceState{ 3105 ID: "bar", 3106 }, 3107 }, 3108 }, 3109 }, 3110 }, 3111 } 3112 ctx := testContext2(t, &ContextOpts{ 3113 Module: m, 3114 Providers: map[string]ResourceProviderFactory{ 3115 "aws": testProviderFuncFixed(p), 3116 }, 3117 State: s, 3118 }) 3119 3120 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3121 if errored { 3122 return s, fmt.Errorf("error") 3123 } 3124 errored = true 3125 3126 return &InstanceState{ 3127 ID: "foo", 3128 Attributes: map[string]string{ 3129 "num": "2", 3130 }, 3131 }, nil 3132 } 3133 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3134 return &InstanceDiff{ 3135 Attributes: map[string]*ResourceAttrDiff{ 3136 "num": &ResourceAttrDiff{ 3137 New: "bar", 3138 }, 3139 }, 3140 }, nil 3141 } 3142 3143 if _, err := ctx.Plan(); err != nil { 3144 t.Fatalf("err: %s", err) 3145 } 3146 3147 state, err := ctx.Apply() 3148 if err == nil { 3149 t.Fatal("should have error") 3150 } 3151 3152 mod := state.RootModule() 3153 if len(mod.Resources) != 2 { 3154 t.Fatalf("bad: %#v", mod.Resources) 3155 } 3156 3157 actual := strings.TrimSpace(state.String()) 3158 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 3159 if actual != expected { 3160 t.Fatalf("bad: \n%s", actual) 3161 } 3162 } 3163 3164 func TestContext2Apply_hook(t *testing.T) { 3165 m := testModule(t, "apply-good") 3166 h := new(MockHook) 3167 p := testProvider("aws") 3168 p.ApplyFn = testApplyFn 3169 p.DiffFn = testDiffFn 3170 ctx := testContext2(t, &ContextOpts{ 3171 Module: m, 3172 Hooks: []Hook{h}, 3173 Providers: map[string]ResourceProviderFactory{ 3174 "aws": testProviderFuncFixed(p), 3175 }, 3176 }) 3177 3178 if _, err := ctx.Plan(); err != nil { 3179 t.Fatalf("err: %s", err) 3180 } 3181 3182 if _, err := ctx.Apply(); err != nil { 3183 t.Fatalf("err: %s", err) 3184 } 3185 3186 if !h.PreApplyCalled { 3187 t.Fatal("should be called") 3188 } 3189 if !h.PostApplyCalled { 3190 t.Fatal("should be called") 3191 } 3192 if !h.PostStateUpdateCalled { 3193 t.Fatalf("should call post state update") 3194 } 3195 } 3196 3197 func TestContext2Apply_hookOrphan(t *testing.T) { 3198 m := testModule(t, "apply-blank") 3199 h := new(MockHook) 3200 p := testProvider("aws") 3201 p.ApplyFn = testApplyFn 3202 p.DiffFn = testDiffFn 3203 3204 state := &State{ 3205 Modules: []*ModuleState{ 3206 &ModuleState{ 3207 Path: rootModulePath, 3208 Resources: map[string]*ResourceState{ 3209 "aws_instance.bar": &ResourceState{ 3210 Type: "aws_instance", 3211 Primary: &InstanceState{ 3212 ID: "bar", 3213 }, 3214 }, 3215 }, 3216 }, 3217 }, 3218 } 3219 3220 ctx := testContext2(t, &ContextOpts{ 3221 Module: m, 3222 State: state, 3223 Hooks: []Hook{h}, 3224 Providers: map[string]ResourceProviderFactory{ 3225 "aws": testProviderFuncFixed(p), 3226 }, 3227 }) 3228 3229 if _, err := ctx.Plan(); err != nil { 3230 t.Fatalf("err: %s", err) 3231 } 3232 3233 if _, err := ctx.Apply(); err != nil { 3234 t.Fatalf("err: %s", err) 3235 } 3236 3237 if !h.PreApplyCalled { 3238 t.Fatal("should be called") 3239 } 3240 if !h.PostApplyCalled { 3241 t.Fatal("should be called") 3242 } 3243 if !h.PostStateUpdateCalled { 3244 t.Fatalf("should call post state update") 3245 } 3246 } 3247 3248 func TestContext2Apply_idAttr(t *testing.T) { 3249 m := testModule(t, "apply-idattr") 3250 p := testProvider("aws") 3251 ctx := testContext2(t, &ContextOpts{ 3252 Module: m, 3253 Providers: map[string]ResourceProviderFactory{ 3254 "aws": testProviderFuncFixed(p), 3255 }, 3256 }) 3257 3258 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3259 result := s.MergeDiff(d) 3260 result.ID = "foo" 3261 result.Attributes = map[string]string{ 3262 "id": "bar", 3263 } 3264 3265 return result, nil 3266 } 3267 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3268 return &InstanceDiff{ 3269 Attributes: map[string]*ResourceAttrDiff{ 3270 "num": &ResourceAttrDiff{ 3271 New: "bar", 3272 }, 3273 }, 3274 }, nil 3275 } 3276 3277 if _, err := ctx.Plan(); err != nil { 3278 t.Fatalf("err: %s", err) 3279 } 3280 3281 state, err := ctx.Apply() 3282 if err != nil { 3283 t.Fatalf("err: %s", err) 3284 } 3285 3286 mod := state.RootModule() 3287 rs, ok := mod.Resources["aws_instance.foo"] 3288 if !ok { 3289 t.Fatal("not in state") 3290 } 3291 if rs.Primary.ID != "foo" { 3292 t.Fatalf("bad: %#v", rs.Primary.ID) 3293 } 3294 if rs.Primary.Attributes["id"] != "foo" { 3295 t.Fatalf("bad: %#v", rs.Primary.Attributes) 3296 } 3297 } 3298 3299 func TestContext2Apply_output(t *testing.T) { 3300 m := testModule(t, "apply-output") 3301 p := testProvider("aws") 3302 p.ApplyFn = testApplyFn 3303 p.DiffFn = testDiffFn 3304 ctx := testContext2(t, &ContextOpts{ 3305 Module: m, 3306 Providers: map[string]ResourceProviderFactory{ 3307 "aws": testProviderFuncFixed(p), 3308 }, 3309 }) 3310 3311 if _, err := ctx.Plan(); err != nil { 3312 t.Fatalf("err: %s", err) 3313 } 3314 3315 state, err := ctx.Apply() 3316 if err != nil { 3317 t.Fatalf("err: %s", err) 3318 } 3319 3320 actual := strings.TrimSpace(state.String()) 3321 expected := strings.TrimSpace(testTerraformApplyOutputStr) 3322 if actual != expected { 3323 t.Fatalf("bad: \n%s", actual) 3324 } 3325 } 3326 3327 func TestContext2Apply_outputInvalid(t *testing.T) { 3328 m := testModule(t, "apply-output-invalid") 3329 p := testProvider("aws") 3330 p.ApplyFn = testApplyFn 3331 p.DiffFn = testDiffFn 3332 ctx := testContext2(t, &ContextOpts{ 3333 Module: m, 3334 Providers: map[string]ResourceProviderFactory{ 3335 "aws": testProviderFuncFixed(p), 3336 }, 3337 }) 3338 3339 _, err := ctx.Plan() 3340 if err == nil { 3341 t.Fatalf("err: %s", err) 3342 } 3343 if !strings.Contains(err.Error(), "is not a valid type") { 3344 t.Fatalf("err: %s", err) 3345 } 3346 } 3347 3348 func TestContext2Apply_outputAdd(t *testing.T) { 3349 m1 := testModule(t, "apply-output-add-before") 3350 p1 := testProvider("aws") 3351 p1.ApplyFn = testApplyFn 3352 p1.DiffFn = testDiffFn 3353 ctx1 := testContext2(t, &ContextOpts{ 3354 Module: m1, 3355 Providers: map[string]ResourceProviderFactory{ 3356 "aws": testProviderFuncFixed(p1), 3357 }, 3358 }) 3359 3360 if _, err := ctx1.Plan(); err != nil { 3361 t.Fatalf("err: %s", err) 3362 } 3363 3364 state1, err := ctx1.Apply() 3365 if err != nil { 3366 t.Fatalf("err: %s", err) 3367 } 3368 3369 m2 := testModule(t, "apply-output-add-after") 3370 p2 := testProvider("aws") 3371 p2.ApplyFn = testApplyFn 3372 p2.DiffFn = testDiffFn 3373 ctx2 := testContext2(t, &ContextOpts{ 3374 Module: m2, 3375 Providers: map[string]ResourceProviderFactory{ 3376 "aws": testProviderFuncFixed(p2), 3377 }, 3378 State: state1, 3379 }) 3380 3381 if _, err := ctx2.Plan(); err != nil { 3382 t.Fatalf("err: %s", err) 3383 } 3384 3385 state2, err := ctx2.Apply() 3386 if err != nil { 3387 t.Fatalf("err: %s", err) 3388 } 3389 3390 actual := strings.TrimSpace(state2.String()) 3391 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 3392 if actual != expected { 3393 t.Fatalf("bad: \n%s", actual) 3394 } 3395 } 3396 3397 func TestContext2Apply_outputList(t *testing.T) { 3398 m := testModule(t, "apply-output-list") 3399 p := testProvider("aws") 3400 p.ApplyFn = testApplyFn 3401 p.DiffFn = testDiffFn 3402 ctx := testContext2(t, &ContextOpts{ 3403 Module: m, 3404 Providers: map[string]ResourceProviderFactory{ 3405 "aws": testProviderFuncFixed(p), 3406 }, 3407 }) 3408 3409 if _, err := ctx.Plan(); err != nil { 3410 t.Fatalf("err: %s", err) 3411 } 3412 3413 state, err := ctx.Apply() 3414 if err != nil { 3415 t.Fatalf("err: %s", err) 3416 } 3417 3418 actual := strings.TrimSpace(state.String()) 3419 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 3420 if actual != expected { 3421 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 3422 } 3423 } 3424 3425 func TestContext2Apply_outputMulti(t *testing.T) { 3426 m := testModule(t, "apply-output-multi") 3427 p := testProvider("aws") 3428 p.ApplyFn = testApplyFn 3429 p.DiffFn = testDiffFn 3430 ctx := testContext2(t, &ContextOpts{ 3431 Module: m, 3432 Providers: map[string]ResourceProviderFactory{ 3433 "aws": testProviderFuncFixed(p), 3434 }, 3435 }) 3436 3437 if _, err := ctx.Plan(); err != nil { 3438 t.Fatalf("err: %s", err) 3439 } 3440 3441 state, err := ctx.Apply() 3442 if err != nil { 3443 t.Fatalf("err: %s", err) 3444 } 3445 3446 actual := strings.TrimSpace(state.String()) 3447 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 3448 if actual != expected { 3449 t.Fatalf("bad: \n%s", actual) 3450 } 3451 } 3452 3453 func TestContext2Apply_outputMultiIndex(t *testing.T) { 3454 m := testModule(t, "apply-output-multi-index") 3455 p := testProvider("aws") 3456 p.ApplyFn = testApplyFn 3457 p.DiffFn = testDiffFn 3458 ctx := testContext2(t, &ContextOpts{ 3459 Module: m, 3460 Providers: map[string]ResourceProviderFactory{ 3461 "aws": testProviderFuncFixed(p), 3462 }, 3463 }) 3464 3465 if _, err := ctx.Plan(); err != nil { 3466 t.Fatalf("err: %s", err) 3467 } 3468 3469 state, err := ctx.Apply() 3470 if err != nil { 3471 t.Fatalf("err: %s", err) 3472 } 3473 3474 actual := strings.TrimSpace(state.String()) 3475 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 3476 if actual != expected { 3477 t.Fatalf("bad: \n%s", actual) 3478 } 3479 } 3480 3481 func TestContext2Apply_taint(t *testing.T) { 3482 m := testModule(t, "apply-taint") 3483 p := testProvider("aws") 3484 3485 // destroyCount tests against regression of 3486 // https://github.com/hashicorp/terraform/issues/1056 3487 var destroyCount = int32(0) 3488 var once sync.Once 3489 simulateProviderDelay := func() { 3490 time.Sleep(10 * time.Millisecond) 3491 } 3492 3493 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3494 once.Do(simulateProviderDelay) 3495 if d.Destroy { 3496 atomic.AddInt32(&destroyCount, 1) 3497 } 3498 return testApplyFn(info, s, d) 3499 } 3500 p.DiffFn = testDiffFn 3501 s := &State{ 3502 Modules: []*ModuleState{ 3503 &ModuleState{ 3504 Path: rootModulePath, 3505 Resources: map[string]*ResourceState{ 3506 "aws_instance.bar": &ResourceState{ 3507 Type: "aws_instance", 3508 Tainted: []*InstanceState{ 3509 &InstanceState{ 3510 ID: "baz", 3511 Attributes: map[string]string{ 3512 "num": "2", 3513 "type": "aws_instance", 3514 }, 3515 }, 3516 }, 3517 }, 3518 }, 3519 }, 3520 }, 3521 } 3522 ctx := testContext2(t, &ContextOpts{ 3523 Module: m, 3524 Providers: map[string]ResourceProviderFactory{ 3525 "aws": testProviderFuncFixed(p), 3526 }, 3527 State: s, 3528 }) 3529 3530 if _, err := ctx.Plan(); err != nil { 3531 t.Fatalf("err: %s", err) 3532 } 3533 3534 state, err := ctx.Apply() 3535 if err != nil { 3536 t.Fatalf("err: %s", err) 3537 } 3538 3539 actual := strings.TrimSpace(state.String()) 3540 expected := strings.TrimSpace(testTerraformApplyTaintStr) 3541 if actual != expected { 3542 t.Fatalf("bad:\n%s", actual) 3543 } 3544 3545 if destroyCount != 1 { 3546 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 3547 } 3548 } 3549 3550 func TestContext2Apply_taintDep(t *testing.T) { 3551 m := testModule(t, "apply-taint-dep") 3552 p := testProvider("aws") 3553 p.ApplyFn = testApplyFn 3554 p.DiffFn = testDiffFn 3555 s := &State{ 3556 Modules: []*ModuleState{ 3557 &ModuleState{ 3558 Path: rootModulePath, 3559 Resources: map[string]*ResourceState{ 3560 "aws_instance.foo": &ResourceState{ 3561 Type: "aws_instance", 3562 Tainted: []*InstanceState{ 3563 &InstanceState{ 3564 ID: "baz", 3565 Attributes: map[string]string{ 3566 "num": "2", 3567 "type": "aws_instance", 3568 }, 3569 }, 3570 }, 3571 }, 3572 "aws_instance.bar": &ResourceState{ 3573 Type: "aws_instance", 3574 Primary: &InstanceState{ 3575 ID: "bar", 3576 Attributes: map[string]string{ 3577 "foo": "baz", 3578 "num": "2", 3579 "type": "aws_instance", 3580 }, 3581 }, 3582 }, 3583 }, 3584 }, 3585 }, 3586 } 3587 ctx := testContext2(t, &ContextOpts{ 3588 Module: m, 3589 Providers: map[string]ResourceProviderFactory{ 3590 "aws": testProviderFuncFixed(p), 3591 }, 3592 State: s, 3593 }) 3594 3595 if p, err := ctx.Plan(); err != nil { 3596 t.Fatalf("err: %s", err) 3597 } else { 3598 t.Logf("plan: %s", p) 3599 } 3600 3601 state, err := ctx.Apply() 3602 if err != nil { 3603 t.Fatalf("err: %s", err) 3604 } 3605 3606 actual := strings.TrimSpace(state.String()) 3607 expected := strings.TrimSpace(testTerraformApplyTaintDepStr) 3608 if actual != expected { 3609 t.Fatalf("bad:\n%s", actual) 3610 } 3611 } 3612 3613 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 3614 m := testModule(t, "apply-taint-dep-requires-new") 3615 p := testProvider("aws") 3616 p.ApplyFn = testApplyFn 3617 p.DiffFn = testDiffFn 3618 s := &State{ 3619 Modules: []*ModuleState{ 3620 &ModuleState{ 3621 Path: rootModulePath, 3622 Resources: map[string]*ResourceState{ 3623 "aws_instance.foo": &ResourceState{ 3624 Type: "aws_instance", 3625 Tainted: []*InstanceState{ 3626 &InstanceState{ 3627 ID: "baz", 3628 Attributes: map[string]string{ 3629 "num": "2", 3630 "type": "aws_instance", 3631 }, 3632 }, 3633 }, 3634 }, 3635 "aws_instance.bar": &ResourceState{ 3636 Type: "aws_instance", 3637 Primary: &InstanceState{ 3638 ID: "bar", 3639 Attributes: map[string]string{ 3640 "foo": "baz", 3641 "num": "2", 3642 "type": "aws_instance", 3643 }, 3644 }, 3645 }, 3646 }, 3647 }, 3648 }, 3649 } 3650 ctx := testContext2(t, &ContextOpts{ 3651 Module: m, 3652 Providers: map[string]ResourceProviderFactory{ 3653 "aws": testProviderFuncFixed(p), 3654 }, 3655 State: s, 3656 }) 3657 3658 if p, err := ctx.Plan(); err != nil { 3659 t.Fatalf("err: %s", err) 3660 } else { 3661 t.Logf("plan: %s", p) 3662 } 3663 3664 state, err := ctx.Apply() 3665 if err != nil { 3666 t.Fatalf("err: %s", err) 3667 } 3668 3669 actual := strings.TrimSpace(state.String()) 3670 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 3671 if actual != expected { 3672 t.Fatalf("bad:\n%s", actual) 3673 } 3674 } 3675 3676 func TestContext2Apply_targeted(t *testing.T) { 3677 m := testModule(t, "apply-targeted") 3678 p := testProvider("aws") 3679 p.ApplyFn = testApplyFn 3680 p.DiffFn = testDiffFn 3681 ctx := testContext2(t, &ContextOpts{ 3682 Module: m, 3683 Providers: map[string]ResourceProviderFactory{ 3684 "aws": testProviderFuncFixed(p), 3685 }, 3686 Targets: []string{"aws_instance.foo"}, 3687 }) 3688 3689 if _, err := ctx.Plan(); err != nil { 3690 t.Fatalf("err: %s", err) 3691 } 3692 3693 state, err := ctx.Apply() 3694 if err != nil { 3695 t.Fatalf("err: %s", err) 3696 } 3697 3698 mod := state.RootModule() 3699 if len(mod.Resources) != 1 { 3700 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 3701 } 3702 3703 checkStateString(t, state, ` 3704 aws_instance.foo: 3705 ID = foo 3706 num = 2 3707 type = aws_instance 3708 `) 3709 } 3710 3711 func TestContext2Apply_targetedCount(t *testing.T) { 3712 m := testModule(t, "apply-targeted-count") 3713 p := testProvider("aws") 3714 p.ApplyFn = testApplyFn 3715 p.DiffFn = testDiffFn 3716 ctx := testContext2(t, &ContextOpts{ 3717 Module: m, 3718 Providers: map[string]ResourceProviderFactory{ 3719 "aws": testProviderFuncFixed(p), 3720 }, 3721 Targets: []string{"aws_instance.foo"}, 3722 }) 3723 3724 if _, err := ctx.Plan(); err != nil { 3725 t.Fatalf("err: %s", err) 3726 } 3727 3728 state, err := ctx.Apply() 3729 if err != nil { 3730 t.Fatalf("err: %s", err) 3731 } 3732 3733 checkStateString(t, state, ` 3734 aws_instance.foo.0: 3735 ID = foo 3736 aws_instance.foo.1: 3737 ID = foo 3738 aws_instance.foo.2: 3739 ID = foo 3740 `) 3741 } 3742 3743 func TestContext2Apply_targetedCountIndex(t *testing.T) { 3744 m := testModule(t, "apply-targeted-count") 3745 p := testProvider("aws") 3746 p.ApplyFn = testApplyFn 3747 p.DiffFn = testDiffFn 3748 ctx := testContext2(t, &ContextOpts{ 3749 Module: m, 3750 Providers: map[string]ResourceProviderFactory{ 3751 "aws": testProviderFuncFixed(p), 3752 }, 3753 Targets: []string{"aws_instance.foo[1]"}, 3754 }) 3755 3756 if _, err := ctx.Plan(); err != nil { 3757 t.Fatalf("err: %s", err) 3758 } 3759 3760 state, err := ctx.Apply() 3761 if err != nil { 3762 t.Fatalf("err: %s", err) 3763 } 3764 3765 checkStateString(t, state, ` 3766 aws_instance.foo.1: 3767 ID = foo 3768 `) 3769 } 3770 3771 func TestContext2Apply_targetedDestroy(t *testing.T) { 3772 m := testModule(t, "apply-targeted") 3773 p := testProvider("aws") 3774 p.ApplyFn = testApplyFn 3775 p.DiffFn = testDiffFn 3776 ctx := testContext2(t, &ContextOpts{ 3777 Module: m, 3778 Providers: map[string]ResourceProviderFactory{ 3779 "aws": testProviderFuncFixed(p), 3780 }, 3781 State: &State{ 3782 Modules: []*ModuleState{ 3783 &ModuleState{ 3784 Path: rootModulePath, 3785 Resources: map[string]*ResourceState{ 3786 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 3787 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 3788 }, 3789 }, 3790 }, 3791 }, 3792 Targets: []string{"aws_instance.foo"}, 3793 Destroy: true, 3794 }) 3795 3796 if _, err := ctx.Plan(); err != nil { 3797 t.Fatalf("err: %s", err) 3798 } 3799 3800 state, err := ctx.Apply() 3801 if err != nil { 3802 t.Fatalf("err: %s", err) 3803 } 3804 3805 mod := state.RootModule() 3806 if len(mod.Resources) != 1 { 3807 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 3808 } 3809 3810 checkStateString(t, state, ` 3811 aws_instance.bar: 3812 ID = i-abc123 3813 `) 3814 } 3815 3816 // https://github.com/hashicorp/terraform/issues/4462 3817 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 3818 m := testModule(t, "apply-targeted-module") 3819 p := testProvider("aws") 3820 p.ApplyFn = testApplyFn 3821 p.DiffFn = testDiffFn 3822 ctx := testContext2(t, &ContextOpts{ 3823 Module: m, 3824 Providers: map[string]ResourceProviderFactory{ 3825 "aws": testProviderFuncFixed(p), 3826 }, 3827 State: &State{ 3828 Modules: []*ModuleState{ 3829 &ModuleState{ 3830 Path: rootModulePath, 3831 Resources: map[string]*ResourceState{ 3832 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 3833 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 3834 }, 3835 }, 3836 &ModuleState{ 3837 Path: []string{"root", "child"}, 3838 Resources: map[string]*ResourceState{ 3839 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 3840 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 3841 }, 3842 }, 3843 }, 3844 }, 3845 Targets: []string{"module.child.aws_instance.foo"}, 3846 Destroy: true, 3847 }) 3848 3849 if _, err := ctx.Plan(); err != nil { 3850 t.Fatalf("err: %s", err) 3851 } 3852 3853 state, err := ctx.Apply() 3854 if err != nil { 3855 t.Fatalf("err: %s", err) 3856 } 3857 3858 checkStateString(t, state, ` 3859 aws_instance.bar: 3860 ID = i-abc123 3861 aws_instance.foo: 3862 ID = i-bcd345 3863 3864 module.child: 3865 aws_instance.bar: 3866 ID = i-abc123 3867 `) 3868 } 3869 3870 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 3871 m := testModule(t, "apply-targeted-count") 3872 p := testProvider("aws") 3873 p.ApplyFn = testApplyFn 3874 p.DiffFn = testDiffFn 3875 ctx := testContext2(t, &ContextOpts{ 3876 Module: m, 3877 Providers: map[string]ResourceProviderFactory{ 3878 "aws": testProviderFuncFixed(p), 3879 }, 3880 State: &State{ 3881 Modules: []*ModuleState{ 3882 &ModuleState{ 3883 Path: rootModulePath, 3884 Resources: map[string]*ResourceState{ 3885 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 3886 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 3887 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 3888 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 3889 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 3890 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 3891 }, 3892 }, 3893 }, 3894 }, 3895 Targets: []string{ 3896 "aws_instance.foo[2]", 3897 "aws_instance.bar[1]", 3898 }, 3899 Destroy: true, 3900 }) 3901 3902 if _, err := ctx.Plan(); err != nil { 3903 t.Fatalf("err: %s", err) 3904 } 3905 3906 state, err := ctx.Apply() 3907 if err != nil { 3908 t.Fatalf("err: %s", err) 3909 } 3910 3911 checkStateString(t, state, ` 3912 aws_instance.bar.0: 3913 ID = i-abc123 3914 aws_instance.bar.2: 3915 ID = i-abc123 3916 aws_instance.foo.0: 3917 ID = i-bcd345 3918 aws_instance.foo.1: 3919 ID = i-bcd345 3920 `) 3921 } 3922 3923 func TestContext2Apply_targetedModule(t *testing.T) { 3924 m := testModule(t, "apply-targeted-module") 3925 p := testProvider("aws") 3926 p.ApplyFn = testApplyFn 3927 p.DiffFn = testDiffFn 3928 ctx := testContext2(t, &ContextOpts{ 3929 Module: m, 3930 Providers: map[string]ResourceProviderFactory{ 3931 "aws": testProviderFuncFixed(p), 3932 }, 3933 Targets: []string{"module.child"}, 3934 }) 3935 3936 if _, err := ctx.Plan(); err != nil { 3937 t.Fatalf("err: %s", err) 3938 } 3939 3940 state, err := ctx.Apply() 3941 if err != nil { 3942 t.Fatalf("err: %s", err) 3943 } 3944 3945 mod := state.ModuleByPath([]string{"root", "child"}) 3946 if mod == nil { 3947 t.Fatalf("no child module found in the state!\n\n%#v", state) 3948 } 3949 if len(mod.Resources) != 2 { 3950 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 3951 } 3952 3953 checkStateString(t, state, ` 3954 <no state> 3955 module.child: 3956 aws_instance.bar: 3957 ID = foo 3958 num = 2 3959 type = aws_instance 3960 aws_instance.foo: 3961 ID = foo 3962 num = 2 3963 type = aws_instance 3964 `) 3965 } 3966 3967 // GH-1858 3968 func TestContext2Apply_targetedModuleDep(t *testing.T) { 3969 m := testModule(t, "apply-targeted-module-dep") 3970 p := testProvider("aws") 3971 p.ApplyFn = testApplyFn 3972 p.DiffFn = testDiffFn 3973 ctx := testContext2(t, &ContextOpts{ 3974 Module: m, 3975 Providers: map[string]ResourceProviderFactory{ 3976 "aws": testProviderFuncFixed(p), 3977 }, 3978 Targets: []string{"aws_instance.foo"}, 3979 }) 3980 3981 if _, err := ctx.Plan(); err != nil { 3982 t.Fatalf("err: %s", err) 3983 } 3984 3985 state, err := ctx.Apply() 3986 if err != nil { 3987 t.Fatalf("err: %s", err) 3988 } 3989 3990 checkStateString(t, state, ` 3991 aws_instance.foo: 3992 ID = foo 3993 foo = foo 3994 type = aws_instance 3995 3996 Dependencies: 3997 module.child 3998 3999 module.child: 4000 aws_instance.mod: 4001 ID = foo 4002 4003 Outputs: 4004 4005 output = foo 4006 `) 4007 } 4008 4009 func TestContext2Apply_targetedModuleResource(t *testing.T) { 4010 m := testModule(t, "apply-targeted-module-resource") 4011 p := testProvider("aws") 4012 p.ApplyFn = testApplyFn 4013 p.DiffFn = testDiffFn 4014 ctx := testContext2(t, &ContextOpts{ 4015 Module: m, 4016 Providers: map[string]ResourceProviderFactory{ 4017 "aws": testProviderFuncFixed(p), 4018 }, 4019 Targets: []string{"module.child.aws_instance.foo"}, 4020 }) 4021 4022 if _, err := ctx.Plan(); err != nil { 4023 t.Fatalf("err: %s", err) 4024 } 4025 4026 state, err := ctx.Apply() 4027 if err != nil { 4028 t.Fatalf("err: %s", err) 4029 } 4030 4031 mod := state.ModuleByPath([]string{"root", "child"}) 4032 if len(mod.Resources) != 1 { 4033 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 4034 } 4035 4036 checkStateString(t, state, ` 4037 <no state> 4038 module.child: 4039 aws_instance.foo: 4040 ID = foo 4041 num = 2 4042 type = aws_instance 4043 `) 4044 } 4045 4046 func TestContext2Apply_unknownAttribute(t *testing.T) { 4047 m := testModule(t, "apply-unknown") 4048 p := testProvider("aws") 4049 p.ApplyFn = testApplyFn 4050 p.DiffFn = testDiffFn 4051 ctx := testContext2(t, &ContextOpts{ 4052 Module: m, 4053 Providers: map[string]ResourceProviderFactory{ 4054 "aws": testProviderFuncFixed(p), 4055 }, 4056 }) 4057 4058 if _, err := ctx.Plan(); err != nil { 4059 t.Fatalf("err: %s", err) 4060 } 4061 4062 state, err := ctx.Apply() 4063 if err == nil { 4064 t.Fatal("should error") 4065 } 4066 4067 actual := strings.TrimSpace(state.String()) 4068 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 4069 if actual != expected { 4070 t.Fatalf("bad: \n%s", actual) 4071 } 4072 } 4073 4074 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 4075 m := testModule(t, "apply-unknown-interpolate") 4076 p := testProvider("aws") 4077 p.ApplyFn = testApplyFn 4078 p.DiffFn = testDiffFn 4079 ctx := testContext2(t, &ContextOpts{ 4080 Module: m, 4081 Providers: map[string]ResourceProviderFactory{ 4082 "aws": testProviderFuncFixed(p), 4083 }, 4084 }) 4085 4086 if _, err := ctx.Plan(); err == nil { 4087 t.Fatal("should error") 4088 } 4089 } 4090 4091 func TestContext2Apply_vars(t *testing.T) { 4092 m := testModule(t, "apply-vars") 4093 p := testProvider("aws") 4094 p.ApplyFn = testApplyFn 4095 p.DiffFn = testDiffFn 4096 ctx := testContext2(t, &ContextOpts{ 4097 Module: m, 4098 Providers: map[string]ResourceProviderFactory{ 4099 "aws": testProviderFuncFixed(p), 4100 }, 4101 Variables: map[string]string{ 4102 "foo": "us-west-2", 4103 "amis.us-east-1": "override", 4104 }, 4105 }) 4106 4107 w, e := ctx.Validate() 4108 if len(w) > 0 { 4109 t.Fatalf("bad: %#v", w) 4110 } 4111 if len(e) > 0 { 4112 t.Fatalf("bad: %s", e) 4113 } 4114 4115 if _, err := ctx.Plan(); err != nil { 4116 t.Fatalf("err: %s", err) 4117 } 4118 4119 state, err := ctx.Apply() 4120 if err != nil { 4121 t.Fatalf("err: %s", err) 4122 } 4123 4124 actual := strings.TrimSpace(state.String()) 4125 expected := strings.TrimSpace(testTerraformApplyVarsStr) 4126 if actual != expected { 4127 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 4128 } 4129 } 4130 4131 func TestContext2Apply_varsEnv(t *testing.T) { 4132 // Set the env var 4133 old := tempEnv(t, "TF_VAR_ami", "baz") 4134 defer os.Setenv("TF_VAR_ami", old) 4135 4136 m := testModule(t, "apply-vars-env") 4137 p := testProvider("aws") 4138 p.ApplyFn = testApplyFn 4139 p.DiffFn = testDiffFn 4140 ctx := testContext2(t, &ContextOpts{ 4141 Module: m, 4142 Providers: map[string]ResourceProviderFactory{ 4143 "aws": testProviderFuncFixed(p), 4144 }, 4145 }) 4146 4147 w, e := ctx.Validate() 4148 if len(w) > 0 { 4149 t.Fatalf("bad: %#v", w) 4150 } 4151 if len(e) > 0 { 4152 t.Fatalf("bad: %s", e) 4153 } 4154 4155 if _, err := ctx.Plan(); err != nil { 4156 t.Fatalf("err: %s", err) 4157 } 4158 4159 state, err := ctx.Apply() 4160 if err != nil { 4161 t.Fatalf("err: %s", err) 4162 } 4163 4164 actual := strings.TrimSpace(state.String()) 4165 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 4166 if actual != expected { 4167 t.Fatalf("bad: \n%s", actual) 4168 } 4169 } 4170 4171 func TestContext2Apply_createBefore_depends(t *testing.T) { 4172 m := testModule(t, "apply-depends-create-before") 4173 h := new(HookRecordApplyOrder) 4174 p := testProvider("aws") 4175 p.ApplyFn = testApplyFn 4176 p.DiffFn = testDiffFn 4177 state := &State{ 4178 Modules: []*ModuleState{ 4179 &ModuleState{ 4180 Path: rootModulePath, 4181 Resources: map[string]*ResourceState{ 4182 "aws_instance.web": &ResourceState{ 4183 Type: "aws_instance", 4184 Primary: &InstanceState{ 4185 ID: "bar", 4186 Attributes: map[string]string{ 4187 "require_new": "ami-old", 4188 }, 4189 }, 4190 }, 4191 "aws_instance.lb": &ResourceState{ 4192 Type: "aws_instance", 4193 Primary: &InstanceState{ 4194 ID: "baz", 4195 Attributes: map[string]string{ 4196 "instance": "bar", 4197 }, 4198 }, 4199 }, 4200 }, 4201 }, 4202 }, 4203 } 4204 ctx := testContext2(t, &ContextOpts{ 4205 Module: m, 4206 Hooks: []Hook{h}, 4207 Providers: map[string]ResourceProviderFactory{ 4208 "aws": testProviderFuncFixed(p), 4209 }, 4210 State: state, 4211 }) 4212 4213 if _, err := ctx.Plan(); err != nil { 4214 t.Fatalf("err: %s", err) 4215 } 4216 4217 h.Active = true 4218 state, err := ctx.Apply() 4219 if err != nil { 4220 t.Fatalf("err: %s", err) 4221 } 4222 4223 mod := state.RootModule() 4224 if len(mod.Resources) < 2 { 4225 t.Fatalf("bad: %#v", mod.Resources) 4226 } 4227 4228 actual := strings.TrimSpace(state.String()) 4229 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 4230 if actual != expected { 4231 t.Fatalf("bad: \n%s\n%s", actual, expected) 4232 } 4233 4234 // Test that things were managed _in the right order_ 4235 order := h.States 4236 diffs := h.Diffs 4237 if order[0].ID != "" || diffs[0].Destroy { 4238 t.Fatalf("should create new instance first: %#v", order) 4239 } 4240 4241 if order[1].ID != "baz" { 4242 t.Fatalf("update must happen after create: %#v", order) 4243 } 4244 4245 if order[2].ID != "bar" || !diffs[2].Destroy { 4246 t.Fatalf("destroy must happen after update: %#v", order) 4247 } 4248 } 4249 4250 func TestContext2Apply_singleDestroy(t *testing.T) { 4251 m := testModule(t, "apply-depends-create-before") 4252 h := new(HookRecordApplyOrder) 4253 p := testProvider("aws") 4254 4255 invokeCount := 0 4256 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 4257 invokeCount++ 4258 switch invokeCount { 4259 case 1: 4260 if d.Destroy { 4261 t.Fatalf("should not destroy") 4262 } 4263 if s.ID != "" { 4264 t.Fatalf("should not have ID") 4265 } 4266 case 2: 4267 if d.Destroy { 4268 t.Fatalf("should not destroy") 4269 } 4270 if s.ID != "baz" { 4271 t.Fatalf("should have id") 4272 } 4273 case 3: 4274 if !d.Destroy { 4275 t.Fatalf("should destroy") 4276 } 4277 if s.ID == "" { 4278 t.Fatalf("should have ID") 4279 } 4280 default: 4281 t.Fatalf("bad invoke count %d", invokeCount) 4282 } 4283 return testApplyFn(info, s, d) 4284 } 4285 p.DiffFn = testDiffFn 4286 state := &State{ 4287 Modules: []*ModuleState{ 4288 &ModuleState{ 4289 Path: rootModulePath, 4290 Resources: map[string]*ResourceState{ 4291 "aws_instance.web": &ResourceState{ 4292 Type: "aws_instance", 4293 Primary: &InstanceState{ 4294 ID: "bar", 4295 Attributes: map[string]string{ 4296 "require_new": "ami-old", 4297 }, 4298 }, 4299 }, 4300 "aws_instance.lb": &ResourceState{ 4301 Type: "aws_instance", 4302 Primary: &InstanceState{ 4303 ID: "baz", 4304 Attributes: map[string]string{ 4305 "instance": "bar", 4306 }, 4307 }, 4308 }, 4309 }, 4310 }, 4311 }, 4312 } 4313 ctx := testContext2(t, &ContextOpts{ 4314 Module: m, 4315 Hooks: []Hook{h}, 4316 Providers: map[string]ResourceProviderFactory{ 4317 "aws": testProviderFuncFixed(p), 4318 }, 4319 State: state, 4320 }) 4321 4322 if _, err := ctx.Plan(); err != nil { 4323 t.Fatalf("err: %s", err) 4324 } 4325 4326 h.Active = true 4327 state, err := ctx.Apply() 4328 if err != nil { 4329 t.Fatalf("err: %s", err) 4330 } 4331 4332 if invokeCount != 3 { 4333 t.Fatalf("bad: %d", invokeCount) 4334 } 4335 } 4336 4337 // GH-5254 4338 func TestContext2Apply_issue5254(t *testing.T) { 4339 // Create a provider. We use "template" here just to match the repro 4340 // we got from the issue itself. 4341 p := testProvider("template") 4342 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 4343 Name: "template_file", 4344 }) 4345 4346 p.ApplyFn = testApplyFn 4347 p.DiffFn = testDiffFn 4348 4349 // Apply cleanly step 0 4350 ctx := testContext2(t, &ContextOpts{ 4351 Module: testModule(t, "issue-5254/step-0"), 4352 Providers: map[string]ResourceProviderFactory{ 4353 "template": testProviderFuncFixed(p), 4354 }, 4355 }) 4356 4357 plan, err := ctx.Plan() 4358 if err != nil { 4359 t.Fatalf("err: %s", err) 4360 } 4361 4362 state, err := ctx.Apply() 4363 if err != nil { 4364 t.Fatalf("err: %s", err) 4365 } 4366 4367 // Application success. Now make the modification and store a plan 4368 ctx = testContext2(t, &ContextOpts{ 4369 Module: testModule(t, "issue-5254/step-1"), 4370 State: state, 4371 Providers: map[string]ResourceProviderFactory{ 4372 "template": testProviderFuncFixed(p), 4373 }, 4374 }) 4375 4376 plan, err = ctx.Plan() 4377 if err != nil { 4378 t.Fatalf("err: %s", err) 4379 } 4380 4381 // Write / Read plan to simulate running it through a Plan file 4382 var buf bytes.Buffer 4383 if err := WritePlan(plan, &buf); err != nil { 4384 t.Fatalf("err: %s", err) 4385 } 4386 4387 planFromFile, err := ReadPlan(&buf) 4388 if err != nil { 4389 t.Fatalf("err: %s", err) 4390 } 4391 4392 ctx, err = planFromFile.Context(&ContextOpts{ 4393 Providers: map[string]ResourceProviderFactory{ 4394 "template": testProviderFuncFixed(p), 4395 }, 4396 }) 4397 if err != nil { 4398 t.Fatalf("err: %s", err) 4399 } 4400 4401 state, err = ctx.Apply() 4402 if err != nil { 4403 t.Fatalf("err: %s", err) 4404 } 4405 4406 actual := strings.TrimSpace(state.String()) 4407 expected := strings.TrimSpace(` 4408 template_file.child: 4409 ID = foo 4410 template = Hi 4411 type = template_file 4412 4413 Dependencies: 4414 template_file.parent 4415 template_file.parent: 4416 ID = foo 4417 template = Hi 4418 type = template_file 4419 `) 4420 if actual != expected { 4421 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 4422 } 4423 } 4424 4425 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 4426 p := testProvider("aws") 4427 p.DiffFn = testDiffFn 4428 p.ApplyFn = testApplyFn 4429 ctx := testContext2(t, &ContextOpts{ 4430 Module: testModule(t, "apply-tainted-targets"), 4431 Providers: map[string]ResourceProviderFactory{ 4432 "aws": testProviderFuncFixed(p), 4433 }, 4434 Targets: []string{"aws_instance.iambeingadded"}, 4435 State: &State{ 4436 Modules: []*ModuleState{ 4437 &ModuleState{ 4438 Path: rootModulePath, 4439 Resources: map[string]*ResourceState{ 4440 "aws_instance.ifailedprovisioners": &ResourceState{ 4441 Tainted: []*InstanceState{ 4442 &InstanceState{ 4443 ID: "ifailedprovisioners", 4444 }, 4445 }, 4446 }, 4447 }, 4448 }, 4449 }, 4450 }, 4451 }) 4452 4453 plan, err := ctx.Plan() 4454 if err != nil { 4455 t.Fatalf("err: %s", err) 4456 } 4457 4458 // Write / Read plan to simulate running it through a Plan file 4459 var buf bytes.Buffer 4460 if err := WritePlan(plan, &buf); err != nil { 4461 t.Fatalf("err: %s", err) 4462 } 4463 4464 planFromFile, err := ReadPlan(&buf) 4465 if err != nil { 4466 t.Fatalf("err: %s", err) 4467 } 4468 4469 ctx, err = planFromFile.Context(&ContextOpts{ 4470 Module: testModule(t, "apply-tainted-targets"), 4471 Providers: map[string]ResourceProviderFactory{ 4472 "aws": testProviderFuncFixed(p), 4473 }, 4474 }) 4475 if err != nil { 4476 t.Fatalf("err: %s", err) 4477 } 4478 4479 state, err := ctx.Apply() 4480 if err != nil { 4481 t.Fatalf("err: %s", err) 4482 } 4483 4484 actual := strings.TrimSpace(state.String()) 4485 expected := strings.TrimSpace(` 4486 aws_instance.iambeingadded: 4487 ID = foo 4488 aws_instance.ifailedprovisioners: (1 tainted) 4489 ID = <not created> 4490 Tainted ID 1 = ifailedprovisioners 4491 `) 4492 if actual != expected { 4493 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 4494 } 4495 } 4496 4497 // Higher level test exposing the bug this covers in 4498 // TestResource_ignoreChangesRequired 4499 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 4500 m := testModule(t, "apply-ignore-changes-create") 4501 p := testProvider("aws") 4502 p.ApplyFn = testApplyFn 4503 p.DiffFn = testDiffFn 4504 ctx := testContext2(t, &ContextOpts{ 4505 Module: m, 4506 Providers: map[string]ResourceProviderFactory{ 4507 "aws": testProviderFuncFixed(p), 4508 }, 4509 }) 4510 4511 if p, err := ctx.Plan(); err != nil { 4512 t.Fatalf("err: %s", err) 4513 } else { 4514 t.Logf(p.String()) 4515 } 4516 4517 state, err := ctx.Apply() 4518 if err != nil { 4519 t.Fatalf("err: %s", err) 4520 } 4521 4522 mod := state.RootModule() 4523 if len(mod.Resources) != 1 { 4524 t.Fatalf("bad: %s", state) 4525 } 4526 4527 actual := strings.TrimSpace(state.String()) 4528 // Expect no changes from original state 4529 expected := strings.TrimSpace(` 4530 aws_instance.foo: 4531 ID = foo 4532 required_field = set 4533 type = aws_instance 4534 `) 4535 if actual != expected { 4536 t.Fatalf("bad: \n%s", actual) 4537 } 4538 }