diff --git a/config/config_test.go b/config/config_test.go index 88dbdc6c5..2c9791877 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -450,7 +450,7 @@ func TestVariableDefaultsMap(t *testing.T) { } func testConfig(t *testing.T, name string) *Config { - c, err := Load(filepath.Join(fixtureDir, name, "main.tf")) + c, err := LoadFile(filepath.Join(fixtureDir, name, "main.tf")) if err != nil { t.Fatalf("file: %s\n\nerr: %s", name, err) } diff --git a/config/loader.go b/config/loader.go index 1848f314d..4f5d8e765 100644 --- a/config/loader.go +++ b/config/loader.go @@ -1,19 +1,41 @@ package config import ( + "encoding/json" "fmt" "io" "os" "path/filepath" "sort" "strings" + + "github.com/hashicorp/hcl" ) -// Load loads the Terraform configuration from a given file. +// LoadJSON loads a single Terraform configuration from a given JSON document. +// +// The document must be a complete Terraform configuration. This function will +// NOT try to load any additional modules so only the given document is loaded. +func LoadJSON(raw json.RawMessage) (*Config, error) { + obj, err := hcl.Parse(string(raw)) + if err != nil { + return nil, fmt.Errorf( + "Error parsing JSON document as HCL: %s", err) + } + + // Start building the result + hclConfig := &hclConfigurable{ + Object: obj, + } + + return hclConfig.Config() +} + +// LoadFile loads the Terraform configuration from a given file. // // This file can be any format that Terraform recognizes, and import any // other format that Terraform recognizes. -func Load(path string) (*Config, error) { +func LoadFile(path string) (*Config, error) { importTree, err := loadTree(path) if err != nil { return nil, err @@ -66,7 +88,7 @@ func LoadDir(root string) (*Config, error) { // Load all the regular files, append them to each other. for _, f := range files { - c, err := Load(f) + c, err := LoadFile(f) if err != nil { return nil, err } @@ -83,7 +105,7 @@ func LoadDir(root string) (*Config, error) { // Load all the overrides, and merge them into the config for _, f := range overrides { - c, err := Load(f) + c, err := LoadFile(f) if err != nil { return nil, err } diff --git a/config/loader_test.go b/config/loader_test.go index d487638e9..28ee242f5 100644 --- a/config/loader_test.go +++ b/config/loader_test.go @@ -1,6 +1,7 @@ package config import ( + "io/ioutil" "path/filepath" "reflect" "strings" @@ -37,15 +38,15 @@ func TestIsEmptyDir_noConfigs(t *testing.T) { } } -func TestLoad_badType(t *testing.T) { - _, err := Load(filepath.Join(fixtureDir, "bad_type.tf.nope")) +func TestLoadFile_badType(t *testing.T) { + _, err := LoadFile(filepath.Join(fixtureDir, "bad_type.tf.nope")) if err == nil { t.Fatal("should have error") } } -func TestLoadBasic(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "basic.tf")) +func TestLoadFileBasic(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -84,8 +85,8 @@ func TestLoadBasic(t *testing.T) { } } -func TestLoadBasic_empty(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "empty.tf")) +func TestLoadFileBasic_empty(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "empty.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -95,11 +96,11 @@ func TestLoadBasic_empty(t *testing.T) { } } -func TestLoadBasic_import(t *testing.T) { +func TestLoadFileBasic_import(t *testing.T) { // Skip because we disabled importing t.Skip() - c, err := Load(filepath.Join(fixtureDir, "import.tf")) + c, err := LoadFile(filepath.Join(fixtureDir, "import.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -124,8 +125,8 @@ func TestLoadBasic_import(t *testing.T) { } } -func TestLoadBasic_json(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "basic.tf.json")) +func TestLoadFileBasic_json(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf.json")) if err != nil { t.Fatalf("err: %s", err) } @@ -164,8 +165,8 @@ func TestLoadBasic_json(t *testing.T) { } } -func TestLoadBasic_modules(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "modules.tf")) +func TestLoadFileBasic_modules(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "modules.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -184,8 +185,53 @@ func TestLoadBasic_modules(t *testing.T) { } } -func TestLoad_variables(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "variables.tf")) +func TestLoadJSONBasic(t *testing.T) { + raw, err := ioutil.ReadFile(filepath.Join(fixtureDir, "basic.tf.json")) + if err != nil { + t.Fatalf("err: %s", err) + } + + c, err := LoadJSON(raw) + if err != nil { + t.Fatalf("err: %s", err) + } + + if c == nil { + t.Fatal("config should not be nil") + } + + if c.Dir != "" { + t.Fatalf("bad: %#v", c.Dir) + } + + expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"} + if !reflect.DeepEqual(c.Atlas, expectedAtlas) { + t.Fatalf("bad: %#v", c.Atlas) + } + + 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 TestLoadFile_variables(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "variables.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -303,8 +349,8 @@ func TestLoadDir_override(t *testing.T) { } } -func TestLoad_provisioners(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "provisioners.tf")) +func TestLoadFile_provisioners(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "provisioners.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -319,8 +365,8 @@ func TestLoad_provisioners(t *testing.T) { } } -func TestLoad_connections(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "connection.tf")) +func TestLoadFile_connections(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "connection.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -357,8 +403,8 @@ func TestLoad_connections(t *testing.T) { } } -func TestLoad_createBeforeDestroy(t *testing.T) { - c, err := Load(filepath.Join(fixtureDir, "create-before-destroy.tf")) +func TestLoadFile_createBeforeDestroy(t *testing.T) { + c, err := LoadFile(filepath.Join(fixtureDir, "create-before-destroy.tf")) if err != nil { t.Fatalf("err: %s", err) } @@ -394,7 +440,7 @@ func TestLoad_createBeforeDestroy(t *testing.T) { } } -func TestLoad_temporary_files(t *testing.T) { +func TestLoadDir_temporary_files(t *testing.T) { _, err := LoadDir(filepath.Join(fixtureDir, "dir-temporary-files")) if err == nil { t.Fatalf("Expected to see an error stating no config files found") diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index e30d27a13..269df7298 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -56,7 +56,7 @@ func tempEnv(t *testing.T, k string, v string) string { } func testConfig(t *testing.T, name string) *config.Config { - c, err := config.Load(filepath.Join(fixtureDir, name, "main.tf")) + c, err := config.LoadFile(filepath.Join(fixtureDir, name, "main.tf")) if err != nil { t.Fatalf("err: %s", err) }