Merge pull request #18 from hashicorp/f-config-changes
Config: Ability to load directories of config files
This commit is contained in:
commit
5a9a960392
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
This file just exists to test that LoadDir doesn't load non-Terraform
|
||||
files.
|
|
@ -0,0 +1,3 @@
|
|||
output "i-am-nested" {
|
||||
value = "what"
|
||||
}
|
|
@ -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}"
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue