Repository: chanzuckerberg/fogg
Pull request #346 (2019-08-15 23:39:48)

Use terraform-config-inspect module, add TF 0.12 input syntax support
### Summary
Replaces uses of the internal function inside Terraform for parsing modules with a more supported separate library hashicorp/terraform-config-inspect. This library also provides support for properly parsing Terraform 0.12 HCL2 syntax. Mostly a drop in replacement, although I renamed some variables to match the new type names of the library.

codecov[bot]: # [Codecov](https://codecov.io/gh/chanzuckerberg/fogg/pull/346?src=pr&el=h1) Report
> Merging [#346](https://codecov.io/gh/chanzuckerberg/fogg/pull/346?src=pr&el=desc) into [master](https://codecov.io/gh/chanzuckerberg/fogg/commit/a70eb8a814a1ad60cf8127ab1fa526bfc4c706a4?src=pr&el=desc) will **decrease** coverage by `0.07%`.
> The diff coverage is `69.23%`.

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

```diff
@@            Coverage Diff             @@
##           master     #346      +/-   ##
==========================================
- Coverage   79.09%   79.01%   -0.08%     
==========================================
  Files          25       25              
  Lines        1894     1897       +3     
==========================================
+ Hits         1498     1499       +1     
- Misses        254      255       +1     
- Partials      142      143       +1
```


| [Impacted Files](https://codecov.io/gh/chanzuckerberg/fogg/pull/346?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [exp/examine/examine.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/346/diff?src=pr&el=tree#diff-ZXhwL2V4YW1pbmUvZXhhbWluZS5nbw==) | `0% <0%> (ø)` | :arrow_up: |
| [exp/examine/local.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/346/diff?src=pr&el=tree#diff-ZXhwL2V4YW1pbmUvbG9jYWwuZ28=) | `50% <60%> (ø)` | :arrow_up: |
| [util/module\_storage.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/346/diff?src=pr&el=tree#diff-dXRpbC9tb2R1bGVfc3RvcmFnZS5nbw==) | `56.52% <60%> (-1.62%)` | :arrow_down: |
| [exp/examine/latest.go](https://codecov.io/gh/chanzuckerberg/fogg/pull/346/diff?src=pr&el=tree#diff-ZXhwL2V4YW1pbmUvbGF0ZXN0Lmdv) | `76% <92.3%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/chanzuckerberg/fogg/pull/346?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/346?src=pr&el=footer). Last update [a70eb8a...47e4aa0](https://codecov.io/gh/chanzuckerberg/fogg/pull/346?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/exp/examine/examine.go b/exp/examine/examine.go
index e1c663ef..33aa7aa5 100644
--- a/exp/examine/examine.go
+++ b/exp/examine/examine.go
@@ -8,13 +8,13 @@ import (
 //TODO: Comparison between local and latest
 func Examine(fs afero.Fs, path string) error {
 	//Collect local modules to be updated
-	config, err := GetLocalModules(fs, path)
-	if err != nil && config != nil {
+	module, err := GetLocalModules(fs, path)
+	if err != nil && module != nil {
 		return err
 	}
 
 	//Load the latest version of each module
-	globalModules, err := LatestModuleVersions(fs, config)
+	globalModules, err := LatestModuleVersions(fs, module)
 	if err != nil {
 		return err
 	}
diff --git a/exp/examine/local.go b/exp/examine/local.go
index c3288d72..6c187a19 100644
--- a/exp/examine/local.go
+++ b/exp/examine/local.go
@@ -3,7 +3,8 @@ package examine
 import (
 	"os"
 
-	"github.com/hashicorp/terraform/config"
+	"github.com/chanzuckerberg/fogg/errs"
+	"github.com/hashicorp/terraform-config-inspect/tfconfig"
 	"github.com/spf13/afero"
 )
 
@@ -15,17 +16,17 @@ const resourceType = "/modules/"
 
 //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) (*config.Config, error) {
+func GetLocalModules(fs afero.Fs, dir string) (*tfconfig.Module, error) {
 	_, err := os.Stat(dir)
 	if err != nil {
 		return nil, err
 	}
 
-	config, err := config.LoadDir(dir)
-	if err != nil {
-		return nil, err
+	module, diag := tfconfig.LoadModule(dir)
+	if diag.HasErrors() {
+		return nil, errs.WrapInternal(diag.Err(), "There was an issue loading the module")
 	}
 
-	return config, nil
+	return module, nil
 	// return getAllModules(fs, dir)
 }
diff --git a/util/module_storage.go b/util/module_storage.go
index a9018f04..a842d1fe 100644
--- a/util/module_storage.go
+++ b/util/module_storage.go
@@ -7,7 +7,7 @@ import (
 
 	"github.com/chanzuckerberg/fogg/errs"
 	getter "github.com/hashicorp/go-getter"
-	"github.com/hashicorp/terraform/config"
+	"github.com/hashicorp/terraform-config-inspect/tfconfig"
 	homedir "github.com/mitchellh/go-homedir"
 	"github.com/spf13/afero"
 )
@@ -66,7 +66,7 @@ func GetFoggCachePath() (string, error) {
 	return dir, nil
 }
 
-func DownloadAndParseModule(fs afero.Fs, mod string) (*config.Config, error) {
+func DownloadAndParseModule(fs afero.Fs, mod string) (*tfconfig.Module, error) {
 	dir, err := GetFoggCachePath()
 	if err != nil {
 		return nil, err
@@ -75,5 +75,9 @@ func DownloadAndParseModule(fs afero.Fs, mod string) (*config.Config, error) {
 	if err != nil {
 		return nil, errs.WrapUser(err, "unable to download module")
 	}
-	return config.LoadDir(d)
+	module, diag := tfconfig.LoadModule(d)
+	if diag.HasErrors() {
+		return nil, errs.WrapInternal(diag.Err(), "There was an issue loading the module")
+	}
+	return module, nil
 }


Test patch:
diff --git a/exp/examine/latest.go b/exp/examine/latest.go
index bcfbaceb..1dff451f 100644
--- a/exp/examine/latest.go
+++ b/exp/examine/latest.go
@@ -6,31 +6,31 @@ import (
 
 	"github.com/chanzuckerberg/fogg/errs"
 	"github.com/google/go-github/v27/github"
-	"github.com/hashicorp/terraform/config"
+	"github.com/hashicorp/terraform-config-inspect/tfconfig"
 	"github.com/spf13/afero"
 )
 
 //LatestModuleVersions retrieves the latest version of the provided modules
-func LatestModuleVersions(fs afero.Fs, config *config.Config) ([]ModuleWrapper, error) {
+func LatestModuleVersions(fs afero.Fs, module *tfconfig.Module) ([]ModuleWrapper, error) {
 	var latestModules []ModuleWrapper
-	var module ModuleWrapper
+	var moduleWrapper ModuleWrapper
 	var resource string
 	var err error
 
-	for _, mod := range config.Modules {
-		if strings.HasPrefix(mod.Source, githubURL) { //If the resource is from github then retrieve from custom url
-			resource, err = createGitUrl(mod)
+	for _, moduleCall := range module.ModuleCalls {
+		if strings.HasPrefix(moduleCall.Source, githubURL) { //If the resource is from github then retrieve from custom url
+			resource, err = createGitUrl(moduleCall)
 			if err != nil {
-				return nil, errs.WrapUserf(err, "Could not generate url for %s latest module", mod.Source)
+				return nil, errs.WrapUserf(err, "Could not generate url for %s latest module", moduleCall.Source)
 			}
-			module.module, err = GetFromGithub(fs, resource)
+			moduleWrapper.module, err = GetFromGithub(fs, resource)
 			if err != nil {
 				return nil, err
 			}
-			module.moduleSource = mod.Source
-			module.version = mod.Version
+			moduleWrapper.moduleSource = moduleCall.Source
+			moduleWrapper.version = moduleCall.Version
 
-			latestModules = append(latestModules, module)
+			latestModules = append(latestModules, moduleWrapper)
 		}
 		//TODO: Implement retrieving the latest module from the terraform registry
 	}
@@ -39,8 +39,8 @@ func LatestModuleVersions(fs afero.Fs, config *config.Config) ([]ModuleWrapper,
 }
 
 //createGitUrl retrieves the latest release version and creates an HTTP accessible link
-func createGitUrl(module *config.Module) (string, error) {
-	splitString := strings.Split(module.Source, "/")
+func createGitUrl(moduleCall *tfconfig.ModuleCall) (string, error) {
+	splitString := strings.Split(moduleCall.Source, "/")
 	owner, repo := splitString[1], splitString[2]
 
 	client := github.NewClient(nil)
@@ -49,5 +49,5 @@ func createGitUrl(module *config.Module) (string, error) {
 		return "", err
 	}
 
-	return strings.Split(module.Source, tagPattern)[0] + tagPattern + *release.TagName, nil
+	return strings.Split(moduleCall.Source, tagPattern)[0] + tagPattern + *release.TagName, nil
 }
diff --git a/exp/examine/latest_test.go b/exp/examine/latest_test.go
index 5e098d80..837b8e3d 100644
--- a/exp/examine/latest_test.go
+++ b/exp/examine/latest_test.go
@@ -14,11 +14,11 @@ func TestCompareLocalAndGlobal(t *testing.T) {
 	r.NoError(err)
 	fs := afero.NewBasePathFs(afero.NewOsFs(), pwd)
 
-	config, err := GetLocalModules(fs, "../../testdata/version_detection/terraform/envs/staging/app/")
+	module, err := GetLocalModules(fs, "../../testdata/version_detection/terraform/envs/staging/app/")
 	r.NoError(err)
-	r.NotNil(config)
+	r.NotNil(module)
 
-	globalModules, err := LatestModuleVersions(fs, config)
+	globalModules, err := LatestModuleVersions(fs, module)
 	r.NoError(err)
 	r.NotNil(globalModules)
 }
@@ -29,11 +29,11 @@ func TestCreateGitUrl(t *testing.T) {
 	r.NoError(err)
 	fs := afero.NewBasePathFs(afero.NewOsFs(), pwd)
 
-	config, err := GetLocalModules(fs, "../../testdata/version_detection/terraform/envs/staging/app/")
+	module, err := GetLocalModules(fs, "../../testdata/version_detection/terraform/envs/staging/app/")
 	r.NoError(err)
-	r.NotNil(config)
+	r.NotNil(module)
 
-	url, err := createGitUrl(config.Modules[1])
+	url, err := createGitUrl(module.ModuleCalls["parameters-policy"])
 	r.NoError(err)
 	r.NotEmpty(url)
 }