github.com/inge4pres/terraform@v0.7.5-0.20160930053151-bd083f84f376/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_destroyTargetWithModuleVariableAndCount(t *testing.T) { 3123 m := testModule(t, "apply-destroy-mod-var-and-count") 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 { 3150 ctx := testContext2(t, &ContextOpts{ 3151 Destroy: true, 3152 Module: m, 3153 State: state, 3154 Providers: map[string]ResourceProviderFactory{ 3155 "aws": testProviderFuncFixed(p), 3156 }, 3157 Targets: []string{"module.child"}, 3158 }) 3159 3160 _, err := ctx.Plan() 3161 if err != nil { 3162 t.Fatalf("plan err: %s", err) 3163 } 3164 3165 // Destroy, targeting the module explicitly 3166 state, err = ctx.Apply() 3167 if err != nil { 3168 t.Fatalf("destroy apply err: %s", err) 3169 } 3170 } 3171 3172 //Test that things were destroyed 3173 actual := strings.TrimSpace(state.String()) 3174 expected := strings.TrimSpace(` 3175 <no state> 3176 module.child: 3177 <no state> 3178 `) 3179 if actual != expected { 3180 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 3181 } 3182 } 3183 3184 func TestContext2Apply_destroyWithModuleVariableAndCountNested(t *testing.T) { 3185 m := testModule(t, "apply-destroy-mod-var-and-count-nested") 3186 p := testProvider("aws") 3187 p.ApplyFn = testApplyFn 3188 p.DiffFn = testDiffFn 3189 3190 var state *State 3191 var err error 3192 { 3193 ctx := testContext2(t, &ContextOpts{ 3194 Module: m, 3195 Providers: map[string]ResourceProviderFactory{ 3196 "aws": testProviderFuncFixed(p), 3197 }, 3198 }) 3199 3200 // First plan and apply a create operation 3201 if _, err := ctx.Plan(); err != nil { 3202 t.Fatalf("plan err: %s", err) 3203 } 3204 3205 state, err = ctx.Apply() 3206 if err != nil { 3207 t.Fatalf("apply err: %s", err) 3208 } 3209 } 3210 3211 h := new(HookRecordApplyOrder) 3212 h.Active = true 3213 3214 { 3215 ctx := testContext2(t, &ContextOpts{ 3216 Destroy: true, 3217 Module: m, 3218 State: state, 3219 Hooks: []Hook{h}, 3220 Providers: map[string]ResourceProviderFactory{ 3221 "aws": testProviderFuncFixed(p), 3222 }, 3223 }) 3224 3225 // First plan and apply a create operation 3226 plan, err := ctx.Plan() 3227 if err != nil { 3228 t.Fatalf("destroy plan err: %s", err) 3229 } 3230 3231 var buf bytes.Buffer 3232 if err := WritePlan(plan, &buf); err != nil { 3233 t.Fatalf("plan write err: %s", err) 3234 } 3235 3236 planFromFile, err := ReadPlan(&buf) 3237 if err != nil { 3238 t.Fatalf("plan read err: %s", err) 3239 } 3240 3241 ctx, err = planFromFile.Context(&ContextOpts{ 3242 Providers: map[string]ResourceProviderFactory{ 3243 "aws": testProviderFuncFixed(p), 3244 }, 3245 }) 3246 if err != nil { 3247 t.Fatalf("err: %s", err) 3248 } 3249 3250 state, err = ctx.Apply() 3251 if err != nil { 3252 t.Fatalf("destroy apply err: %s", err) 3253 } 3254 } 3255 3256 //Test that things were destroyed 3257 actual := strings.TrimSpace(state.String()) 3258 expected := strings.TrimSpace(` 3259 <no state> 3260 module.child: 3261 <no state> 3262 module.child.child2: 3263 <no state> 3264 `) 3265 if actual != expected { 3266 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 3267 } 3268 } 3269 3270 func TestContext2Apply_destroyOutputs(t *testing.T) { 3271 m := testModule(t, "apply-destroy-outputs") 3272 h := new(HookRecordApplyOrder) 3273 p := testProvider("aws") 3274 p.ApplyFn = testApplyFn 3275 p.DiffFn = testDiffFn 3276 ctx := testContext2(t, &ContextOpts{ 3277 Module: m, 3278 Hooks: []Hook{h}, 3279 Providers: map[string]ResourceProviderFactory{ 3280 "aws": testProviderFuncFixed(p), 3281 }, 3282 }) 3283 3284 // First plan and apply a create operation 3285 if _, err := ctx.Plan(); err != nil { 3286 t.Fatalf("err: %s", err) 3287 } 3288 3289 state, err := ctx.Apply() 3290 3291 if err != nil { 3292 t.Fatalf("err: %s", err) 3293 } 3294 3295 // Next, plan and apply a destroy operation 3296 h.Active = true 3297 ctx = testContext2(t, &ContextOpts{ 3298 Destroy: true, 3299 State: state, 3300 Module: m, 3301 Hooks: []Hook{h}, 3302 Providers: map[string]ResourceProviderFactory{ 3303 "aws": testProviderFuncFixed(p), 3304 }, 3305 }) 3306 3307 if _, err := ctx.Plan(); err != nil { 3308 t.Fatalf("err: %s", err) 3309 } 3310 3311 state, err = ctx.Apply() 3312 if err != nil { 3313 t.Fatalf("err: %s", err) 3314 } 3315 3316 mod := state.RootModule() 3317 if len(mod.Resources) > 0 { 3318 t.Fatalf("bad: %#v", mod) 3319 } 3320 } 3321 3322 func TestContext2Apply_destroyOrphan(t *testing.T) { 3323 m := testModule(t, "apply-error") 3324 p := testProvider("aws") 3325 s := &State{ 3326 Modules: []*ModuleState{ 3327 &ModuleState{ 3328 Path: rootModulePath, 3329 Resources: map[string]*ResourceState{ 3330 "aws_instance.baz": &ResourceState{ 3331 Type: "aws_instance", 3332 Primary: &InstanceState{ 3333 ID: "bar", 3334 }, 3335 }, 3336 }, 3337 }, 3338 }, 3339 } 3340 ctx := testContext2(t, &ContextOpts{ 3341 Module: m, 3342 Providers: map[string]ResourceProviderFactory{ 3343 "aws": testProviderFuncFixed(p), 3344 }, 3345 State: s, 3346 }) 3347 3348 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3349 if d.Destroy { 3350 return nil, nil 3351 } 3352 3353 result := s.MergeDiff(d) 3354 result.ID = "foo" 3355 return result, nil 3356 } 3357 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3358 return &InstanceDiff{ 3359 Attributes: map[string]*ResourceAttrDiff{ 3360 "num": &ResourceAttrDiff{ 3361 New: "bar", 3362 }, 3363 }, 3364 }, nil 3365 } 3366 3367 if _, err := ctx.Plan(); err != nil { 3368 t.Fatalf("err: %s", err) 3369 } 3370 3371 state, err := ctx.Apply() 3372 if err != nil { 3373 t.Fatalf("err: %s", err) 3374 } 3375 3376 mod := state.RootModule() 3377 if _, ok := mod.Resources["aws_instance.baz"]; ok { 3378 t.Fatalf("bad: %#v", mod.Resources) 3379 } 3380 } 3381 3382 func TestContext2Apply_destroyTaintedProvisioner(t *testing.T) { 3383 m := testModule(t, "apply-destroy-provisioner") 3384 p := testProvider("aws") 3385 pr := testProvisioner() 3386 p.ApplyFn = testApplyFn 3387 p.DiffFn = testDiffFn 3388 3389 called := false 3390 pr.ApplyFn = func(rs *InstanceState, c *ResourceConfig) error { 3391 called = true 3392 return nil 3393 } 3394 3395 s := &State{ 3396 Modules: []*ModuleState{ 3397 &ModuleState{ 3398 Path: rootModulePath, 3399 Resources: map[string]*ResourceState{ 3400 "aws_instance.foo": &ResourceState{ 3401 Type: "aws_instance", 3402 Primary: &InstanceState{ 3403 ID: "bar", 3404 Attributes: map[string]string{ 3405 "id": "bar", 3406 }, 3407 Tainted: true, 3408 }, 3409 }, 3410 }, 3411 }, 3412 }, 3413 } 3414 3415 ctx := testContext2(t, &ContextOpts{ 3416 Module: m, 3417 Providers: map[string]ResourceProviderFactory{ 3418 "aws": testProviderFuncFixed(p), 3419 }, 3420 Provisioners: map[string]ResourceProvisionerFactory{ 3421 "shell": testProvisionerFuncFixed(pr), 3422 }, 3423 State: s, 3424 Destroy: true, 3425 }) 3426 3427 if _, err := ctx.Plan(); err != nil { 3428 t.Fatalf("err: %s", err) 3429 } 3430 3431 state, err := ctx.Apply() 3432 if err != nil { 3433 t.Fatalf("err: %s", err) 3434 } 3435 3436 if called { 3437 t.Fatal("provisioner should not be called") 3438 } 3439 3440 actual := strings.TrimSpace(state.String()) 3441 expected := strings.TrimSpace("<no state>") 3442 if actual != expected { 3443 t.Fatalf("bad: \n%s", actual) 3444 } 3445 } 3446 3447 func TestContext2Apply_error(t *testing.T) { 3448 errored := false 3449 3450 m := testModule(t, "apply-error") 3451 p := testProvider("aws") 3452 ctx := testContext2(t, &ContextOpts{ 3453 Module: m, 3454 Providers: map[string]ResourceProviderFactory{ 3455 "aws": testProviderFuncFixed(p), 3456 }, 3457 }) 3458 3459 p.ApplyFn = func(*InstanceInfo, *InstanceState, *InstanceDiff) (*InstanceState, error) { 3460 if errored { 3461 state := &InstanceState{ 3462 ID: "bar", 3463 } 3464 return state, fmt.Errorf("error") 3465 } 3466 errored = true 3467 3468 return &InstanceState{ 3469 ID: "foo", 3470 Attributes: map[string]string{ 3471 "num": "2", 3472 }, 3473 }, nil 3474 } 3475 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3476 return &InstanceDiff{ 3477 Attributes: map[string]*ResourceAttrDiff{ 3478 "num": &ResourceAttrDiff{ 3479 New: "bar", 3480 }, 3481 }, 3482 }, nil 3483 } 3484 3485 if _, err := ctx.Plan(); err != nil { 3486 t.Fatalf("err: %s", err) 3487 } 3488 3489 state, err := ctx.Apply() 3490 if err == nil { 3491 t.Fatal("should have error") 3492 } 3493 3494 actual := strings.TrimSpace(state.String()) 3495 expected := strings.TrimSpace(testTerraformApplyErrorStr) 3496 if actual != expected { 3497 t.Fatalf("bad: \n%s", actual) 3498 } 3499 } 3500 3501 func TestContext2Apply_errorPartial(t *testing.T) { 3502 errored := false 3503 3504 m := testModule(t, "apply-error") 3505 p := testProvider("aws") 3506 s := &State{ 3507 Modules: []*ModuleState{ 3508 &ModuleState{ 3509 Path: rootModulePath, 3510 Resources: map[string]*ResourceState{ 3511 "aws_instance.bar": &ResourceState{ 3512 Type: "aws_instance", 3513 Primary: &InstanceState{ 3514 ID: "bar", 3515 }, 3516 }, 3517 }, 3518 }, 3519 }, 3520 } 3521 ctx := testContext2(t, &ContextOpts{ 3522 Module: m, 3523 Providers: map[string]ResourceProviderFactory{ 3524 "aws": testProviderFuncFixed(p), 3525 }, 3526 State: s, 3527 }) 3528 3529 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3530 if errored { 3531 return s, fmt.Errorf("error") 3532 } 3533 errored = true 3534 3535 return &InstanceState{ 3536 ID: "foo", 3537 Attributes: map[string]string{ 3538 "num": "2", 3539 }, 3540 }, nil 3541 } 3542 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3543 return &InstanceDiff{ 3544 Attributes: map[string]*ResourceAttrDiff{ 3545 "num": &ResourceAttrDiff{ 3546 New: "bar", 3547 }, 3548 }, 3549 }, nil 3550 } 3551 3552 if _, err := ctx.Plan(); err != nil { 3553 t.Fatalf("err: %s", err) 3554 } 3555 3556 state, err := ctx.Apply() 3557 if err == nil { 3558 t.Fatal("should have error") 3559 } 3560 3561 mod := state.RootModule() 3562 if len(mod.Resources) != 2 { 3563 t.Fatalf("bad: %#v", mod.Resources) 3564 } 3565 3566 actual := strings.TrimSpace(state.String()) 3567 expected := strings.TrimSpace(testTerraformApplyErrorPartialStr) 3568 if actual != expected { 3569 t.Fatalf("bad: \n%s", actual) 3570 } 3571 } 3572 3573 func TestContext2Apply_hook(t *testing.T) { 3574 m := testModule(t, "apply-good") 3575 h := new(MockHook) 3576 p := testProvider("aws") 3577 p.ApplyFn = testApplyFn 3578 p.DiffFn = testDiffFn 3579 ctx := testContext2(t, &ContextOpts{ 3580 Module: m, 3581 Hooks: []Hook{h}, 3582 Providers: map[string]ResourceProviderFactory{ 3583 "aws": testProviderFuncFixed(p), 3584 }, 3585 }) 3586 3587 if _, err := ctx.Plan(); err != nil { 3588 t.Fatalf("err: %s", err) 3589 } 3590 3591 if _, err := ctx.Apply(); err != nil { 3592 t.Fatalf("err: %s", err) 3593 } 3594 3595 if !h.PreApplyCalled { 3596 t.Fatal("should be called") 3597 } 3598 if !h.PostApplyCalled { 3599 t.Fatal("should be called") 3600 } 3601 if !h.PostStateUpdateCalled { 3602 t.Fatalf("should call post state update") 3603 } 3604 } 3605 3606 func TestContext2Apply_hookOrphan(t *testing.T) { 3607 m := testModule(t, "apply-blank") 3608 h := new(MockHook) 3609 p := testProvider("aws") 3610 p.ApplyFn = testApplyFn 3611 p.DiffFn = testDiffFn 3612 3613 state := &State{ 3614 Modules: []*ModuleState{ 3615 &ModuleState{ 3616 Path: rootModulePath, 3617 Resources: map[string]*ResourceState{ 3618 "aws_instance.bar": &ResourceState{ 3619 Type: "aws_instance", 3620 Primary: &InstanceState{ 3621 ID: "bar", 3622 }, 3623 }, 3624 }, 3625 }, 3626 }, 3627 } 3628 3629 ctx := testContext2(t, &ContextOpts{ 3630 Module: m, 3631 State: state, 3632 Hooks: []Hook{h}, 3633 Providers: map[string]ResourceProviderFactory{ 3634 "aws": testProviderFuncFixed(p), 3635 }, 3636 }) 3637 3638 if _, err := ctx.Plan(); err != nil { 3639 t.Fatalf("err: %s", err) 3640 } 3641 3642 if _, err := ctx.Apply(); err != nil { 3643 t.Fatalf("err: %s", err) 3644 } 3645 3646 if !h.PreApplyCalled { 3647 t.Fatal("should be called") 3648 } 3649 if !h.PostApplyCalled { 3650 t.Fatal("should be called") 3651 } 3652 if !h.PostStateUpdateCalled { 3653 t.Fatalf("should call post state update") 3654 } 3655 } 3656 3657 func TestContext2Apply_idAttr(t *testing.T) { 3658 m := testModule(t, "apply-idattr") 3659 p := testProvider("aws") 3660 ctx := testContext2(t, &ContextOpts{ 3661 Module: m, 3662 Providers: map[string]ResourceProviderFactory{ 3663 "aws": testProviderFuncFixed(p), 3664 }, 3665 }) 3666 3667 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3668 result := s.MergeDiff(d) 3669 result.ID = "foo" 3670 result.Attributes = map[string]string{ 3671 "id": "bar", 3672 } 3673 3674 return result, nil 3675 } 3676 p.DiffFn = func(*InstanceInfo, *InstanceState, *ResourceConfig) (*InstanceDiff, error) { 3677 return &InstanceDiff{ 3678 Attributes: map[string]*ResourceAttrDiff{ 3679 "num": &ResourceAttrDiff{ 3680 New: "bar", 3681 }, 3682 }, 3683 }, nil 3684 } 3685 3686 if _, err := ctx.Plan(); err != nil { 3687 t.Fatalf("err: %s", err) 3688 } 3689 3690 state, err := ctx.Apply() 3691 if err != nil { 3692 t.Fatalf("err: %s", err) 3693 } 3694 3695 mod := state.RootModule() 3696 rs, ok := mod.Resources["aws_instance.foo"] 3697 if !ok { 3698 t.Fatal("not in state") 3699 } 3700 if rs.Primary.ID != "foo" { 3701 t.Fatalf("bad: %#v", rs.Primary.ID) 3702 } 3703 if rs.Primary.Attributes["id"] != "foo" { 3704 t.Fatalf("bad: %#v", rs.Primary.Attributes) 3705 } 3706 } 3707 3708 func TestContext2Apply_output(t *testing.T) { 3709 m := testModule(t, "apply-output") 3710 p := testProvider("aws") 3711 p.ApplyFn = testApplyFn 3712 p.DiffFn = testDiffFn 3713 ctx := testContext2(t, &ContextOpts{ 3714 Module: m, 3715 Providers: map[string]ResourceProviderFactory{ 3716 "aws": testProviderFuncFixed(p), 3717 }, 3718 }) 3719 3720 if _, err := ctx.Plan(); err != nil { 3721 t.Fatalf("err: %s", err) 3722 } 3723 3724 state, err := ctx.Apply() 3725 if err != nil { 3726 t.Fatalf("err: %s", err) 3727 } 3728 3729 actual := strings.TrimSpace(state.String()) 3730 expected := strings.TrimSpace(testTerraformApplyOutputStr) 3731 if actual != expected { 3732 t.Fatalf("bad: \n%s", actual) 3733 } 3734 } 3735 3736 func TestContext2Apply_outputInvalid(t *testing.T) { 3737 m := testModule(t, "apply-output-invalid") 3738 p := testProvider("aws") 3739 p.ApplyFn = testApplyFn 3740 p.DiffFn = testDiffFn 3741 ctx := testContext2(t, &ContextOpts{ 3742 Module: m, 3743 Providers: map[string]ResourceProviderFactory{ 3744 "aws": testProviderFuncFixed(p), 3745 }, 3746 }) 3747 3748 _, err := ctx.Plan() 3749 if err == nil { 3750 t.Fatalf("err: %s", err) 3751 } 3752 if !strings.Contains(err.Error(), "is not a valid type") { 3753 t.Fatalf("err: %s", err) 3754 } 3755 } 3756 3757 func TestContext2Apply_outputAdd(t *testing.T) { 3758 m1 := testModule(t, "apply-output-add-before") 3759 p1 := testProvider("aws") 3760 p1.ApplyFn = testApplyFn 3761 p1.DiffFn = testDiffFn 3762 ctx1 := testContext2(t, &ContextOpts{ 3763 Module: m1, 3764 Providers: map[string]ResourceProviderFactory{ 3765 "aws": testProviderFuncFixed(p1), 3766 }, 3767 }) 3768 3769 if _, err := ctx1.Plan(); err != nil { 3770 t.Fatalf("err: %s", err) 3771 } 3772 3773 state1, err := ctx1.Apply() 3774 if err != nil { 3775 t.Fatalf("err: %s", err) 3776 } 3777 3778 m2 := testModule(t, "apply-output-add-after") 3779 p2 := testProvider("aws") 3780 p2.ApplyFn = testApplyFn 3781 p2.DiffFn = testDiffFn 3782 ctx2 := testContext2(t, &ContextOpts{ 3783 Module: m2, 3784 Providers: map[string]ResourceProviderFactory{ 3785 "aws": testProviderFuncFixed(p2), 3786 }, 3787 State: state1, 3788 }) 3789 3790 if _, err := ctx2.Plan(); err != nil { 3791 t.Fatalf("err: %s", err) 3792 } 3793 3794 state2, err := ctx2.Apply() 3795 if err != nil { 3796 t.Fatalf("err: %s", err) 3797 } 3798 3799 actual := strings.TrimSpace(state2.String()) 3800 expected := strings.TrimSpace(testTerraformApplyOutputAddStr) 3801 if actual != expected { 3802 t.Fatalf("bad: \n%s", actual) 3803 } 3804 } 3805 3806 func TestContext2Apply_outputList(t *testing.T) { 3807 m := testModule(t, "apply-output-list") 3808 p := testProvider("aws") 3809 p.ApplyFn = testApplyFn 3810 p.DiffFn = testDiffFn 3811 ctx := testContext2(t, &ContextOpts{ 3812 Module: m, 3813 Providers: map[string]ResourceProviderFactory{ 3814 "aws": testProviderFuncFixed(p), 3815 }, 3816 }) 3817 3818 if _, err := ctx.Plan(); err != nil { 3819 t.Fatalf("err: %s", err) 3820 } 3821 3822 state, err := ctx.Apply() 3823 if err != nil { 3824 t.Fatalf("err: %s", err) 3825 } 3826 3827 actual := strings.TrimSpace(state.String()) 3828 expected := strings.TrimSpace(testTerraformApplyOutputListStr) 3829 if actual != expected { 3830 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 3831 } 3832 } 3833 3834 func TestContext2Apply_outputMulti(t *testing.T) { 3835 m := testModule(t, "apply-output-multi") 3836 p := testProvider("aws") 3837 p.ApplyFn = testApplyFn 3838 p.DiffFn = testDiffFn 3839 ctx := testContext2(t, &ContextOpts{ 3840 Module: m, 3841 Providers: map[string]ResourceProviderFactory{ 3842 "aws": testProviderFuncFixed(p), 3843 }, 3844 }) 3845 3846 if _, err := ctx.Plan(); err != nil { 3847 t.Fatalf("err: %s", err) 3848 } 3849 3850 state, err := ctx.Apply() 3851 if err != nil { 3852 t.Fatalf("err: %s", err) 3853 } 3854 3855 actual := strings.TrimSpace(state.String()) 3856 expected := strings.TrimSpace(testTerraformApplyOutputMultiStr) 3857 if actual != expected { 3858 t.Fatalf("bad: \n%s", actual) 3859 } 3860 } 3861 3862 func TestContext2Apply_outputMultiIndex(t *testing.T) { 3863 m := testModule(t, "apply-output-multi-index") 3864 p := testProvider("aws") 3865 p.ApplyFn = testApplyFn 3866 p.DiffFn = testDiffFn 3867 ctx := testContext2(t, &ContextOpts{ 3868 Module: m, 3869 Providers: map[string]ResourceProviderFactory{ 3870 "aws": testProviderFuncFixed(p), 3871 }, 3872 }) 3873 3874 if _, err := ctx.Plan(); err != nil { 3875 t.Fatalf("err: %s", err) 3876 } 3877 3878 state, err := ctx.Apply() 3879 if err != nil { 3880 t.Fatalf("err: %s", err) 3881 } 3882 3883 actual := strings.TrimSpace(state.String()) 3884 expected := strings.TrimSpace(testTerraformApplyOutputMultiIndexStr) 3885 if actual != expected { 3886 t.Fatalf("bad: \n%s", actual) 3887 } 3888 } 3889 3890 func TestContext2Apply_taint(t *testing.T) { 3891 m := testModule(t, "apply-taint") 3892 p := testProvider("aws") 3893 3894 // destroyCount tests against regression of 3895 // https://github.com/hashicorp/terraform/issues/1056 3896 var destroyCount = int32(0) 3897 var once sync.Once 3898 simulateProviderDelay := func() { 3899 time.Sleep(10 * time.Millisecond) 3900 } 3901 3902 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 3903 once.Do(simulateProviderDelay) 3904 if d.Destroy { 3905 atomic.AddInt32(&destroyCount, 1) 3906 } 3907 return testApplyFn(info, s, d) 3908 } 3909 p.DiffFn = testDiffFn 3910 s := &State{ 3911 Modules: []*ModuleState{ 3912 &ModuleState{ 3913 Path: rootModulePath, 3914 Resources: map[string]*ResourceState{ 3915 "aws_instance.bar": &ResourceState{ 3916 Type: "aws_instance", 3917 Primary: &InstanceState{ 3918 ID: "baz", 3919 Attributes: map[string]string{ 3920 "num": "2", 3921 "type": "aws_instance", 3922 }, 3923 Tainted: true, 3924 }, 3925 }, 3926 }, 3927 }, 3928 }, 3929 } 3930 ctx := testContext2(t, &ContextOpts{ 3931 Module: m, 3932 Providers: map[string]ResourceProviderFactory{ 3933 "aws": testProviderFuncFixed(p), 3934 }, 3935 State: s, 3936 }) 3937 3938 if _, err := ctx.Plan(); err != nil { 3939 t.Fatalf("err: %s", err) 3940 } 3941 3942 state, err := ctx.Apply() 3943 if err != nil { 3944 t.Fatalf("err: %s", err) 3945 } 3946 3947 actual := strings.TrimSpace(state.String()) 3948 expected := strings.TrimSpace(testTerraformApplyTaintStr) 3949 if actual != expected { 3950 t.Fatalf("bad:\n%s", actual) 3951 } 3952 3953 if destroyCount != 1 { 3954 t.Fatalf("Expected 1 destroy, got %d", destroyCount) 3955 } 3956 } 3957 3958 func TestContext2Apply_taintDep(t *testing.T) { 3959 m := testModule(t, "apply-taint-dep") 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(testTerraformApplyTaintDepStr) 4015 if actual != expected { 4016 t.Fatalf("bad:\n%s", actual) 4017 } 4018 } 4019 4020 func TestContext2Apply_taintDepRequiresNew(t *testing.T) { 4021 m := testModule(t, "apply-taint-dep-requires-new") 4022 p := testProvider("aws") 4023 p.ApplyFn = testApplyFn 4024 p.DiffFn = testDiffFn 4025 s := &State{ 4026 Modules: []*ModuleState{ 4027 &ModuleState{ 4028 Path: rootModulePath, 4029 Resources: map[string]*ResourceState{ 4030 "aws_instance.foo": &ResourceState{ 4031 Type: "aws_instance", 4032 Primary: &InstanceState{ 4033 ID: "baz", 4034 Attributes: map[string]string{ 4035 "num": "2", 4036 "type": "aws_instance", 4037 }, 4038 Tainted: true, 4039 }, 4040 }, 4041 "aws_instance.bar": &ResourceState{ 4042 Type: "aws_instance", 4043 Primary: &InstanceState{ 4044 ID: "bar", 4045 Attributes: map[string]string{ 4046 "foo": "baz", 4047 "num": "2", 4048 "type": "aws_instance", 4049 }, 4050 }, 4051 }, 4052 }, 4053 }, 4054 }, 4055 } 4056 ctx := testContext2(t, &ContextOpts{ 4057 Module: m, 4058 Providers: map[string]ResourceProviderFactory{ 4059 "aws": testProviderFuncFixed(p), 4060 }, 4061 State: s, 4062 }) 4063 4064 if p, err := ctx.Plan(); err != nil { 4065 t.Fatalf("err: %s", err) 4066 } else { 4067 t.Logf("plan: %s", p) 4068 } 4069 4070 state, err := ctx.Apply() 4071 if err != nil { 4072 t.Fatalf("err: %s", err) 4073 } 4074 4075 actual := strings.TrimSpace(state.String()) 4076 expected := strings.TrimSpace(testTerraformApplyTaintDepRequireNewStr) 4077 if actual != expected { 4078 t.Fatalf("bad:\n%s", actual) 4079 } 4080 } 4081 4082 func TestContext2Apply_targeted(t *testing.T) { 4083 m := testModule(t, "apply-targeted") 4084 p := testProvider("aws") 4085 p.ApplyFn = testApplyFn 4086 p.DiffFn = testDiffFn 4087 ctx := testContext2(t, &ContextOpts{ 4088 Module: m, 4089 Providers: map[string]ResourceProviderFactory{ 4090 "aws": testProviderFuncFixed(p), 4091 }, 4092 Targets: []string{"aws_instance.foo"}, 4093 }) 4094 4095 if _, err := ctx.Plan(); err != nil { 4096 t.Fatalf("err: %s", err) 4097 } 4098 4099 state, err := ctx.Apply() 4100 if err != nil { 4101 t.Fatalf("err: %s", err) 4102 } 4103 4104 mod := state.RootModule() 4105 if len(mod.Resources) != 1 { 4106 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 4107 } 4108 4109 checkStateString(t, state, ` 4110 aws_instance.foo: 4111 ID = foo 4112 num = 2 4113 type = aws_instance 4114 `) 4115 } 4116 4117 func TestContext2Apply_targetedCount(t *testing.T) { 4118 m := testModule(t, "apply-targeted-count") 4119 p := testProvider("aws") 4120 p.ApplyFn = testApplyFn 4121 p.DiffFn = testDiffFn 4122 ctx := testContext2(t, &ContextOpts{ 4123 Module: m, 4124 Providers: map[string]ResourceProviderFactory{ 4125 "aws": testProviderFuncFixed(p), 4126 }, 4127 Targets: []string{"aws_instance.foo"}, 4128 }) 4129 4130 if _, err := ctx.Plan(); err != nil { 4131 t.Fatalf("err: %s", err) 4132 } 4133 4134 state, err := ctx.Apply() 4135 if err != nil { 4136 t.Fatalf("err: %s", err) 4137 } 4138 4139 checkStateString(t, state, ` 4140 aws_instance.foo.0: 4141 ID = foo 4142 aws_instance.foo.1: 4143 ID = foo 4144 aws_instance.foo.2: 4145 ID = foo 4146 `) 4147 } 4148 4149 func TestContext2Apply_targetedCountIndex(t *testing.T) { 4150 m := testModule(t, "apply-targeted-count") 4151 p := testProvider("aws") 4152 p.ApplyFn = testApplyFn 4153 p.DiffFn = testDiffFn 4154 ctx := testContext2(t, &ContextOpts{ 4155 Module: m, 4156 Providers: map[string]ResourceProviderFactory{ 4157 "aws": testProviderFuncFixed(p), 4158 }, 4159 Targets: []string{"aws_instance.foo[1]"}, 4160 }) 4161 4162 if _, err := ctx.Plan(); err != nil { 4163 t.Fatalf("err: %s", err) 4164 } 4165 4166 state, err := ctx.Apply() 4167 if err != nil { 4168 t.Fatalf("err: %s", err) 4169 } 4170 4171 checkStateString(t, state, ` 4172 aws_instance.foo.1: 4173 ID = foo 4174 `) 4175 } 4176 4177 func TestContext2Apply_targetedDestroy(t *testing.T) { 4178 m := testModule(t, "apply-targeted") 4179 p := testProvider("aws") 4180 p.ApplyFn = testApplyFn 4181 p.DiffFn = testDiffFn 4182 ctx := testContext2(t, &ContextOpts{ 4183 Module: m, 4184 Providers: map[string]ResourceProviderFactory{ 4185 "aws": testProviderFuncFixed(p), 4186 }, 4187 State: &State{ 4188 Modules: []*ModuleState{ 4189 &ModuleState{ 4190 Path: rootModulePath, 4191 Resources: map[string]*ResourceState{ 4192 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 4193 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 4194 }, 4195 }, 4196 }, 4197 }, 4198 Targets: []string{"aws_instance.foo"}, 4199 Destroy: true, 4200 }) 4201 4202 if _, err := ctx.Plan(); err != nil { 4203 t.Fatalf("err: %s", err) 4204 } 4205 4206 state, err := ctx.Apply() 4207 if err != nil { 4208 t.Fatalf("err: %s", err) 4209 } 4210 4211 mod := state.RootModule() 4212 if len(mod.Resources) != 1 { 4213 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 4214 } 4215 4216 checkStateString(t, state, ` 4217 aws_instance.bar: 4218 ID = i-abc123 4219 `) 4220 } 4221 4222 // https://github.com/hashicorp/terraform/issues/4462 4223 func TestContext2Apply_targetedDestroyModule(t *testing.T) { 4224 m := testModule(t, "apply-targeted-module") 4225 p := testProvider("aws") 4226 p.ApplyFn = testApplyFn 4227 p.DiffFn = testDiffFn 4228 ctx := testContext2(t, &ContextOpts{ 4229 Module: m, 4230 Providers: map[string]ResourceProviderFactory{ 4231 "aws": testProviderFuncFixed(p), 4232 }, 4233 State: &State{ 4234 Modules: []*ModuleState{ 4235 &ModuleState{ 4236 Path: rootModulePath, 4237 Resources: map[string]*ResourceState{ 4238 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 4239 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 4240 }, 4241 }, 4242 &ModuleState{ 4243 Path: []string{"root", "child"}, 4244 Resources: map[string]*ResourceState{ 4245 "aws_instance.foo": resourceState("aws_instance", "i-bcd345"), 4246 "aws_instance.bar": resourceState("aws_instance", "i-abc123"), 4247 }, 4248 }, 4249 }, 4250 }, 4251 Targets: []string{"module.child.aws_instance.foo"}, 4252 Destroy: true, 4253 }) 4254 4255 if _, err := ctx.Plan(); err != nil { 4256 t.Fatalf("err: %s", err) 4257 } 4258 4259 state, err := ctx.Apply() 4260 if err != nil { 4261 t.Fatalf("err: %s", err) 4262 } 4263 4264 checkStateString(t, state, ` 4265 aws_instance.bar: 4266 ID = i-abc123 4267 aws_instance.foo: 4268 ID = i-bcd345 4269 4270 module.child: 4271 aws_instance.bar: 4272 ID = i-abc123 4273 `) 4274 } 4275 4276 func TestContext2Apply_targetedDestroyCountIndex(t *testing.T) { 4277 m := testModule(t, "apply-targeted-count") 4278 p := testProvider("aws") 4279 p.ApplyFn = testApplyFn 4280 p.DiffFn = testDiffFn 4281 ctx := testContext2(t, &ContextOpts{ 4282 Module: m, 4283 Providers: map[string]ResourceProviderFactory{ 4284 "aws": testProviderFuncFixed(p), 4285 }, 4286 State: &State{ 4287 Modules: []*ModuleState{ 4288 &ModuleState{ 4289 Path: rootModulePath, 4290 Resources: map[string]*ResourceState{ 4291 "aws_instance.foo.0": resourceState("aws_instance", "i-bcd345"), 4292 "aws_instance.foo.1": resourceState("aws_instance", "i-bcd345"), 4293 "aws_instance.foo.2": resourceState("aws_instance", "i-bcd345"), 4294 "aws_instance.bar.0": resourceState("aws_instance", "i-abc123"), 4295 "aws_instance.bar.1": resourceState("aws_instance", "i-abc123"), 4296 "aws_instance.bar.2": resourceState("aws_instance", "i-abc123"), 4297 }, 4298 }, 4299 }, 4300 }, 4301 Targets: []string{ 4302 "aws_instance.foo[2]", 4303 "aws_instance.bar[1]", 4304 }, 4305 Destroy: true, 4306 }) 4307 4308 if _, err := ctx.Plan(); err != nil { 4309 t.Fatalf("err: %s", err) 4310 } 4311 4312 state, err := ctx.Apply() 4313 if err != nil { 4314 t.Fatalf("err: %s", err) 4315 } 4316 4317 checkStateString(t, state, ` 4318 aws_instance.bar.0: 4319 ID = i-abc123 4320 aws_instance.bar.2: 4321 ID = i-abc123 4322 aws_instance.foo.0: 4323 ID = i-bcd345 4324 aws_instance.foo.1: 4325 ID = i-bcd345 4326 `) 4327 } 4328 4329 func TestContext2Apply_targetedModule(t *testing.T) { 4330 m := testModule(t, "apply-targeted-module") 4331 p := testProvider("aws") 4332 p.ApplyFn = testApplyFn 4333 p.DiffFn = testDiffFn 4334 ctx := testContext2(t, &ContextOpts{ 4335 Module: m, 4336 Providers: map[string]ResourceProviderFactory{ 4337 "aws": testProviderFuncFixed(p), 4338 }, 4339 Targets: []string{"module.child"}, 4340 }) 4341 4342 if _, err := ctx.Plan(); err != nil { 4343 t.Fatalf("err: %s", err) 4344 } 4345 4346 state, err := ctx.Apply() 4347 if err != nil { 4348 t.Fatalf("err: %s", err) 4349 } 4350 4351 mod := state.ModuleByPath([]string{"root", "child"}) 4352 if mod == nil { 4353 t.Fatalf("no child module found in the state!\n\n%#v", state) 4354 } 4355 if len(mod.Resources) != 2 { 4356 t.Fatalf("expected 2 resources, got: %#v", mod.Resources) 4357 } 4358 4359 checkStateString(t, state, ` 4360 <no state> 4361 module.child: 4362 aws_instance.bar: 4363 ID = foo 4364 num = 2 4365 type = aws_instance 4366 aws_instance.foo: 4367 ID = foo 4368 num = 2 4369 type = aws_instance 4370 `) 4371 } 4372 4373 // GH-1858 4374 func TestContext2Apply_targetedModuleDep(t *testing.T) { 4375 m := testModule(t, "apply-targeted-module-dep") 4376 p := testProvider("aws") 4377 p.ApplyFn = testApplyFn 4378 p.DiffFn = testDiffFn 4379 ctx := testContext2(t, &ContextOpts{ 4380 Module: m, 4381 Providers: map[string]ResourceProviderFactory{ 4382 "aws": testProviderFuncFixed(p), 4383 }, 4384 Targets: []string{"aws_instance.foo"}, 4385 }) 4386 4387 if _, err := ctx.Plan(); err != nil { 4388 t.Fatalf("err: %s", err) 4389 } 4390 4391 state, err := ctx.Apply() 4392 if err != nil { 4393 t.Fatalf("err: %s", err) 4394 } 4395 4396 checkStateString(t, state, ` 4397 aws_instance.foo: 4398 ID = foo 4399 foo = foo 4400 type = aws_instance 4401 4402 Dependencies: 4403 module.child 4404 4405 module.child: 4406 aws_instance.mod: 4407 ID = foo 4408 4409 Outputs: 4410 4411 output = foo 4412 `) 4413 } 4414 4415 func TestContext2Apply_targetedModuleResource(t *testing.T) { 4416 m := testModule(t, "apply-targeted-module-resource") 4417 p := testProvider("aws") 4418 p.ApplyFn = testApplyFn 4419 p.DiffFn = testDiffFn 4420 ctx := testContext2(t, &ContextOpts{ 4421 Module: m, 4422 Providers: map[string]ResourceProviderFactory{ 4423 "aws": testProviderFuncFixed(p), 4424 }, 4425 Targets: []string{"module.child.aws_instance.foo"}, 4426 }) 4427 4428 if _, err := ctx.Plan(); err != nil { 4429 t.Fatalf("err: %s", err) 4430 } 4431 4432 state, err := ctx.Apply() 4433 if err != nil { 4434 t.Fatalf("err: %s", err) 4435 } 4436 4437 mod := state.ModuleByPath([]string{"root", "child"}) 4438 if len(mod.Resources) != 1 { 4439 t.Fatalf("expected 1 resource, got: %#v", mod.Resources) 4440 } 4441 4442 checkStateString(t, state, ` 4443 <no state> 4444 module.child: 4445 aws_instance.foo: 4446 ID = foo 4447 num = 2 4448 type = aws_instance 4449 `) 4450 } 4451 4452 func TestContext2Apply_unknownAttribute(t *testing.T) { 4453 m := testModule(t, "apply-unknown") 4454 p := testProvider("aws") 4455 p.ApplyFn = testApplyFn 4456 p.DiffFn = testDiffFn 4457 ctx := testContext2(t, &ContextOpts{ 4458 Module: m, 4459 Providers: map[string]ResourceProviderFactory{ 4460 "aws": testProviderFuncFixed(p), 4461 }, 4462 }) 4463 4464 if _, err := ctx.Plan(); err != nil { 4465 t.Fatalf("err: %s", err) 4466 } 4467 4468 state, err := ctx.Apply() 4469 if err == nil { 4470 t.Fatal("should error") 4471 } 4472 4473 actual := strings.TrimSpace(state.String()) 4474 expected := strings.TrimSpace(testTerraformApplyUnknownAttrStr) 4475 if actual != expected { 4476 t.Fatalf("bad: \n%s", actual) 4477 } 4478 } 4479 4480 func TestContext2Apply_unknownAttributeInterpolate(t *testing.T) { 4481 m := testModule(t, "apply-unknown-interpolate") 4482 p := testProvider("aws") 4483 p.ApplyFn = testApplyFn 4484 p.DiffFn = testDiffFn 4485 ctx := testContext2(t, &ContextOpts{ 4486 Module: m, 4487 Providers: map[string]ResourceProviderFactory{ 4488 "aws": testProviderFuncFixed(p), 4489 }, 4490 }) 4491 4492 if _, err := ctx.Plan(); err == nil { 4493 t.Fatal("should error") 4494 } 4495 } 4496 4497 func TestContext2Apply_vars(t *testing.T) { 4498 m := testModule(t, "apply-vars") 4499 p := testProvider("aws") 4500 p.ApplyFn = testApplyFn 4501 p.DiffFn = testDiffFn 4502 ctx := testContext2(t, &ContextOpts{ 4503 Module: m, 4504 Providers: map[string]ResourceProviderFactory{ 4505 "aws": testProviderFuncFixed(p), 4506 }, 4507 Variables: map[string]interface{}{ 4508 "foo": "us-west-2", 4509 "test_list": []interface{}{"Hello", "World"}, 4510 "test_map": map[string]interface{}{ 4511 "Hello": "World", 4512 "Foo": "Bar", 4513 "Baz": "Foo", 4514 }, 4515 "amis": []map[string]interface{}{ 4516 map[string]interface{}{ 4517 "us-east-1": "override", 4518 }, 4519 }, 4520 }, 4521 }) 4522 4523 w, e := ctx.Validate() 4524 if len(w) > 0 { 4525 t.Fatalf("bad: %#v", w) 4526 } 4527 if len(e) > 0 { 4528 t.Fatalf("bad: %s", e) 4529 } 4530 4531 if _, err := ctx.Plan(); err != nil { 4532 t.Fatalf("err: %s", err) 4533 } 4534 4535 state, err := ctx.Apply() 4536 if err != nil { 4537 t.Fatalf("err: %s", err) 4538 } 4539 4540 actual := strings.TrimSpace(state.String()) 4541 expected := strings.TrimSpace(testTerraformApplyVarsStr) 4542 if actual != expected { 4543 t.Fatalf("expected: %s\n got:\n%s", expected, actual) 4544 } 4545 } 4546 4547 func TestContext2Apply_varsEnv(t *testing.T) { 4548 // Set the env var 4549 defer tempEnv(t, "TF_VAR_ami", "baz")() 4550 defer tempEnv(t, "TF_VAR_list", `["Hello", "World"]`)() 4551 defer tempEnv(t, "TF_VAR_map", `{"Hello" = "World", "Foo" = "Bar", "Baz" = "Foo"}`)() 4552 4553 m := testModule(t, "apply-vars-env") 4554 p := testProvider("aws") 4555 p.ApplyFn = testApplyFn 4556 p.DiffFn = testDiffFn 4557 ctx := testContext2(t, &ContextOpts{ 4558 Module: m, 4559 Providers: map[string]ResourceProviderFactory{ 4560 "aws": testProviderFuncFixed(p), 4561 }, 4562 }) 4563 4564 w, e := ctx.Validate() 4565 if len(w) > 0 { 4566 t.Fatalf("bad: %#v", w) 4567 } 4568 if len(e) > 0 { 4569 t.Fatalf("bad: %s", e) 4570 } 4571 4572 if _, err := ctx.Plan(); err != nil { 4573 t.Fatalf("err: %s", err) 4574 } 4575 4576 state, err := ctx.Apply() 4577 if err != nil { 4578 t.Fatalf("err: %s", err) 4579 } 4580 4581 actual := strings.TrimSpace(state.String()) 4582 expected := strings.TrimSpace(testTerraformApplyVarsEnvStr) 4583 if actual != expected { 4584 t.Fatalf("bad: \n%s", actual) 4585 } 4586 } 4587 4588 func TestContext2Apply_createBefore_depends(t *testing.T) { 4589 m := testModule(t, "apply-depends-create-before") 4590 h := new(HookRecordApplyOrder) 4591 p := testProvider("aws") 4592 p.ApplyFn = testApplyFn 4593 p.DiffFn = testDiffFn 4594 state := &State{ 4595 Modules: []*ModuleState{ 4596 &ModuleState{ 4597 Path: rootModulePath, 4598 Resources: map[string]*ResourceState{ 4599 "aws_instance.web": &ResourceState{ 4600 Type: "aws_instance", 4601 Primary: &InstanceState{ 4602 ID: "bar", 4603 Attributes: map[string]string{ 4604 "require_new": "ami-old", 4605 }, 4606 }, 4607 }, 4608 "aws_instance.lb": &ResourceState{ 4609 Type: "aws_instance", 4610 Primary: &InstanceState{ 4611 ID: "baz", 4612 Attributes: map[string]string{ 4613 "instance": "bar", 4614 }, 4615 }, 4616 }, 4617 }, 4618 }, 4619 }, 4620 } 4621 ctx := testContext2(t, &ContextOpts{ 4622 Module: m, 4623 Hooks: []Hook{h}, 4624 Providers: map[string]ResourceProviderFactory{ 4625 "aws": testProviderFuncFixed(p), 4626 }, 4627 State: state, 4628 }) 4629 4630 if _, err := ctx.Plan(); err != nil { 4631 t.Fatalf("err: %s", err) 4632 } 4633 4634 h.Active = true 4635 state, err := ctx.Apply() 4636 if err != nil { 4637 t.Fatalf("err: %s", err) 4638 } 4639 4640 mod := state.RootModule() 4641 if len(mod.Resources) < 2 { 4642 t.Fatalf("bad: %#v", mod.Resources) 4643 } 4644 4645 actual := strings.TrimSpace(state.String()) 4646 expected := strings.TrimSpace(testTerraformApplyDependsCreateBeforeStr) 4647 if actual != expected { 4648 t.Fatalf("bad: \n%s\n%s", actual, expected) 4649 } 4650 4651 // Test that things were managed _in the right order_ 4652 order := h.States 4653 diffs := h.Diffs 4654 if order[0].ID != "" || diffs[0].Destroy { 4655 t.Fatalf("should create new instance first: %#v", order) 4656 } 4657 4658 if order[1].ID != "baz" { 4659 t.Fatalf("update must happen after create: %#v", order) 4660 } 4661 4662 if order[2].ID != "bar" || !diffs[2].Destroy { 4663 t.Fatalf("destroy must happen after update: %#v", order) 4664 } 4665 } 4666 4667 func TestContext2Apply_singleDestroy(t *testing.T) { 4668 m := testModule(t, "apply-depends-create-before") 4669 h := new(HookRecordApplyOrder) 4670 p := testProvider("aws") 4671 4672 invokeCount := 0 4673 p.ApplyFn = func(info *InstanceInfo, s *InstanceState, d *InstanceDiff) (*InstanceState, error) { 4674 invokeCount++ 4675 switch invokeCount { 4676 case 1: 4677 if d.Destroy { 4678 t.Fatalf("should not destroy") 4679 } 4680 if s.ID != "" { 4681 t.Fatalf("should not have ID") 4682 } 4683 case 2: 4684 if d.Destroy { 4685 t.Fatalf("should not destroy") 4686 } 4687 if s.ID != "baz" { 4688 t.Fatalf("should have id") 4689 } 4690 case 3: 4691 if !d.Destroy { 4692 t.Fatalf("should destroy") 4693 } 4694 if s.ID == "" { 4695 t.Fatalf("should have ID") 4696 } 4697 default: 4698 t.Fatalf("bad invoke count %d", invokeCount) 4699 } 4700 return testApplyFn(info, s, d) 4701 } 4702 p.DiffFn = testDiffFn 4703 state := &State{ 4704 Modules: []*ModuleState{ 4705 &ModuleState{ 4706 Path: rootModulePath, 4707 Resources: map[string]*ResourceState{ 4708 "aws_instance.web": &ResourceState{ 4709 Type: "aws_instance", 4710 Primary: &InstanceState{ 4711 ID: "bar", 4712 Attributes: map[string]string{ 4713 "require_new": "ami-old", 4714 }, 4715 }, 4716 }, 4717 "aws_instance.lb": &ResourceState{ 4718 Type: "aws_instance", 4719 Primary: &InstanceState{ 4720 ID: "baz", 4721 Attributes: map[string]string{ 4722 "instance": "bar", 4723 }, 4724 }, 4725 }, 4726 }, 4727 }, 4728 }, 4729 } 4730 ctx := testContext2(t, &ContextOpts{ 4731 Module: m, 4732 Hooks: []Hook{h}, 4733 Providers: map[string]ResourceProviderFactory{ 4734 "aws": testProviderFuncFixed(p), 4735 }, 4736 State: state, 4737 }) 4738 4739 if _, err := ctx.Plan(); err != nil { 4740 t.Fatalf("err: %s", err) 4741 } 4742 4743 h.Active = true 4744 state, err := ctx.Apply() 4745 if err != nil { 4746 t.Fatalf("err: %s", err) 4747 } 4748 4749 if invokeCount != 3 { 4750 t.Fatalf("bad: %d", invokeCount) 4751 } 4752 } 4753 4754 // GH-7824 4755 func TestContext2Apply_issue7824(t *testing.T) { 4756 p := testProvider("template") 4757 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 4758 Name: "template_file", 4759 }) 4760 4761 p.ApplyFn = testApplyFn 4762 p.DiffFn = testDiffFn 4763 4764 // Apply cleanly step 0 4765 ctx := testContext2(t, &ContextOpts{ 4766 Module: testModule(t, "issue-7824"), 4767 Providers: map[string]ResourceProviderFactory{ 4768 "template": testProviderFuncFixed(p), 4769 }, 4770 }) 4771 4772 plan, err := ctx.Plan() 4773 if err != nil { 4774 t.Fatalf("err: %s", err) 4775 } 4776 4777 // Write / Read plan to simulate running it through a Plan file 4778 var buf bytes.Buffer 4779 if err := WritePlan(plan, &buf); err != nil { 4780 t.Fatalf("err: %s", err) 4781 } 4782 4783 planFromFile, err := ReadPlan(&buf) 4784 if err != nil { 4785 t.Fatalf("err: %s", err) 4786 } 4787 4788 ctx, err = planFromFile.Context(&ContextOpts{ 4789 Providers: map[string]ResourceProviderFactory{ 4790 "template": testProviderFuncFixed(p), 4791 }, 4792 }) 4793 if err != nil { 4794 t.Fatalf("err: %s", err) 4795 } 4796 4797 _, err = ctx.Apply() 4798 if err != nil { 4799 t.Fatalf("err: %s", err) 4800 } 4801 } 4802 4803 // GH-5254 4804 func TestContext2Apply_issue5254(t *testing.T) { 4805 // Create a provider. We use "template" here just to match the repro 4806 // we got from the issue itself. 4807 p := testProvider("template") 4808 p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ 4809 Name: "template_file", 4810 }) 4811 4812 p.ApplyFn = testApplyFn 4813 p.DiffFn = testDiffFn 4814 4815 // Apply cleanly step 0 4816 ctx := testContext2(t, &ContextOpts{ 4817 Module: testModule(t, "issue-5254/step-0"), 4818 Providers: map[string]ResourceProviderFactory{ 4819 "template": testProviderFuncFixed(p), 4820 }, 4821 }) 4822 4823 plan, err := ctx.Plan() 4824 if err != nil { 4825 t.Fatalf("err: %s", err) 4826 } 4827 4828 state, err := ctx.Apply() 4829 if err != nil { 4830 t.Fatalf("err: %s", err) 4831 } 4832 4833 // Application success. Now make the modification and store a plan 4834 ctx = testContext2(t, &ContextOpts{ 4835 Module: testModule(t, "issue-5254/step-1"), 4836 State: state, 4837 Providers: map[string]ResourceProviderFactory{ 4838 "template": testProviderFuncFixed(p), 4839 }, 4840 }) 4841 4842 plan, err = ctx.Plan() 4843 if err != nil { 4844 t.Fatalf("err: %s", err) 4845 } 4846 4847 // Write / Read plan to simulate running it through a Plan file 4848 var buf bytes.Buffer 4849 if err := WritePlan(plan, &buf); err != nil { 4850 t.Fatalf("err: %s", err) 4851 } 4852 4853 planFromFile, err := ReadPlan(&buf) 4854 if err != nil { 4855 t.Fatalf("err: %s", err) 4856 } 4857 4858 ctx, err = planFromFile.Context(&ContextOpts{ 4859 Providers: map[string]ResourceProviderFactory{ 4860 "template": testProviderFuncFixed(p), 4861 }, 4862 }) 4863 if err != nil { 4864 t.Fatalf("err: %s", err) 4865 } 4866 4867 state, err = ctx.Apply() 4868 if err != nil { 4869 t.Fatalf("err: %s", err) 4870 } 4871 4872 actual := strings.TrimSpace(state.String()) 4873 expected := strings.TrimSpace(` 4874 template_file.child: 4875 ID = foo 4876 template = Hi 4877 type = template_file 4878 4879 Dependencies: 4880 template_file.parent 4881 template_file.parent: 4882 ID = foo 4883 template = Hi 4884 type = template_file 4885 `) 4886 if actual != expected { 4887 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 4888 } 4889 } 4890 4891 func TestContext2Apply_targetedWithTaintedInState(t *testing.T) { 4892 p := testProvider("aws") 4893 p.DiffFn = testDiffFn 4894 p.ApplyFn = testApplyFn 4895 ctx := testContext2(t, &ContextOpts{ 4896 Module: testModule(t, "apply-tainted-targets"), 4897 Providers: map[string]ResourceProviderFactory{ 4898 "aws": testProviderFuncFixed(p), 4899 }, 4900 Targets: []string{"aws_instance.iambeingadded"}, 4901 State: &State{ 4902 Modules: []*ModuleState{ 4903 &ModuleState{ 4904 Path: rootModulePath, 4905 Resources: map[string]*ResourceState{ 4906 "aws_instance.ifailedprovisioners": &ResourceState{ 4907 Primary: &InstanceState{ 4908 ID: "ifailedprovisioners", 4909 Tainted: true, 4910 }, 4911 }, 4912 }, 4913 }, 4914 }, 4915 }, 4916 }) 4917 4918 plan, err := ctx.Plan() 4919 if err != nil { 4920 t.Fatalf("err: %s", err) 4921 } 4922 4923 // Write / Read plan to simulate running it through a Plan file 4924 var buf bytes.Buffer 4925 if err := WritePlan(plan, &buf); err != nil { 4926 t.Fatalf("err: %s", err) 4927 } 4928 4929 planFromFile, err := ReadPlan(&buf) 4930 if err != nil { 4931 t.Fatalf("err: %s", err) 4932 } 4933 4934 ctx, err = planFromFile.Context(&ContextOpts{ 4935 Module: testModule(t, "apply-tainted-targets"), 4936 Providers: map[string]ResourceProviderFactory{ 4937 "aws": testProviderFuncFixed(p), 4938 }, 4939 }) 4940 if err != nil { 4941 t.Fatalf("err: %s", err) 4942 } 4943 4944 state, err := ctx.Apply() 4945 if err != nil { 4946 t.Fatalf("err: %s", err) 4947 } 4948 4949 actual := strings.TrimSpace(state.String()) 4950 expected := strings.TrimSpace(` 4951 aws_instance.iambeingadded: 4952 ID = foo 4953 aws_instance.ifailedprovisioners: (tainted) 4954 ID = ifailedprovisioners 4955 `) 4956 if actual != expected { 4957 t.Fatalf("expected state: \n%s\ngot: \n%s", expected, actual) 4958 } 4959 } 4960 4961 // Higher level test exposing the bug this covers in 4962 // TestResource_ignoreChangesRequired 4963 func TestContext2Apply_ignoreChangesCreate(t *testing.T) { 4964 m := testModule(t, "apply-ignore-changes-create") 4965 p := testProvider("aws") 4966 p.ApplyFn = testApplyFn 4967 p.DiffFn = testDiffFn 4968 ctx := testContext2(t, &ContextOpts{ 4969 Module: m, 4970 Providers: map[string]ResourceProviderFactory{ 4971 "aws": testProviderFuncFixed(p), 4972 }, 4973 }) 4974 4975 if p, err := ctx.Plan(); err != nil { 4976 t.Fatalf("err: %s", err) 4977 } else { 4978 t.Logf(p.String()) 4979 } 4980 4981 state, err := ctx.Apply() 4982 if err != nil { 4983 t.Fatalf("err: %s", err) 4984 } 4985 4986 mod := state.RootModule() 4987 if len(mod.Resources) != 1 { 4988 t.Fatalf("bad: %s", state) 4989 } 4990 4991 actual := strings.TrimSpace(state.String()) 4992 // Expect no changes from original state 4993 expected := strings.TrimSpace(` 4994 aws_instance.foo: 4995 ID = foo 4996 required_field = set 4997 type = aws_instance 4998 `) 4999 if actual != expected { 5000 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 5001 } 5002 } 5003 5004 func TestContext2Apply_ignoreChangesWithDep(t *testing.T) { 5005 m := testModule(t, "apply-ignore-changes-dep") 5006 p := testProvider("aws") 5007 p.ApplyFn = testApplyFn 5008 p.DiffFn = func(i *InstanceInfo, s *InstanceState, c *ResourceConfig) (*InstanceDiff, error) { 5009 switch i.Type { 5010 case "aws_instance": 5011 newAmi, _ := c.Get("ami") 5012 return &InstanceDiff{ 5013 Attributes: map[string]*ResourceAttrDiff{ 5014 "ami": &ResourceAttrDiff{ 5015 Old: s.Attributes["ami"], 5016 New: newAmi.(string), 5017 RequiresNew: true, 5018 }, 5019 }, 5020 }, nil 5021 case "aws_eip": 5022 return testDiffFn(i, s, c) 5023 default: 5024 t.Fatalf("Unexpected type: %s", i.Type) 5025 return nil, nil 5026 } 5027 } 5028 s := &State{ 5029 Modules: []*ModuleState{ 5030 &ModuleState{ 5031 Path: rootModulePath, 5032 Resources: map[string]*ResourceState{ 5033 "aws_instance.foo.0": &ResourceState{ 5034 Primary: &InstanceState{ 5035 ID: "i-abc123", 5036 Attributes: map[string]string{ 5037 "ami": "ami-abcd1234", 5038 "id": "i-abc123", 5039 }, 5040 }, 5041 }, 5042 "aws_instance.foo.1": &ResourceState{ 5043 Primary: &InstanceState{ 5044 ID: "i-bcd234", 5045 Attributes: map[string]string{ 5046 "ami": "ami-abcd1234", 5047 "id": "i-bcd234", 5048 }, 5049 }, 5050 }, 5051 "aws_eip.foo.0": &ResourceState{ 5052 Primary: &InstanceState{ 5053 ID: "eip-abc123", 5054 Attributes: map[string]string{ 5055 "id": "eip-abc123", 5056 "instance": "i-abc123", 5057 }, 5058 }, 5059 }, 5060 "aws_eip.foo.1": &ResourceState{ 5061 Primary: &InstanceState{ 5062 ID: "eip-bcd234", 5063 Attributes: map[string]string{ 5064 "id": "eip-bcd234", 5065 "instance": "i-bcd234", 5066 }, 5067 }, 5068 }, 5069 }, 5070 }, 5071 }, 5072 } 5073 ctx := testContext2(t, &ContextOpts{ 5074 Module: m, 5075 Providers: map[string]ResourceProviderFactory{ 5076 "aws": testProviderFuncFixed(p), 5077 }, 5078 State: s, 5079 }) 5080 5081 if p, err := ctx.Plan(); err != nil { 5082 t.Fatalf("err: %s", err) 5083 } else { 5084 t.Logf(p.String()) 5085 } 5086 5087 state, err := ctx.Apply() 5088 if err != nil { 5089 t.Fatalf("err: %s", err) 5090 } 5091 5092 actual := strings.TrimSpace(state.String()) 5093 expected := strings.TrimSpace(s.String()) 5094 if actual != expected { 5095 t.Fatalf("bad: \n%s", actual) 5096 } 5097 } 5098 5099 func TestContext2Apply_ignoreChangesWildcard(t *testing.T) { 5100 m := testModule(t, "apply-ignore-changes-wildcard") 5101 p := testProvider("aws") 5102 p.ApplyFn = testApplyFn 5103 p.DiffFn = testDiffFn 5104 ctx := testContext2(t, &ContextOpts{ 5105 Module: m, 5106 Providers: map[string]ResourceProviderFactory{ 5107 "aws": testProviderFuncFixed(p), 5108 }, 5109 }) 5110 5111 if p, err := ctx.Plan(); err != nil { 5112 t.Fatalf("err: %s", err) 5113 } else { 5114 t.Logf(p.String()) 5115 } 5116 5117 state, err := ctx.Apply() 5118 if err != nil { 5119 t.Fatalf("err: %s", err) 5120 } 5121 5122 mod := state.RootModule() 5123 if len(mod.Resources) != 1 { 5124 t.Fatalf("bad: %s", state) 5125 } 5126 5127 actual := strings.TrimSpace(state.String()) 5128 // Expect no changes from original state 5129 expected := strings.TrimSpace(` 5130 aws_instance.foo: 5131 ID = foo 5132 required_field = set 5133 type = aws_instance 5134 `) 5135 if actual != expected { 5136 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 5137 } 5138 } 5139 5140 // https://github.com/hashicorp/terraform/issues/7378 5141 func TestContext2Apply_destroyNestedModuleWithAttrsReferencingResource(t *testing.T) { 5142 m := testModule(t, "apply-destroy-nested-module-with-attrs") 5143 p := testProvider("null") 5144 p.ApplyFn = testApplyFn 5145 p.DiffFn = testDiffFn 5146 5147 var state *State 5148 var err error 5149 { 5150 ctx := testContext2(t, &ContextOpts{ 5151 Module: m, 5152 Providers: map[string]ResourceProviderFactory{ 5153 "null": testProviderFuncFixed(p), 5154 }, 5155 }) 5156 5157 // First plan and apply a create operation 5158 if _, err := ctx.Plan(); err != nil { 5159 t.Fatalf("plan err: %s", err) 5160 } 5161 5162 state, err = ctx.Apply() 5163 if err != nil { 5164 t.Fatalf("apply err: %s", err) 5165 } 5166 } 5167 5168 { 5169 ctx := testContext2(t, &ContextOpts{ 5170 Destroy: true, 5171 Module: m, 5172 State: state, 5173 Providers: map[string]ResourceProviderFactory{ 5174 "null": testProviderFuncFixed(p), 5175 }, 5176 }) 5177 5178 plan, err := ctx.Plan() 5179 if err != nil { 5180 t.Fatalf("destroy plan err: %s", err) 5181 } 5182 5183 var buf bytes.Buffer 5184 if err := WritePlan(plan, &buf); err != nil { 5185 t.Fatalf("plan write err: %s", err) 5186 } 5187 5188 planFromFile, err := ReadPlan(&buf) 5189 if err != nil { 5190 t.Fatalf("plan read err: %s", err) 5191 } 5192 5193 ctx, err = planFromFile.Context(&ContextOpts{ 5194 Providers: map[string]ResourceProviderFactory{ 5195 "null": testProviderFuncFixed(p), 5196 }, 5197 }) 5198 if err != nil { 5199 t.Fatalf("err: %s", err) 5200 } 5201 5202 state, err = ctx.Apply() 5203 if err != nil { 5204 t.Fatalf("destroy apply err: %s", err) 5205 } 5206 } 5207 5208 //Test that things were destroyed 5209 actual := strings.TrimSpace(state.String()) 5210 expected := strings.TrimSpace(` 5211 <no state> 5212 module.middle: 5213 <no state> 5214 module.middle.bottom: 5215 <no state> 5216 `) 5217 if actual != expected { 5218 t.Fatalf("expected: \n%s\n\nbad: \n%s", expected, actual) 5219 } 5220 }