github.com/anuaimi/terraform@v0.6.4-0.20150904235404-2bf9aec61da8/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 TestLoad_preventDestroyString(t *testing.T) { 444 c, err := LoadFile(filepath.Join(fixtureDir, "prevent-destroy-string.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 if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) { 455 t.Fatalf("bad:\n%s", actual) 456 } 457 458 // Check for the flag value 459 r := c.Resources[0] 460 if r.Name != "web" && r.Type != "aws_instance" { 461 t.Fatalf("Bad: %#v", r) 462 } 463 464 // Should enable create before destroy 465 if !r.Lifecycle.PreventDestroy { 466 t.Fatalf("Bad: %#v", r) 467 } 468 469 r = c.Resources[1] 470 if r.Name != "bar" && r.Type != "aws_instance" { 471 t.Fatalf("Bad: %#v", r) 472 } 473 474 // Should not enable create before destroy 475 if r.Lifecycle.PreventDestroy { 476 t.Fatalf("Bad: %#v", r) 477 } 478 } 479 480 func TestLoad_temporary_files(t *testing.T) { 481 _, err := LoadDir(filepath.Join(fixtureDir, "dir-temporary-files")) 482 if err == nil { 483 t.Fatalf("Expected to see an error stating no config files found") 484 } 485 } 486 487 const basicOutputsStr = ` 488 web_ip 489 vars 490 resource: aws_instance.web.private_ip 491 ` 492 493 const basicProvidersStr = ` 494 aws 495 access_key 496 secret_key 497 do 498 api_key 499 vars 500 user: var.foo 501 ` 502 503 const basicResourcesStr = ` 504 aws_instance[db] (x1) 505 VPC 506 security_groups 507 provisioners 508 file 509 destination 510 source 511 dependsOn 512 aws_instance.web 513 vars 514 resource: aws_security_group.firewall.*.id 515 aws_instance[web] (x1) 516 ami 517 network_interface 518 security_groups 519 provisioners 520 file 521 destination 522 source 523 vars 524 resource: aws_security_group.firewall.foo 525 user: var.foo 526 aws_security_group[firewall] (x5) 527 ` 528 529 const basicVariablesStr = ` 530 foo 531 bar 532 bar 533 ` 534 535 const dirBasicOutputsStr = ` 536 web_ip 537 vars 538 resource: aws_instance.web.private_ip 539 ` 540 541 const dirBasicProvidersStr = ` 542 aws 543 access_key 544 secret_key 545 do 546 api_key 547 vars 548 user: var.foo 549 ` 550 551 const dirBasicResourcesStr = ` 552 aws_instance[db] (x1) 553 security_groups 554 vars 555 resource: aws_security_group.firewall.*.id 556 aws_instance[web] (x1) 557 ami 558 network_interface 559 security_groups 560 vars 561 resource: aws_security_group.firewall.foo 562 user: var.foo 563 aws_security_group[firewall] (x5) 564 ` 565 566 const dirBasicVariablesStr = ` 567 foo 568 bar 569 bar 570 ` 571 572 const dirOverrideOutputsStr = ` 573 web_ip 574 vars 575 resource: aws_instance.web.private_ip 576 ` 577 578 const dirOverrideProvidersStr = ` 579 aws 580 access_key 581 secret_key 582 do 583 api_key 584 vars 585 user: var.foo 586 ` 587 588 const dirOverrideResourcesStr = ` 589 aws_instance[db] (x1) 590 ami 591 security_groups 592 aws_instance[web] (x1) 593 ami 594 foo 595 network_interface 596 security_groups 597 vars 598 resource: aws_security_group.firewall.foo 599 user: var.foo 600 aws_security_group[firewall] (x5) 601 ` 602 603 const dirOverrideVariablesStr = ` 604 foo 605 bar 606 bar 607 ` 608 609 const importProvidersStr = ` 610 aws 611 bar 612 foo 613 ` 614 615 const importResourcesStr = ` 616 aws_security_group[db] (x1) 617 aws_security_group[web] (x1) 618 ` 619 620 const importVariablesStr = ` 621 bar (required) 622 <> 623 <> 624 foo 625 bar 626 bar 627 ` 628 629 const modulesModulesStr = ` 630 bar 631 source = baz 632 memory 633 ` 634 635 const provisionerResourcesStr = ` 636 aws_instance[web] (x1) 637 ami 638 security_groups 639 provisioners 640 shell 641 path 642 vars 643 resource: aws_security_group.firewall.foo 644 user: var.foo 645 ` 646 647 const connectionResourcesStr = ` 648 aws_instance[web] (x1) 649 ami 650 security_groups 651 provisioners 652 shell 653 path 654 shell 655 path 656 vars 657 resource: aws_security_group.firewall.foo 658 user: var.foo 659 ` 660 661 const variablesVariablesStr = ` 662 bar 663 <> 664 <> 665 baz 666 foo 667 <> 668 foo (required) 669 <> 670 <> 671 ` 672 673 const createBeforeDestroyResourcesStr = ` 674 aws_instance[bar] (x1) 675 ami 676 aws_instance[web] (x1) 677 ami 678 `