From 9d028ab6de5086d04f5b7480f1d4122a08c1e15a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 11 Jul 2014 20:05:38 -0700 Subject: [PATCH 1/4] config: reword for ".tf" extension force --- config/import_tree.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/import_tree.go b/config/import_tree.go index c878116da..0e1c39c08 100644 --- a/config/import_tree.go +++ b/config/import_tree.go @@ -38,7 +38,7 @@ func loadTree(root string) (*importTree, error) { f = loadFileLibucl default: return nil, fmt.Errorf( - "%s: uknown configuration format. Use '.tf' or '.tf.rb' extension", + "%s: unknown configuration format. Use '.tf' extension", root) } From 14b29d0ecdf22b8195db11de6d54e6f327b217be Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 11 Jul 2014 20:15:09 -0700 Subject: [PATCH 2/4] config: LoadDir --- config/config_tree.go | 10 ++++ config/loader.go | 32 +++++++++++++ config/loader_test.go | 68 +++++++++++++++++++++++++++ config/test-fixtures/dir-basic/one.tf | 17 +++++++ config/test-fixtures/dir-basic/two.tf | 20 ++++++++ 5 files changed, 147 insertions(+) create mode 100644 config/test-fixtures/dir-basic/one.tf create mode 100644 config/test-fixtures/dir-basic/two.tf diff --git a/config/config_tree.go b/config/config_tree.go index 1b3daf52c..765910e8c 100644 --- a/config/config_tree.go +++ b/config/config_tree.go @@ -66,6 +66,16 @@ func mergeConfig(c1, c2 *Config) (*Config, error) { c.Variables[k] = v2 } + // Merge outputs: If they collide, just take the latest one for now. In + // the future, we might provide smarter merge functionality. + c.Outputs = make(map[string]*Output) + for k, v := range c1.Outputs { + c.Outputs[k] = v + } + for k, v := range c2.Outputs { + c.Outputs[k] = v + } + // Merge provider configs: If they collide, we just take the latest one // for now. In the future, we might provide smarter merge functionality. c.ProviderConfigs = make(map[string]*ProviderConfig) diff --git a/config/loader.go b/config/loader.go index a7d992804..750e9d15d 100644 --- a/config/loader.go +++ b/config/loader.go @@ -1,5 +1,9 @@ package config +import ( + "path/filepath" +) + // Load loads the Terraform configuration from a given file. // // This file can be any format that Terraform recognizes, and import any @@ -22,3 +26,31 @@ func Load(path string) (*Config, error) { return configTree.Flatten() } + +// LoadDir loads all the Terraform configuration files in a single +// directory and merges them together. +func LoadDir(path string) (*Config, error) { + matches, err := filepath.Glob(filepath.Join(path, "*.tf")) + if err != nil { + return nil, err + } + + var result *Config + for _, f := range matches { + c, err := Load(f) + if err != nil { + return nil, err + } + + if result != nil { + result, err = mergeConfig(result, c) + if err != nil { + return nil, err + } + } else { + result = c + } + } + + return result, nil +} diff --git a/config/loader_test.go b/config/loader_test.go index 56e46b272..2737ab38b 100644 --- a/config/loader_test.go +++ b/config/loader_test.go @@ -97,6 +97,37 @@ func TestLoad_variables(t *testing.T) { } } +func TestLoadDir_basic(t *testing.T) { + c, err := LoadDir(filepath.Join(fixtureDir, "dir-basic")) + if err != nil { + t.Fatalf("err: %s", err) + } + + if c == nil { + t.Fatal("config should not be nil") + } + + actual := variablesStr(c.Variables) + if actual != strings.TrimSpace(dirBasicVariablesStr) { + t.Fatalf("bad:\n%s", actual) + } + + actual = providerConfigsStr(c.ProviderConfigs) + if actual != strings.TrimSpace(dirBasicProvidersStr) { + t.Fatalf("bad:\n%s", actual) + } + + actual = resourcesStr(c.Resources) + if actual != strings.TrimSpace(dirBasicResourcesStr) { + t.Fatalf("bad:\n%s", actual) + } + + actual = outputsStr(c.Outputs) + if actual != strings.TrimSpace(dirBasicOutputsStr) { + t.Fatalf("bad:\n%s", actual) + } +} + func outputsStr(os map[string]*Output) string { ns := make([]string, 0, len(os)) for n, _ := range os { @@ -342,6 +373,43 @@ foo bar ` +const dirBasicOutputsStr = ` +web_ip + vars + resource: aws_instance.web.private_ip +` + +const dirBasicProvidersStr = ` +aws + access_key + secret_key +do + api_key + vars + user: var.foo +` + +const dirBasicResourcesStr = ` +aws_instance[db] (x1) + security_groups + vars + resource: aws_security_group.firewall.*.id +aws_instance[web] (x1) + ami + network_interface + security_groups + vars + resource: aws_security_group.firewall.foo + user: var.foo +aws_security_group[firewall] (x5) +` + +const dirBasicVariablesStr = ` +foo + bar + bar +` + const importProvidersStr = ` aws foo diff --git a/config/test-fixtures/dir-basic/one.tf b/config/test-fixtures/dir-basic/one.tf new file mode 100644 index 000000000..a4b59f1ae --- /dev/null +++ b/config/test-fixtures/dir-basic/one.tf @@ -0,0 +1,17 @@ +variable "foo" { + default = "bar"; + description = "bar"; +} + +provider "aws" { + access_key = "foo"; + secret_key = "bar"; +} + +resource "aws_instance" "db" { + security_groups = "${aws_security_group.firewall.*.id}" +} + +output "web_ip" { + value = "${aws_instance.web.private_ip}" +} diff --git a/config/test-fixtures/dir-basic/two.tf b/config/test-fixtures/dir-basic/two.tf new file mode 100644 index 000000000..c87c5059a --- /dev/null +++ b/config/test-fixtures/dir-basic/two.tf @@ -0,0 +1,20 @@ +provider "do" { + api_key = "${var.foo}"; +} + +resource "aws_security_group" "firewall" { + count = 5 +} + +resource aws_instance "web" { + ami = "${var.foo}" + security_groups = [ + "foo", + "${aws_security_group.firewall.foo}" + ] + + network_interface { + device_index = 0 + description = "Main network interface" + } +} From 8655711a3f819ac72e3433206e39153ab1530cf2 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 11 Jul 2014 20:16:49 -0700 Subject: [PATCH 3/4] config: test that LoadDir doesn't load nested --- config/test-fixtures/dir-basic/nested/nested.tf | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 config/test-fixtures/dir-basic/nested/nested.tf diff --git a/config/test-fixtures/dir-basic/nested/nested.tf b/config/test-fixtures/dir-basic/nested/nested.tf new file mode 100644 index 000000000..11a40a1d1 --- /dev/null +++ b/config/test-fixtures/dir-basic/nested/nested.tf @@ -0,0 +1,3 @@ +output "i-am-nested" { + value = "what" +} From 6dfebcae69f7a3eb9d7958cec5a0dbbb44a45647 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 11 Jul 2014 20:17:25 -0700 Subject: [PATCH 4/4] config: test that we only load tf files --- config/test-fixtures/dir-basic/README.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 config/test-fixtures/dir-basic/README.md diff --git a/config/test-fixtures/dir-basic/README.md b/config/test-fixtures/dir-basic/README.md new file mode 100644 index 000000000..0e528aca0 --- /dev/null +++ b/config/test-fixtures/dir-basic/README.md @@ -0,0 +1,2 @@ +This file just exists to test that LoadDir doesn't load non-Terraform +files.