Repository: chanzuckerberg/fogg
Pull request #484 (2020-06-09 07:54:45)

[feature] Allow overriding name of module when using module_source
### Summary
When using module_source in a component, allow providing the name of the module that is autogenerated by fogg, by providing a "module_name" field. This is useful if you want to use a different module name than the name matching the subdirectory. This can be desired when you have similar modules with different names but mostly compatible contents, and you don't want to force a user to do state mv migrations between the modules.

If module_name is not provided or is empty string, falls back to current default behavior of using the last directory in the module's subdirectory path as the module name

### Test Plan
Unit tests added

codecov-commenter: # [Codecov](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=h1) Report
> Merging [#484](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=desc) into [master](https://codecov.io/gh/chanzuckerberg/fogg/commit/3821ea4801d6ba82bffa43e2f39201f2499f4b8e&el=desc) will **increase** coverage by `0.10%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/chanzuckerberg/fogg/pull/484/graphs/tree.svg?width=650&height=150&src=pr&token=57DhtZ7g2A)](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #484      +/-   ##
==========================================
+ Coverage   59.08%   59.18%   +0.10%     
==========================================
  Files          19       19              
  Lines        1982     1987       +5     
==========================================
+ Hits         1171     1176       +5     
  Misses        653      653              
  Partials      158      158              
```


| [Impacted Files](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [config/v2/config.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/484/diff?src=pr&el=tree#diff-Y29uZmlnL3YyL2NvbmZpZy5nbw==) | `8.60% <ø> (ø)` | |
| [apply/apply.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/484/diff?src=pr&el=tree#diff-YXBwbHkvYXBwbHkuZ28=) | `64.53% <100.00%> (+0.51%)` | :arrow_up: |
| [plan/plan.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/484/diff?src=pr&el=tree#diff-cGxhbi9wbGFuLmdv) | `84.24% <100.00%> (+0.05%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=footer). Last update [3821ea4...323d6d6](https://codecov.io/gh/chanzuckerberg/fogg/pull/484?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/apply/apply.go b/apply/apply.go
index d2070424..ccb2f8c8 100644
--- a/apply/apply.go
+++ b/apply/apply.go
@@ -190,7 +190,7 @@ func applyEnvs(fs afero.Fs, p *plan.Plan, envBox *packr.Box, componentBoxes map[
 			}
 
 			if componentPlan.ModuleSource != nil {
-				e := applyModuleInvocation(fs, path, *componentPlan.ModuleSource, templates.Templates.ModuleInvocation, commonBox)
+				e := applyModuleInvocation(fs, path, *componentPlan.ModuleSource, componentPlan.ModuleName, templates.Templates.ModuleInvocation, commonBox)
 				if e != nil {
 					return errs.WrapUser(e, "unable to apply module invocation")
 				}
@@ -352,7 +352,7 @@ type moduleData struct {
 	Outputs      []string
 }
 
-func applyModuleInvocation(fs afero.Fs, path, moduleAddress string, box packr.Box, commonBox *packr.Box) error {
+func applyModuleInvocation(fs afero.Fs, path, moduleAddress string, inModuleName *string, box packr.Box, commonBox *packr.Box) error {
 	e := fs.MkdirAll(path, 0755)
 	if e != nil {
 		return errs.WrapUserf(e, "couldn't create %s directory", path)
@@ -376,9 +376,16 @@ func applyModuleInvocation(fs afero.Fs, path, moduleAddress string, box packr.Bo
 		outputs = append(outputs, o.Name)
 	}
 	sort.Strings(outputs)
-	moduleName := filepath.Base(moduleAddress)
-	re := regexp.MustCompile(`\?ref=.*`)
-	moduleName = re.ReplaceAllString(moduleName, "")
+
+	moduleName := ""
+	if inModuleName != nil {
+		moduleName = *inModuleName
+	}
+	if moduleName == "" {
+		moduleName = filepath.Base(moduleAddress)
+		re := regexp.MustCompile(`\?ref=.*`)
+		moduleName = re.ReplaceAllString(moduleName, "")
+	}
 
 	moduleAddressForSource, _ := calculateModuleAddressForSource(path, moduleAddress)
 	// MAIN
diff --git a/config/v2/config.go b/config/v2/config.go
index 60152296..13ac14af 100644
--- a/config/v2/config.go
+++ b/config/v2/config.go
@@ -97,6 +97,7 @@ type Component struct {
 	EKS          *EKSConfig     `yaml:"eks,omitempty"`
 	Kind         *ComponentKind `yaml:"kind,omitempty"`
 	ModuleSource *string        `yaml:"module_source,omitempty"`
+	ModuleName   *string        `yaml:"module_name,omitempty"`
 }
 
 type Providers struct {
diff --git a/go.mod b/go.mod
index 44a3adff..a5db777b 100644
--- a/go.mod
+++ b/go.mod
@@ -61,7 +61,7 @@ require (
 	github.com/zclconf/go-cty v1.4.0 // indirect
 	golang.org/x/crypto v0.0.0-20200422194213-44a606286825 // indirect
 	golang.org/x/net v0.0.0-20200421231249-e086a090c8fd // indirect
-	golang.org/x/tools v0.0.0-20200422170737-3d37a6779637 // indirect
+	golang.org/x/tools v0.0.0-20200609060408-6eec81c74686 // indirect
 	google.golang.org/api v0.22.0 // indirect
 	google.golang.org/appengine v1.6.6 // indirect
 	google.golang.org/genproto v0.0.0-20200420144010-e5e8543f8aeb // indirect
diff --git a/go.sum b/go.sum
index 4aa29664..4cf24c9a 100644
--- a/go.sum
+++ b/go.sum
@@ -843,8 +843,8 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
 golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200422170737-3d37a6779637 h1:CrcVdHw7UBbAsehywW8kKwdmIZ6F2ksYzRaU7Y/oVg0=
-golang.org/x/tools v0.0.0-20200422170737-3d37a6779637/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200609060408-6eec81c74686 h1:46pmlxpNgDeSXRJPAJt7cIdrKrLjIUObw2iIhhHan1U=
+golang.org/x/tools v0.0.0-20200609060408-6eec81c74686/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
diff --git a/plan/plan.go b/plan/plan.go
index 762029ac..95353b75 100644
--- a/plan/plan.go
+++ b/plan/plan.go
@@ -239,6 +239,7 @@ type Component struct {
 
 	Kind              *v2.ComponentKind  `yaml:"kind,omitempty"`
 	ModuleSource      *string            `yaml:"module_source"`
+	ModuleName        *string            `yaml:"module_name"`
 	ComponentBackends map[string]Backend `yaml:"component_backends"`
 	Global            *Component         `yaml:"global"`
 }
@@ -409,6 +410,7 @@ func (p *Plan) buildEnvs(conf *v2.Config) (map[string]Env, error) {
 			componentPlan.Env = envName
 			componentPlan.Component = componentName
 			componentPlan.ModuleSource = componentConf.ModuleSource
+			componentPlan.ModuleName = componentConf.ModuleName
 			componentPlan.PathToRepoRoot = "../../../../"
 
 			componentPlan.Global = &p.Global


Test patch:
diff --git a/apply/apply_test.go b/apply/apply_test.go
index 4d2cfd10..87fc868b 100644
--- a/apply/apply_test.go
+++ b/apply/apply_test.go
@@ -258,7 +258,7 @@ func TestApplyModuleInvocation(t *testing.T) {
 
 	fs := afero.NewCopyOnWriteFs(pwdFs, testFs)
 
-	e := applyModuleInvocation(fs, "mymodule", "test-module", templates.Templates.ModuleInvocation, &templates.Templates.Common)
+	e := applyModuleInvocation(fs, "mymodule", "test-module", nil, templates.Templates.ModuleInvocation, &templates.Templates.Common)
 	r.NoError(e)
 
 	s, e := fs.Stat("mymodule")
@@ -279,6 +279,40 @@ func TestApplyModuleInvocation(t *testing.T) {
 	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"
 	r.Equal(expected, string(i))
 }
+
+func TestApplyModuleInvocationWithModuleName(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)
+
+	moduleName := "module-name"
+	e := applyModuleInvocation(fs, "mymodule", "test-module", &moduleName, templates.Templates.ModuleInvocation, &templates.Templates.Common)
+	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  foo    = local.foo\n\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"
+	r.Equal(expected, string(i))
+}
+
 func TestGetTargetPath(t *testing.T) {
 	data := []struct {
 		base   string
diff --git a/plan/plan_test.go b/plan/plan_test.go
index 78124f5e..405526c0 100644
--- a/plan/plan_test.go
+++ b/plan/plan_test.go
@@ -91,6 +91,7 @@ func TestPlanBasicV2Yaml(t *testing.T) {
 	logrus.Debugf("%#v\n", plan.Envs["staging"].Components["vpc"].ModuleSource)
 	r.NotNil(*plan.Envs["staging"].Components["vpc"].ModuleSource)
 	r.Equal("github.com/terraform-aws-modules/terraform-aws-vpc?ref=v1.30.0", *plan.Envs["staging"].Components["vpc"].ModuleSource)
+	r.Nil(plan.Envs["staging"].Components["vpc"].ModuleName)
 
 	r.NotNil(plan.Envs["staging"].Components["comp1"])
 	r.Equal("0.100.0", plan.Envs["staging"].Components["comp1"].TerraformVersion)
@@ -108,6 +109,12 @@ func TestPlanBasicV2Yaml(t *testing.T) {
 	r.NotNil(plan.Envs["prod"].Components["datadog"].Providers)
 	r.NotNil(plan.Envs["prod"].Components["datadog"].Providers.Datadog)
 
+	r.NotNil(plan.Envs["prod"])
+	r.NotNil(plan.Envs["prod"].Components["vpc"])
+	r.NotNil(*plan.Envs["prod"].Components["vpc"].ModuleSource)
+	r.Equal("github.com/terraform-aws-modules/terraform-aws-vpc?ref=v1.30.0", *plan.Envs["staging"].Components["vpc"].ModuleSource)
+	r.Equal(*plan.Envs["prod"].Components["vpc"].ModuleName, "prod-vpc")
+
 	// accts inherit defaults
 	r.Equal("bar1", plan.Accounts["foo"].ExtraVars["foo"])
 	// envs overwrite defaults
diff --git a/testdata/v2_full_yaml/fogg.yml b/testdata/v2_full_yaml/fogg.yml
index 5c2d3298..76a61171 100644
--- a/testdata/v2_full_yaml/fogg.yml
+++ b/testdata/v2_full_yaml/fogg.yml
@@ -37,6 +37,9 @@ envs:
       datadog:
         providers:
           datadog: {}
+      vpc:
+        module_source: github.com/terraform-aws-modules/terraform-aws-vpc?ref=v1.30.0
+        module_name: prod-vpc
   staging:
     components:
       comp_helm_template:
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/Makefile b/testdata/v2_full_yaml/terraform/envs/prod/Makefile
index a9c838c2..b2a576c1 100644
--- a/testdata/v2_full_yaml/terraform/envs/prod/Makefile
+++ b/testdata/v2_full_yaml/terraform/envs/prod/Makefile
@@ -1,7 +1,7 @@
 # Auto-generated by fogg. Do not edit
 # Make improvements in fogg, so that everyone can benefit.
 
-COMPONENTS=datadog hero
+COMPONENTS=datadog hero vpc
 
 all:
 .PHONY: all
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/datadog/fogg.tf b/testdata/v2_full_yaml/terraform/envs/prod/datadog/fogg.tf
index 35ea7002..968e08e8 100644
--- a/testdata/v2_full_yaml/terraform/envs/prod/datadog/fogg.tf
+++ b/testdata/v2_full_yaml/terraform/envs/prod/datadog/fogg.tf
@@ -92,6 +92,20 @@ data terraform_remote_state hero {
     profile = "profile"
 
 
+  }
+}
+data terraform_remote_state vpc {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/envs/prod/components/vpc.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
   }
 }
 # remote state for accounts
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/hero/fogg.tf b/testdata/v2_full_yaml/terraform/envs/prod/hero/fogg.tf
index 90d5691b..62e4684d 100644
--- a/testdata/v2_full_yaml/terraform/envs/prod/hero/fogg.tf
+++ b/testdata/v2_full_yaml/terraform/envs/prod/hero/fogg.tf
@@ -92,6 +92,20 @@ data terraform_remote_state datadog {
     profile = "profile"
 
 
+  }
+}
+data terraform_remote_state vpc {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/envs/prod/components/vpc.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
   }
 }
 # remote state for accounts
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/Makefile b/testdata/v2_full_yaml/terraform/envs/prod/vpc/Makefile
new file mode 100644
index 00000000..40858100
--- /dev/null
+++ b/testdata/v2_full_yaml/terraform/envs/prod/vpc/Makefile
@@ -0,0 +1,21 @@
+# Auto-generated by fogg. Do not edit
+# Make improvements in fogg, so that everyone can benefit.
+
+
+export TERRAFORM_VERSION := 0.100.0
+export TFLINT_ENABLED := 0
+export TF_PLUGIN_CACHE_DIR := ../../../..//.terraform.d/plugin-cache
+export TF_BACKEND_KIND := s3
+export AWS_BACKEND_PROFILE := profile
+
+export AWS_PROVIDER_PROFILE := profile
+
+
+
+include ../../../..//scripts/component.mk
+
+
+help: ## display help for this makefile
+	@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
+.PHONY: help
+
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/README.md b/testdata/v2_full_yaml/terraform/envs/prod/vpc/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/fogg.tf b/testdata/v2_full_yaml/terraform/envs/prod/vpc/fogg.tf
new file mode 100644
index 00000000..8b256955
--- /dev/null
+++ b/testdata/v2_full_yaml/terraform/envs/prod/vpc/fogg.tf
@@ -0,0 +1,169 @@
+# Auto-generated by fogg. Do not edit
+# Make improvements in fogg, so that everyone can benefit.
+provider aws {
+
+  version = "~> 0.12.0"
+  region  = "us-west-2"
+  profile = "profile"
+
+  allowed_account_ids = [456]
+}
+# Aliased Providers (for doing things in every region).
+
+terraform {
+  required_version = "~>0.100.0"
+
+  backend s3 {
+
+    bucket = "buck"
+
+    key     = "terraform/proj/envs/prod/components/vpc.tfstate"
+    encrypt = true
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+variable env {
+  type    = string
+  default = "prod"
+}
+variable project {
+  type    = string
+  default = "proj"
+}
+variable region {
+  type    = string
+  default = "us-west-2"
+}
+variable component {
+  type    = string
+  default = "vpc"
+}
+variable aws_profile {
+  type    = string
+  default = "profile"
+}
+variable owner {
+  type    = string
+  default = "foo@example.com"
+}
+variable tags {
+  type = map(string)
+  default = {
+    project   = "proj"
+    env       = "prod"
+    service   = "vpc"
+    owner     = "foo@example.com"
+    managedBy = "terraform"
+  }
+}
+variable foo {
+  type    = string
+  default = "bar1"
+}
+data terraform_remote_state global {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/global.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+data terraform_remote_state datadog {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/envs/prod/components/datadog.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+data terraform_remote_state hero {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/envs/prod/components/hero.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+# remote state for accounts
+data terraform_remote_state bar {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/accounts/bar.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+data terraform_remote_state foo {
+  backend = "s3"
+  config = {
+
+
+    bucket = "buck"
+
+    key     = "terraform/proj/accounts/foo.tfstate"
+    region  = "us-west-2"
+    profile = "profile"
+
+
+  }
+}
+# map of aws_accounts
+variable aws_accounts {
+  type = map
+  default = {
+
+
+    bar = 456
+
+
+
+    foo = 123
+
+
+  }
+}
+provider random {
+  version = "~> 2.2"
+}
+provider template {
+  version = "~> 2.1"
+}
+provider archive {
+  version = "~> 1.3"
+}
+provider null {
+  version = "~> 2.1"
+}
+provider local {
+  version = "~> 1.4"
+}
+provider tls {
+  version = "~> 2.1"
+}
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/main.tf b/testdata/v2_full_yaml/terraform/envs/prod/vpc/main.tf
new file mode 100644
index 00000000..52e4e59e
--- /dev/null
+++ b/testdata/v2_full_yaml/terraform/envs/prod/vpc/main.tf
@@ -0,0 +1,54 @@
+# Auto-generated by fogg. Do not edit
+# Make improvements in fogg, so that everyone can benefit.
+
+module prod-vpc {
+  source                             = "github.com/terraform-aws-modules/terraform-aws-vpc?ref=v1.30.0"
+  azs                                = local.azs
+  cidr                               = local.cidr
+  create_database_subnet_group       = local.create_database_subnet_group
+  create_vpc                         = local.create_vpc
+  database_subnet_tags               = local.database_subnet_tags
+  database_subnets                   = local.database_subnets
+  default_route_table_tags           = local.default_route_table_tags
+  default_vpc_enable_classiclink     = local.default_vpc_enable_classiclink
+  default_vpc_enable_dns_hostnames   = local.default_vpc_enable_dns_hostnames
+  default_vpc_enable_dns_support     = local.default_vpc_enable_dns_support
+  default_vpc_name                   = local.default_vpc_name
+  default_vpc_tags                   = local.default_vpc_tags
+  dhcp_options_domain_name           = local.dhcp_options_domain_name
+  dhcp_options_domain_name_servers   = local.dhcp_options_domain_name_servers
+  dhcp_options_netbios_name_servers  = local.dhcp_options_netbios_name_servers
+  dhcp_options_netbios_node_type     = local.dhcp_options_netbios_node_type
+  dhcp_options_ntp_servers           = local.dhcp_options_ntp_servers
+  dhcp_options_tags                  = local.dhcp_options_tags
+  elasticache_subnet_tags            = local.elasticache_subnet_tags
+  elasticache_subnets                = local.elasticache_subnets
+  enable_dhcp_options                = local.enable_dhcp_options
+  enable_dns_hostnames               = local.enable_dns_hostnames
+  enable_dns_support                 = local.enable_dns_support
+  enable_dynamodb_endpoint           = local.enable_dynamodb_endpoint
+  enable_nat_gateway                 = local.enable_nat_gateway
+  enable_s3_endpoint                 = local.enable_s3_endpoint
+  enable_vpn_gateway                 = local.enable_vpn_gateway
+  external_nat_ip_ids                = local.external_nat_ip_ids
+  instance_tenancy                   = local.instance_tenancy
+  manage_default_vpc                 = local.manage_default_vpc
+  map_public_ip_on_launch            = local.map_public_ip_on_launch
+  name                               = local.name
+  private_route_table_tags           = local.private_route_table_tags
+  private_subnet_tags                = local.private_subnet_tags
+  private_subnets                    = local.private_subnets
+  propagate_private_route_tables_vgw = local.propagate_private_route_tables_vgw
+  propagate_public_route_tables_vgw  = local.propagate_public_route_tables_vgw
+  public_route_table_tags            = local.public_route_table_tags
+  public_subnet_tags                 = local.public_subnet_tags
+  public_subnets                     = local.public_subnets
+  redshift_subnet_tags               = local.redshift_subnet_tags
+  redshift_subnets                   = local.redshift_subnets
+  reuse_nat_ips                      = local.reuse_nat_ips
+  single_nat_gateway                 = local.single_nat_gateway
+  tags                               = local.tags
+  vpc_tags                           = local.vpc_tags
+  vpn_gateway_id                     = local.vpn_gateway_id
+
+}
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/outputs.tf b/testdata/v2_full_yaml/terraform/envs/prod/vpc/outputs.tf
new file mode 100644
index 00000000..dfa5ea2f
--- /dev/null
+++ b/testdata/v2_full_yaml/terraform/envs/prod/vpc/outputs.tf
@@ -0,0 +1,176 @@
+# Auto-generated by fogg. Do not edit
+# Make improvements in fogg, so that everyone can benefit.
+
+output database_subnet_group {
+  value = module.prod-vpc.database_subnet_group
+}
+
+output database_subnets {
+  value = module.prod-vpc.database_subnets
+}
+
+output database_subnets_cidr_blocks {
+  value = module.prod-vpc.database_subnets_cidr_blocks
+}
+
+output default_network_acl_id {
+  value = module.prod-vpc.default_network_acl_id
+}
+
+output default_route_table_id {
+  value = module.prod-vpc.default_route_table_id
+}
+
+output default_security_group_id {
+  value = module.prod-vpc.default_security_group_id
+}
+
+output default_vpc_cidr_block {
+  value = module.prod-vpc.default_vpc_cidr_block
+}
+
+output default_vpc_default_network_acl_id {
+  value = module.prod-vpc.default_vpc_default_network_acl_id
+}
+
+output default_vpc_default_route_table_id {
+  value = module.prod-vpc.default_vpc_default_route_table_id
+}
+
+output default_vpc_default_security_group_id {
+  value = module.prod-vpc.default_vpc_default_security_group_id
+}
+
+output default_vpc_enable_dns_hostnames {
+  value = module.prod-vpc.default_vpc_enable_dns_hostnames
+}
+
+output default_vpc_enable_dns_support {
+  value = module.prod-vpc.default_vpc_enable_dns_support
+}
+
+output default_vpc_id {
+  value = module.prod-vpc.default_vpc_id
+}
+
+output default_vpc_instance_tenancy {
+  value = module.prod-vpc.default_vpc_instance_tenancy
+}
+
+output default_vpc_main_route_table_id {
+  value = module.prod-vpc.default_vpc_main_route_table_id
+}
+
+output elasticache_subnet_group {
+  value = module.prod-vpc.elasticache_subnet_group
+}
+
+output elasticache_subnet_group_name {
+  value = module.prod-vpc.elasticache_subnet_group_name
+}
+
+output elasticache_subnets {
+  value = module.prod-vpc.elasticache_subnets
+}
+
+output elasticache_subnets_cidr_blocks {
+  value = module.prod-vpc.elasticache_subnets_cidr_blocks
+}
+
+output igw_id {
+  value = module.prod-vpc.igw_id
+}
+
+output nat_ids {
+  value = module.prod-vpc.nat_ids
+}
+
+output nat_public_ips {
+  value = module.prod-vpc.nat_public_ips
+}
+
+output natgw_ids {
+  value = module.prod-vpc.natgw_ids
+}
+
+output private_route_table_ids {
+  value = module.prod-vpc.private_route_table_ids
+}
+
+output private_subnets {
+  value = module.prod-vpc.private_subnets
+}
+
+output private_subnets_cidr_blocks {
+  value = module.prod-vpc.private_subnets_cidr_blocks
+}
+
+output public_route_table_ids {
+  value = module.prod-vpc.public_route_table_ids
+}
+
+output public_subnets {
+  value = module.prod-vpc.public_subnets
+}
+
+output public_subnets_cidr_blocks {
+  value = module.prod-vpc.public_subnets_cidr_blocks
+}
+
+output redshift_subnet_group {
+  value = module.prod-vpc.redshift_subnet_group
+}
+
+output redshift_subnets {
+  value = module.prod-vpc.redshift_subnets
+}
+
+output redshift_subnets_cidr_blocks {
+  value = module.prod-vpc.redshift_subnets_cidr_blocks
+}
+
+output vgw_id {
+  value = module.prod-vpc.vgw_id
+}
+
+output vpc_cidr_block {
+  value = module.prod-vpc.vpc_cidr_block
+}
+
+output vpc_enable_dns_hostnames {
+  value = module.prod-vpc.vpc_enable_dns_hostnames
+}
+
+output vpc_enable_dns_support {
+  value = module.prod-vpc.vpc_enable_dns_support
+}
+
+output vpc_endpoint_dynamodb_id {
+  value = module.prod-vpc.vpc_endpoint_dynamodb_id
+}
+
+output vpc_endpoint_dynamodb_pl_id {
+  value = module.prod-vpc.vpc_endpoint_dynamodb_pl_id
+}
+
+output vpc_endpoint_s3_id {
+  value = module.prod-vpc.vpc_endpoint_s3_id
+}
+
+output vpc_endpoint_s3_pl_id {
+  value = module.prod-vpc.vpc_endpoint_s3_pl_id
+}
+
+output vpc_id {
+  value = module.prod-vpc.vpc_id
+}
+
+output vpc_instance_tenancy {
+  value = module.prod-vpc.vpc_instance_tenancy
+}
+
+output vpc_main_route_table_id {
+  value = module.prod-vpc.vpc_main_route_table_id
+}
+
+
diff --git a/testdata/v2_full_yaml/terraform/envs/prod/vpc/terraform.d b/testdata/v2_full_yaml/terraform/envs/prod/vpc/terraform.d
new file mode 120000
index 00000000..b482d75b
--- /dev/null
+++ b/testdata/v2_full_yaml/terraform/envs/prod/vpc/terraform.d
@@ -0,0 +1,1 @@
+../../../../terraform.d
\ No newline at end of file