Skip to content

Commit

Permalink
terraform linter now loads modules
Browse files Browse the repository at this point in the history
  • Loading branch information
Larry Hitchon committed Jul 26, 2018
1 parent 9a5ee0a commit 23b23be
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 0 deletions.
4 changes: 4 additions & 0 deletions linter/resource_linter.go
Expand Up @@ -24,10 +24,14 @@ func (r ResourceLinter) ValidateResources(resources []assertion.Resource, rules
for _, rule := range resolvedRules {
assertion.Debugf("Rule: ID: %v Message: %s\n", rule.ID, rule.Message)
filteredResources := assertion.FilterResourcesForRule(resources, rule)
if len(filteredResources) == 0 {
assertion.Debugf("No resources to check\n")
}
for _, resource := range filteredResources {
if assertion.ExcludeResource(rule, resource) {
assertion.Debugf("Ignoring resource %s\n", resource.ID)
} else {
assertion.Debugf("Checking resource %s\n", resource.ID)
status, violations, err := assertion.CheckRule(rule, resource, externalRules)
if err != nil {
return report, nil
Expand Down
43 changes: 43 additions & 0 deletions linter/terraform.go
Expand Up @@ -22,6 +22,7 @@ type (
Resources []interface{}
Data []interface{}
Providers []interface{}
Modules []interface{}
Variables []Variable
AST *ast.File
}
Expand All @@ -32,6 +33,7 @@ func loadHCL(filename string) (TerraformLoadResult, error) {
Resources: []interface{}{},
Data: []interface{}{},
Providers: []interface{}{},
Modules: []interface{}{},
Variables: []Variable{},
}
template, err := ioutil.ReadFile(filename)
Expand Down Expand Up @@ -68,6 +70,9 @@ func loadHCL(filename string) (TerraformLoadResult, error) {
if m["provider"] != nil {
result.Providers = append(result.Providers, m["provider"].([]interface{})...)
}
if m["module"] != nil {
result.Modules = append(result.Modules, m["module"].([]interface{})...)
}
assertion.Debugf("LoadHCL Variables: %v\n", result.Variables)
return result, nil
}
Expand Down Expand Up @@ -120,6 +125,10 @@ func (l TerraformResourceLoader) Load(filename string) (FileResources, error) {
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, result.Resources, "resource")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, result.Data, "data")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, addIDToProviders(result.Providers), "provider")...)
loaded.Resources = append(loaded.Resources, getResources(filename, result.AST, addKeyToModules(result.Modules), "module")...)

assertion.DebugJSON("loaded.Resources", loaded.Resources)

return loaded, nil
}

Expand Down Expand Up @@ -152,6 +161,40 @@ func addIDToProviderValue(value interface{}) interface{} {
return []interface{}{m}
}

// use the source attribute of modules as the key
func addKeyToModules(modules []interface{}) []interface{} {
resources := map[string]interface{}{}
for _, module := range modules {
resources = addKeyToModule(resources, module)
}
return []interface{}{resources}
}

func addKeyToModule(resources map[string]interface{}, module interface{}) map[string]interface{} {
m := module.(map[string]interface{})
for moduleName, valueList := range m {
a := valueList.([]interface{})
for _, value := range a {
properties := value.(map[string]interface{})
source := properties["source"].(string)

inner := []interface{}{properties}

outer := map[string]interface{}{}
outer[moduleName] = inner

existing, ok := resources[source]
if ok {
list := existing.([]interface{})
resources[source] = append(list, outer)
} else {
resources[source] = []interface{}{outer}
}
}
}
return resources
}

func getResources(filename string, ast *ast.File, objects []interface{}, category string) []assertion.Resource {
resources := []assertion.Resource{}
for _, resource := range objects {
Expand Down
6 changes: 6 additions & 0 deletions linter/terraform_test.go
Expand Up @@ -153,6 +153,12 @@ func TestTerraformLinterCases(t *testing.T) {
0,
"",
},
"Module": {
"./testdata/resources/terraform_module.tf",
"./testdata/rules/terraform_module.yml",
1,
"MODULE_DESCRIPTION",
},
}
for name, tc := range testCases {
options := Options{
Expand Down
11 changes: 11 additions & 0 deletions linter/testdata/resources/terraform_module.tf
@@ -0,0 +1,11 @@
module "test_module" {
source = "./modules/foo"
name = "counter_1"
count = 4
}

module "test_module_with_description" {
source = "./modules/foo"
name = "counter_2"
description = "here is a description"
}
15 changes: 15 additions & 0 deletions linter/testdata/rules/terraform_module.yml
@@ -0,0 +1,15 @@
version: 1
description: Rules for Terraform configuration files
type: Terraform
files:
- "*.tf"
rules:

- id: MODULE_DESCRIPTION
message: Testing
resource: "./modules/foo"
category: module
assertions:
- key: description
op: present

0 comments on commit 23b23be

Please sign in to comment.