config: LoadDir

This commit is contained in:
Mitchell Hashimoto 2014-07-11 20:15:09 -07:00
parent 9d028ab6de
commit 14b29d0ecd
5 changed files with 147 additions and 0 deletions

View File

@ -66,6 +66,16 @@ func mergeConfig(c1, c2 *Config) (*Config, error) {
c.Variables[k] = v2 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 // Merge provider configs: If they collide, we just take the latest one
// for now. In the future, we might provide smarter merge functionality. // for now. In the future, we might provide smarter merge functionality.
c.ProviderConfigs = make(map[string]*ProviderConfig) c.ProviderConfigs = make(map[string]*ProviderConfig)

View File

@ -1,5 +1,9 @@
package config package config
import (
"path/filepath"
)
// Load loads the Terraform configuration from a given file. // Load loads the Terraform configuration from a given file.
// //
// This file can be any format that Terraform recognizes, and import any // 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() 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
}

View File

@ -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 { func outputsStr(os map[string]*Output) string {
ns := make([]string, 0, len(os)) ns := make([]string, 0, len(os))
for n, _ := range os { for n, _ := range os {
@ -342,6 +373,43 @@ foo
bar 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 = ` const importProvidersStr = `
aws aws
foo foo

View File

@ -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}"
}

View File

@ -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"
}
}