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