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