github.com/acm1/terraform@v0.6.2-0.20150729164239-1f314444f45c/terraform/context_refresh_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "sort" 6 "strings" 7 "testing" 8 ) 9 10 func TestContext2Refresh(t *testing.T) { 11 p := testProvider("aws") 12 m := testModule(t, "refresh-basic") 13 ctx := testContext2(t, &ContextOpts{ 14 Module: m, 15 Providers: map[string]ResourceProviderFactory{ 16 "aws": testProviderFuncFixed(p), 17 }, 18 State: &State{ 19 Modules: []*ModuleState{ 20 &ModuleState{ 21 Path: rootModulePath, 22 Resources: map[string]*ResourceState{ 23 "aws_instance.web": &ResourceState{ 24 Type: "aws_instance", 25 Primary: &InstanceState{ 26 ID: "foo", 27 }, 28 }, 29 }, 30 }, 31 }, 32 }, 33 }) 34 35 p.RefreshFn = nil 36 p.RefreshReturn = &InstanceState{ 37 ID: "foo", 38 } 39 40 s, err := ctx.Refresh() 41 mod := s.RootModule() 42 if err != nil { 43 t.Fatalf("err: %s", err) 44 } 45 if !p.RefreshCalled { 46 t.Fatal("refresh should be called") 47 } 48 if p.RefreshState.ID != "foo" { 49 t.Fatalf("bad: %#v", p.RefreshState) 50 } 51 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 52 t.Fatalf("bad: %#v %#v", mod.Resources["aws_instance.web"], p.RefreshReturn) 53 } 54 55 for _, r := range mod.Resources { 56 if r.Type == "" { 57 t.Fatalf("no type: %#v", r) 58 } 59 } 60 } 61 62 func TestContext2Refresh_targeted(t *testing.T) { 63 p := testProvider("aws") 64 m := testModule(t, "refresh-targeted") 65 ctx := testContext2(t, &ContextOpts{ 66 Module: m, 67 Providers: map[string]ResourceProviderFactory{ 68 "aws": testProviderFuncFixed(p), 69 }, 70 State: &State{ 71 Modules: []*ModuleState{ 72 &ModuleState{ 73 Path: rootModulePath, 74 Resources: map[string]*ResourceState{ 75 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 76 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 77 "aws_instance.me": resourceState("aws_instance", "i-abc123"), 78 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 79 }, 80 }, 81 }, 82 }, 83 Targets: []string{"aws_instance.me"}, 84 }) 85 86 refreshedResources := make([]string, 0, 2) 87 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 88 refreshedResources = append(refreshedResources, i.Id) 89 return is, nil 90 } 91 92 _, err := ctx.Refresh() 93 if err != nil { 94 t.Fatalf("err: %s", err) 95 } 96 97 expected := []string{"aws_vpc.metoo", "aws_instance.me"} 98 if !reflect.DeepEqual(refreshedResources, expected) { 99 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 100 } 101 } 102 103 func TestContext2Refresh_targetedCount(t *testing.T) { 104 p := testProvider("aws") 105 m := testModule(t, "refresh-targeted-count") 106 ctx := testContext2(t, &ContextOpts{ 107 Module: m, 108 Providers: map[string]ResourceProviderFactory{ 109 "aws": testProviderFuncFixed(p), 110 }, 111 State: &State{ 112 Modules: []*ModuleState{ 113 &ModuleState{ 114 Path: rootModulePath, 115 Resources: map[string]*ResourceState{ 116 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 117 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 118 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 119 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 120 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 121 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 122 }, 123 }, 124 }, 125 }, 126 Targets: []string{"aws_instance.me"}, 127 }) 128 129 refreshedResources := make([]string, 0, 2) 130 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 131 refreshedResources = append(refreshedResources, i.Id) 132 return is, nil 133 } 134 135 _, err := ctx.Refresh() 136 if err != nil { 137 t.Fatalf("err: %s", err) 138 } 139 140 // Target didn't specify index, so we should get all our instances 141 expected := []string{ 142 "aws_vpc.metoo", 143 "aws_instance.me.0", 144 "aws_instance.me.1", 145 "aws_instance.me.2", 146 } 147 sort.Strings(expected) 148 sort.Strings(refreshedResources) 149 if !reflect.DeepEqual(refreshedResources, expected) { 150 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 151 } 152 } 153 154 func TestContext2Refresh_targetedCountIndex(t *testing.T) { 155 p := testProvider("aws") 156 m := testModule(t, "refresh-targeted-count") 157 ctx := testContext2(t, &ContextOpts{ 158 Module: m, 159 Providers: map[string]ResourceProviderFactory{ 160 "aws": testProviderFuncFixed(p), 161 }, 162 State: &State{ 163 Modules: []*ModuleState{ 164 &ModuleState{ 165 Path: rootModulePath, 166 Resources: map[string]*ResourceState{ 167 "aws_vpc.metoo": resourceState("aws_vpc", "vpc-abc123"), 168 "aws_instance.notme": resourceState("aws_instance", "i-bcd345"), 169 "aws_instance.me.0": resourceState("aws_instance", "i-abc123"), 170 "aws_instance.me.1": resourceState("aws_instance", "i-cde567"), 171 "aws_instance.me.2": resourceState("aws_instance", "i-cde789"), 172 "aws_elb.meneither": resourceState("aws_elb", "lb-abc123"), 173 }, 174 }, 175 }, 176 }, 177 Targets: []string{"aws_instance.me[0]"}, 178 }) 179 180 refreshedResources := make([]string, 0, 2) 181 p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { 182 refreshedResources = append(refreshedResources, i.Id) 183 return is, nil 184 } 185 186 _, err := ctx.Refresh() 187 if err != nil { 188 t.Fatalf("err: %s", err) 189 } 190 191 expected := []string{"aws_vpc.metoo", "aws_instance.me.0"} 192 if !reflect.DeepEqual(refreshedResources, expected) { 193 t.Fatalf("expected: %#v, got: %#v", expected, refreshedResources) 194 } 195 } 196 197 func TestContext2Refresh_moduleComputedVar(t *testing.T) { 198 p := testProvider("aws") 199 m := testModule(t, "refresh-module-computed-var") 200 ctx := testContext2(t, &ContextOpts{ 201 Module: m, 202 Providers: map[string]ResourceProviderFactory{ 203 "aws": testProviderFuncFixed(p), 204 }, 205 }) 206 207 // This was failing (see GH-2188) at some point, so this test just 208 // verifies that the failure goes away. 209 if _, err := ctx.Refresh(); err != nil { 210 t.Fatalf("err: %s", err) 211 } 212 } 213 214 func TestContext2Refresh_delete(t *testing.T) { 215 p := testProvider("aws") 216 m := testModule(t, "refresh-basic") 217 ctx := testContext2(t, &ContextOpts{ 218 Module: m, 219 Providers: map[string]ResourceProviderFactory{ 220 "aws": testProviderFuncFixed(p), 221 }, 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: "foo", 231 }, 232 }, 233 }, 234 }, 235 }, 236 }, 237 }) 238 239 p.RefreshFn = nil 240 p.RefreshReturn = nil 241 242 s, err := ctx.Refresh() 243 if err != nil { 244 t.Fatalf("err: %s", err) 245 } 246 247 mod := s.RootModule() 248 if len(mod.Resources) > 0 { 249 t.Fatal("resources should be empty") 250 } 251 } 252 253 func TestContext2Refresh_ignoreUncreated(t *testing.T) { 254 p := testProvider("aws") 255 m := testModule(t, "refresh-basic") 256 ctx := testContext2(t, &ContextOpts{ 257 Module: m, 258 Providers: map[string]ResourceProviderFactory{ 259 "aws": testProviderFuncFixed(p), 260 }, 261 State: nil, 262 }) 263 264 p.RefreshFn = nil 265 p.RefreshReturn = &InstanceState{ 266 ID: "foo", 267 } 268 269 _, err := ctx.Refresh() 270 if err != nil { 271 t.Fatalf("err: %s", err) 272 } 273 if p.RefreshCalled { 274 t.Fatal("refresh should not be called") 275 } 276 } 277 278 func TestContext2Refresh_hook(t *testing.T) { 279 h := new(MockHook) 280 p := testProvider("aws") 281 m := testModule(t, "refresh-basic") 282 ctx := testContext2(t, &ContextOpts{ 283 Module: m, 284 Hooks: []Hook{h}, 285 Providers: map[string]ResourceProviderFactory{ 286 "aws": testProviderFuncFixed(p), 287 }, 288 State: &State{ 289 Modules: []*ModuleState{ 290 &ModuleState{ 291 Path: rootModulePath, 292 Resources: map[string]*ResourceState{ 293 "aws_instance.web": &ResourceState{ 294 Type: "aws_instance", 295 Primary: &InstanceState{ 296 ID: "foo", 297 }, 298 }, 299 }, 300 }, 301 }, 302 }, 303 }) 304 305 if _, err := ctx.Refresh(); err != nil { 306 t.Fatalf("err: %s", err) 307 } 308 if !h.PreRefreshCalled { 309 t.Fatal("should be called") 310 } 311 if !h.PostRefreshCalled { 312 t.Fatal("should be called") 313 } 314 } 315 316 func TestContext2Refresh_modules(t *testing.T) { 317 p := testProvider("aws") 318 m := testModule(t, "refresh-modules") 319 state := &State{ 320 Modules: []*ModuleState{ 321 &ModuleState{ 322 Path: rootModulePath, 323 Resources: map[string]*ResourceState{ 324 "aws_instance.web": &ResourceState{ 325 Type: "aws_instance", 326 Tainted: []*InstanceState{ 327 &InstanceState{ 328 ID: "bar", 329 }, 330 }, 331 }, 332 }, 333 }, 334 335 &ModuleState{ 336 Path: []string{"root", "child"}, 337 Resources: map[string]*ResourceState{ 338 "aws_instance.web": &ResourceState{ 339 Type: "aws_instance", 340 Primary: &InstanceState{ 341 ID: "baz", 342 }, 343 }, 344 }, 345 }, 346 }, 347 } 348 ctx := testContext2(t, &ContextOpts{ 349 Module: m, 350 Providers: map[string]ResourceProviderFactory{ 351 "aws": testProviderFuncFixed(p), 352 }, 353 State: state, 354 }) 355 356 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 357 if s.ID != "baz" { 358 return s, nil 359 } 360 361 s.ID = "new" 362 return s, nil 363 } 364 365 s, err := ctx.Refresh() 366 if err != nil { 367 t.Fatalf("err: %s", err) 368 } 369 370 actual := strings.TrimSpace(s.String()) 371 expected := strings.TrimSpace(testContextRefreshModuleStr) 372 if actual != expected { 373 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 374 } 375 } 376 377 func TestContext2Refresh_moduleInputComputedOutput(t *testing.T) { 378 m := testModule(t, "refresh-module-input-computed-output") 379 p := testProvider("aws") 380 p.DiffFn = testDiffFn 381 ctx := testContext2(t, &ContextOpts{ 382 Module: m, 383 Providers: map[string]ResourceProviderFactory{ 384 "aws": testProviderFuncFixed(p), 385 }, 386 }) 387 388 if _, err := ctx.Refresh(); err != nil { 389 t.Fatalf("err: %s", err) 390 } 391 } 392 393 func TestContext2Refresh_moduleVarModule(t *testing.T) { 394 m := testModule(t, "refresh-module-var-module") 395 p := testProvider("aws") 396 p.DiffFn = testDiffFn 397 ctx := testContext2(t, &ContextOpts{ 398 Module: m, 399 Providers: map[string]ResourceProviderFactory{ 400 "aws": testProviderFuncFixed(p), 401 }, 402 }) 403 404 if _, err := ctx.Refresh(); err != nil { 405 t.Fatalf("err: %s", err) 406 } 407 } 408 409 // GH-70 410 func TestContext2Refresh_noState(t *testing.T) { 411 p := testProvider("aws") 412 m := testModule(t, "refresh-no-state") 413 ctx := testContext2(t, &ContextOpts{ 414 Module: m, 415 Providers: map[string]ResourceProviderFactory{ 416 "aws": testProviderFuncFixed(p), 417 }, 418 }) 419 420 p.RefreshFn = nil 421 p.RefreshReturn = &InstanceState{ 422 ID: "foo", 423 } 424 425 if _, err := ctx.Refresh(); err != nil { 426 t.Fatalf("err: %s", err) 427 } 428 } 429 430 func TestContext2Refresh_output(t *testing.T) { 431 p := testProvider("aws") 432 m := testModule(t, "refresh-output") 433 ctx := testContext2(t, &ContextOpts{ 434 Module: m, 435 Providers: map[string]ResourceProviderFactory{ 436 "aws": testProviderFuncFixed(p), 437 }, 438 State: &State{ 439 Modules: []*ModuleState{ 440 &ModuleState{ 441 Path: rootModulePath, 442 Resources: map[string]*ResourceState{ 443 "aws_instance.web": &ResourceState{ 444 Type: "aws_instance", 445 Primary: &InstanceState{ 446 ID: "foo", 447 Attributes: map[string]string{ 448 "foo": "bar", 449 }, 450 }, 451 }, 452 }, 453 454 Outputs: map[string]string{ 455 "foo": "foo", 456 }, 457 }, 458 }, 459 }, 460 }) 461 462 p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { 463 return s, nil 464 } 465 466 s, err := ctx.Refresh() 467 if err != nil { 468 t.Fatalf("err: %s", err) 469 } 470 471 actual := strings.TrimSpace(s.String()) 472 expected := strings.TrimSpace(testContextRefreshOutputStr) 473 if actual != expected { 474 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 475 } 476 } 477 478 func TestContext2Refresh_outputPartial(t *testing.T) { 479 p := testProvider("aws") 480 m := testModule(t, "refresh-output-partial") 481 ctx := testContext2(t, &ContextOpts{ 482 Module: m, 483 Providers: map[string]ResourceProviderFactory{ 484 "aws": testProviderFuncFixed(p), 485 }, 486 State: &State{ 487 Modules: []*ModuleState{ 488 &ModuleState{ 489 Path: rootModulePath, 490 Resources: map[string]*ResourceState{ 491 "aws_instance.foo": &ResourceState{ 492 Type: "aws_instance", 493 Primary: &InstanceState{ 494 ID: "foo", 495 }, 496 }, 497 }, 498 }, 499 }, 500 }, 501 }) 502 503 p.RefreshFn = nil 504 p.RefreshReturn = nil 505 506 s, err := ctx.Refresh() 507 if err != nil { 508 t.Fatalf("err: %s", err) 509 } 510 511 actual := strings.TrimSpace(s.String()) 512 expected := strings.TrimSpace(testContextRefreshOutputPartialStr) 513 if actual != expected { 514 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 515 } 516 } 517 518 func TestContext2Refresh_state(t *testing.T) { 519 p := testProvider("aws") 520 m := testModule(t, "refresh-basic") 521 state := &State{ 522 Modules: []*ModuleState{ 523 &ModuleState{ 524 Path: rootModulePath, 525 Resources: map[string]*ResourceState{ 526 "aws_instance.web": &ResourceState{ 527 Primary: &InstanceState{ 528 ID: "bar", 529 }, 530 }, 531 }, 532 }, 533 }, 534 } 535 ctx := testContext2(t, &ContextOpts{ 536 Module: m, 537 Providers: map[string]ResourceProviderFactory{ 538 "aws": testProviderFuncFixed(p), 539 }, 540 State: state, 541 }) 542 543 p.RefreshFn = nil 544 p.RefreshReturn = &InstanceState{ 545 ID: "foo", 546 } 547 548 s, err := ctx.Refresh() 549 if err != nil { 550 t.Fatalf("err: %s", err) 551 } 552 originalMod := state.RootModule() 553 mod := s.RootModule() 554 if !p.RefreshCalled { 555 t.Fatal("refresh should be called") 556 } 557 if !reflect.DeepEqual(p.RefreshState, originalMod.Resources["aws_instance.web"].Primary) { 558 t.Fatalf( 559 "bad:\n\n%#v\n\n%#v", 560 p.RefreshState, 561 originalMod.Resources["aws_instance.web"].Primary) 562 } 563 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 564 t.Fatalf("bad: %#v", mod.Resources) 565 } 566 } 567 568 func TestContext2Refresh_tainted(t *testing.T) { 569 p := testProvider("aws") 570 m := testModule(t, "refresh-basic") 571 state := &State{ 572 Modules: []*ModuleState{ 573 &ModuleState{ 574 Path: rootModulePath, 575 Resources: map[string]*ResourceState{ 576 "aws_instance.web": &ResourceState{ 577 Type: "aws_instance", 578 Tainted: []*InstanceState{ 579 &InstanceState{ 580 ID: "bar", 581 }, 582 }, 583 }, 584 }, 585 }, 586 }, 587 } 588 ctx := testContext2(t, &ContextOpts{ 589 Module: m, 590 Providers: map[string]ResourceProviderFactory{ 591 "aws": testProviderFuncFixed(p), 592 }, 593 State: state, 594 }) 595 596 p.RefreshFn = nil 597 p.RefreshReturn = &InstanceState{ 598 ID: "foo", 599 } 600 601 s, err := ctx.Refresh() 602 if err != nil { 603 t.Fatalf("err: %s", err) 604 } 605 if !p.RefreshCalled { 606 t.Fatal("refresh should be called") 607 } 608 609 actual := strings.TrimSpace(s.String()) 610 expected := strings.TrimSpace(testContextRefreshTaintedStr) 611 if actual != expected { 612 t.Fatalf("bad:\n\n%s\n\n%s", actual, expected) 613 } 614 } 615 616 // Doing a Refresh (or any operation really, but Refresh usually 617 // happens first) with a config with an unknown provider should result in 618 // an error. The key bug this found was that this wasn't happening if 619 // Providers was _empty_. 620 func TestContext2Refresh_unknownProvider(t *testing.T) { 621 m := testModule(t, "refresh-unknown-provider") 622 p := testProvider("aws") 623 p.ApplyFn = testApplyFn 624 p.DiffFn = testDiffFn 625 ctx := testContext2(t, &ContextOpts{ 626 Module: m, 627 Providers: map[string]ResourceProviderFactory{}, 628 }) 629 630 if _, err := ctx.Refresh(); err == nil { 631 t.Fatal("should error") 632 } 633 } 634 635 func TestContext2Refresh_vars(t *testing.T) { 636 p := testProvider("aws") 637 m := testModule(t, "refresh-vars") 638 ctx := testContext2(t, &ContextOpts{ 639 Module: m, 640 Providers: map[string]ResourceProviderFactory{ 641 "aws": testProviderFuncFixed(p), 642 }, 643 State: &State{ 644 645 Modules: []*ModuleState{ 646 &ModuleState{ 647 Path: rootModulePath, 648 Resources: map[string]*ResourceState{ 649 "aws_instance.web": &ResourceState{ 650 Type: "aws_instance", 651 Primary: &InstanceState{ 652 ID: "foo", 653 }, 654 }, 655 }, 656 }, 657 }, 658 }, 659 }) 660 661 p.RefreshFn = nil 662 p.RefreshReturn = &InstanceState{ 663 ID: "foo", 664 } 665 666 s, err := ctx.Refresh() 667 if err != nil { 668 t.Fatalf("err: %s", err) 669 } 670 mod := s.RootModule() 671 if !p.RefreshCalled { 672 t.Fatal("refresh should be called") 673 } 674 if p.RefreshState.ID != "foo" { 675 t.Fatalf("bad: %#v", p.RefreshState) 676 } 677 if !reflect.DeepEqual(mod.Resources["aws_instance.web"].Primary, p.RefreshReturn) { 678 t.Fatalf("bad: %#v", mod.Resources["aws_instance.web"]) 679 } 680 681 for _, r := range mod.Resources { 682 if r.Type == "" { 683 t.Fatalf("no type: %#v", r) 684 } 685 } 686 } 687 688 func TestContext2Validate(t *testing.T) { 689 p := testProvider("aws") 690 m := testModule(t, "validate-good") 691 c := testContext2(t, &ContextOpts{ 692 Module: m, 693 Providers: map[string]ResourceProviderFactory{ 694 "aws": testProviderFuncFixed(p), 695 }, 696 }) 697 698 w, e := c.Validate() 699 if len(w) > 0 { 700 t.Fatalf("bad: %#v", w) 701 } 702 if len(e) > 0 { 703 t.Fatalf("bad: %s", e) 704 } 705 }