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