terraform/config/loader_test.go

640 lines
12 KiB
Go
Raw Normal View History

2014-05-23 01:56:28 +02:00
package config
import (
"fmt"
"path/filepath"
2014-07-01 19:28:42 +02:00
"sort"
2014-05-23 01:56:28 +02:00
"strings"
"testing"
)
2014-05-24 00:42:29 +02:00
func TestLoad_badType(t *testing.T) {
_, err := Load(filepath.Join(fixtureDir, "bad_type.tf.nope"))
if err == nil {
t.Fatal("should have error")
}
}
2014-05-23 01:56:28 +02:00
func TestLoadBasic(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "basic.tf"))
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(basicVariablesStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-05-26 03:05:18 +02:00
actual = providerConfigsStr(c.ProviderConfigs)
if actual != strings.TrimSpace(basicProvidersStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-05-23 01:56:28 +02:00
actual = resourcesStr(c.Resources)
if actual != strings.TrimSpace(basicResourcesStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-07-04 19:43:06 +02:00
actual = outputsStr(c.Outputs)
if actual != strings.TrimSpace(basicOutputsStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-05-23 01:56:28 +02:00
}
2014-05-24 00:11:57 +02:00
func TestLoadBasic_import(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "import.tf"))
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(importVariablesStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-05-26 03:05:18 +02:00
actual = providerConfigsStr(c.ProviderConfigs)
if actual != strings.TrimSpace(importProvidersStr) {
t.Fatalf("bad:\n%s", actual)
}
2014-05-24 00:11:57 +02:00
actual = resourcesStr(c.Resources)
2014-05-24 01:25:54 +02:00
if actual != strings.TrimSpace(importResourcesStr) {
2014-05-24 00:11:57 +02:00
t.Fatalf("bad:\n%s", actual)
}
}
func TestLoadBasic_json(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "basic.tf.json"))
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(basicVariablesStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = providerConfigsStr(c.ProviderConfigs)
if actual != strings.TrimSpace(basicProvidersStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = resourcesStr(c.Resources)
if actual != strings.TrimSpace(basicResourcesStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = outputsStr(c.Outputs)
if actual != strings.TrimSpace(basicOutputsStr) {
t.Fatalf("bad:\n%s", actual)
}
}
func TestLoad_variables(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "variables.tf"))
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(variablesVariablesStr) {
t.Fatalf("bad:\n%s", actual)
}
}
2014-07-12 05:15:09 +02:00
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 TestLoadDir_noConfigs(t *testing.T) {
_, err := LoadDir(filepath.Join(fixtureDir, "dir-empty"))
if err == nil {
t.Fatal("should error")
}
}
func TestLoadDir_noMerge(t *testing.T) {
c, err := LoadDir(filepath.Join(fixtureDir, "dir-merge"))
if err != nil {
t.Fatalf("err: %s", err)
}
if c == nil {
t.Fatal("config should not be nil")
}
if err := c.Validate(); err == nil {
t.Fatal("should not be valid")
}
}
2014-07-21 02:52:46 +02:00
func TestLoadDir_override(t *testing.T) {
c, err := LoadDir(filepath.Join(fixtureDir, "dir-override"))
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(dirOverrideVariablesStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = providerConfigsStr(c.ProviderConfigs)
if actual != strings.TrimSpace(dirOverrideProvidersStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = resourcesStr(c.Resources)
if actual != strings.TrimSpace(dirOverrideResourcesStr) {
t.Fatalf("bad:\n%s", actual)
}
actual = outputsStr(c.Outputs)
if actual != strings.TrimSpace(dirOverrideOutputsStr) {
t.Fatalf("bad:\n%s", actual)
}
}
2014-07-19 07:21:52 +02:00
func outputsStr(os []*Output) string {
2014-07-04 19:43:06 +02:00
ns := make([]string, 0, len(os))
2014-07-19 07:21:52 +02:00
m := make(map[string]*Output)
for _, o := range os {
ns = append(ns, o.Name)
m[o.Name] = o
2014-07-04 19:43:06 +02:00
}
sort.Strings(ns)
result := ""
for _, n := range ns {
2014-07-19 07:21:52 +02:00
o := m[n]
2014-07-04 19:43:06 +02:00
result += fmt.Sprintf("%s\n", n)
if len(o.RawConfig.Variables) > 0 {
result += fmt.Sprintf(" vars\n")
for _, rawV := range o.RawConfig.Variables {
kind := "unknown"
str := rawV.FullKey()
switch rawV.(type) {
case *ResourceVariable:
kind = "resource"
case *UserVariable:
kind = "user"
}
result += fmt.Sprintf(" %s: %s\n", kind, str)
}
}
}
return strings.TrimSpace(result)
}
func TestLoad_provisioners(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "provisioners.tf"))
if err != nil {
t.Fatalf("err: %s", err)
}
if c == nil {
t.Fatal("config should not be nil")
}
actual := resourcesStr(c.Resources)
if actual != strings.TrimSpace(provisionerResourcesStr) {
t.Fatalf("bad:\n%s", actual)
}
}
func TestLoad_connections(t *testing.T) {
c, err := Load(filepath.Join(fixtureDir, "connection.tf"))
if err != nil {
t.Fatalf("err: %s", err)
}
if c == nil {
t.Fatal("config should not be nil")
}
actual := resourcesStr(c.Resources)
if actual != strings.TrimSpace(connectionResourcesStr) {
t.Fatalf("bad:\n%s", actual)
}
// Check for the connection info
r := c.Resources[0]
if r.Name != "web" && r.Type != "aws_instance" {
t.Fatalf("Bad: %#v", r)
}
p1 := r.Provisioners[0]
if p1.ConnInfo == nil || len(p1.ConnInfo.Raw) != 2 {
t.Fatalf("Bad: %#v", p1.ConnInfo)
}
if p1.ConnInfo.Raw["user"] != "nobody" {
t.Fatalf("Bad: %#v", p1.ConnInfo)
}
p2 := r.Provisioners[1]
if p2.ConnInfo == nil || len(p2.ConnInfo.Raw) != 2 {
t.Fatalf("Bad: %#v", p2.ConnInfo)
}
if p2.ConnInfo.Raw["user"] != "root" {
t.Fatalf("Bad: %#v", p2.ConnInfo)
}
}
2014-05-26 03:05:18 +02:00
// This helper turns a provider configs field into a deterministic
// string value for comparison in tests.
2014-07-20 01:05:48 +02:00
func providerConfigsStr(pcs []*ProviderConfig) string {
2014-05-26 03:05:18 +02:00
result := ""
2014-07-01 19:28:42 +02:00
ns := make([]string, 0, len(pcs))
2014-07-20 01:05:48 +02:00
m := make(map[string]*ProviderConfig)
for _, n := range pcs {
ns = append(ns, n.Name)
m[n.Name] = n
2014-07-01 19:28:42 +02:00
}
sort.Strings(ns)
for _, n := range ns {
2014-07-20 01:05:48 +02:00
pc := m[n]
2014-07-01 19:28:42 +02:00
2014-05-26 03:05:18 +02:00
result += fmt.Sprintf("%s\n", n)
2014-07-01 19:28:42 +02:00
keys := make([]string, 0, len(pc.RawConfig.Raw))
for k, _ := range pc.RawConfig.Raw {
2014-07-01 19:28:42 +02:00
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
2014-05-26 03:05:18 +02:00
result += fmt.Sprintf(" %s\n", k)
}
if len(pc.RawConfig.Variables) > 0 {
2014-05-26 03:05:18 +02:00
result += fmt.Sprintf(" vars\n")
for _, rawV := range pc.RawConfig.Variables {
2014-05-26 03:05:18 +02:00
kind := "unknown"
str := rawV.FullKey()
switch rawV.(type) {
case *ResourceVariable:
kind = "resource"
case *UserVariable:
kind = "user"
}
result += fmt.Sprintf(" %s: %s\n", kind, str)
}
}
}
return strings.TrimSpace(result)
}
2014-05-23 01:56:28 +02:00
// This helper turns a resources field into a deterministic
// string value for comparison in tests.
2014-05-24 22:57:51 +02:00
func resourcesStr(rs []*Resource) string {
2014-05-23 01:56:28 +02:00
result := ""
2014-07-08 23:57:47 +02:00
order := make([]int, 0, len(rs))
ks := make([]string, 0, len(rs))
mapping := make(map[string]int)
for i, r := range rs {
k := fmt.Sprintf("%s[%s]", r.Type, r.Name)
ks = append(ks, k)
mapping[k] = i
}
sort.Strings(ks)
for _, k := range ks {
order = append(order, mapping[k])
}
for _, i := range order {
r := rs[i]
2014-05-23 01:56:28 +02:00
result += fmt.Sprintf(
2014-07-04 05:11:58 +02:00
"%s[%s] (x%d)\n",
2014-05-23 01:56:28 +02:00
r.Type,
2014-07-04 05:11:58 +02:00
r.Name,
r.Count)
2014-05-23 01:56:28 +02:00
2014-07-01 19:28:42 +02:00
ks := make([]string, 0, len(r.RawConfig.Raw))
for k, _ := range r.RawConfig.Raw {
2014-07-01 19:28:42 +02:00
ks = append(ks, k)
}
sort.Strings(ks)
for _, k := range ks {
2014-05-23 01:56:28 +02:00
result += fmt.Sprintf(" %s\n", k)
}
if len(r.Provisioners) > 0 {
result += fmt.Sprintf(" provisioners\n")
for _, p := range r.Provisioners {
result += fmt.Sprintf(" %s\n", p.Type)
ks := make([]string, 0, len(p.RawConfig.Raw))
for k, _ := range p.RawConfig.Raw {
ks = append(ks, k)
}
sort.Strings(ks)
for _, k := range ks {
result += fmt.Sprintf(" %s\n", k)
}
}
}
2014-07-23 02:10:17 +02:00
if len(r.DependsOn) > 0 {
result += fmt.Sprintf(" dependsOn\n")
for _, d := range r.DependsOn {
result += fmt.Sprintf(" %s\n", d)
}
}
if len(r.RawConfig.Variables) > 0 {
result += fmt.Sprintf(" vars\n")
2014-07-02 19:05:39 +02:00
ks := make([]string, 0, len(r.RawConfig.Variables))
for k, _ := range r.RawConfig.Variables {
ks = append(ks, k)
}
sort.Strings(ks)
for _, k := range ks {
rawV := r.RawConfig.Variables[k]
kind := "unknown"
str := rawV.FullKey()
switch rawV.(type) {
case *ResourceVariable:
kind = "resource"
case *UserVariable:
kind = "user"
}
result += fmt.Sprintf(" %s: %s\n", kind, str)
}
}
2014-05-23 01:56:28 +02:00
}
return strings.TrimSpace(result)
}
// This helper turns a variables field into a deterministic
// string value for comparison in tests.
2014-07-19 02:48:30 +02:00
func variablesStr(vs []*Variable) string {
2014-05-23 01:56:28 +02:00
result := ""
2014-07-01 19:28:42 +02:00
ks := make([]string, 0, len(vs))
2014-07-19 02:48:30 +02:00
m := make(map[string]*Variable)
for _, v := range vs {
ks = append(ks, v.Name)
m[v.Name] = v
2014-07-01 19:28:42 +02:00
}
sort.Strings(ks)
for _, k := range ks {
2014-07-19 02:48:30 +02:00
v := m[k]
2014-07-01 19:28:42 +02:00
required := ""
if v.Required() {
required = " (required)"
}
if v.Default == nil || v.Default == "" {
2014-05-24 01:09:41 +02:00
v.Default = "<>"
}
if v.Description == "" {
v.Description = "<>"
}
2014-05-23 01:56:28 +02:00
result += fmt.Sprintf(
"%s%s\n %v\n %s\n",
2014-05-23 01:56:28 +02:00
k,
2014-07-19 02:48:30 +02:00
required,
2014-05-23 01:56:28 +02:00
v.Default,
v.Description)
}
return strings.TrimSpace(result)
}
2014-07-04 19:43:06 +02:00
const basicOutputsStr = `
web_ip
vars
resource: aws_instance.web.private_ip
`
2014-05-26 03:05:18 +02:00
const basicProvidersStr = `
aws
access_key
secret_key
do
api_key
vars
user: var.foo
`
2014-05-23 01:56:28 +02:00
const basicResourcesStr = `
2014-07-08 23:57:47 +02:00
aws_instance[db] (x1)
security_groups
2014-07-23 02:10:17 +02:00
dependsOn
aws_instance.web
2014-07-08 23:57:47 +02:00
vars
resource: aws_security_group.firewall.*.id
2014-07-04 05:11:58 +02:00
aws_instance[web] (x1)
2014-05-23 01:56:28 +02:00
ami
network_interface
2014-05-23 01:56:28 +02:00
security_groups
vars
resource: aws_security_group.firewall.foo
2014-07-02 19:05:39 +02:00
user: var.foo
2014-07-08 23:57:47 +02:00
aws_security_group[firewall] (x5)
2014-05-23 01:56:28 +02:00
`
const basicVariablesStr = `
foo
bar
bar
`
2014-05-24 00:11:57 +02:00
2014-07-12 05:15:09 +02:00
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
`
2014-07-21 02:52:46 +02:00
const dirOverrideOutputsStr = `
web_ip
vars
resource: aws_instance.web.private_ip
`
const dirOverrideProvidersStr = `
aws
access_key
secret_key
do
api_key
vars
user: var.foo
`
const dirOverrideResourcesStr = `
aws_instance[db] (x1)
ami
security_groups
aws_instance[web] (x1)
ami
foo
2014-07-21 02:52:46 +02:00
network_interface
security_groups
vars
resource: aws_security_group.firewall.foo
user: var.foo
aws_security_group[firewall] (x5)
`
const dirOverrideVariablesStr = `
foo
bar
bar
`
2014-05-26 03:05:18 +02:00
const importProvidersStr = `
aws
2014-07-21 02:17:03 +02:00
bar
2014-05-26 03:05:18 +02:00
foo
`
2014-05-24 01:25:54 +02:00
const importResourcesStr = `
2014-07-04 05:11:58 +02:00
aws_security_group[db] (x1)
aws_security_group[web] (x1)
2014-05-24 01:25:54 +02:00
`
2014-05-24 00:11:57 +02:00
const importVariablesStr = `
2014-07-19 02:48:30 +02:00
bar (required)
2014-05-24 01:09:41 +02:00
<>
<>
2014-05-24 00:11:57 +02:00
foo
bar
bar
`
const provisionerResourcesStr = `
2014-07-07 20:35:33 +02:00
aws_instance[web] (x1)
ami
security_groups
provisioners
shell
path
vars
resource: aws_security_group.firewall.foo
user: var.foo
`
const connectionResourcesStr = `
aws_instance[web] (x1)
ami
security_groups
provisioners
shell
path
shell
path
vars
resource: aws_security_group.firewall.foo
user: var.foo
`
const variablesVariablesStr = `
bar
<>
<>
baz
foo
<>
2014-07-19 02:48:30 +02:00
foo (required)
2014-07-01 19:28:42 +02:00
<>
<>
`