github.com/ojiry/terraform@v0.8.2-0.20161218223921-e50cec712c4a/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/terraform/helper/logging" 15 ) 16 17 // This is the directory where our test fixtures are. 18 const fixtureDir = "./test-fixtures" 19 20 func TestMain(m *testing.M) { 21 flag.Parse() 22 if testing.Verbose() { 23 // if we're verbose, use the logging requested by TF_LOG 24 logging.SetOutput() 25 } else { 26 // otherwise silence all logs 27 log.SetOutput(ioutil.Discard) 28 } 29 30 os.Exit(m.Run()) 31 } 32 33 func TestConfigCopy(t *testing.T) { 34 c := testConfig(t, "copy-basic") 35 rOrig := c.Resources[0] 36 rCopy := rOrig.Copy() 37 38 if rCopy.Name != rOrig.Name { 39 t.Fatalf("Expected names to equal: %q <=> %q", rCopy.Name, rOrig.Name) 40 } 41 42 if rCopy.Type != rOrig.Type { 43 t.Fatalf("Expected types to equal: %q <=> %q", rCopy.Type, rOrig.Type) 44 } 45 46 origCount := rOrig.RawCount.Config()["count"] 47 rCopy.RawCount.Config()["count"] = "5" 48 if rOrig.RawCount.Config()["count"] != origCount { 49 t.Fatalf("Expected RawCount to be copied, but it behaves like a ref!") 50 } 51 52 rCopy.RawConfig.Config()["newfield"] = "hello" 53 if rOrig.RawConfig.Config()["newfield"] == "hello" { 54 t.Fatalf("Expected RawConfig to be copied, but it behaves like a ref!") 55 } 56 57 rCopy.Provisioners = append(rCopy.Provisioners, &Provisioner{}) 58 if len(rOrig.Provisioners) == len(rCopy.Provisioners) { 59 t.Fatalf("Expected Provisioners to be copied, but it behaves like a ref!") 60 } 61 62 if rCopy.Provider != rOrig.Provider { 63 t.Fatalf("Expected providers to equal: %q <=> %q", 64 rCopy.Provider, rOrig.Provider) 65 } 66 67 rCopy.DependsOn[0] = "gotchya" 68 if rOrig.DependsOn[0] == rCopy.DependsOn[0] { 69 t.Fatalf("Expected DependsOn to be copied, but it behaves like a ref!") 70 } 71 72 rCopy.Lifecycle.IgnoreChanges[0] = "gotchya" 73 if rOrig.Lifecycle.IgnoreChanges[0] == rCopy.Lifecycle.IgnoreChanges[0] { 74 t.Fatalf("Expected Lifecycle to be copied, but it behaves like a ref!") 75 } 76 77 } 78 79 func TestConfigCount(t *testing.T) { 80 c := testConfig(t, "count-int") 81 actual, err := c.Resources[0].Count() 82 if err != nil { 83 t.Fatalf("err: %s", err) 84 } 85 if actual != 5 { 86 t.Fatalf("bad: %#v", actual) 87 } 88 } 89 90 func TestConfigCount_string(t *testing.T) { 91 c := testConfig(t, "count-string") 92 actual, err := c.Resources[0].Count() 93 if err != nil { 94 t.Fatalf("err: %s", err) 95 } 96 if actual != 5 { 97 t.Fatalf("bad: %#v", actual) 98 } 99 } 100 101 func TestConfigCount_var(t *testing.T) { 102 c := testConfig(t, "count-var") 103 _, err := c.Resources[0].Count() 104 if err == nil { 105 t.Fatalf("should error") 106 } 107 } 108 109 func TestConfig_emptyCollections(t *testing.T) { 110 c := testConfig(t, "empty-collections") 111 if len(c.Variables) != 3 { 112 t.Fatalf("bad: expected 3 variables, got %d", len(c.Variables)) 113 } 114 for _, variable := range c.Variables { 115 switch variable.Name { 116 case "empty_string": 117 if variable.Default != "" { 118 t.Fatalf("bad: wrong default %q for variable empty_string", variable.Default) 119 } 120 case "empty_map": 121 if !reflect.DeepEqual(variable.Default, map[string]interface{}{}) { 122 t.Fatalf("bad: wrong default %#v for variable empty_map", variable.Default) 123 } 124 case "empty_list": 125 if !reflect.DeepEqual(variable.Default, []interface{}{}) { 126 t.Fatalf("bad: wrong default %#v for variable empty_list", variable.Default) 127 } 128 default: 129 t.Fatalf("Unexpected variable: %s", variable.Name) 130 } 131 } 132 } 133 134 // This table test is the preferred way to test validation of configuration. 135 // There are dozens of functions below which do not follow this that are 136 // there mostly historically. They should be converted at some point. 137 func TestConfigValidate_table(t *testing.T) { 138 cases := []struct { 139 Name string 140 Fixture string 141 Err bool 142 ErrString string 143 }{ 144 { 145 "basic good", 146 "validate-good", 147 false, 148 "", 149 }, 150 151 { 152 "depends on module", 153 "validate-depends-on-module", 154 false, 155 "", 156 }, 157 158 { 159 "depends on non-existent module", 160 "validate-depends-on-bad-module", 161 true, 162 "non-existent module 'foo'", 163 }, 164 165 { 166 "data source with provisioners", 167 "validate-data-provisioner", 168 true, 169 "data sources cannot have", 170 }, 171 } 172 173 for i, tc := range cases { 174 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 175 c := testConfig(t, tc.Fixture) 176 err := c.Validate() 177 if (err != nil) != tc.Err { 178 t.Fatalf("err: %s", err) 179 } 180 if err != nil { 181 if tc.ErrString != "" && !strings.Contains(err.Error(), tc.ErrString) { 182 t.Fatalf("expected err to contain: %s\n\ngot: %s", tc.ErrString, err) 183 } 184 185 return 186 } 187 }) 188 } 189 190 } 191 192 func TestConfigValidate_tfVersion(t *testing.T) { 193 c := testConfig(t, "validate-tf-version") 194 if err := c.Validate(); err != nil { 195 t.Fatalf("err: %s", err) 196 } 197 } 198 199 func TestConfigValidate_tfVersionBad(t *testing.T) { 200 c := testConfig(t, "validate-bad-tf-version") 201 if err := c.Validate(); err == nil { 202 t.Fatal("should not be valid") 203 } 204 } 205 206 func TestConfigValidate_tfVersionInterpolations(t *testing.T) { 207 c := testConfig(t, "validate-tf-version-interp") 208 if err := c.Validate(); err == nil { 209 t.Fatal("should not be valid") 210 } 211 } 212 213 func TestConfigValidate_badDependsOn(t *testing.T) { 214 c := testConfig(t, "validate-bad-depends-on") 215 if err := c.Validate(); err == nil { 216 t.Fatal("should not be valid") 217 } 218 } 219 220 func TestConfigValidate_countInt(t *testing.T) { 221 c := testConfig(t, "validate-count-int") 222 if err := c.Validate(); err != nil { 223 t.Fatalf("err: %s", err) 224 } 225 } 226 227 func TestConfigValidate_countBadContext(t *testing.T) { 228 c := testConfig(t, "validate-count-bad-context") 229 230 err := c.Validate() 231 232 expected := []string{ 233 "no_count_in_output: count variables are only valid within resources", 234 "no_count_in_module: count variables are only valid within resources", 235 } 236 for _, exp := range expected { 237 if !strings.Contains(err.Error(), exp) { 238 t.Fatalf("expected: %q,\nto contain: %q", err, exp) 239 } 240 } 241 } 242 243 func TestConfigValidate_countCountVar(t *testing.T) { 244 c := testConfig(t, "validate-count-count-var") 245 if err := c.Validate(); err == nil { 246 t.Fatal("should not be valid") 247 } 248 } 249 250 func TestConfigValidate_countModuleVar(t *testing.T) { 251 c := testConfig(t, "validate-count-module-var") 252 if err := c.Validate(); err == nil { 253 t.Fatal("should not be valid") 254 } 255 } 256 257 func TestConfigValidate_countNotInt(t *testing.T) { 258 c := testConfig(t, "validate-count-not-int") 259 if err := c.Validate(); err == nil { 260 t.Fatal("should not be valid") 261 } 262 } 263 264 func TestConfigValidate_countResourceVar(t *testing.T) { 265 c := testConfig(t, "validate-count-resource-var") 266 if err := c.Validate(); err == nil { 267 t.Fatal("should not be valid") 268 } 269 } 270 271 func TestConfigValidate_countResourceVarMulti(t *testing.T) { 272 c := testConfig(t, "validate-count-resource-var-multi") 273 if err := c.Validate(); err == nil { 274 t.Fatal("should not be valid") 275 } 276 } 277 278 func TestConfigValidate_countUserVar(t *testing.T) { 279 c := testConfig(t, "validate-count-user-var") 280 if err := c.Validate(); err != nil { 281 t.Fatalf("err: %s", err) 282 } 283 } 284 285 func TestConfigValidate_countVar(t *testing.T) { 286 c := testConfig(t, "validate-count-var") 287 if err := c.Validate(); err != nil { 288 t.Fatalf("err: %s", err) 289 } 290 } 291 292 func TestConfigValidate_countVarInvalid(t *testing.T) { 293 c := testConfig(t, "validate-count-var-invalid") 294 if err := c.Validate(); err == nil { 295 t.Fatal("should not be valid") 296 } 297 } 298 299 func TestConfigValidate_countVarUnknown(t *testing.T) { 300 c := testConfig(t, "validate-count-var-unknown") 301 if err := c.Validate(); err == nil { 302 t.Fatal("should not be valid") 303 } 304 } 305 306 func TestConfigValidate_dependsOnVar(t *testing.T) { 307 c := testConfig(t, "validate-depends-on-var") 308 if err := c.Validate(); err == nil { 309 t.Fatal("should not be valid") 310 } 311 } 312 313 func TestConfigValidate_dupModule(t *testing.T) { 314 c := testConfig(t, "validate-dup-module") 315 if err := c.Validate(); err == nil { 316 t.Fatal("should not be valid") 317 } 318 } 319 320 func TestConfigValidate_dupResource(t *testing.T) { 321 c := testConfig(t, "validate-dup-resource") 322 if err := c.Validate(); err == nil { 323 t.Fatal("should not be valid") 324 } 325 } 326 327 func TestConfigValidate_ignoreChanges(t *testing.T) { 328 c := testConfig(t, "validate-ignore-changes") 329 if err := c.Validate(); err != nil { 330 t.Fatalf("err: %s", err) 331 } 332 } 333 334 func TestConfigValidate_ignoreChangesBad(t *testing.T) { 335 c := testConfig(t, "validate-ignore-changes-bad") 336 if err := c.Validate(); err == nil { 337 t.Fatal("should not be valid") 338 } 339 } 340 341 func TestConfigValidate_ignoreChangesInterpolate(t *testing.T) { 342 c := testConfig(t, "validate-ignore-changes-interpolate") 343 if err := c.Validate(); err == nil { 344 t.Fatal("should not be valid") 345 } 346 } 347 348 func TestConfigValidate_moduleNameBad(t *testing.T) { 349 c := testConfig(t, "validate-module-name-bad") 350 if err := c.Validate(); err == nil { 351 t.Fatal("should not be valid") 352 } 353 } 354 355 func TestConfigValidate_moduleSourceVar(t *testing.T) { 356 c := testConfig(t, "validate-module-source-var") 357 if err := c.Validate(); err == nil { 358 t.Fatal("should not be valid") 359 } 360 } 361 362 func TestConfigValidate_moduleVarInt(t *testing.T) { 363 c := testConfig(t, "validate-module-var-int") 364 if err := c.Validate(); err != nil { 365 t.Fatalf("should be valid: %s", err) 366 } 367 } 368 369 func TestConfigValidate_moduleVarMap(t *testing.T) { 370 c := testConfig(t, "validate-module-var-map") 371 if err := c.Validate(); err != nil { 372 t.Fatalf("should be valid: %s", err) 373 } 374 } 375 376 func TestConfigValidate_moduleVarList(t *testing.T) { 377 c := testConfig(t, "validate-module-var-list") 378 if err := c.Validate(); err != nil { 379 t.Fatalf("should be valid: %s", err) 380 } 381 } 382 383 func TestConfigValidate_moduleVarSelf(t *testing.T) { 384 c := testConfig(t, "validate-module-var-self") 385 if err := c.Validate(); err == nil { 386 t.Fatal("should be invalid") 387 } 388 } 389 390 func TestConfigValidate_nil(t *testing.T) { 391 var c Config 392 if err := c.Validate(); err != nil { 393 t.Fatalf("err: %s", err) 394 } 395 } 396 397 func TestConfigValidate_outputBadField(t *testing.T) { 398 c := testConfig(t, "validate-output-bad-field") 399 if err := c.Validate(); err == nil { 400 t.Fatal("should not be valid") 401 } 402 } 403 404 func TestConfigValidate_outputDescription(t *testing.T) { 405 c := testConfig(t, "validate-output-description") 406 if err := c.Validate(); err != nil { 407 t.Fatalf("err: %s", err) 408 } 409 if len(c.Outputs) != 1 { 410 t.Fatalf("got %d outputs; want 1", len(c.Outputs)) 411 } 412 if got, want := "Number 5", c.Outputs[0].Description; got != want { 413 t.Fatalf("got description %q; want %q", got, want) 414 } 415 } 416 417 func TestConfigValidate_outputDuplicate(t *testing.T) { 418 c := testConfig(t, "validate-output-dup") 419 if err := c.Validate(); err == nil { 420 t.Fatal("should not be valid") 421 } 422 } 423 424 func TestConfigValidate_pathVar(t *testing.T) { 425 c := testConfig(t, "validate-path-var") 426 if err := c.Validate(); err != nil { 427 t.Fatalf("err: %s", err) 428 } 429 } 430 431 func TestConfigValidate_pathVarInvalid(t *testing.T) { 432 c := testConfig(t, "validate-path-var-invalid") 433 if err := c.Validate(); err == nil { 434 t.Fatal("should not be valid") 435 } 436 } 437 438 func TestConfigValidate_providerMulti(t *testing.T) { 439 c := testConfig(t, "validate-provider-multi") 440 if err := c.Validate(); err == nil { 441 t.Fatal("should not be valid") 442 } 443 } 444 445 func TestConfigValidate_providerMultiGood(t *testing.T) { 446 c := testConfig(t, "validate-provider-multi-good") 447 if err := c.Validate(); err != nil { 448 t.Fatalf("should be valid: %s", err) 449 } 450 } 451 452 func TestConfigValidate_providerMultiRefGood(t *testing.T) { 453 c := testConfig(t, "validate-provider-multi-ref-good") 454 if err := c.Validate(); err != nil { 455 t.Fatalf("should be valid: %s", err) 456 } 457 } 458 459 func TestConfigValidate_providerMultiRefBad(t *testing.T) { 460 c := testConfig(t, "validate-provider-multi-ref-bad") 461 if err := c.Validate(); err == nil { 462 t.Fatal("should not be valid") 463 } 464 } 465 466 func TestConfigValidate_provConnSplatOther(t *testing.T) { 467 c := testConfig(t, "validate-prov-conn-splat-other") 468 if err := c.Validate(); err != nil { 469 t.Fatalf("should be valid: %s", err) 470 } 471 } 472 473 func TestConfigValidate_provConnSplatSelf(t *testing.T) { 474 c := testConfig(t, "validate-prov-conn-splat-self") 475 if err := c.Validate(); err == nil { 476 t.Fatal("should not be valid") 477 } 478 } 479 480 func TestConfigValidate_provSplatOther(t *testing.T) { 481 c := testConfig(t, "validate-prov-splat-other") 482 if err := c.Validate(); err != nil { 483 t.Fatalf("should be valid: %s", err) 484 } 485 } 486 487 func TestConfigValidate_provSplatSelf(t *testing.T) { 488 c := testConfig(t, "validate-prov-splat-self") 489 if err := c.Validate(); err == nil { 490 t.Fatal("should not be valid") 491 } 492 } 493 494 func TestConfigValidate_resourceProvVarSelf(t *testing.T) { 495 c := testConfig(t, "validate-resource-prov-self") 496 if err := c.Validate(); err != nil { 497 t.Fatalf("should be valid: %s", err) 498 } 499 } 500 501 func TestConfigValidate_resourceVarSelf(t *testing.T) { 502 c := testConfig(t, "validate-resource-self") 503 if err := c.Validate(); err == nil { 504 t.Fatal("should not be valid") 505 } 506 } 507 508 func TestConfigValidate_unknownThing(t *testing.T) { 509 c := testConfig(t, "validate-unknownthing") 510 if err := c.Validate(); err == nil { 511 t.Fatal("should not be valid") 512 } 513 } 514 515 func TestConfigValidate_unknownResourceVar(t *testing.T) { 516 c := testConfig(t, "validate-unknown-resource-var") 517 if err := c.Validate(); err == nil { 518 t.Fatal("should not be valid") 519 } 520 } 521 522 func TestConfigValidate_unknownResourceVar_output(t *testing.T) { 523 c := testConfig(t, "validate-unknown-resource-var-output") 524 if err := c.Validate(); err == nil { 525 t.Fatal("should not be valid") 526 } 527 } 528 529 func TestConfigValidate_unknownVar(t *testing.T) { 530 c := testConfig(t, "validate-unknownvar") 531 if err := c.Validate(); err == nil { 532 t.Fatal("should not be valid") 533 } 534 } 535 536 func TestConfigValidate_unknownVarCount(t *testing.T) { 537 c := testConfig(t, "validate-unknownvar-count") 538 if err := c.Validate(); err == nil { 539 t.Fatal("should not be valid") 540 } 541 } 542 543 func TestConfigValidate_varDefault(t *testing.T) { 544 c := testConfig(t, "validate-var-default") 545 if err := c.Validate(); err != nil { 546 t.Fatalf("should be valid: %s", err) 547 } 548 } 549 550 func TestConfigValidate_varDefaultListType(t *testing.T) { 551 c := testConfig(t, "validate-var-default-list-type") 552 if err := c.Validate(); err != nil { 553 t.Fatalf("should be valid: %s", err) 554 } 555 } 556 557 func TestConfigValidate_varDefaultInterpolate(t *testing.T) { 558 c := testConfig(t, "validate-var-default-interpolate") 559 if err := c.Validate(); err == nil { 560 t.Fatal("should not be valid") 561 } 562 } 563 564 func TestConfigValidate_varDup(t *testing.T) { 565 c := testConfig(t, "validate-var-dup") 566 if err := c.Validate(); err == nil { 567 t.Fatal("should not be valid") 568 } 569 } 570 571 func TestConfigValidate_varMultiExactNonSlice(t *testing.T) { 572 c := testConfig(t, "validate-var-multi-exact-non-slice") 573 if err := c.Validate(); err != nil { 574 t.Fatalf("should be valid: %s", err) 575 } 576 } 577 578 func TestConfigValidate_varMultiNonSlice(t *testing.T) { 579 c := testConfig(t, "validate-var-multi-non-slice") 580 if err := c.Validate(); err == nil { 581 t.Fatal("should not be valid") 582 } 583 } 584 585 func TestConfigValidate_varMultiNonSliceProvisioner(t *testing.T) { 586 c := testConfig(t, "validate-var-multi-non-slice-provisioner") 587 if err := c.Validate(); err == nil { 588 t.Fatal("should not be valid") 589 } 590 } 591 592 func TestConfigValidate_varMultiFunctionCall(t *testing.T) { 593 c := testConfig(t, "validate-var-multi-func") 594 if err := c.Validate(); err != nil { 595 t.Fatalf("should be valid: %s", err) 596 } 597 } 598 599 func TestConfigValidate_varModule(t *testing.T) { 600 c := testConfig(t, "validate-var-module") 601 if err := c.Validate(); err != nil { 602 t.Fatalf("err: %s", err) 603 } 604 } 605 606 func TestConfigValidate_varModuleInvalid(t *testing.T) { 607 c := testConfig(t, "validate-var-module-invalid") 608 if err := c.Validate(); err == nil { 609 t.Fatal("should not be valid") 610 } 611 } 612 613 func TestNameRegexp(t *testing.T) { 614 cases := []struct { 615 Input string 616 Match bool 617 }{ 618 {"hello", true}, 619 {"foo-bar", true}, 620 {"foo_bar", true}, 621 {"_hello", true}, 622 {"foo bar", false}, 623 {"foo.bar", false}, 624 } 625 626 for _, tc := range cases { 627 if NameRegexp.Match([]byte(tc.Input)) != tc.Match { 628 t.Fatalf("Input: %s\n\nExpected: %#v", tc.Input, tc.Match) 629 } 630 } 631 } 632 633 func TestProviderConfigName(t *testing.T) { 634 pcs := []*ProviderConfig{ 635 &ProviderConfig{Name: "aw"}, 636 &ProviderConfig{Name: "aws"}, 637 &ProviderConfig{Name: "a"}, 638 &ProviderConfig{Name: "gce_"}, 639 } 640 641 n := ProviderConfigName("aws_instance", pcs) 642 if n != "aws" { 643 t.Fatalf("bad: %s", n) 644 } 645 } 646 647 func testConfig(t *testing.T, name string) *Config { 648 c, err := LoadFile(filepath.Join(fixtureDir, name, "main.tf")) 649 if err != nil { 650 t.Fatalf("file: %s\n\nerr: %s", name, err) 651 } 652 653 return c 654 } 655 656 func TestConfigDataCount(t *testing.T) { 657 c := testConfig(t, "data-count") 658 actual, err := c.Resources[0].Count() 659 if err != nil { 660 t.Fatalf("err: %s", err) 661 } 662 if actual != 5 { 663 t.Fatalf("bad: %#v", actual) 664 } 665 666 // we need to make sure "count" has been removed from the RawConfig, since 667 // it's not a real key and won't validate. 668 if _, ok := c.Resources[0].RawConfig.Raw["count"]; ok { 669 t.Fatal("count key still exists in RawConfig") 670 } 671 }