github.com/jorgemarey/terraform@v0.6.7-0.20151113041428-536ba76b21bb/config/loader_test.go (about) 1 package config 2 3 import ( 4 "io/ioutil" 5 "path/filepath" 6 "reflect" 7 "strings" 8 "testing" 9 ) 10 11 func TestIsEmptyDir(t *testing.T) { 12 val, err := IsEmptyDir(fixtureDir) 13 if err != nil { 14 t.Fatalf("err: %s", err) 15 } 16 if val { 17 t.Fatal("should not be empty") 18 } 19 } 20 21 func TestIsEmptyDir_noExist(t *testing.T) { 22 val, err := IsEmptyDir(filepath.Join(fixtureDir, "nopenopenope")) 23 if err != nil { 24 t.Fatalf("err: %s", err) 25 } 26 if !val { 27 t.Fatal("should be empty") 28 } 29 } 30 31 func TestIsEmptyDir_noConfigs(t *testing.T) { 32 val, err := IsEmptyDir(filepath.Join(fixtureDir, "dir-empty")) 33 if err != nil { 34 t.Fatalf("err: %s", err) 35 } 36 if !val { 37 t.Fatal("should be empty") 38 } 39 } 40 41 func TestLoadFile_badType(t *testing.T) { 42 _, err := LoadFile(filepath.Join(fixtureDir, "bad_type.tf.nope")) 43 if err == nil { 44 t.Fatal("should have error") 45 } 46 } 47 48 func TestLoadFileHeredoc(t *testing.T) { 49 c, err := LoadFile(filepath.Join(fixtureDir, "heredoc.tf")) 50 if err != nil { 51 t.Fatalf("err: %s", err) 52 } 53 54 if c == nil { 55 t.Fatal("config should not be nil") 56 } 57 58 if c.Dir != "" { 59 t.Fatalf("bad: %#v", c.Dir) 60 } 61 62 actual := providerConfigsStr(c.ProviderConfigs) 63 if actual != strings.TrimSpace(heredocProvidersStr) { 64 t.Fatalf("bad:\n%s", actual) 65 } 66 67 actual = resourcesStr(c.Resources) 68 if actual != strings.TrimSpace(heredocResourcesStr) { 69 t.Fatalf("bad:\n%s", actual) 70 } 71 } 72 73 func TestLoadFileBasic(t *testing.T) { 74 c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf")) 75 if err != nil { 76 t.Fatalf("err: %s", err) 77 } 78 79 if c == nil { 80 t.Fatal("config should not be nil") 81 } 82 83 if c.Dir != "" { 84 t.Fatalf("bad: %#v", c.Dir) 85 } 86 87 expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"} 88 if !reflect.DeepEqual(c.Atlas, expectedAtlas) { 89 t.Fatalf("bad: %#v", c.Atlas) 90 } 91 92 actual := variablesStr(c.Variables) 93 if actual != strings.TrimSpace(basicVariablesStr) { 94 t.Fatalf("bad:\n%s", actual) 95 } 96 97 actual = providerConfigsStr(c.ProviderConfigs) 98 if actual != strings.TrimSpace(basicProvidersStr) { 99 t.Fatalf("bad:\n%s", actual) 100 } 101 102 actual = resourcesStr(c.Resources) 103 if actual != strings.TrimSpace(basicResourcesStr) { 104 t.Fatalf("bad:\n%s", actual) 105 } 106 107 actual = outputsStr(c.Outputs) 108 if actual != strings.TrimSpace(basicOutputsStr) { 109 t.Fatalf("bad:\n%s", actual) 110 } 111 } 112 113 func TestLoadFileBasic_empty(t *testing.T) { 114 c, err := LoadFile(filepath.Join(fixtureDir, "empty.tf")) 115 if err != nil { 116 t.Fatalf("err: %s", err) 117 } 118 119 if c == nil { 120 t.Fatal("config should not be nil") 121 } 122 } 123 124 func TestLoadFileBasic_import(t *testing.T) { 125 // Skip because we disabled importing 126 t.Skip() 127 128 c, err := LoadFile(filepath.Join(fixtureDir, "import.tf")) 129 if err != nil { 130 t.Fatalf("err: %s", err) 131 } 132 133 if c == nil { 134 t.Fatal("config should not be nil") 135 } 136 137 actual := variablesStr(c.Variables) 138 if actual != strings.TrimSpace(importVariablesStr) { 139 t.Fatalf("bad:\n%s", actual) 140 } 141 142 actual = providerConfigsStr(c.ProviderConfigs) 143 if actual != strings.TrimSpace(importProvidersStr) { 144 t.Fatalf("bad:\n%s", actual) 145 } 146 147 actual = resourcesStr(c.Resources) 148 if actual != strings.TrimSpace(importResourcesStr) { 149 t.Fatalf("bad:\n%s", actual) 150 } 151 } 152 153 func TestLoadFileBasic_json(t *testing.T) { 154 c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf.json")) 155 if err != nil { 156 t.Fatalf("err: %s", err) 157 } 158 159 if c == nil { 160 t.Fatal("config should not be nil") 161 } 162 163 if c.Dir != "" { 164 t.Fatalf("bad: %#v", c.Dir) 165 } 166 167 expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"} 168 if !reflect.DeepEqual(c.Atlas, expectedAtlas) { 169 t.Fatalf("bad: %#v", c.Atlas) 170 } 171 172 actual := variablesStr(c.Variables) 173 if actual != strings.TrimSpace(basicVariablesStr) { 174 t.Fatalf("bad:\n%s", actual) 175 } 176 177 actual = providerConfigsStr(c.ProviderConfigs) 178 if actual != strings.TrimSpace(basicProvidersStr) { 179 t.Fatalf("bad:\n%s", actual) 180 } 181 182 actual = resourcesStr(c.Resources) 183 if actual != strings.TrimSpace(basicResourcesStr) { 184 t.Fatalf("bad:\n%s", actual) 185 } 186 187 actual = outputsStr(c.Outputs) 188 if actual != strings.TrimSpace(basicOutputsStr) { 189 t.Fatalf("bad:\n%s", actual) 190 } 191 } 192 193 func TestLoadFileBasic_modules(t *testing.T) { 194 c, err := LoadFile(filepath.Join(fixtureDir, "modules.tf")) 195 if err != nil { 196 t.Fatalf("err: %s", err) 197 } 198 199 if c == nil { 200 t.Fatal("config should not be nil") 201 } 202 203 if c.Dir != "" { 204 t.Fatalf("bad: %#v", c.Dir) 205 } 206 207 actual := modulesStr(c.Modules) 208 if actual != strings.TrimSpace(modulesModulesStr) { 209 t.Fatalf("bad:\n%s", actual) 210 } 211 } 212 213 func TestLoadJSONBasic(t *testing.T) { 214 raw, err := ioutil.ReadFile(filepath.Join(fixtureDir, "basic.tf.json")) 215 if err != nil { 216 t.Fatalf("err: %s", err) 217 } 218 219 c, err := LoadJSON(raw) 220 if err != nil { 221 t.Fatalf("err: %s", err) 222 } 223 224 if c == nil { 225 t.Fatal("config should not be nil") 226 } 227 228 if c.Dir != "" { 229 t.Fatalf("bad: %#v", c.Dir) 230 } 231 232 expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"} 233 if !reflect.DeepEqual(c.Atlas, expectedAtlas) { 234 t.Fatalf("bad: %#v", c.Atlas) 235 } 236 237 actual := variablesStr(c.Variables) 238 if actual != strings.TrimSpace(basicVariablesStr) { 239 t.Fatalf("bad:\n%s", actual) 240 } 241 242 actual = providerConfigsStr(c.ProviderConfigs) 243 if actual != strings.TrimSpace(basicProvidersStr) { 244 t.Fatalf("bad:\n%s", actual) 245 } 246 247 actual = resourcesStr(c.Resources) 248 if actual != strings.TrimSpace(basicResourcesStr) { 249 t.Fatalf("bad:\n%s", actual) 250 } 251 252 actual = outputsStr(c.Outputs) 253 if actual != strings.TrimSpace(basicOutputsStr) { 254 t.Fatalf("bad:\n%s", actual) 255 } 256 } 257 258 func TestLoadFile_variables(t *testing.T) { 259 c, err := LoadFile(filepath.Join(fixtureDir, "variables.tf")) 260 if err != nil { 261 t.Fatalf("err: %s", err) 262 } 263 if c == nil { 264 t.Fatal("config should not be nil") 265 } 266 267 if c.Dir != "" { 268 t.Fatalf("bad: %#v", c.Dir) 269 } 270 271 actual := variablesStr(c.Variables) 272 if actual != strings.TrimSpace(variablesVariablesStr) { 273 t.Fatalf("bad:\n%s", actual) 274 } 275 } 276 277 func TestLoadDir_basic(t *testing.T) { 278 dir := filepath.Join(fixtureDir, "dir-basic") 279 c, err := LoadDir(dir) 280 if err != nil { 281 t.Fatalf("err: %s", err) 282 } 283 284 if c == nil { 285 t.Fatal("config should not be nil") 286 } 287 288 dirAbs, err := filepath.Abs(dir) 289 if err != nil { 290 t.Fatalf("err: %s", err) 291 } 292 if c.Dir != dirAbs { 293 t.Fatalf("bad: %#v", c.Dir) 294 } 295 296 actual := variablesStr(c.Variables) 297 if actual != strings.TrimSpace(dirBasicVariablesStr) { 298 t.Fatalf("bad:\n%s", actual) 299 } 300 301 actual = providerConfigsStr(c.ProviderConfigs) 302 if actual != strings.TrimSpace(dirBasicProvidersStr) { 303 t.Fatalf("bad:\n%s", actual) 304 } 305 306 actual = resourcesStr(c.Resources) 307 if actual != strings.TrimSpace(dirBasicResourcesStr) { 308 t.Fatalf("bad:\n%s", actual) 309 } 310 311 actual = outputsStr(c.Outputs) 312 if actual != strings.TrimSpace(dirBasicOutputsStr) { 313 t.Fatalf("bad:\n%s", actual) 314 } 315 } 316 317 func TestLoadDir_file(t *testing.T) { 318 _, err := LoadDir(filepath.Join(fixtureDir, "variables.tf")) 319 if err == nil { 320 t.Fatal("should error") 321 } 322 } 323 324 func TestLoadDir_noConfigs(t *testing.T) { 325 _, err := LoadDir(filepath.Join(fixtureDir, "dir-empty")) 326 if err == nil { 327 t.Fatal("should error") 328 } 329 } 330 331 func TestLoadDir_noMerge(t *testing.T) { 332 c, err := LoadDir(filepath.Join(fixtureDir, "dir-merge")) 333 if err != nil { 334 t.Fatalf("err: %s", err) 335 } 336 337 if c == nil { 338 t.Fatal("config should not be nil") 339 } 340 341 if err := c.Validate(); err == nil { 342 t.Fatal("should not be valid") 343 } 344 } 345 346 func TestLoadDir_override(t *testing.T) { 347 c, err := LoadDir(filepath.Join(fixtureDir, "dir-override")) 348 if err != nil { 349 t.Fatalf("err: %s", err) 350 } 351 352 if c == nil { 353 t.Fatal("config should not be nil") 354 } 355 356 actual := variablesStr(c.Variables) 357 if actual != strings.TrimSpace(dirOverrideVariablesStr) { 358 t.Fatalf("bad:\n%s", actual) 359 } 360 361 actual = providerConfigsStr(c.ProviderConfigs) 362 if actual != strings.TrimSpace(dirOverrideProvidersStr) { 363 t.Fatalf("bad:\n%s", actual) 364 } 365 366 actual = resourcesStr(c.Resources) 367 if actual != strings.TrimSpace(dirOverrideResourcesStr) { 368 t.Fatalf("bad:\n%s", actual) 369 } 370 371 actual = outputsStr(c.Outputs) 372 if actual != strings.TrimSpace(dirOverrideOutputsStr) { 373 t.Fatalf("bad:\n%s", actual) 374 } 375 } 376 377 func TestLoadFile_provisioners(t *testing.T) { 378 c, err := LoadFile(filepath.Join(fixtureDir, "provisioners.tf")) 379 if err != nil { 380 t.Fatalf("err: %s", err) 381 } 382 383 if c == nil { 384 t.Fatal("config should not be nil") 385 } 386 387 actual := resourcesStr(c.Resources) 388 if actual != strings.TrimSpace(provisionerResourcesStr) { 389 t.Fatalf("bad:\n%s", actual) 390 } 391 } 392 393 func TestLoadFile_connections(t *testing.T) { 394 c, err := LoadFile(filepath.Join(fixtureDir, "connection.tf")) 395 if err != nil { 396 t.Fatalf("err: %s", err) 397 } 398 399 if c == nil { 400 t.Fatal("config should not be nil") 401 } 402 403 actual := resourcesStr(c.Resources) 404 if actual != strings.TrimSpace(connectionResourcesStr) { 405 t.Fatalf("bad:\n%s", actual) 406 } 407 408 // Check for the connection info 409 r := c.Resources[0] 410 if r.Name != "web" && r.Type != "aws_instance" { 411 t.Fatalf("Bad: %#v", r) 412 } 413 414 p1 := r.Provisioners[0] 415 if p1.ConnInfo == nil || len(p1.ConnInfo.Raw) != 2 { 416 t.Fatalf("Bad: %#v", p1.ConnInfo) 417 } 418 if p1.ConnInfo.Raw["user"] != "nobody" { 419 t.Fatalf("Bad: %#v", p1.ConnInfo) 420 } 421 422 p2 := r.Provisioners[1] 423 if p2.ConnInfo == nil || len(p2.ConnInfo.Raw) != 2 { 424 t.Fatalf("Bad: %#v", p2.ConnInfo) 425 } 426 if p2.ConnInfo.Raw["user"] != "root" { 427 t.Fatalf("Bad: %#v", p2.ConnInfo) 428 } 429 } 430 431 func TestLoadFile_createBeforeDestroy(t *testing.T) { 432 c, err := LoadFile(filepath.Join(fixtureDir, "create-before-destroy.tf")) 433 if err != nil { 434 t.Fatalf("err: %s", err) 435 } 436 437 if c == nil { 438 t.Fatal("config should not be nil") 439 } 440 441 actual := resourcesStr(c.Resources) 442 if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) { 443 t.Fatalf("bad:\n%s", actual) 444 } 445 446 // Check for the flag value 447 r := c.Resources[0] 448 if r.Name != "web" && r.Type != "aws_instance" { 449 t.Fatalf("Bad: %#v", r) 450 } 451 452 // Should enable create before destroy 453 if !r.Lifecycle.CreateBeforeDestroy { 454 t.Fatalf("Bad: %#v", r) 455 } 456 457 r = c.Resources[1] 458 if r.Name != "bar" && r.Type != "aws_instance" { 459 t.Fatalf("Bad: %#v", r) 460 } 461 462 // Should not enable create before destroy 463 if r.Lifecycle.CreateBeforeDestroy { 464 t.Fatalf("Bad: %#v", r) 465 } 466 } 467 468 func TestLoadFile_ignoreChanges(t *testing.T) { 469 c, err := LoadFile(filepath.Join(fixtureDir, "ignore-changes.tf")) 470 if err != nil { 471 t.Fatalf("err: %s", err) 472 } 473 474 if c == nil { 475 t.Fatal("config should not be nil") 476 } 477 478 actual := resourcesStr(c.Resources) 479 print(actual) 480 if actual != strings.TrimSpace(ignoreChangesResourcesStr) { 481 t.Fatalf("bad:\n%s", actual) 482 } 483 484 // Check for the flag value 485 r := c.Resources[0] 486 if r.Name != "web" && r.Type != "aws_instance" { 487 t.Fatalf("Bad: %#v", r) 488 } 489 490 // Should populate ignore changes 491 if len(r.Lifecycle.IgnoreChanges) == 0 { 492 t.Fatalf("Bad: %#v", r) 493 } 494 495 r = c.Resources[1] 496 if r.Name != "bar" && r.Type != "aws_instance" { 497 t.Fatalf("Bad: %#v", r) 498 } 499 500 // Should not populate ignore changes 501 if len(r.Lifecycle.IgnoreChanges) > 0 { 502 t.Fatalf("Bad: %#v", r) 503 } 504 505 r = c.Resources[2] 506 if r.Name != "baz" && r.Type != "aws_instance" { 507 t.Fatalf("Bad: %#v", r) 508 } 509 510 // Should not populate ignore changes 511 if len(r.Lifecycle.IgnoreChanges) > 0 { 512 t.Fatalf("Bad: %#v", r) 513 } 514 } 515 516 func TestLoad_preventDestroyString(t *testing.T) { 517 c, err := LoadFile(filepath.Join(fixtureDir, "prevent-destroy-string.tf")) 518 if err != nil { 519 t.Fatalf("err: %s", err) 520 } 521 522 if c == nil { 523 t.Fatal("config should not be nil") 524 } 525 526 actual := resourcesStr(c.Resources) 527 if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) { 528 t.Fatalf("bad:\n%s", actual) 529 } 530 531 // Check for the flag value 532 r := c.Resources[0] 533 if r.Name != "web" && r.Type != "aws_instance" { 534 t.Fatalf("Bad: %#v", r) 535 } 536 537 // Should enable create before destroy 538 if !r.Lifecycle.PreventDestroy { 539 t.Fatalf("Bad: %#v", r) 540 } 541 542 r = c.Resources[1] 543 if r.Name != "bar" && r.Type != "aws_instance" { 544 t.Fatalf("Bad: %#v", r) 545 } 546 547 // Should not enable create before destroy 548 if r.Lifecycle.PreventDestroy { 549 t.Fatalf("Bad: %#v", r) 550 } 551 } 552 553 func TestLoad_temporary_files(t *testing.T) { 554 _, err := LoadDir(filepath.Join(fixtureDir, "dir-temporary-files")) 555 if err == nil { 556 t.Fatalf("Expected to see an error stating no config files found") 557 } 558 } 559 560 const heredocProvidersStr = ` 561 aws 562 access_key 563 secret_key 564 ` 565 566 const heredocResourcesStr = ` 567 aws_iam_policy[policy] (x1) 568 description 569 name 570 path 571 policy 572 ` 573 574 const basicOutputsStr = ` 575 web_ip 576 vars 577 resource: aws_instance.web.private_ip 578 ` 579 580 const basicProvidersStr = ` 581 aws 582 access_key 583 secret_key 584 do 585 api_key 586 vars 587 user: var.foo 588 ` 589 590 const basicResourcesStr = ` 591 aws_instance[db] (x1) 592 VPC 593 security_groups 594 provisioners 595 file 596 destination 597 source 598 dependsOn 599 aws_instance.web 600 vars 601 resource: aws_security_group.firewall.*.id 602 aws_instance[web] (x1) 603 ami 604 network_interface 605 security_groups 606 provisioners 607 file 608 destination 609 source 610 vars 611 resource: aws_security_group.firewall.foo 612 user: var.foo 613 aws_security_group[firewall] (x5) 614 ` 615 616 const basicVariablesStr = ` 617 foo 618 bar 619 bar 620 ` 621 622 const dirBasicOutputsStr = ` 623 web_ip 624 vars 625 resource: aws_instance.web.private_ip 626 ` 627 628 const dirBasicProvidersStr = ` 629 aws 630 access_key 631 secret_key 632 do 633 api_key 634 vars 635 user: var.foo 636 ` 637 638 const dirBasicResourcesStr = ` 639 aws_instance[db] (x1) 640 security_groups 641 vars 642 resource: aws_security_group.firewall.*.id 643 aws_instance[web] (x1) 644 ami 645 network_interface 646 security_groups 647 vars 648 resource: aws_security_group.firewall.foo 649 user: var.foo 650 aws_security_group[firewall] (x5) 651 ` 652 653 const dirBasicVariablesStr = ` 654 foo 655 bar 656 bar 657 ` 658 659 const dirOverrideOutputsStr = ` 660 web_ip 661 vars 662 resource: aws_instance.web.private_ip 663 ` 664 665 const dirOverrideProvidersStr = ` 666 aws 667 access_key 668 secret_key 669 do 670 api_key 671 vars 672 user: var.foo 673 ` 674 675 const dirOverrideResourcesStr = ` 676 aws_instance[db] (x1) 677 ami 678 security_groups 679 aws_instance[web] (x1) 680 ami 681 foo 682 network_interface 683 security_groups 684 vars 685 resource: aws_security_group.firewall.foo 686 user: var.foo 687 aws_security_group[firewall] (x5) 688 ` 689 690 const dirOverrideVariablesStr = ` 691 foo 692 bar 693 bar 694 ` 695 696 const importProvidersStr = ` 697 aws 698 bar 699 foo 700 ` 701 702 const importResourcesStr = ` 703 aws_security_group[db] (x1) 704 aws_security_group[web] (x1) 705 ` 706 707 const importVariablesStr = ` 708 bar (required) 709 <> 710 <> 711 foo 712 bar 713 bar 714 ` 715 716 const modulesModulesStr = ` 717 bar 718 source = baz 719 memory 720 ` 721 722 const provisionerResourcesStr = ` 723 aws_instance[web] (x1) 724 ami 725 security_groups 726 provisioners 727 shell 728 path 729 vars 730 resource: aws_security_group.firewall.foo 731 user: var.foo 732 ` 733 734 const connectionResourcesStr = ` 735 aws_instance[web] (x1) 736 ami 737 security_groups 738 provisioners 739 shell 740 path 741 shell 742 path 743 vars 744 resource: aws_security_group.firewall.foo 745 user: var.foo 746 ` 747 748 const variablesVariablesStr = ` 749 bar 750 <> 751 <> 752 baz 753 foo 754 <> 755 foo (required) 756 <> 757 <> 758 ` 759 760 const createBeforeDestroyResourcesStr = ` 761 aws_instance[bar] (x1) 762 ami 763 aws_instance[web] (x1) 764 ami 765 ` 766 767 const ignoreChangesResourcesStr = ` 768 aws_instance[bar] (x1) 769 ami 770 aws_instance[baz] (x1) 771 ami 772 aws_instance[web] (x1) 773 ami 774 `