github.com/trawler/terraform@v0.10.8-0.20171106022149-4b1c7a1d9b48/config/config_test.go (about) 1 package config 2 3 import ( 4 "flag" 5 "fmt" 6 "io/ioutil" 7 "log" 8 "os" 9 "path/filepath" 10 "reflect" 11 "strings" 12 "testing" 13 14 "github.com/hashicorp/hil/ast" 15 "github.com/hashicorp/terraform/helper/logging" 16 ) 17 18 // This is the directory where our test fixtures are. 19 const fixtureDir = "./test-fixtures" 20 21 func TestMain(m *testing.M) { 22 flag.Parse() 23 if testing.Verbose() { 24 // if we're verbose, use the logging requested by TF_LOG 25 logging.SetOutput() 26 } else { 27 // otherwise silence all logs 28 log.SetOutput(ioutil.Discard) 29 } 30 31 os.Exit(m.Run()) 32 } 33 34 func TestConfigCopy(t *testing.T) { 35 c := testConfig(t, "copy-basic") 36 rOrig := c.Resources[0] 37 rCopy := rOrig.Copy() 38 39 if rCopy.Name != rOrig.Name { 40 t.Fatalf("Expected names to equal: %q <=> %q", rCopy.Name, rOrig.Name) 41 } 42 43 if rCopy.Type != rOrig.Type { 44 t.Fatalf("Expected types to equal: %q <=> %q", rCopy.Type, rOrig.Type) 45 } 46 47 origCount := rOrig.RawCount.Config()["count"] 48 rCopy.RawCount.Config()["count"] = "5" 49 if rOrig.RawCount.Config()["count"] != origCount { 50 t.Fatalf("Expected RawCount to be copied, but it behaves like a ref!") 51 } 52 53 rCopy.RawConfig.Config()["newfield"] = "hello" 54 if rOrig.RawConfig.Config()["newfield"] == "hello" { 55 t.Fatalf("Expected RawConfig to be copied, but it behaves like a ref!") 56 } 57 58 rCopy.Provisioners = append(rCopy.Provisioners, &Provisioner{}) 59 if len(rOrig.Provisioners) == len(rCopy.Provisioners) { 60 t.Fatalf("Expected Provisioners to be copied, but it behaves like a ref!") 61 } 62 63 if rCopy.Provider != rOrig.Provider { 64 t.Fatalf("Expected providers to equal: %q <=> %q", 65 rCopy.Provider, rOrig.Provider) 66 } 67 68 rCopy.DependsOn[0] = "gotchya" 69 if rOrig.DependsOn[0] == rCopy.DependsOn[0] { 70 t.Fatalf("Expected DependsOn to be copied, but it behaves like a ref!") 71 } 72 73 rCopy.Lifecycle.IgnoreChanges[0] = "gotchya" 74 if rOrig.Lifecycle.IgnoreChanges[0] == rCopy.Lifecycle.IgnoreChanges[0] { 75 t.Fatalf("Expected Lifecycle to be copied, but it behaves like a ref!") 76 } 77 78 } 79 80 func TestConfigCount(t *testing.T) { 81 c := testConfig(t, "count-int") 82 actual, err := c.Resources[0].Count() 83 if err != nil { 84 t.Fatalf("err: %s", err) 85 } 86 if actual != 5 { 87 t.Fatalf("bad: %#v", actual) 88 } 89 } 90 91 func TestConfigCount_string(t *testing.T) { 92 c := testConfig(t, "count-string") 93 actual, err := c.Resources[0].Count() 94 if err != nil { 95 t.Fatalf("err: %s", err) 96 } 97 if actual != 5 { 98 t.Fatalf("bad: %#v", actual) 99 } 100 } 101 102 // Terraform GH-11800 103 func TestConfigCount_list(t *testing.T) { 104 c := testConfig(t, "count-list") 105 106 // The key is to interpolate so it doesn't fail parsing 107 c.Resources[0].RawCount.Interpolate(map[string]ast.Variable{ 108 "var.list": ast.Variable{ 109 Value: []ast.Variable{}, 110 Type: ast.TypeList, 111 }, 112 }) 113 114 _, err := c.Resources[0].Count() 115 if err == nil { 116 t.Fatal("should error") 117 } 118 } 119 120 func TestConfigCount_var(t *testing.T) { 121 c := testConfig(t, "count-var") 122 _, err := c.Resources[0].Count() 123 if err == nil { 124 t.Fatalf("should error") 125 } 126 } 127 128 func TestConfig_emptyCollections(t *testing.T) { 129 c := testConfig(t, "empty-collections") 130 if len(c.Variables) != 3 { 131 t.Fatalf("bad: expected 3 variables, got %d", len(c.Variables)) 132 } 133 for _, variable := range c.Variables { 134 switch variable.Name { 135 case "empty_string": 136 if variable.Default != "" { 137 t.Fatalf("bad: wrong default %q for variable empty_string", variable.Default) 138 } 139 case "empty_map": 140 if !reflect.DeepEqual(variable.Default, map[string]interface{}{}) { 141 t.Fatalf("bad: wrong default %#v for variable empty_map", variable.Default) 142 } 143 case "empty_list": 144 if !reflect.DeepEqual(variable.Default, []interface{}{}) { 145 t.Fatalf("bad: wrong default %#v for variable empty_list", variable.Default) 146 } 147 default: 148 t.Fatalf("Unexpected variable: %s", variable.Name) 149 } 150 } 151 } 152 153 // This table test is the preferred way to test validation of configuration. 154 // There are dozens of functions below which do not follow this that are 155 // there mostly historically. They should be converted at some point. 156 func TestConfigValidate_table(t *testing.T) { 157 cases := []struct { 158 Name string 159 Fixture string 160 Err bool 161 ErrString string 162 }{ 163 { 164 "basic good", 165 "validate-good", 166 false, 167 "", 168 }, 169 170 { 171 "depends on module", 172 "validate-depends-on-module", 173 false, 174 "", 175 }, 176 177 { 178 "depends on non-existent module", 179 "validate-depends-on-bad-module", 180 true, 181 "non-existent module 'foo'", 182 }, 183 184 { 185 "data source with provisioners", 186 "validate-data-provisioner", 187 true, 188 "data sources cannot have", 189 }, 190 191 { 192 "basic provisioners", 193 "validate-basic-provisioners", 194 false, 195 "", 196 }, 197 198 { 199 "backend config with interpolations", 200 "validate-backend-interpolate", 201 true, 202 "cannot contain interp", 203 }, 204 { 205 "nested types in variable default", 206 "validate-var-nested", 207 false, 208 "", 209 }, 210 { 211 "provider with valid version constraint", 212 "provider-version", 213 false, 214 "", 215 }, 216 { 217 "provider with invalid version constraint", 218 "provider-version-invalid", 219 true, 220 "invalid version constraint", 221 }, 222 } 223 224 for i, tc := range cases { 225 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 226 c := testConfig(t, tc.Fixture) 227 err := c.Validate() 228 if (err != nil) != tc.Err { 229 t.Fatalf("err: %s", err) 230 } 231 if err != nil { 232 if tc.ErrString != "" && !strings.Contains(err.Error(), tc.ErrString) { 233 t.Fatalf("expected err to contain: %s\n\ngot: %s", tc.ErrString, err) 234 } 235 236 return 237 } 238 }) 239 } 240 241 } 242 243 func TestConfigValidate_tfVersion(t *testing.T) { 244 c := testConfig(t, "validate-tf-version") 245 if err := c.Validate(); err != nil { 246 t.Fatalf("err: %s", err) 247 } 248 } 249 250 func TestConfigValidate_tfVersionBad(t *testing.T) { 251 c := testConfig(t, "validate-bad-tf-version") 252 if err := c.Validate(); err == nil { 253 t.Fatal("should not be valid") 254 } 255 } 256 257 func TestConfigValidate_tfVersionInterpolations(t *testing.T) { 258 c := testConfig(t, "validate-tf-version-interp") 259 if err := c.Validate(); err == nil { 260 t.Fatal("should not be valid") 261 } 262 } 263 264 func TestConfigValidate_badDependsOn(t *testing.T) { 265 c := testConfig(t, "validate-bad-depends-on") 266 if err := c.Validate(); err == nil { 267 t.Fatal("should not be valid") 268 } 269 } 270 271 func TestConfigValidate_countInt(t *testing.T) { 272 c := testConfig(t, "validate-count-int") 273 if err := c.Validate(); err != nil { 274 t.Fatalf("err: %s", err) 275 } 276 } 277 278 func TestConfigValidate_countInt_HCL2(t *testing.T) { 279 c := testConfigHCL2(t, "validate-count-int") 280 if err := c.Validate(); err != nil { 281 t.Fatalf("unexpected error: %s", err) 282 } 283 } 284 285 func TestConfigValidate_countBadContext(t *testing.T) { 286 c := testConfig(t, "validate-count-bad-context") 287 288 err := c.Validate() 289 290 expected := []string{ 291 "no_count_in_output: count variables are only valid within resources", 292 "no_count_in_module: count variables are only valid within resources", 293 } 294 for _, exp := range expected { 295 if !strings.Contains(err.Error(), exp) { 296 t.Fatalf("expected: %q,\nto contain: %q", err, exp) 297 } 298 } 299 } 300 301 func TestConfigValidate_countCountVar(t *testing.T) { 302 c := testConfig(t, "validate-count-count-var") 303 if err := c.Validate(); err == nil { 304 t.Fatal("should not be valid") 305 } 306 } 307 308 func TestConfigValidate_countNotInt(t *testing.T) { 309 c := testConfig(t, "validate-count-not-int") 310 if err := c.Validate(); err == nil { 311 t.Fatal("should not be valid") 312 } 313 } 314 315 func TestConfigValidate_countNotInt_HCL2(t *testing.T) { 316 c := testConfigHCL2(t, "validate-count-not-int-const") 317 if err := c.Validate(); err == nil { 318 t.Fatal("should not be valid") 319 } 320 } 321 322 func TestConfigValidate_countNotIntUnknown_HCL2(t *testing.T) { 323 c := testConfigHCL2(t, "validate-count-not-int") 324 // In HCL2 this is not an error because the unknown variable interpolates 325 // to produce an unknown string, which we assume (incorrectly, it turns out) 326 // will become a string containing only digits. This is okay because 327 // the config validation is only a "best effort" and we'll get a definitive 328 // result during the validation graph walk. 329 if err := c.Validate(); err != nil { 330 t.Fatalf("unexpected error: %s", err) 331 } 332 } 333 334 func TestConfigValidate_countUserVar(t *testing.T) { 335 c := testConfig(t, "validate-count-user-var") 336 if err := c.Validate(); err != nil { 337 t.Fatalf("err: %s", err) 338 } 339 } 340 341 func TestConfigValidate_countUserVar_HCL2(t *testing.T) { 342 c := testConfigHCL2(t, "validate-count-user-var") 343 if err := c.Validate(); err != nil { 344 t.Fatalf("err: %s", err) 345 } 346 } 347 348 func TestConfigValidate_countLocalValue(t *testing.T) { 349 c := testConfig(t, "validate-local-value-count") 350 if err := c.Validate(); err != nil { 351 t.Fatalf("err: %s", err) 352 } 353 } 354 355 func TestConfigValidate_countVar(t *testing.T) { 356 c := testConfig(t, "validate-count-var") 357 if err := c.Validate(); err != nil { 358 t.Fatalf("err: %s", err) 359 } 360 } 361 362 func TestConfigValidate_countVarInvalid(t *testing.T) { 363 c := testConfig(t, "validate-count-var-invalid") 364 if err := c.Validate(); err == nil { 365 t.Fatal("should not be valid") 366 } 367 } 368 369 func TestConfigValidate_countVarUnknown(t *testing.T) { 370 c := testConfig(t, "validate-count-var-unknown") 371 if err := c.Validate(); err == nil { 372 t.Fatal("should not be valid") 373 } 374 } 375 376 func TestConfigValidate_dependsOnVar(t *testing.T) { 377 c := testConfig(t, "validate-depends-on-var") 378 if err := c.Validate(); err == nil { 379 t.Fatal("should not be valid") 380 } 381 } 382 383 func TestConfigValidate_dupModule(t *testing.T) { 384 c := testConfig(t, "validate-dup-module") 385 if err := c.Validate(); err == nil { 386 t.Fatal("should not be valid") 387 } 388 } 389 390 func TestConfigValidate_dupResource(t *testing.T) { 391 c := testConfig(t, "validate-dup-resource") 392 if err := c.Validate(); err == nil { 393 t.Fatal("should not be valid") 394 } 395 } 396 397 func TestConfigValidate_ignoreChanges(t *testing.T) { 398 c := testConfig(t, "validate-ignore-changes") 399 if err := c.Validate(); err != nil { 400 t.Fatalf("err: %s", err) 401 } 402 } 403 404 func TestConfigValidate_ignoreChangesBad(t *testing.T) { 405 c := testConfig(t, "validate-ignore-changes-bad") 406 if err := c.Validate(); err == nil { 407 t.Fatal("should not be valid") 408 } 409 } 410 411 func TestConfigValidate_ignoreChangesInterpolate(t *testing.T) { 412 c := testConfig(t, "validate-ignore-changes-interpolate") 413 if err := c.Validate(); err == nil { 414 t.Fatal("should not be valid") 415 } 416 } 417 418 func TestConfigValidate_moduleNameBad(t *testing.T) { 419 c := testConfig(t, "validate-module-name-bad") 420 if err := c.Validate(); err == nil { 421 t.Fatal("should not be valid") 422 } 423 } 424 425 func TestConfigValidate_moduleSourceVar(t *testing.T) { 426 c := testConfig(t, "validate-module-source-var") 427 if err := c.Validate(); err == nil { 428 t.Fatal("should not be valid") 429 } 430 } 431 432 func TestConfigValidate_moduleVarInt(t *testing.T) { 433 c := testConfig(t, "validate-module-var-int") 434 if err := c.Validate(); err != nil { 435 t.Fatalf("should be valid: %s", err) 436 } 437 } 438 439 func TestConfigValidate_moduleVarMap(t *testing.T) { 440 c := testConfig(t, "validate-module-var-map") 441 if err := c.Validate(); err != nil { 442 t.Fatalf("should be valid: %s", err) 443 } 444 } 445 446 func TestConfigValidate_moduleVarList(t *testing.T) { 447 c := testConfig(t, "validate-module-var-list") 448 if err := c.Validate(); err != nil { 449 t.Fatalf("should be valid: %s", err) 450 } 451 } 452 453 func TestConfigValidate_moduleVarSelf(t *testing.T) { 454 c := testConfig(t, "validate-module-var-self") 455 if err := c.Validate(); err == nil { 456 t.Fatal("should be invalid") 457 } 458 } 459 460 func TestConfigValidate_nil(t *testing.T) { 461 var c Config 462 if err := c.Validate(); err != nil { 463 t.Fatalf("err: %s", err) 464 } 465 } 466 467 func TestConfigValidate_outputBadField(t *testing.T) { 468 c := testConfig(t, "validate-output-bad-field") 469 if err := c.Validate(); err == nil { 470 t.Fatal("should not be valid") 471 } 472 } 473 474 func TestConfigValidate_outputDescription(t *testing.T) { 475 c := testConfig(t, "validate-output-description") 476 if err := c.Validate(); err != nil { 477 t.Fatalf("err: %s", err) 478 } 479 if len(c.Outputs) != 1 { 480 t.Fatalf("got %d outputs; want 1", len(c.Outputs)) 481 } 482 if got, want := "Number 5", c.Outputs[0].Description; got != want { 483 t.Fatalf("got description %q; want %q", got, want) 484 } 485 } 486 487 func TestConfigValidate_outputDuplicate(t *testing.T) { 488 c := testConfig(t, "validate-output-dup") 489 if err := c.Validate(); err == nil { 490 t.Fatal("should not be valid") 491 } 492 } 493 494 func TestConfigValidate_pathVar(t *testing.T) { 495 c := testConfig(t, "validate-path-var") 496 if err := c.Validate(); err != nil { 497 t.Fatalf("err: %s", err) 498 } 499 } 500 501 func TestConfigValidate_pathVarInvalid(t *testing.T) { 502 c := testConfig(t, "validate-path-var-invalid") 503 if err := c.Validate(); err == nil { 504 t.Fatal("should not be valid") 505 } 506 } 507 508 func TestConfigValidate_providerMulti(t *testing.T) { 509 c := testConfig(t, "validate-provider-multi") 510 if err := c.Validate(); err == nil { 511 t.Fatal("should not be valid") 512 } 513 } 514 515 func TestConfigValidate_providerMultiGood(t *testing.T) { 516 c := testConfig(t, "validate-provider-multi-good") 517 if err := c.Validate(); err != nil { 518 t.Fatalf("should be valid: %s", err) 519 } 520 } 521 522 func TestConfigValidate_providerMultiRefGood(t *testing.T) { 523 c := testConfig(t, "validate-provider-multi-ref-good") 524 if err := c.Validate(); err != nil { 525 t.Fatalf("should be valid: %s", err) 526 } 527 } 528 529 func TestConfigValidate_provConnSplatOther(t *testing.T) { 530 c := testConfig(t, "validate-prov-conn-splat-other") 531 if err := c.Validate(); err != nil { 532 t.Fatalf("should be valid: %s", err) 533 } 534 } 535 536 func TestConfigValidate_provConnSplatSelf(t *testing.T) { 537 c := testConfig(t, "validate-prov-conn-splat-self") 538 if err := c.Validate(); err == nil { 539 t.Fatal("should not be valid") 540 } 541 } 542 543 func TestConfigValidate_provSplatOther(t *testing.T) { 544 c := testConfig(t, "validate-prov-splat-other") 545 if err := c.Validate(); err != nil { 546 t.Fatalf("should be valid: %s", err) 547 } 548 } 549 550 func TestConfigValidate_provSplatSelf(t *testing.T) { 551 c := testConfig(t, "validate-prov-splat-self") 552 if err := c.Validate(); err == nil { 553 t.Fatal("should not be valid") 554 } 555 } 556 557 func TestConfigValidate_resourceProvVarSelf(t *testing.T) { 558 c := testConfig(t, "validate-resource-prov-self") 559 if err := c.Validate(); err != nil { 560 t.Fatalf("should be valid: %s", err) 561 } 562 } 563 564 func TestConfigValidate_resourceVarSelf(t *testing.T) { 565 c := testConfig(t, "validate-resource-self") 566 if err := c.Validate(); err == nil { 567 t.Fatal("should not be valid") 568 } 569 } 570 571 func TestConfigValidate_unknownThing(t *testing.T) { 572 c := testConfig(t, "validate-unknownthing") 573 if err := c.Validate(); err == nil { 574 t.Fatal("should not be valid") 575 } 576 } 577 578 func TestConfigValidate_unknownResourceVar(t *testing.T) { 579 c := testConfig(t, "validate-unknown-resource-var") 580 if err := c.Validate(); err == nil { 581 t.Fatal("should not be valid") 582 } 583 } 584 585 func TestConfigValidate_unknownResourceVar_output(t *testing.T) { 586 c := testConfig(t, "validate-unknown-resource-var-output") 587 if err := c.Validate(); err == nil { 588 t.Fatal("should not be valid") 589 } 590 } 591 592 func TestConfigValidate_unknownVar(t *testing.T) { 593 c := testConfig(t, "validate-unknownvar") 594 if err := c.Validate(); err == nil { 595 t.Fatal("should not be valid") 596 } 597 } 598 599 func TestConfigValidate_unknownVarCount(t *testing.T) { 600 c := testConfig(t, "validate-unknownvar-count") 601 if err := c.Validate(); err == nil { 602 t.Fatal("should not be valid") 603 } 604 } 605 606 func TestConfigValidate_varDefault(t *testing.T) { 607 c := testConfig(t, "validate-var-default") 608 if err := c.Validate(); err != nil { 609 t.Fatalf("should be valid: %s", err) 610 } 611 } 612 613 func TestConfigValidate_varDefaultListType(t *testing.T) { 614 c := testConfig(t, "validate-var-default-list-type") 615 if err := c.Validate(); err != nil { 616 t.Fatalf("should be valid: %s", err) 617 } 618 } 619 620 func TestConfigValidate_varDefaultInterpolate(t *testing.T) { 621 c := testConfig(t, "validate-var-default-interpolate") 622 if err := c.Validate(); err == nil { 623 t.Fatal("should not be valid") 624 } 625 } 626 627 func TestConfigValidate_varDefaultInterpolateEscaped(t *testing.T) { 628 c := testConfig(t, "validate-var-default-interpolate-escaped") 629 if err := c.Validate(); err != nil { 630 t.Fatalf("should be valid, but got err: %s", err) 631 } 632 } 633 634 func TestConfigValidate_varDup(t *testing.T) { 635 c := testConfig(t, "validate-var-dup") 636 if err := c.Validate(); err == nil { 637 t.Fatal("should not be valid") 638 } 639 } 640 641 func TestConfigValidate_varMultiExactNonSlice(t *testing.T) { 642 c := testConfig(t, "validate-var-multi-exact-non-slice") 643 if err := c.Validate(); err != nil { 644 t.Fatalf("should be valid: %s", err) 645 } 646 } 647 648 func TestConfigValidate_varMultiFunctionCall(t *testing.T) { 649 c := testConfig(t, "validate-var-multi-func") 650 if err := c.Validate(); err != nil { 651 t.Fatalf("should be valid: %s", err) 652 } 653 } 654 655 func TestConfigValidate_varModule(t *testing.T) { 656 c := testConfig(t, "validate-var-module") 657 if err := c.Validate(); err != nil { 658 t.Fatalf("err: %s", err) 659 } 660 } 661 662 func TestConfigValidate_varModuleInvalid(t *testing.T) { 663 c := testConfig(t, "validate-var-module-invalid") 664 if err := c.Validate(); err == nil { 665 t.Fatal("should not be valid") 666 } 667 } 668 669 func TestConfigValidate_varProviderVersionInvalid(t *testing.T) { 670 c := testConfig(t, "validate-provider-version-invalid") 671 if err := c.Validate(); err == nil { 672 t.Fatal("should not be valid") 673 } 674 } 675 676 func TestNameRegexp(t *testing.T) { 677 cases := []struct { 678 Input string 679 Match bool 680 }{ 681 {"hello", true}, 682 {"foo-bar", true}, 683 {"foo_bar", true}, 684 {"_hello", true}, 685 {"foo bar", false}, 686 {"foo.bar", false}, 687 } 688 689 for _, tc := range cases { 690 if NameRegexp.Match([]byte(tc.Input)) != tc.Match { 691 t.Fatalf("Input: %s\n\nExpected: %#v", tc.Input, tc.Match) 692 } 693 } 694 } 695 696 func TestConfigValidate_localValuesMultiFile(t *testing.T) { 697 c, err := LoadDir(filepath.Join(fixtureDir, "validate-local-multi-file")) 698 if err != nil { 699 t.Fatalf("unexpected error during load: %s", err) 700 } 701 if err := c.Validate(); err != nil { 702 t.Fatalf("unexpected error from validate: %s", err) 703 } 704 if len(c.Locals) != 1 { 705 t.Fatalf("got 0 locals; want 1") 706 } 707 if got, want := c.Locals[0].Name, "test"; got != want { 708 t.Errorf("wrong local name\ngot: %#v\nwant: %#v", got, want) 709 } 710 } 711 712 func TestProviderConfigName(t *testing.T) { 713 pcs := []*ProviderConfig{ 714 &ProviderConfig{Name: "aw"}, 715 &ProviderConfig{Name: "aws"}, 716 &ProviderConfig{Name: "a"}, 717 &ProviderConfig{Name: "gce_"}, 718 } 719 720 n := ProviderConfigName("aws_instance", pcs) 721 if n != "aws" { 722 t.Fatalf("bad: %s", n) 723 } 724 } 725 726 func testConfig(t *testing.T, name string) *Config { 727 c, err := LoadFile(filepath.Join(fixtureDir, name, "main.tf")) 728 if err != nil { 729 t.Fatalf("file: %s\n\nerr: %s", name, err) 730 } 731 732 return c 733 } 734 735 // testConfigHCL loads a config, forcing it to be processed with the HCL2 736 // loader even if it doesn't explicitly opt in to the HCL2 experiment. 737 func testConfigHCL2(t *testing.T, name string) *Config { 738 t.Helper() 739 cer, _, err := globalHCL2Loader.loadFile(filepath.Join(fixtureDir, name, "main.tf")) 740 if err != nil { 741 t.Fatalf("failed to load %s: %s", name, err) 742 } 743 744 cfg, err := cer.Config() 745 if err != nil { 746 t.Fatalf("failed to decode %s: %s", name, err) 747 } 748 749 return cfg 750 } 751 752 func TestConfigDataCount(t *testing.T) { 753 c := testConfig(t, "data-count") 754 actual, err := c.Resources[0].Count() 755 if err != nil { 756 t.Fatalf("err: %s", err) 757 } 758 if actual != 5 { 759 t.Fatalf("bad: %#v", actual) 760 } 761 762 // we need to make sure "count" has been removed from the RawConfig, since 763 // it's not a real key and won't validate. 764 if _, ok := c.Resources[0].RawConfig.Raw["count"]; ok { 765 t.Fatal("count key still exists in RawConfig") 766 } 767 } 768 769 func TestConfigProviderVersion(t *testing.T) { 770 c := testConfig(t, "provider-version") 771 772 if len(c.ProviderConfigs) != 1 { 773 t.Fatal("expected 1 provider") 774 } 775 776 p := c.ProviderConfigs[0] 777 if p.Name != "aws" { 778 t.Fatalf("expected provider name 'aws', got %q", p.Name) 779 } 780 781 if p.Version != "0.0.1" { 782 t.Fatalf("expected providers version '0.0.1', got %q", p.Version) 783 } 784 785 if _, ok := p.RawConfig.Raw["version"]; ok { 786 t.Fatal("'version' should not exist in raw config") 787 } 788 } 789 790 func TestResourceProviderFullName(t *testing.T) { 791 type testCase struct { 792 ResourceName string 793 Alias string 794 Expected string 795 } 796 797 tests := []testCase{ 798 { 799 // If no alias is provided, the first underscore-separated segment 800 // is assumed to be the provider name. 801 ResourceName: "aws_thing", 802 Alias: "", 803 Expected: "aws", 804 }, 805 { 806 // If we have more than one underscore then it's the first one that we'll use. 807 ResourceName: "aws_thingy_thing", 808 Alias: "", 809 Expected: "aws", 810 }, 811 { 812 // A provider can export a resource whose name is just the bare provider name, 813 // e.g. because the provider only has one resource and so any additional 814 // parts would be redundant. 815 ResourceName: "external", 816 Alias: "", 817 Expected: "external", 818 }, 819 { 820 // Alias always overrides the default extraction of the name 821 ResourceName: "aws_thing", 822 Alias: "tls.baz", 823 Expected: "tls.baz", 824 }, 825 } 826 827 for _, test := range tests { 828 got := ResourceProviderFullName(test.ResourceName, test.Alias) 829 if got != test.Expected { 830 t.Errorf( 831 "(%q, %q) produced %q; want %q", 832 test.ResourceName, test.Alias, 833 got, 834 test.Expected, 835 ) 836 } 837 } 838 } 839 840 func TestConfigModuleProviders(t *testing.T) { 841 c := testConfig(t, "module-providers") 842 843 if len(c.Modules) != 1 { 844 t.Fatalf("expected 1 module, got %d", len(c.Modules)) 845 } 846 847 expected := map[string]string{ 848 "aws": "aws.foo", 849 } 850 851 got := c.Modules[0].Providers 852 853 if !reflect.DeepEqual(expected, got) { 854 t.Fatalf("exptected providers %#v, got providers %#v", expected, got) 855 } 856 }