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