diff --git a/apply/apply.go b/apply/apply.go index 2adf2f42b..064e23429 100644 --- a/apply/apply.go +++ b/apply/apply.go @@ -234,10 +234,21 @@ func applyTFE(fs afero.Fs, plan *plan.Plan, tmpl *templates.T) error { } if plan.TFE.ModuleSource != nil { downloader, err := util.MakeDownloader(*plan.TFE.ModuleSource) + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Name: nil, + Prefix: nil, + Source: plan.TFE.ModuleSource, + Variables: []string{}, + }, + downloadFunc: downloader, + }, + } if err != nil { return errs.WrapUser(err, "unable to make a downloader") } - err = applyModuleInvocation(fs, path, *plan.TFE.ModuleSource, plan.TFE.ModuleName, nil, templates.Templates.ModuleInvocation, tmpl.Common, downloader) + err = applyModuleInvocation(fs, path, templates.Templates.ModuleInvocation, tmpl.Common, mi) if err != nil { return errs.WrapUser(err, "unable to apply module invocation") } @@ -366,15 +377,36 @@ func applyEnvs( return errs.WrapUser(err, "unable to apply templates for component") } + mi := make([]moduleInvocation, 0) if componentPlan.ModuleSource != nil { downloader, err := util.MakeDownloader(*componentPlan.ModuleSource) if err != nil { return errs.WrapUser(err, "unable to make a downloader") } - err = applyModuleInvocation(fs, path, *componentPlan.ModuleSource, componentPlan.ModuleName, componentPlan.Variables, templates.Templates.ModuleInvocation, commonBox, downloader) + mi = append(mi, moduleInvocation{ + module: v2.ComponentModule{ + Name: componentPlan.ModuleName, + Source: componentPlan.ModuleSource, + Variables: componentPlan.Variables, + Prefix: nil, + }, + downloadFunc: downloader, + }) + } + + for _, m := range componentPlan.Modules { + downloader, err := util.MakeDownloader(*m.Source) if err != nil { - return errs.WrapUser(err, "unable to apply module invocation") + return errs.WrapUser(err, "unable to make a downloader") } + mi = append(mi, moduleInvocation{ + module: m, + downloadFunc: downloader, + }) + } + err = applyModuleInvocation(fs, path, templates.Templates.ModuleInvocation, commonBox, mi) + if err != nil { + return errs.WrapUser(err, "unable to apply module invocation") } } } @@ -537,60 +569,84 @@ func applyTemplate(sourceFile io.Reader, commonTemplates fs.FS, dest afero.Fs, p type moduleData struct { ModuleName string ModuleSource string + ModulePrefix string Variables []string Outputs []string } +type modulesData struct { + Modules []*moduleData +} + +type moduleInvocation struct { + module v2.ComponentModule + downloadFunc util.ModuleDownloader +} + func applyModuleInvocation( fs afero.Fs, - path, moduleAddress string, - inModuleName *string, - variables []string, + path string, box fs.FS, commonBox fs.FS, - downloadFunc util.ModuleDownloader, + moduleInvocations []moduleInvocation, ) error { e := fs.MkdirAll(path, 0755) if e != nil { return errs.WrapUserf(e, "couldn't create %s directory", path) } + arr := make([]*moduleData, 0) + // TODO: parallel downloads with go routines + for _, mi := range moduleInvocations { + moduleConfig, e := mi.downloadFunc.DownloadAndParseModule(fs) + if e != nil { + return errs.WrapUser(e, "could not download or parse module") + } - moduleConfig, e := downloadFunc.DownloadAndParseModule(fs) - if e != nil { - return errs.WrapUser(e, "could not download or parse module") - } - - // This should really be part of the plan stage, not apply. But going to - // leave it here for now and re-think it when we make this mechanism - // general purpose. - addAll := variables == nil - for _, v := range moduleConfig.Variables { - if addAll { - variables = append(variables, v.Name) - } else { - if v.Required && !slices.Contains(variables, v.Name) { + // This should really be part of the plan stage, not apply. But going to + // leave it here for now and re-think it when we make this mechanism + // general purpose. + variables := mi.module.Variables + addAll := variables == nil + for _, v := range moduleConfig.Variables { + if addAll { variables = append(variables, v.Name) + } else { + if v.Required && !slices.Contains(variables, v.Name) { + variables = append(variables, v.Name) + } } } - } - sort.Strings(variables) - outputs := make([]string, 0) - for _, o := range moduleConfig.Outputs { - outputs = append(outputs, o.Name) - } - sort.Strings(outputs) + sort.Strings(variables) + outputs := make([]string, 0) + for _, o := range moduleConfig.Outputs { + outputs = append(outputs, o.Name) + } + sort.Strings(outputs) - moduleName := "" - if inModuleName != nil { - moduleName = *inModuleName - } - if moduleName == "" { - moduleName = filepath.Base(moduleAddress) - re := regexp.MustCompile(`\?ref=.*`) - moduleName = re.ReplaceAllString(moduleName, "") + moduleName := "" + if mi.module.Name != nil { + moduleName = *mi.module.Name + } + if moduleName == "" { + moduleName = filepath.Base(*mi.module.Source) + re := regexp.MustCompile(`\?ref=.*`) + moduleName = re.ReplaceAllString(moduleName, "") + } + + modulePrefix := "" + if mi.module.Prefix != nil { + modulePrefix = *mi.module.Prefix + "_" + } + moduleAddressForSource, _ := calculateModuleAddressForSource(path, *mi.module.Source) + arr = append(arr, &moduleData{ + moduleName, + moduleAddressForSource, + modulePrefix, + variables, + outputs, + }) } - moduleAddressForSource, _ := calculateModuleAddressForSource(path, moduleAddress) // MAIN f, e := box.Open("main.tf.tmpl") if e != nil { @@ -601,7 +657,7 @@ func applyModuleInvocation( commonBox, fs, filepath.Join(path, "main.tf"), - &moduleData{moduleName, moduleAddressForSource, variables, outputs}) + &modulesData{arr}) if e != nil { return errs.WrapUser(e, "unable to apply template for main.tf") } @@ -616,7 +672,7 @@ func applyModuleInvocation( return errs.WrapUser(e, "could not open template file") } - e = applyTemplate(f, commonBox, fs, filepath.Join(path, "outputs.tf"), &moduleData{moduleName, moduleAddressForSource, variables, outputs}) + e = applyTemplate(f, commonBox, fs, filepath.Join(path, "outputs.tf"), &modulesData{arr}) if e != nil { return errs.WrapUser(e, "unable to apply template for outputs.tf") } diff --git a/apply/apply_test.go b/apply/apply_test.go index 415ba9688..1bc10da97 100644 --- a/apply/apply_test.go +++ b/apply/apply_test.go @@ -404,10 +404,20 @@ func TestApplyModuleInvocation(t *testing.T) { pwdFs, err := util.PwdFs() r.NoError(err) + moduleSource := "test-module" fs := afero.NewCopyOnWriteFs(pwdFs, testFs) downloader, err := util.MakeDownloader("test-module") r.NoError(err) - e := applyModuleInvocation(fs, "mymodule", "test-module", nil, nil, templates.Templates.ModuleInvocation, templates.Templates.Common, downloader) + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Source: &moduleSource, + Variables: nil, + }, + downloadFunc: downloader, + }, + } + e := applyModuleInvocation(fs, "mymodule", templates.Templates.ModuleInvocation, templates.Templates.Common, mi) r.NoError(e) s, e := fs.Stat("mymodule") @@ -418,14 +428,14 @@ func TestApplyModuleInvocation(t *testing.T) { r.Nil(e) i, e := afero.ReadFile(fs, "mymodule/main.tf") r.Nil(e) - expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n quux = local.quux\n\n}\n" + expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n quux = local.quux\n}\n" r.Equal(expected, string(i)) _, e = fs.Stat("mymodule/outputs.tf") r.Nil(e) i, e = afero.ReadFile(fs, "mymodule/outputs.tf") r.Nil(e) - expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\noutput \"bar\" {\n value = module.test-module.bar\n}\n\noutput \"foo\" {\n value = module.test-module.foo\n}\n\n\n" + expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\n// module \"test-module\" outputs\noutput \"bar\" {\n value = module.test-module.bar\n}\noutput \"foo\" {\n value = module.test-module.foo\n}\n" r.Equal(expected, string(i)) } @@ -437,10 +447,20 @@ func TestApplyModuleInvocationWithEmptyVariables(t *testing.T) { pwdFs, err := util.PwdFs() r.NoError(err) + moduleSource := "test-module" fs := afero.NewCopyOnWriteFs(pwdFs, testFs) - downloader, err := util.MakeDownloader("test-module") + downloader, err := util.MakeDownloader(moduleSource) r.NoError(err) - e := applyModuleInvocation(fs, "mymodule", "test-module", nil, []string{}, templates.Templates.ModuleInvocation, templates.Templates.Common, downloader) + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Source: &moduleSource, + Variables: []string{}, + }, + downloadFunc: downloader, + }, + } + e := applyModuleInvocation(fs, "mymodule", templates.Templates.ModuleInvocation, templates.Templates.Common, mi) r.NoError(e) s, e := fs.Stat("mymodule") @@ -451,14 +471,14 @@ func TestApplyModuleInvocationWithEmptyVariables(t *testing.T) { r.Nil(e) i, e := afero.ReadFile(fs, "mymodule/main.tf") r.Nil(e) - expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n foo = local.foo\n\n}\n" + expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n foo = local.foo\n}\n" r.Equal(expected, string(i)) _, e = fs.Stat("mymodule/outputs.tf") r.Nil(e) i, e = afero.ReadFile(fs, "mymodule/outputs.tf") r.Nil(e) - expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\noutput \"bar\" {\n value = module.test-module.bar\n}\n\noutput \"foo\" {\n value = module.test-module.foo\n}\n\n\n" + expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\n// module \"test-module\" outputs\noutput \"bar\" {\n value = module.test-module.bar\n}\noutput \"foo\" {\n value = module.test-module.foo\n}\n" r.Equal(expected, string(i)) } @@ -473,7 +493,17 @@ func TestApplyModuleInvocationWithOneDefaultVariable(t *testing.T) { fs := afero.NewCopyOnWriteFs(pwdFs, testFs) downloader, err := util.MakeDownloader("test-module") r.NoError(err) - e := applyModuleInvocation(fs, "mymodule", "test-module", nil, []string{"baz"}, templates.Templates.ModuleInvocation, templates.Templates.Common, downloader) + moduleName := "test-module" + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Source: &moduleName, + Variables: []string{"baz"}, + }, + downloadFunc: downloader, + }, + } + e := applyModuleInvocation(fs, "mymodule", templates.Templates.ModuleInvocation, templates.Templates.Common, mi) r.NoError(e) s, e := fs.Stat("mymodule") @@ -484,14 +514,14 @@ func TestApplyModuleInvocationWithOneDefaultVariable(t *testing.T) { r.Nil(e) i, e := afero.ReadFile(fs, "mymodule/main.tf") r.Nil(e) - expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n\n}\n" + expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"test-module\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n}\n" r.Equal(expected, string(i)) _, e = fs.Stat("mymodule/outputs.tf") r.Nil(e) i, e = afero.ReadFile(fs, "mymodule/outputs.tf") r.Nil(e) - expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\noutput \"bar\" {\n value = module.test-module.bar\n}\n\noutput \"foo\" {\n value = module.test-module.foo\n}\n\n\n" + expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\n// module \"test-module\" outputs\noutput \"bar\" {\n value = module.test-module.bar\n}\noutput \"foo\" {\n value = module.test-module.foo\n}\n" r.Equal(expected, string(i)) } @@ -505,10 +535,69 @@ func TestApplyModuleInvocationWithModuleName(t *testing.T) { fs := afero.NewCopyOnWriteFs(pwdFs, testFs) - moduleName := "module-name" + moduleSource := "test-module" + downloader, err := util.MakeDownloader(moduleSource) + r.NoError(err) + moduleName := "module_name" + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Name: &moduleName, + Source: &moduleSource, + Variables: nil, + }, + downloadFunc: downloader, + }, + } + e := applyModuleInvocation(fs, "mymodule", templates.Templates.ModuleInvocation, templates.Templates.Common, mi) + r.NoError(e) + + s, e := fs.Stat("mymodule") + r.Nil(e) + r.True(s.IsDir()) + + _, e = fs.Stat("mymodule/main.tf") + r.Nil(e) + i, e := afero.ReadFile(fs, "mymodule/main.tf") + r.Nil(e) + expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"module_name\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n quux = local.quux\n}\n" + r.Equal(expected, string(i)) + + _, e = fs.Stat("mymodule/outputs.tf") + r.Nil(e) + i, e = afero.ReadFile(fs, "mymodule/outputs.tf") + r.Nil(e) + expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\n// module \"module_name\" outputs\noutput \"bar\" {\n value = module.module_name.bar\n}\noutput \"foo\" {\n value = module.module_name.foo\n}\n" + r.Equal(expected, string(i)) +} + +func TestApplyModuleInvocationWithModulePrefix(t *testing.T) { + r := require.New(t) + testFs, d, err := util.TestFs() + r.NoError(err) + defer os.RemoveAll(d) + pwdFs, err := util.PwdFs() + r.NoError(err) + + fs := afero.NewCopyOnWriteFs(pwdFs, testFs) + downloader, err := util.MakeDownloader("test-module") r.NoError(err) - e := applyModuleInvocation(fs, "mymodule", "test-module", &moduleName, nil, templates.Templates.ModuleInvocation, templates.Templates.Common, downloader) + moduleName := "module_name" + modulePrefix := "prefix" + moduleSource := "test-module" + mi := []moduleInvocation{ + { + module: v2.ComponentModule{ + Name: &moduleName, + Prefix: &modulePrefix, + Source: &moduleSource, + Variables: []string{}, + }, + downloadFunc: downloader, + }, + } + e := applyModuleInvocation(fs, "mymodule", templates.Templates.ModuleInvocation, templates.Templates.Common, mi) r.NoError(e) s, e := fs.Stat("mymodule") @@ -519,14 +608,14 @@ func TestApplyModuleInvocationWithModuleName(t *testing.T) { r.Nil(e) i, e := afero.ReadFile(fs, "mymodule/main.tf") r.Nil(e) - expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"module-name\" {\n source = \"../test-module\"\n bar = local.bar\n baz = local.baz\n foo = local.foo\n quux = local.quux\n\n}\n" + expected := "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\nmodule \"module_name\" {\n source = \"../test-module\"\n bar = local.prefix_bar\n foo = local.prefix_foo\n}\n" r.Equal(expected, string(i)) _, e = fs.Stat("mymodule/outputs.tf") r.Nil(e) i, e = afero.ReadFile(fs, "mymodule/outputs.tf") r.Nil(e) - expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\noutput \"bar\" {\n value = module.module-name.bar\n}\n\noutput \"foo\" {\n value = module.module-name.foo\n}\n\n\n" + expected = "# Auto-generated by fogg. Do not edit\n# Make improvements in fogg, so that everyone can benefit.\n\n// module \"prefix_module_name\" outputs\noutput \"prefix_bar\" {\n value = module.module_name.bar\n}\noutput \"prefix_foo\" {\n value = module.module_name.foo\n}\n" r.Equal(expected, string(i)) } diff --git a/cmd/exp_examine.go b/cmd/exp_examine.go index c4df242fb..5cbde1fc2 100644 --- a/cmd/exp_examine.go +++ b/cmd/exp_examine.go @@ -13,7 +13,7 @@ func init() { expCmd.AddCommand(examineCmd) } -//TODO:(EC) Create a flag for path to walk +// TODO:(EC) Create a flag for path to walk var examineCmd = &cobra.Command{ Use: "examine", Short: "Detects terraform module updates", diff --git a/config/config.go b/config/config.go index e2bb00aba..e06823e49 100644 --- a/config/config.go +++ b/config/config.go @@ -15,10 +15,10 @@ import ( var defaultTerraformVersion = goVersion.Must(goVersion.NewVersion("0.13.5")) -//DefaultFoggVersion is the version that fogg will generate by default +// DefaultFoggVersion is the version that fogg will generate by default const DefaultFoggVersion = 2 -//InitConfig initializes the config file using user input +// InitConfig initializes the config file using user input func InitConfig(project, region, bucket, table, awsProfile, owner *string, awsProviderVersion string) *v2.Config { return &v2.Config{ Defaults: v2.Defaults{ @@ -69,7 +69,7 @@ func FindConfig(fs afero.Fs, configFile string) ([]byte, int, error) { return b, v, nil } -//FindAndReadConfig locates config file and reads it based on the version +// FindAndReadConfig locates config file and reads it based on the version func FindAndReadConfig(fs afero.Fs, configFile string) (*v2.Config, error) { b, v, err := FindConfig(fs, configFile) if err != nil { diff --git a/config/v2/config.go b/config/v2/config.go index 22e479a08..b3d2fdd97 100644 --- a/config/v2/config.go +++ b/config/v2/config.go @@ -57,7 +57,7 @@ type Config struct { Defaults Defaults `yaml:"defaults" validate:"required"` Envs map[string]Env `yaml:"envs,omitempty"` Global Component `yaml:"global,omitempty"` - Modules map[string]Module `yaml:"modules,omitempty"` + Modules map[string]Module `yaml:"modules,omitempty"` // BUG: order is important Plugins Plugins `yaml:"plugins,omitempty"` Version int `validate:"required,eq=2"` TFE *TFE `yaml:"tfe,omitempty"` @@ -122,11 +122,23 @@ type Env struct { type Component struct { Common `yaml:",inline"` - EKS *EKSConfig `yaml:"eks,omitempty"` - Kind *ComponentKind `yaml:"kind,omitempty"` - ModuleSource *string `yaml:"module_source,omitempty"` - ModuleName *string `yaml:"module_name,omitempty"` - Variables []string `yaml:"variables,omitempty"` + EKS *EKSConfig `yaml:"eks,omitempty"` + Kind *ComponentKind `yaml:"kind,omitempty"` + ModuleSource *string `yaml:"module_source,omitempty"` + ModuleName *string `yaml:"module_name,omitempty"` + Variables []string `yaml:"variables,omitempty"` + Modules []ComponentModule `yaml:"modules,omitempty"` +} + +type ComponentModule struct { + // Source for Terraform module as supported by Terraform + Source *string `yaml:"source,omitempty"` + // Name for generated module block, defaults to Source stripped from special characters + Name *string `yaml:"name,omitempty"` + // Prefix for all generated input and output placeholder to handle overlapping references + Prefix *string `yaml:"prefix,omitempty"` + // Variables to limit generated input placeholders (and use module defaults for others) + Variables []string `yaml:"variables,omitempty"` } type Providers struct { diff --git a/exp/examine/examine.go b/exp/examine/examine.go index 9bb9c8a33..4ed374f29 100644 --- a/exp/examine/examine.go +++ b/exp/examine/examine.go @@ -4,8 +4,8 @@ import ( "github.com/spf13/afero" ) -//Examine loads local modules and compares them to their latest version to see differences -//TODO: Comparison between local and latest +// Examine loads local modules and compares them to their latest version to see differences +// TODO: Comparison between local and latest func Examine(fs afero.Fs, path string) error { //Collect local modules to be updated module, err := GetLocalModules(fs, path) diff --git a/exp/examine/latest.go b/exp/examine/latest.go index fa1cf2bde..ef79fe5de 100644 --- a/exp/examine/latest.go +++ b/exp/examine/latest.go @@ -10,7 +10,7 @@ import ( "github.com/spf13/afero" ) -//LatestModuleVersions retrieves the latest version of the provided modules +// LatestModuleVersions retrieves the latest version of the provided modules func LatestModuleVersions(fs afero.Fs, module *tfconfig.Module) ([]ModuleWrapper, error) { var latestModules []ModuleWrapper var moduleWrapper ModuleWrapper @@ -38,7 +38,7 @@ func LatestModuleVersions(fs afero.Fs, module *tfconfig.Module) ([]ModuleWrapper return latestModules, nil } -//createGitURL retrieves the latest release version and creates an HTTP accessible link +// createGitURL retrieves the latest release version and creates an HTTP accessible link func createGitURL(moduleCall *tfconfig.ModuleCall) (string, error) { splitString := strings.Split(moduleCall.Source, "/") owner, repo := splitString[1], splitString[2] diff --git a/exp/examine/local.go b/exp/examine/local.go index cbbf9b1a7..83847a84e 100644 --- a/exp/examine/local.go +++ b/exp/examine/local.go @@ -10,8 +10,8 @@ import ( //**Local refers to any files located within your local file system** -//GetLocalModules retrieves all terraform modules within a given directory -//TODO:(EC) Define local and global modules OR rename the values +// GetLocalModules retrieves all terraform modules within a given directory +// TODO:(EC) Define local and global modules OR rename the values func GetLocalModules(fs afero.Fs, dir string) (*tfconfig.Module, error) { _, err := os.Stat(dir) if err != nil { diff --git a/exp/examine/local_test.go b/exp/examine/local_test.go index 8f2bff353..c6e7829cc 100644 --- a/exp/examine/local_test.go +++ b/exp/examine/local_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" ) -//TODO: Move fs to versioning.go +// TODO: Move fs to versioning.go func TestGetLocalModules(t *testing.T) { r := require.New(t) pwd, err := os.Getwd() diff --git a/exp/examine/util.go b/exp/examine/util.go index 4442ba2e3..5ed4763e4 100644 --- a/exp/examine/util.go +++ b/exp/examine/util.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/afero" ) -//TODO:(EC) Add a RegistryModule field +// TODO:(EC) Add a RegistryModule field type ModuleWrapper struct { moduleSource string version string @@ -62,7 +62,7 @@ type Submodule struct { const githubURL = "github.com" const tagPattern = "ref=" -//GetFromGithub Retrieves modules that are available through github +// GetFromGithub Retrieves modules that are available through github func GetFromGithub(fs afero.Fs, repo string) (*tfconfig.Module, error) { //FIXME: (EC) Create temporary directory, when tests fail directory stays //TODO: Make directory name more general diff --git a/init/init.go b/init/init.go index 2f7e95365..a6b1219d2 100644 --- a/init/init.go +++ b/init/init.go @@ -11,7 +11,7 @@ type FoggProject struct { Project, Region, Bucket, Table, Profile, Owner *string } -//Init reads user console input and generates a fogg.yml file +// Init reads user console input and generates a fogg.yml file func Init(fs afero.Fs, foggProject *FoggProject) error { config := config.InitConfig( foggProject.Project, diff --git a/migrations/migrations.go b/migrations/migrations.go index 76c1bd2d0..24420e368 100644 --- a/migrations/migrations.go +++ b/migrations/migrations.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/afero" ) -//Migration Defines a fogg migration and the actions that it can perform +// Migration Defines a fogg migration and the actions that it can perform type Migration interface { Description() string //Describes the migration taking Guard(afero.Fs, string) (bool, error) //Returns true if migration is runnable, otherwise error @@ -13,7 +13,7 @@ type Migration interface { Prompt() bool //Returns whether the user would like to run the migration } -//RunMigrations cycles through a list of migrations and applies them if necessary +// RunMigrations cycles through a list of migrations and applies them if necessary func RunMigrations(fs afero.Fs, configFile string, forceApply bool) error { migrations := []Migration{} diff --git a/plan/plan.go b/plan/plan.go index 098208b0a..0edb4bde4 100644 --- a/plan/plan.go +++ b/plan/plan.go @@ -319,12 +319,13 @@ type Account struct { type Component struct { ComponentCommon `yaml:",inline"` - EKS *v2.EKSConfig `yaml:"eks,omitempty"` - Kind *v2.ComponentKind `yaml:"kind,omitempty"` - ModuleSource *string `yaml:"module_source"` - ModuleName *string `yaml:"module_name"` - Variables []string `yaml:"variables"` - Global *Component `yaml:"global"` + EKS *v2.EKSConfig `yaml:"eks,omitempty"` + Kind *v2.ComponentKind `yaml:"kind,omitempty"` + ModuleSource *string `yaml:"module_source"` + ModuleName *string `yaml:"module_name"` + Variables []string `yaml:"variables"` + Modules []v2.ComponentModule `yaml:"modules"` + Global *Component `yaml:"global"` } // Env is an env @@ -603,6 +604,7 @@ func (p *Plan) buildEnvs(conf *v2.Config) (map[string]Env, error) { componentPlan.ModuleSource = componentConf.ModuleSource componentPlan.ModuleName = componentConf.ModuleName componentPlan.Variables = componentConf.Variables + componentPlan.Modules = componentConf.Modules componentPlan.PathToRepoRoot = "../../../../" componentPlan.Global = &p.Global diff --git a/templates/templates/module-invocation/main.tf.tmpl b/templates/templates/module-invocation/main.tf.tmpl index 1da0ecf6f..87c1b415d 100644 --- a/templates/templates/module-invocation/main.tf.tmpl +++ b/templates/templates/module-invocation/main.tf.tmpl @@ -1,9 +1,11 @@ # Auto-generated by fogg. Do not edit # Make improvements in fogg, so that everyone can benefit. - +{{ range .Modules }} module "{{.ModuleName}}" { source = "{{.ModuleSource}}" + {{ $outer := . -}} {{range .Variables -}} - {{.}} = local.{{.}} - {{ end}} + {{.}} = local.{{$outer.ModulePrefix}}{{.}} + {{ end -}} } +{{ end }} \ No newline at end of file diff --git a/templates/templates/module-invocation/outputs.tf.tmpl b/templates/templates/module-invocation/outputs.tf.tmpl index d7262f3c0..ca29d079a 100644 --- a/templates/templates/module-invocation/outputs.tf.tmpl +++ b/templates/templates/module-invocation/outputs.tf.tmpl @@ -1,10 +1,12 @@ # Auto-generated by fogg. Do not edit # Make improvements in fogg, so that everyone can benefit. +{{ range .Modules -}} +// module "{{.ModulePrefix}}{{.ModuleName}}" outputs {{ $outer := . -}} {{- range .Outputs -}} -output "{{.}}" { +output "{{$outer.ModulePrefix}}{{.}}" { value = module.{{$outer.ModuleName}}.{{.}} } - -{{end}} +{{end }} +{{- end }} \ No newline at end of file