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