diff --git a/config/config.go b/config/config.go index dec8e3bb23..e220e8a483 100644 --- a/config/config.go +++ b/config/config.go @@ -55,6 +55,8 @@ type AtlasConfig struct { type Module struct { Name string Source string + Version string + Providers map[string]string RawConfig *RawConfig } @@ -67,6 +69,11 @@ type ProviderConfig struct { Alias string Version string RawConfig *RawConfig + + // Scope records where the Provider was declared in a module tree, so that + // it can be copied into child module providers yes still interpolated in + // the correct scope. + Scope []string } // A resource represents a single Terraform resource in the configuration. diff --git a/config/config_test.go b/config/config_test.go index cae5bac928..ace096397d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -836,3 +836,21 @@ func TestResourceProviderFullName(t *testing.T) { } } } + +func TestConfigModuleProviders(t *testing.T) { + c := testConfig(t, "module-providers") + + if len(c.Modules) != 1 { + t.Fatalf("expected 1 module, got %d", len(c.Modules)) + } + + expected := map[string]string{ + "aws": "aws.foo", + } + + got := c.Modules[0].Providers + + if !reflect.DeepEqual(expected, got) { + t.Fatalf("exptected providers %#v, got providers %#v", expected, got) + } +} diff --git a/config/loader_hcl.go b/config/loader_hcl.go index c8c82c312f..68cffe2ccc 100644 --- a/config/loader_hcl.go +++ b/config/loader_hcl.go @@ -393,9 +393,6 @@ func loadModulesHcl(list *ast.ObjectList) ([]*Module, error) { err) } - // Remove the fields we handle specially - delete(config, "source") - rawConfig, err := NewRawConfig(config) if err != nil { return nil, fmt.Errorf( @@ -404,7 +401,11 @@ func loadModulesHcl(list *ast.ObjectList) ([]*Module, error) { err) } - // If we have a count, then figure it out + // Remove the fields we handle specially + delete(config, "source") + delete(config, "version") + delete(config, "providers") + var source string if o := listVal.Filter("source"); len(o.Items) > 0 { err = hcl.DecodeObject(&source, o.Items[0].Val) @@ -416,9 +417,33 @@ func loadModulesHcl(list *ast.ObjectList) ([]*Module, error) { } } + var version string + if o := listVal.Filter("version"); len(o.Items) > 0 { + err = hcl.DecodeObject(&version, o.Items[0].Val) + if err != nil { + return nil, fmt.Errorf( + "Error parsing version for %s: %s", + k, + err) + } + } + + var providers map[string]string + if o := listVal.Filter("providers"); len(o.Items) > 0 { + err = hcl.DecodeObject(&providers, o.Items[0].Val) + if err != nil { + return nil, fmt.Errorf( + "Error parsing providers for %s: %s", + k, + err) + } + } + result = append(result, &Module{ Name: k, Source: source, + Version: version, + Providers: providers, RawConfig: rawConfig, }) } diff --git a/config/loader_hcl2.go b/config/loader_hcl2.go index 9243bfb769..bcc671fdf0 100644 --- a/config/loader_hcl2.go +++ b/config/loader_hcl2.go @@ -75,17 +75,20 @@ func (t *hcl2Configurable) Config() (*Config, error) { Include *[]string `hcl:"include"` Exclude *[]string `hcl:"exclude"` } - type module struct { - Name string `hcl:"name,label"` - Source string `hcl:"source,attr"` - Config hcl2.Body `hcl:",remain"` - } type provider struct { Name string `hcl:"name,label"` Alias *string `hcl:"alias,attr"` Version *string `hcl:"version,attr"` Config hcl2.Body `hcl:",remain"` } + type module struct { + Name string `hcl:"name,label"` + Source string `hcl:"source,attr"` + Version *string `hcl:"version,attr"` + // FIXME, maps not working + // Providers *map[string]string `hcl:"providers,attr"` + Config hcl2.Body `hcl:",remain"` + } type resourceLifecycle struct { CreateBeforeDestroy *bool `hcl:"create_before_destroy,attr"` PreventDestroy *bool `hcl:"prevent_destroy,attr"` @@ -248,6 +251,15 @@ func (t *hcl2Configurable) Config() (*Config, error) { Source: rawM.Source, RawConfig: NewRawConfigHCL2(rawM.Config), } + + if rawM.Version != nil { + m.Version = *rawM.Version + } + + //if rawM.Providers != nil { + // m.Providers = *rawM.Providers + //} + config.Modules = append(config.Modules, m) } diff --git a/config/module/module.go b/config/module/module.go index f8649f6e9d..8d74715c7c 100644 --- a/config/module/module.go +++ b/config/module/module.go @@ -1,7 +1,11 @@ package module +import "github.com/hashicorp/terraform/config" + // Module represents the metadata for a single module. type Module struct { - Name string - Source string + Name string + Source string + Version string + Providers []*config.ProviderConfig } diff --git a/config/module/tree.go b/config/module/tree.go index 262224a04e..444219983a 100644 --- a/config/module/tree.go +++ b/config/module/tree.go @@ -130,8 +130,10 @@ func (t *Tree) Modules() []*Module { result := make([]*Module, len(t.config.Modules)) for i, m := range t.config.Modules { result[i] = &Module{ - Name: m.Name, - Source: m.Source, + Name: m.Name, + Version: m.Version, + Source: m.Source, + Providers: m.Providers, } } @@ -167,10 +169,12 @@ func (t *Tree) Load(s getter.Storage, mode GetMode) error { t.children = nil modules := t.Modules() + children := make(map[string]*Tree) // Go through all the modules and get the directory for them. for _, m := range modules { + if _, ok := children[m.Name]; ok { return fmt.Errorf( "module %s: duplicated. module names must be unique", m.Name) diff --git a/config/test-fixtures/module-providers/main.tf b/config/test-fixtures/module-providers/main.tf new file mode 100644 index 0000000000..301ad89d2e --- /dev/null +++ b/config/test-fixtures/module-providers/main.tf @@ -0,0 +1,7 @@ +module "child" { + source = "./child" + version = "0.1.2" + providers = { + "aws" = "aws.foo" + } +}