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