github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/context_plan_test.go (about) 1 package terraform 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "reflect" 8 "sort" 9 "strings" 10 "sync" 11 "testing" 12 ) 13 14 func TestContext2Plan(t *testing.T) { 15 m := testModule(t, "plan-good") 16 p := testProvider("aws") 17 p.DiffFn = testDiffFn 18 ctx := testContext2(t, &ContextOpts{ 19 Module: m, 20 Providers: map[string]ResourceProviderFactory{ 21 "aws": testProviderFuncFixed(p), 22 }, 23 }) 24 25 plan, err := ctx.Plan() 26 if err != nil { 27 t.Fatalf("err: %s", err) 28 } 29 30 if len(plan.Diff.RootModule().Resources) < 2 { 31 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 32 } 33 34 actual := strings.TrimSpace(plan.String()) 35 expected := strings.TrimSpace(testTerraformPlanStr) 36 if actual != expected { 37 t.Fatalf("bad:\n%s", actual) 38 } 39 } 40 41 func TestContext2Plan_createBefore_maintainRoot(t *testing.T) { 42 m := testModule(t, "plan-cbd-maintain-root") 43 p := testProvider("aws") 44 p.DiffFn = testDiffFn 45 ctx := testContext2(t, &ContextOpts{ 46 Module: m, 47 Providers: map[string]ResourceProviderFactory{ 48 "aws": testProviderFuncFixed(p), 49 }, 50 Variables: map[string]string{ 51 "in": "a,b,c", 52 }, 53 }) 54 55 plan, err := ctx.Plan() 56 if err != nil { 57 t.Fatalf("err: %s", err) 58 } 59 60 actual := strings.TrimSpace(plan.String()) 61 expected := strings.TrimSpace(` 62 DIFF: 63 64 CREATE: aws_instance.bar.0 65 CREATE: aws_instance.bar.1 66 CREATE: aws_instance.foo.0 67 CREATE: aws_instance.foo.1 68 69 STATE: 70 71 <no state> 72 `) 73 if actual != expected { 74 t.Fatalf("expected:\n%s, got:\n%s", expected, actual) 75 } 76 } 77 78 func TestContext2Plan_emptyDiff(t *testing.T) { 79 m := testModule(t, "plan-empty") 80 p := testProvider("aws") 81 p.DiffFn = func( 82 info *InstanceInfo, 83 s *InstanceState, 84 c *ResourceConfig) (*InstanceDiff, error) { 85 return nil, nil 86 } 87 88 ctx := testContext2(t, &ContextOpts{ 89 Module: m, 90 Providers: map[string]ResourceProviderFactory{ 91 "aws": testProviderFuncFixed(p), 92 }, 93 }) 94 95 plan, err := ctx.Plan() 96 if err != nil { 97 t.Fatalf("err: %s", err) 98 } 99 100 actual := strings.TrimSpace(plan.String()) 101 expected := strings.TrimSpace(testTerraformPlanEmptyStr) 102 if actual != expected { 103 t.Fatalf("bad:\n%s", actual) 104 } 105 } 106 107 func TestContext2Plan_minimal(t *testing.T) { 108 m := testModule(t, "plan-empty") 109 p := testProvider("aws") 110 p.DiffFn = testDiffFn 111 ctx := testContext2(t, &ContextOpts{ 112 Module: m, 113 Providers: map[string]ResourceProviderFactory{ 114 "aws": testProviderFuncFixed(p), 115 }, 116 }) 117 118 plan, err := ctx.Plan() 119 if err != nil { 120 t.Fatalf("err: %s", err) 121 } 122 123 actual := strings.TrimSpace(plan.String()) 124 expected := strings.TrimSpace(testTerraformPlanEmptyStr) 125 if actual != expected { 126 t.Fatalf("bad:\n%s", actual) 127 } 128 } 129 130 func TestContext2Plan_modules(t *testing.T) { 131 m := testModule(t, "plan-modules") 132 p := testProvider("aws") 133 p.DiffFn = testDiffFn 134 ctx := testContext2(t, &ContextOpts{ 135 Module: m, 136 Providers: map[string]ResourceProviderFactory{ 137 "aws": testProviderFuncFixed(p), 138 }, 139 }) 140 141 plan, err := ctx.Plan() 142 if err != nil { 143 t.Fatalf("err: %s", err) 144 } 145 146 actual := strings.TrimSpace(plan.String()) 147 expected := strings.TrimSpace(testTerraformPlanModulesStr) 148 if actual != expected { 149 t.Fatalf("bad:\n%s", actual) 150 } 151 } 152 153 // GH-1475 154 func TestContext2Plan_moduleCycle(t *testing.T) { 155 m := testModule(t, "plan-module-cycle") 156 p := testProvider("aws") 157 p.DiffFn = testDiffFn 158 ctx := testContext2(t, &ContextOpts{ 159 Module: m, 160 Providers: map[string]ResourceProviderFactory{ 161 "aws": testProviderFuncFixed(p), 162 }, 163 }) 164 165 plan, err := ctx.Plan() 166 if err != nil { 167 t.Fatalf("err: %s", err) 168 } 169 170 actual := strings.TrimSpace(plan.String()) 171 expected := strings.TrimSpace(testTerraformPlanModuleCycleStr) 172 if actual != expected { 173 t.Fatalf("bad:\n%s", actual) 174 } 175 } 176 177 func TestContext2Plan_moduleDeadlock(t *testing.T) { 178 testCheckDeadlock(t, func() { 179 m := testModule(t, "plan-module-deadlock") 180 p := testProvider("aws") 181 p.DiffFn = testDiffFn 182 183 ctx := testContext2(t, &ContextOpts{ 184 Module: m, 185 Providers: map[string]ResourceProviderFactory{ 186 "aws": testProviderFuncFixed(p), 187 }, 188 }) 189 190 plan, err := ctx.Plan() 191 if err != nil { 192 t.Fatalf("err: %s", err) 193 } 194 195 actual := strings.TrimSpace(plan.String()) 196 expected := strings.TrimSpace(` 197 DIFF: 198 199 module.child: 200 CREATE: aws_instance.foo.0 201 CREATE: aws_instance.foo.1 202 CREATE: aws_instance.foo.2 203 204 STATE: 205 206 <no state> 207 `) 208 if actual != expected { 209 t.Fatalf("expected:\n%sgot:\n%s", expected, actual) 210 } 211 }) 212 } 213 214 func TestContext2Plan_moduleInput(t *testing.T) { 215 m := testModule(t, "plan-module-input") 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(testTerraformPlanModuleInputStr) 232 if actual != expected { 233 t.Fatalf("bad:\n%s", actual) 234 } 235 } 236 237 func TestContext2Plan_moduleInputComputed(t *testing.T) { 238 m := testModule(t, "plan-module-input-computed") 239 p := testProvider("aws") 240 p.DiffFn = testDiffFn 241 ctx := testContext2(t, &ContextOpts{ 242 Module: m, 243 Providers: map[string]ResourceProviderFactory{ 244 "aws": testProviderFuncFixed(p), 245 }, 246 }) 247 248 plan, err := ctx.Plan() 249 if err != nil { 250 t.Fatalf("err: %s", err) 251 } 252 253 actual := strings.TrimSpace(plan.String()) 254 expected := strings.TrimSpace(testTerraformPlanModuleInputComputedStr) 255 if actual != expected { 256 t.Fatalf("bad:\n%s", actual) 257 } 258 } 259 260 func TestContext2Plan_moduleInputFromVar(t *testing.T) { 261 m := testModule(t, "plan-module-input-var") 262 p := testProvider("aws") 263 p.DiffFn = testDiffFn 264 ctx := testContext2(t, &ContextOpts{ 265 Module: m, 266 Providers: map[string]ResourceProviderFactory{ 267 "aws": testProviderFuncFixed(p), 268 }, 269 Variables: map[string]string{ 270 "foo": "52", 271 }, 272 }) 273 274 plan, err := ctx.Plan() 275 if err != nil { 276 t.Fatalf("err: %s", err) 277 } 278 279 actual := strings.TrimSpace(plan.String()) 280 expected := strings.TrimSpace(testTerraformPlanModuleInputVarStr) 281 if actual != expected { 282 t.Fatalf("bad:\n%s", actual) 283 } 284 } 285 286 func TestContext2Plan_moduleMultiVar(t *testing.T) { 287 m := testModule(t, "plan-module-multi-var") 288 p := testProvider("aws") 289 p.DiffFn = testDiffFn 290 ctx := testContext2(t, &ContextOpts{ 291 Module: m, 292 Providers: map[string]ResourceProviderFactory{ 293 "aws": testProviderFuncFixed(p), 294 }, 295 }) 296 297 plan, err := ctx.Plan() 298 if err != nil { 299 t.Fatalf("err: %s", err) 300 } 301 302 actual := strings.TrimSpace(plan.String()) 303 expected := strings.TrimSpace(testTerraformPlanModuleMultiVarStr) 304 if actual != expected { 305 t.Fatalf("bad:\n%s", actual) 306 } 307 } 308 309 func TestContext2Plan_moduleOrphans(t *testing.T) { 310 m := testModule(t, "plan-modules-remove") 311 p := testProvider("aws") 312 p.DiffFn = testDiffFn 313 s := &State{ 314 Modules: []*ModuleState{ 315 &ModuleState{ 316 Path: []string{"root", "child"}, 317 Resources: map[string]*ResourceState{ 318 "aws_instance.foo": &ResourceState{ 319 Type: "aws_instance", 320 Primary: &InstanceState{ 321 ID: "baz", 322 }, 323 }, 324 }, 325 }, 326 }, 327 } 328 ctx := testContext2(t, &ContextOpts{ 329 Module: m, 330 Providers: map[string]ResourceProviderFactory{ 331 "aws": testProviderFuncFixed(p), 332 }, 333 State: s, 334 }) 335 336 plan, err := ctx.Plan() 337 if err != nil { 338 t.Fatalf("err: %s", err) 339 } 340 341 actual := strings.TrimSpace(plan.String()) 342 expected := strings.TrimSpace(testTerraformPlanModuleOrphansStr) 343 if actual != expected { 344 t.Fatalf("bad:\n%s", actual) 345 } 346 } 347 348 func TestContext2Plan_moduleProviderInherit(t *testing.T) { 349 var l sync.Mutex 350 var calls []string 351 352 m := testModule(t, "plan-module-provider-inherit") 353 ctx := testContext2(t, &ContextOpts{ 354 Module: m, 355 Providers: map[string]ResourceProviderFactory{ 356 "aws": func() (ResourceProvider, error) { 357 l.Lock() 358 defer l.Unlock() 359 360 p := testProvider("aws") 361 p.ConfigureFn = func(c *ResourceConfig) error { 362 if v, ok := c.Get("from"); !ok || v.(string) != "root" { 363 return fmt.Errorf("bad") 364 } 365 366 return nil 367 } 368 p.DiffFn = func( 369 info *InstanceInfo, 370 state *InstanceState, 371 c *ResourceConfig) (*InstanceDiff, error) { 372 v, _ := c.Get("from") 373 calls = append(calls, v.(string)) 374 return testDiffFn(info, state, c) 375 } 376 return p, nil 377 }, 378 }, 379 }) 380 381 _, err := ctx.Plan() 382 if err != nil { 383 t.Fatalf("err: %s", err) 384 } 385 386 actual := calls 387 sort.Strings(actual) 388 expected := []string{"child", "root"} 389 if !reflect.DeepEqual(actual, expected) { 390 t.Fatalf("bad: %#v", actual) 391 } 392 } 393 394 func TestContext2Plan_moduleProviderDefaults(t *testing.T) { 395 var l sync.Mutex 396 var calls []string 397 toCount := 0 398 399 m := testModule(t, "plan-module-provider-defaults") 400 ctx := testContext2(t, &ContextOpts{ 401 Module: m, 402 Providers: map[string]ResourceProviderFactory{ 403 "aws": func() (ResourceProvider, error) { 404 l.Lock() 405 defer l.Unlock() 406 407 p := testProvider("aws") 408 p.ConfigureFn = func(c *ResourceConfig) error { 409 if v, ok := c.Get("from"); !ok || v.(string) != "root" { 410 return fmt.Errorf("bad") 411 } 412 if v, ok := c.Get("to"); ok && v.(string) == "child" { 413 toCount++ 414 } 415 416 return nil 417 } 418 p.DiffFn = func( 419 info *InstanceInfo, 420 state *InstanceState, 421 c *ResourceConfig) (*InstanceDiff, error) { 422 v, _ := c.Get("from") 423 calls = append(calls, v.(string)) 424 return testDiffFn(info, state, c) 425 } 426 return p, nil 427 }, 428 }, 429 }) 430 431 _, err := ctx.Plan() 432 if err != nil { 433 t.Fatalf("err: %s", err) 434 } 435 436 if toCount != 1 { 437 t.Fatalf( 438 "provider in child didn't set proper config\n\n"+ 439 "toCount: %d", toCount) 440 } 441 442 actual := calls 443 sort.Strings(actual) 444 expected := []string{"child", "root"} 445 if !reflect.DeepEqual(actual, expected) { 446 t.Fatalf("bad: %#v", actual) 447 } 448 } 449 450 func TestContext2Plan_moduleProviderDefaultsVar(t *testing.T) { 451 var l sync.Mutex 452 var calls []string 453 454 m := testModule(t, "plan-module-provider-defaults-var") 455 ctx := testContext2(t, &ContextOpts{ 456 Module: m, 457 Providers: map[string]ResourceProviderFactory{ 458 "aws": func() (ResourceProvider, error) { 459 l.Lock() 460 defer l.Unlock() 461 462 p := testProvider("aws") 463 p.ConfigureFn = func(c *ResourceConfig) error { 464 var buf bytes.Buffer 465 if v, ok := c.Get("from"); ok { 466 buf.WriteString(v.(string) + "\n") 467 } 468 if v, ok := c.Get("to"); ok { 469 buf.WriteString(v.(string) + "\n") 470 } 471 472 calls = append(calls, buf.String()) 473 return nil 474 } 475 p.DiffFn = testDiffFn 476 return p, nil 477 }, 478 }, 479 Variables: map[string]string{ 480 "foo": "root", 481 }, 482 }) 483 484 _, err := ctx.Plan() 485 if err != nil { 486 t.Fatalf("err: %s", err) 487 } 488 489 expected := []string{ 490 "root\n", 491 "root\nchild\n", 492 } 493 if !reflect.DeepEqual(calls, expected) { 494 t.Fatalf("BAD: %#v", calls) 495 } 496 } 497 498 func TestContext2Plan_moduleVar(t *testing.T) { 499 m := testModule(t, "plan-module-var") 500 p := testProvider("aws") 501 p.DiffFn = testDiffFn 502 ctx := testContext2(t, &ContextOpts{ 503 Module: m, 504 Providers: map[string]ResourceProviderFactory{ 505 "aws": testProviderFuncFixed(p), 506 }, 507 }) 508 509 plan, err := ctx.Plan() 510 if err != nil { 511 t.Fatalf("err: %s", err) 512 } 513 514 actual := strings.TrimSpace(plan.String()) 515 expected := strings.TrimSpace(testTerraformPlanModuleVarStr) 516 if actual != expected { 517 t.Fatalf("bad:\n%s", actual) 518 } 519 } 520 521 func TestContext2Plan_moduleVarComputed(t *testing.T) { 522 m := testModule(t, "plan-module-var-computed") 523 p := testProvider("aws") 524 p.DiffFn = testDiffFn 525 ctx := testContext2(t, &ContextOpts{ 526 Module: m, 527 Providers: map[string]ResourceProviderFactory{ 528 "aws": testProviderFuncFixed(p), 529 }, 530 }) 531 532 plan, err := ctx.Plan() 533 if err != nil { 534 t.Fatalf("err: %s", err) 535 } 536 537 actual := strings.TrimSpace(plan.String()) 538 expected := strings.TrimSpace(testTerraformPlanModuleVarComputedStr) 539 if actual != expected { 540 t.Fatalf("bad:\n%s", actual) 541 } 542 } 543 544 func TestContext2Plan_nil(t *testing.T) { 545 m := testModule(t, "plan-nil") 546 p := testProvider("aws") 547 p.DiffFn = testDiffFn 548 ctx := testContext2(t, &ContextOpts{ 549 Module: m, 550 Providers: map[string]ResourceProviderFactory{ 551 "aws": testProviderFuncFixed(p), 552 }, 553 State: &State{ 554 Modules: []*ModuleState{ 555 &ModuleState{ 556 Path: rootModulePath, 557 Resources: map[string]*ResourceState{ 558 "aws_instance.foo": &ResourceState{ 559 Type: "aws_instance", 560 Primary: &InstanceState{ 561 ID: "bar", 562 }, 563 }, 564 }, 565 }, 566 }, 567 }, 568 }) 569 570 plan, err := ctx.Plan() 571 if err != nil { 572 t.Fatalf("err: %s", err) 573 } 574 if len(plan.Diff.RootModule().Resources) != 0 { 575 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 576 } 577 } 578 579 func TestContext2Plan_preventDestroy_bad(t *testing.T) { 580 m := testModule(t, "plan-prevent-destroy-bad") 581 p := testProvider("aws") 582 p.DiffFn = testDiffFn 583 ctx := testContext2(t, &ContextOpts{ 584 Module: m, 585 Providers: map[string]ResourceProviderFactory{ 586 "aws": testProviderFuncFixed(p), 587 }, 588 State: &State{ 589 Modules: []*ModuleState{ 590 &ModuleState{ 591 Path: rootModulePath, 592 Resources: map[string]*ResourceState{ 593 "aws_instance.foo": &ResourceState{ 594 Type: "aws_instance", 595 Primary: &InstanceState{ 596 ID: "i-abc123", 597 }, 598 }, 599 }, 600 }, 601 }, 602 }, 603 }) 604 605 plan, err := ctx.Plan() 606 607 expectedErr := "aws_instance.foo: the plan would destroy" 608 if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) { 609 t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s", 610 expectedErr, err, plan) 611 } 612 } 613 614 func TestContext2Plan_preventDestroy_good(t *testing.T) { 615 m := testModule(t, "plan-prevent-destroy-good") 616 p := testProvider("aws") 617 p.DiffFn = testDiffFn 618 ctx := testContext2(t, &ContextOpts{ 619 Module: m, 620 Providers: map[string]ResourceProviderFactory{ 621 "aws": testProviderFuncFixed(p), 622 }, 623 State: &State{ 624 Modules: []*ModuleState{ 625 &ModuleState{ 626 Path: rootModulePath, 627 Resources: map[string]*ResourceState{ 628 "aws_instance.foo": &ResourceState{ 629 Type: "aws_instance", 630 Primary: &InstanceState{ 631 ID: "i-abc123", 632 }, 633 }, 634 }, 635 }, 636 }, 637 }, 638 }) 639 640 plan, err := ctx.Plan() 641 if err != nil { 642 t.Fatalf("err: %s", err) 643 } 644 if !plan.Diff.Empty() { 645 t.Fatalf("Expected empty plan, got %s", plan.String()) 646 } 647 } 648 649 func TestContext2Plan_preventDestroy_destroyPlan(t *testing.T) { 650 m := testModule(t, "plan-prevent-destroy-good") 651 p := testProvider("aws") 652 p.DiffFn = testDiffFn 653 ctx := testContext2(t, &ContextOpts{ 654 Module: m, 655 Providers: map[string]ResourceProviderFactory{ 656 "aws": testProviderFuncFixed(p), 657 }, 658 State: &State{ 659 Modules: []*ModuleState{ 660 &ModuleState{ 661 Path: rootModulePath, 662 Resources: map[string]*ResourceState{ 663 "aws_instance.foo": &ResourceState{ 664 Type: "aws_instance", 665 Primary: &InstanceState{ 666 ID: "i-abc123", 667 }, 668 }, 669 }, 670 }, 671 }, 672 }, 673 Destroy: true, 674 }) 675 676 plan, err := ctx.Plan() 677 678 expectedErr := "aws_instance.foo: the plan would destroy" 679 if !strings.Contains(fmt.Sprintf("%s", err), expectedErr) { 680 t.Fatalf("expected err would contain %q\nerr: %s\nplan: %s", 681 expectedErr, err, plan) 682 } 683 } 684 685 func TestContext2Plan_computed(t *testing.T) { 686 m := testModule(t, "plan-computed") 687 p := testProvider("aws") 688 p.DiffFn = testDiffFn 689 ctx := testContext2(t, &ContextOpts{ 690 Module: m, 691 Providers: map[string]ResourceProviderFactory{ 692 "aws": testProviderFuncFixed(p), 693 }, 694 }) 695 696 plan, err := ctx.Plan() 697 if err != nil { 698 t.Fatalf("err: %s", err) 699 } 700 701 actual := strings.TrimSpace(plan.String()) 702 expected := strings.TrimSpace(testTerraformPlanComputedStr) 703 if actual != expected { 704 t.Fatalf("bad:\n%s", actual) 705 } 706 } 707 708 func TestContext2Plan_computedList(t *testing.T) { 709 m := testModule(t, "plan-computed-list") 710 p := testProvider("aws") 711 p.DiffFn = testDiffFn 712 ctx := testContext2(t, &ContextOpts{ 713 Module: m, 714 Providers: map[string]ResourceProviderFactory{ 715 "aws": testProviderFuncFixed(p), 716 }, 717 }) 718 719 plan, err := ctx.Plan() 720 if err != nil { 721 t.Fatalf("err: %s", err) 722 } 723 724 actual := strings.TrimSpace(plan.String()) 725 expected := strings.TrimSpace(testTerraformPlanComputedListStr) 726 if actual != expected { 727 t.Fatalf("bad:\n%s", actual) 728 } 729 } 730 731 func TestContext2Plan_count(t *testing.T) { 732 m := testModule(t, "plan-count") 733 p := testProvider("aws") 734 p.DiffFn = testDiffFn 735 ctx := testContext2(t, &ContextOpts{ 736 Module: m, 737 Providers: map[string]ResourceProviderFactory{ 738 "aws": testProviderFuncFixed(p), 739 }, 740 }) 741 742 plan, err := ctx.Plan() 743 if err != nil { 744 t.Fatalf("err: %s", err) 745 } 746 747 if len(plan.Diff.RootModule().Resources) < 6 { 748 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 749 } 750 751 actual := strings.TrimSpace(plan.String()) 752 expected := strings.TrimSpace(testTerraformPlanCountStr) 753 if actual != expected { 754 t.Fatalf("bad:\n%s", actual) 755 } 756 } 757 758 func TestContext2Plan_countComputed(t *testing.T) { 759 m := testModule(t, "plan-count-computed") 760 p := testProvider("aws") 761 p.DiffFn = testDiffFn 762 ctx := testContext2(t, &ContextOpts{ 763 Module: m, 764 Providers: map[string]ResourceProviderFactory{ 765 "aws": testProviderFuncFixed(p), 766 }, 767 }) 768 769 _, err := ctx.Plan() 770 if err == nil { 771 t.Fatal("should error") 772 } 773 } 774 775 func TestContext2Plan_countIndex(t *testing.T) { 776 m := testModule(t, "plan-count-index") 777 p := testProvider("aws") 778 p.DiffFn = testDiffFn 779 ctx := testContext2(t, &ContextOpts{ 780 Module: m, 781 Providers: map[string]ResourceProviderFactory{ 782 "aws": testProviderFuncFixed(p), 783 }, 784 }) 785 786 plan, err := ctx.Plan() 787 if err != nil { 788 t.Fatalf("err: %s", err) 789 } 790 791 actual := strings.TrimSpace(plan.String()) 792 expected := strings.TrimSpace(testTerraformPlanCountIndexStr) 793 if actual != expected { 794 t.Fatalf("bad:\n%s", actual) 795 } 796 } 797 798 func TestContext2Plan_countIndexZero(t *testing.T) { 799 m := testModule(t, "plan-count-index-zero") 800 p := testProvider("aws") 801 p.DiffFn = testDiffFn 802 ctx := testContext2(t, &ContextOpts{ 803 Module: m, 804 Providers: map[string]ResourceProviderFactory{ 805 "aws": testProviderFuncFixed(p), 806 }, 807 }) 808 809 plan, err := ctx.Plan() 810 if err != nil { 811 t.Fatalf("err: %s", err) 812 } 813 814 actual := strings.TrimSpace(plan.String()) 815 expected := strings.TrimSpace(testTerraformPlanCountIndexZeroStr) 816 if actual != expected { 817 t.Fatalf("bad:\n%s", actual) 818 } 819 } 820 821 func TestContext2Plan_countVar(t *testing.T) { 822 m := testModule(t, "plan-count-var") 823 p := testProvider("aws") 824 p.DiffFn = testDiffFn 825 ctx := testContext2(t, &ContextOpts{ 826 Module: m, 827 Providers: map[string]ResourceProviderFactory{ 828 "aws": testProviderFuncFixed(p), 829 }, 830 Variables: map[string]string{ 831 "count": "3", 832 }, 833 }) 834 835 plan, err := ctx.Plan() 836 if err != nil { 837 t.Fatalf("err: %s", err) 838 } 839 840 actual := strings.TrimSpace(plan.String()) 841 expected := strings.TrimSpace(testTerraformPlanCountVarStr) 842 if actual != expected { 843 t.Fatalf("bad:\n%s", actual) 844 } 845 } 846 847 func TestContext2Plan_countZero(t *testing.T) { 848 m := testModule(t, "plan-count-zero") 849 p := testProvider("aws") 850 p.DiffFn = testDiffFn 851 ctx := testContext2(t, &ContextOpts{ 852 Module: m, 853 Providers: map[string]ResourceProviderFactory{ 854 "aws": testProviderFuncFixed(p), 855 }, 856 }) 857 858 plan, err := ctx.Plan() 859 if err != nil { 860 t.Fatalf("err: %s", err) 861 } 862 863 actual := strings.TrimSpace(plan.String()) 864 expected := strings.TrimSpace(testTerraformPlanCountZeroStr) 865 if actual != expected { 866 t.Fatalf("bad:\n%s", actual) 867 } 868 } 869 870 func TestContext2Plan_countOneIndex(t *testing.T) { 871 m := testModule(t, "plan-count-one-index") 872 p := testProvider("aws") 873 p.DiffFn = testDiffFn 874 ctx := testContext2(t, &ContextOpts{ 875 Module: m, 876 Providers: map[string]ResourceProviderFactory{ 877 "aws": testProviderFuncFixed(p), 878 }, 879 }) 880 881 plan, err := ctx.Plan() 882 if err != nil { 883 t.Fatalf("err: %s", err) 884 } 885 886 actual := strings.TrimSpace(plan.String()) 887 expected := strings.TrimSpace(testTerraformPlanCountOneIndexStr) 888 if actual != expected { 889 t.Fatalf("bad:\n%s", actual) 890 } 891 } 892 893 func TestContext2Plan_countDecreaseToOne(t *testing.T) { 894 m := testModule(t, "plan-count-dec") 895 p := testProvider("aws") 896 p.DiffFn = testDiffFn 897 s := &State{ 898 Modules: []*ModuleState{ 899 &ModuleState{ 900 Path: rootModulePath, 901 Resources: map[string]*ResourceState{ 902 "aws_instance.foo.0": &ResourceState{ 903 Type: "aws_instance", 904 Primary: &InstanceState{ 905 ID: "bar", 906 Attributes: map[string]string{ 907 "foo": "foo", 908 "type": "aws_instance", 909 }, 910 }, 911 }, 912 "aws_instance.foo.1": &ResourceState{ 913 Type: "aws_instance", 914 Primary: &InstanceState{ 915 ID: "bar", 916 }, 917 }, 918 "aws_instance.foo.2": &ResourceState{ 919 Type: "aws_instance", 920 Primary: &InstanceState{ 921 ID: "bar", 922 }, 923 }, 924 }, 925 }, 926 }, 927 } 928 ctx := testContext2(t, &ContextOpts{ 929 Module: m, 930 Providers: map[string]ResourceProviderFactory{ 931 "aws": testProviderFuncFixed(p), 932 }, 933 State: s, 934 }) 935 936 plan, err := ctx.Plan() 937 if err != nil { 938 t.Fatalf("err: %s", err) 939 } 940 941 actual := strings.TrimSpace(plan.String()) 942 expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr) 943 if actual != expected { 944 t.Fatalf("bad:\n%s", actual) 945 } 946 } 947 948 func TestContext2Plan_countIncreaseFromNotSet(t *testing.T) { 949 m := testModule(t, "plan-count-inc") 950 p := testProvider("aws") 951 p.DiffFn = testDiffFn 952 s := &State{ 953 Modules: []*ModuleState{ 954 &ModuleState{ 955 Path: rootModulePath, 956 Resources: map[string]*ResourceState{ 957 "aws_instance.foo": &ResourceState{ 958 Type: "aws_instance", 959 Primary: &InstanceState{ 960 ID: "bar", 961 Attributes: map[string]string{ 962 "foo": "foo", 963 "type": "aws_instance", 964 }, 965 }, 966 }, 967 }, 968 }, 969 }, 970 } 971 ctx := testContext2(t, &ContextOpts{ 972 Module: m, 973 Providers: map[string]ResourceProviderFactory{ 974 "aws": testProviderFuncFixed(p), 975 }, 976 State: s, 977 }) 978 979 plan, err := ctx.Plan() 980 if err != nil { 981 t.Fatalf("err: %s", err) 982 } 983 984 actual := strings.TrimSpace(plan.String()) 985 expected := strings.TrimSpace(testTerraformPlanCountIncreaseStr) 986 if actual != expected { 987 t.Fatalf("bad:\n%s", actual) 988 } 989 } 990 991 func TestContext2Plan_countIncreaseFromOne(t *testing.T) { 992 m := testModule(t, "plan-count-inc") 993 p := testProvider("aws") 994 p.DiffFn = testDiffFn 995 s := &State{ 996 Modules: []*ModuleState{ 997 &ModuleState{ 998 Path: rootModulePath, 999 Resources: map[string]*ResourceState{ 1000 "aws_instance.foo.0": &ResourceState{ 1001 Type: "aws_instance", 1002 Primary: &InstanceState{ 1003 ID: "bar", 1004 Attributes: map[string]string{ 1005 "foo": "foo", 1006 "type": "aws_instance", 1007 }, 1008 }, 1009 }, 1010 }, 1011 }, 1012 }, 1013 } 1014 ctx := testContext2(t, &ContextOpts{ 1015 Module: m, 1016 Providers: map[string]ResourceProviderFactory{ 1017 "aws": testProviderFuncFixed(p), 1018 }, 1019 State: s, 1020 }) 1021 1022 plan, err := ctx.Plan() 1023 if err != nil { 1024 t.Fatalf("err: %s", err) 1025 } 1026 1027 actual := strings.TrimSpace(plan.String()) 1028 expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneStr) 1029 if actual != expected { 1030 t.Fatalf("bad:\n%s", actual) 1031 } 1032 } 1033 1034 // https://github.com/PeoplePerHour/terraform/pull/11 1035 // 1036 // This tests a case where both a "resource" and "resource.0" are in 1037 // the state file, which apparently is a reasonable backwards compatibility 1038 // concern found in the above 3rd party repo. 1039 func TestContext2Plan_countIncreaseFromOneCorrupted(t *testing.T) { 1040 m := testModule(t, "plan-count-inc") 1041 p := testProvider("aws") 1042 p.DiffFn = testDiffFn 1043 s := &State{ 1044 Modules: []*ModuleState{ 1045 &ModuleState{ 1046 Path: rootModulePath, 1047 Resources: map[string]*ResourceState{ 1048 "aws_instance.foo": &ResourceState{ 1049 Type: "aws_instance", 1050 Primary: &InstanceState{ 1051 ID: "bar", 1052 Attributes: map[string]string{ 1053 "foo": "foo", 1054 "type": "aws_instance", 1055 }, 1056 }, 1057 }, 1058 "aws_instance.foo.0": &ResourceState{ 1059 Type: "aws_instance", 1060 Primary: &InstanceState{ 1061 ID: "bar", 1062 Attributes: map[string]string{ 1063 "foo": "foo", 1064 "type": "aws_instance", 1065 }, 1066 }, 1067 }, 1068 }, 1069 }, 1070 }, 1071 } 1072 ctx := testContext2(t, &ContextOpts{ 1073 Module: m, 1074 Providers: map[string]ResourceProviderFactory{ 1075 "aws": testProviderFuncFixed(p), 1076 }, 1077 State: s, 1078 }) 1079 1080 plan, err := ctx.Plan() 1081 if err != nil { 1082 t.Fatalf("err: %s", err) 1083 } 1084 1085 actual := strings.TrimSpace(plan.String()) 1086 expected := strings.TrimSpace(testTerraformPlanCountIncreaseFromOneCorruptedStr) 1087 if actual != expected { 1088 t.Fatalf("bad:\n%s", actual) 1089 } 1090 } 1091 1092 func TestContext2Plan_destroy(t *testing.T) { 1093 m := testModule(t, "plan-destroy") 1094 p := testProvider("aws") 1095 p.DiffFn = testDiffFn 1096 s := &State{ 1097 Modules: []*ModuleState{ 1098 &ModuleState{ 1099 Path: rootModulePath, 1100 Resources: map[string]*ResourceState{ 1101 "aws_instance.one": &ResourceState{ 1102 Type: "aws_instance", 1103 Primary: &InstanceState{ 1104 ID: "bar", 1105 }, 1106 }, 1107 "aws_instance.two": &ResourceState{ 1108 Type: "aws_instance", 1109 Primary: &InstanceState{ 1110 ID: "baz", 1111 }, 1112 }, 1113 }, 1114 }, 1115 }, 1116 } 1117 ctx := testContext2(t, &ContextOpts{ 1118 Module: m, 1119 Providers: map[string]ResourceProviderFactory{ 1120 "aws": testProviderFuncFixed(p), 1121 }, 1122 State: s, 1123 Destroy: true, 1124 }) 1125 1126 plan, err := ctx.Plan() 1127 if err != nil { 1128 t.Fatalf("err: %s", err) 1129 } 1130 1131 if len(plan.Diff.RootModule().Resources) != 2 { 1132 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 1133 } 1134 1135 actual := strings.TrimSpace(plan.String()) 1136 expected := strings.TrimSpace(testTerraformPlanDestroyStr) 1137 if actual != expected { 1138 t.Fatalf("bad:\n%s", actual) 1139 } 1140 } 1141 1142 func TestContext2Plan_moduleDestroy(t *testing.T) { 1143 m := testModule(t, "plan-module-destroy") 1144 p := testProvider("aws") 1145 p.DiffFn = testDiffFn 1146 s := &State{ 1147 Modules: []*ModuleState{ 1148 &ModuleState{ 1149 Path: rootModulePath, 1150 Resources: map[string]*ResourceState{ 1151 "aws_instance.foo": &ResourceState{ 1152 Type: "aws_instance", 1153 Primary: &InstanceState{ 1154 ID: "bar", 1155 }, 1156 }, 1157 }, 1158 }, 1159 &ModuleState{ 1160 Path: []string{"root", "child"}, 1161 Resources: map[string]*ResourceState{ 1162 "aws_instance.foo": &ResourceState{ 1163 Type: "aws_instance", 1164 Primary: &InstanceState{ 1165 ID: "bar", 1166 }, 1167 }, 1168 }, 1169 }, 1170 }, 1171 } 1172 ctx := testContext2(t, &ContextOpts{ 1173 Module: m, 1174 Providers: map[string]ResourceProviderFactory{ 1175 "aws": testProviderFuncFixed(p), 1176 }, 1177 State: s, 1178 Destroy: true, 1179 }) 1180 1181 plan, err := ctx.Plan() 1182 if err != nil { 1183 t.Fatalf("err: %s", err) 1184 } 1185 1186 actual := strings.TrimSpace(plan.String()) 1187 expected := strings.TrimSpace(testTerraformPlanModuleDestroyStr) 1188 if actual != expected { 1189 t.Fatalf("bad:\n%s", actual) 1190 } 1191 } 1192 1193 // GH-1835 1194 func TestContext2Plan_moduleDestroyCycle(t *testing.T) { 1195 m := testModule(t, "plan-module-destroy-gh-1835") 1196 p := testProvider("aws") 1197 p.DiffFn = testDiffFn 1198 s := &State{ 1199 Modules: []*ModuleState{ 1200 &ModuleState{ 1201 Path: []string{"root", "a_module"}, 1202 Resources: map[string]*ResourceState{ 1203 "aws_instance.a": &ResourceState{ 1204 Type: "aws_instance", 1205 Primary: &InstanceState{ 1206 ID: "a", 1207 }, 1208 }, 1209 }, 1210 }, 1211 &ModuleState{ 1212 Path: []string{"root", "b_module"}, 1213 Resources: map[string]*ResourceState{ 1214 "aws_instance.b": &ResourceState{ 1215 Type: "aws_instance", 1216 Primary: &InstanceState{ 1217 ID: "b", 1218 }, 1219 }, 1220 }, 1221 }, 1222 }, 1223 } 1224 ctx := testContext2(t, &ContextOpts{ 1225 Module: m, 1226 Providers: map[string]ResourceProviderFactory{ 1227 "aws": testProviderFuncFixed(p), 1228 }, 1229 State: s, 1230 Destroy: true, 1231 }) 1232 1233 plan, err := ctx.Plan() 1234 if err != nil { 1235 t.Fatalf("err: %s", err) 1236 } 1237 1238 actual := strings.TrimSpace(plan.String()) 1239 expected := strings.TrimSpace(testTerraformPlanModuleDestroyCycleStr) 1240 if actual != expected { 1241 t.Fatalf("bad:\n%s", actual) 1242 } 1243 } 1244 1245 func TestContext2Plan_moduleDestroyMultivar(t *testing.T) { 1246 m := testModule(t, "plan-module-destroy-multivar") 1247 p := testProvider("aws") 1248 p.DiffFn = testDiffFn 1249 s := &State{ 1250 Modules: []*ModuleState{ 1251 &ModuleState{ 1252 Path: rootModulePath, 1253 Resources: map[string]*ResourceState{}, 1254 }, 1255 &ModuleState{ 1256 Path: []string{"root", "child"}, 1257 Resources: map[string]*ResourceState{ 1258 "aws_instance.foo.0": &ResourceState{ 1259 Type: "aws_instance", 1260 Primary: &InstanceState{ 1261 ID: "bar0", 1262 }, 1263 }, 1264 "aws_instance.foo.1": &ResourceState{ 1265 Type: "aws_instance", 1266 Primary: &InstanceState{ 1267 ID: "bar1", 1268 }, 1269 }, 1270 }, 1271 }, 1272 }, 1273 } 1274 ctx := testContext2(t, &ContextOpts{ 1275 Module: m, 1276 Providers: map[string]ResourceProviderFactory{ 1277 "aws": testProviderFuncFixed(p), 1278 }, 1279 State: s, 1280 Destroy: true, 1281 }) 1282 1283 plan, err := ctx.Plan() 1284 if err != nil { 1285 t.Fatalf("err: %s", err) 1286 } 1287 1288 actual := strings.TrimSpace(plan.String()) 1289 expected := strings.TrimSpace(testTerraformPlanModuleDestroyMultivarStr) 1290 if actual != expected { 1291 t.Fatalf("bad:\n%s", actual) 1292 } 1293 } 1294 1295 func TestContext2Plan_pathVar(t *testing.T) { 1296 cwd, err := os.Getwd() 1297 if err != nil { 1298 t.Fatalf("err: %s", err) 1299 } 1300 1301 m := testModule(t, "plan-path-var") 1302 p := testProvider("aws") 1303 p.DiffFn = testDiffFn 1304 ctx := testContext2(t, &ContextOpts{ 1305 Module: m, 1306 Providers: map[string]ResourceProviderFactory{ 1307 "aws": testProviderFuncFixed(p), 1308 }, 1309 }) 1310 1311 plan, err := ctx.Plan() 1312 if err != nil { 1313 t.Fatalf("err: %s", err) 1314 } 1315 1316 actual := strings.TrimSpace(plan.String()) 1317 expected := strings.TrimSpace(testTerraformPlanPathVarStr) 1318 1319 // Warning: this ordering REALLY matters for this test. The 1320 // order is: cwd, module, root. 1321 expected = fmt.Sprintf( 1322 expected, 1323 cwd, 1324 m.Config().Dir, 1325 m.Config().Dir) 1326 1327 if actual != expected { 1328 t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected) 1329 } 1330 } 1331 1332 func TestContext2Plan_diffVar(t *testing.T) { 1333 m := testModule(t, "plan-diffvar") 1334 p := testProvider("aws") 1335 s := &State{ 1336 Modules: []*ModuleState{ 1337 &ModuleState{ 1338 Path: rootModulePath, 1339 Resources: map[string]*ResourceState{ 1340 "aws_instance.foo": &ResourceState{ 1341 Primary: &InstanceState{ 1342 ID: "bar", 1343 Attributes: map[string]string{ 1344 "num": "2", 1345 }, 1346 }, 1347 }, 1348 }, 1349 }, 1350 }, 1351 } 1352 ctx := testContext2(t, &ContextOpts{ 1353 Module: m, 1354 Providers: map[string]ResourceProviderFactory{ 1355 "aws": testProviderFuncFixed(p), 1356 }, 1357 State: s, 1358 }) 1359 1360 p.DiffFn = func( 1361 info *InstanceInfo, 1362 s *InstanceState, 1363 c *ResourceConfig) (*InstanceDiff, error) { 1364 if s.ID != "bar" { 1365 return testDiffFn(info, s, c) 1366 } 1367 1368 return &InstanceDiff{ 1369 Attributes: map[string]*ResourceAttrDiff{ 1370 "num": &ResourceAttrDiff{ 1371 Old: "2", 1372 New: "3", 1373 }, 1374 }, 1375 }, nil 1376 } 1377 1378 plan, err := ctx.Plan() 1379 if err != nil { 1380 t.Fatalf("err: %s", err) 1381 } 1382 1383 actual := strings.TrimSpace(plan.String()) 1384 expected := strings.TrimSpace(testTerraformPlanDiffVarStr) 1385 if actual != expected { 1386 t.Fatalf("actual:\n%s\n\nexpected:\n%s", actual, expected) 1387 } 1388 } 1389 1390 func TestContext2Plan_hook(t *testing.T) { 1391 m := testModule(t, "plan-good") 1392 h := new(MockHook) 1393 p := testProvider("aws") 1394 p.DiffFn = testDiffFn 1395 ctx := testContext2(t, &ContextOpts{ 1396 Module: m, 1397 Hooks: []Hook{h}, 1398 Providers: map[string]ResourceProviderFactory{ 1399 "aws": testProviderFuncFixed(p), 1400 }, 1401 }) 1402 1403 _, err := ctx.Plan() 1404 if err != nil { 1405 t.Fatalf("err: %s", err) 1406 } 1407 1408 if !h.PreDiffCalled { 1409 t.Fatal("should be called") 1410 } 1411 if !h.PostDiffCalled { 1412 t.Fatal("should be called") 1413 } 1414 } 1415 1416 func TestContext2Plan_orphan(t *testing.T) { 1417 m := testModule(t, "plan-orphan") 1418 p := testProvider("aws") 1419 p.DiffFn = testDiffFn 1420 s := &State{ 1421 Modules: []*ModuleState{ 1422 &ModuleState{ 1423 Path: rootModulePath, 1424 Resources: map[string]*ResourceState{ 1425 "aws_instance.baz": &ResourceState{ 1426 Type: "aws_instance", 1427 Primary: &InstanceState{ 1428 ID: "bar", 1429 }, 1430 }, 1431 }, 1432 }, 1433 }, 1434 } 1435 ctx := testContext2(t, &ContextOpts{ 1436 Module: m, 1437 Providers: map[string]ResourceProviderFactory{ 1438 "aws": testProviderFuncFixed(p), 1439 }, 1440 State: s, 1441 }) 1442 1443 plan, err := ctx.Plan() 1444 if err != nil { 1445 t.Fatalf("err: %s", err) 1446 } 1447 1448 actual := strings.TrimSpace(plan.String()) 1449 expected := strings.TrimSpace(testTerraformPlanOrphanStr) 1450 if actual != expected { 1451 t.Fatalf("bad:\n%s", actual) 1452 } 1453 } 1454 1455 func TestContext2Plan_state(t *testing.T) { 1456 m := testModule(t, "plan-good") 1457 p := testProvider("aws") 1458 p.DiffFn = testDiffFn 1459 s := &State{ 1460 Modules: []*ModuleState{ 1461 &ModuleState{ 1462 Path: rootModulePath, 1463 Resources: map[string]*ResourceState{ 1464 "aws_instance.foo": &ResourceState{ 1465 Primary: &InstanceState{ 1466 ID: "bar", 1467 }, 1468 }, 1469 }, 1470 }, 1471 }, 1472 } 1473 ctx := testContext2(t, &ContextOpts{ 1474 Module: m, 1475 Providers: map[string]ResourceProviderFactory{ 1476 "aws": testProviderFuncFixed(p), 1477 }, 1478 State: s, 1479 }) 1480 1481 plan, err := ctx.Plan() 1482 if err != nil { 1483 t.Fatalf("err: %s", err) 1484 } 1485 1486 if len(plan.Diff.RootModule().Resources) < 2 { 1487 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 1488 } 1489 1490 actual := strings.TrimSpace(plan.String()) 1491 expected := strings.TrimSpace(testTerraformPlanStateStr) 1492 if actual != expected { 1493 t.Fatalf("bad:\n%s\n\nexpected:\n\n%s", actual, expected) 1494 } 1495 } 1496 1497 func TestContext2Plan_taint(t *testing.T) { 1498 m := testModule(t, "plan-taint") 1499 p := testProvider("aws") 1500 p.DiffFn = testDiffFn 1501 s := &State{ 1502 Modules: []*ModuleState{ 1503 &ModuleState{ 1504 Path: rootModulePath, 1505 Resources: map[string]*ResourceState{ 1506 "aws_instance.foo": &ResourceState{ 1507 Type: "aws_instance", 1508 Primary: &InstanceState{ 1509 ID: "bar", 1510 Attributes: map[string]string{"num": "2"}, 1511 }, 1512 }, 1513 "aws_instance.bar": &ResourceState{ 1514 Type: "aws_instance", 1515 Tainted: []*InstanceState{ 1516 &InstanceState{ 1517 ID: "baz", 1518 }, 1519 }, 1520 }, 1521 }, 1522 }, 1523 }, 1524 } 1525 ctx := testContext2(t, &ContextOpts{ 1526 Module: m, 1527 Providers: map[string]ResourceProviderFactory{ 1528 "aws": testProviderFuncFixed(p), 1529 }, 1530 State: s, 1531 }) 1532 1533 plan, err := ctx.Plan() 1534 if err != nil { 1535 t.Fatalf("err: %s", err) 1536 } 1537 1538 actual := strings.TrimSpace(plan.String()) 1539 expected := strings.TrimSpace(testTerraformPlanTaintStr) 1540 if actual != expected { 1541 t.Fatalf("bad:\n%s", actual) 1542 } 1543 } 1544 1545 func TestContext2Plan_multiple_taint(t *testing.T) { 1546 m := testModule(t, "plan-taint") 1547 p := testProvider("aws") 1548 p.DiffFn = testDiffFn 1549 s := &State{ 1550 Modules: []*ModuleState{ 1551 &ModuleState{ 1552 Path: rootModulePath, 1553 Resources: map[string]*ResourceState{ 1554 "aws_instance.foo": &ResourceState{ 1555 Type: "aws_instance", 1556 Primary: &InstanceState{ 1557 ID: "bar", 1558 Attributes: map[string]string{"num": "2"}, 1559 }, 1560 }, 1561 "aws_instance.bar": &ResourceState{ 1562 Type: "aws_instance", 1563 Tainted: []*InstanceState{ 1564 &InstanceState{ 1565 ID: "baz", 1566 }, 1567 &InstanceState{ 1568 ID: "zip", 1569 }, 1570 }, 1571 }, 1572 }, 1573 }, 1574 }, 1575 } 1576 ctx := testContext2(t, &ContextOpts{ 1577 Module: m, 1578 Providers: map[string]ResourceProviderFactory{ 1579 "aws": testProviderFuncFixed(p), 1580 }, 1581 State: s, 1582 }) 1583 1584 plan, err := ctx.Plan() 1585 if err != nil { 1586 t.Fatalf("err: %s", err) 1587 } 1588 1589 actual := strings.TrimSpace(plan.String()) 1590 expected := strings.TrimSpace(testTerraformPlanMultipleTaintStr) 1591 if actual != expected { 1592 t.Fatalf("bad:\n%s", actual) 1593 } 1594 } 1595 1596 func TestContext2Plan_targeted(t *testing.T) { 1597 m := testModule(t, "plan-targeted") 1598 p := testProvider("aws") 1599 p.DiffFn = testDiffFn 1600 ctx := testContext2(t, &ContextOpts{ 1601 Module: m, 1602 Providers: map[string]ResourceProviderFactory{ 1603 "aws": testProviderFuncFixed(p), 1604 }, 1605 Targets: []string{"aws_instance.foo"}, 1606 }) 1607 1608 plan, err := ctx.Plan() 1609 if err != nil { 1610 t.Fatalf("err: %s", err) 1611 } 1612 1613 actual := strings.TrimSpace(plan.String()) 1614 expected := strings.TrimSpace(` 1615 DIFF: 1616 1617 CREATE: aws_instance.foo 1618 num: "" => "2" 1619 type: "" => "aws_instance" 1620 1621 STATE: 1622 1623 <no state> 1624 `) 1625 if actual != expected { 1626 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 1627 } 1628 } 1629 1630 func TestContext2Plan_targetedOrphan(t *testing.T) { 1631 m := testModule(t, "plan-targeted-orphan") 1632 p := testProvider("aws") 1633 p.DiffFn = testDiffFn 1634 ctx := testContext2(t, &ContextOpts{ 1635 Module: m, 1636 Providers: map[string]ResourceProviderFactory{ 1637 "aws": testProviderFuncFixed(p), 1638 }, 1639 State: &State{ 1640 Modules: []*ModuleState{ 1641 &ModuleState{ 1642 Path: rootModulePath, 1643 Resources: map[string]*ResourceState{ 1644 "aws_instance.orphan": &ResourceState{ 1645 Type: "aws_instance", 1646 Primary: &InstanceState{ 1647 ID: "i-789xyz", 1648 }, 1649 }, 1650 }, 1651 }, 1652 }, 1653 }, 1654 Destroy: true, 1655 Targets: []string{"aws_instance.orphan"}, 1656 }) 1657 1658 plan, err := ctx.Plan() 1659 if err != nil { 1660 t.Fatalf("err: %s", err) 1661 } 1662 1663 actual := strings.TrimSpace(plan.String()) 1664 expected := strings.TrimSpace(`DIFF: 1665 1666 DESTROY: aws_instance.orphan 1667 1668 STATE: 1669 1670 aws_instance.orphan: 1671 ID = i-789xyz`) 1672 if actual != expected { 1673 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 1674 } 1675 } 1676 1677 func TestContext2Plan_provider(t *testing.T) { 1678 m := testModule(t, "plan-provider") 1679 p := testProvider("aws") 1680 p.DiffFn = testDiffFn 1681 1682 var value interface{} 1683 p.ConfigureFn = func(c *ResourceConfig) error { 1684 value, _ = c.Get("foo") 1685 return nil 1686 } 1687 1688 ctx := testContext2(t, &ContextOpts{ 1689 Module: m, 1690 Providers: map[string]ResourceProviderFactory{ 1691 "aws": testProviderFuncFixed(p), 1692 }, 1693 Variables: map[string]string{ 1694 "foo": "bar", 1695 }, 1696 }) 1697 1698 if _, err := ctx.Plan(); err != nil { 1699 t.Fatalf("err: %s", err) 1700 } 1701 1702 if value != "bar" { 1703 t.Fatalf("bad: %#v", value) 1704 } 1705 } 1706 1707 func TestContext2Plan_varListErr(t *testing.T) { 1708 m := testModule(t, "plan-var-list-err") 1709 p := testProvider("aws") 1710 ctx := testContext2(t, &ContextOpts{ 1711 Module: m, 1712 Providers: map[string]ResourceProviderFactory{ 1713 "aws": testProviderFuncFixed(p), 1714 }, 1715 }) 1716 1717 _, err := ctx.Plan() 1718 if err == nil { 1719 t.Fatal("should error") 1720 } 1721 } 1722 1723 func TestContext2Plan_ignoreChanges(t *testing.T) { 1724 m := testModule(t, "plan-ignore-changes") 1725 p := testProvider("aws") 1726 p.DiffFn = testDiffFn 1727 s := &State{ 1728 Modules: []*ModuleState{ 1729 &ModuleState{ 1730 Path: rootModulePath, 1731 Resources: map[string]*ResourceState{ 1732 "aws_instance.foo": &ResourceState{ 1733 Primary: &InstanceState{ 1734 ID: "bar", 1735 Attributes: map[string]string{"ami": "ami-abcd1234"}, 1736 }, 1737 }, 1738 }, 1739 }, 1740 }, 1741 } 1742 ctx := testContext2(t, &ContextOpts{ 1743 Module: m, 1744 Providers: map[string]ResourceProviderFactory{ 1745 "aws": testProviderFuncFixed(p), 1746 }, 1747 Variables: map[string]string{ 1748 "foo": "ami-1234abcd", 1749 }, 1750 State: s, 1751 }) 1752 1753 plan, err := ctx.Plan() 1754 if err != nil { 1755 t.Fatalf("err: %s", err) 1756 } 1757 1758 if len(plan.Diff.RootModule().Resources) < 1 { 1759 t.Fatalf("bad: %#v", plan.Diff.RootModule().Resources) 1760 } 1761 1762 actual := strings.TrimSpace(plan.String()) 1763 expected := strings.TrimSpace(testTerraformPlanIgnoreChangesStr) 1764 if actual != expected { 1765 t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected) 1766 } 1767 }