Skip to content

Commit

Permalink
Merge pull request #105 from wata727/interpolate_module_attr
Browse files Browse the repository at this point in the history
Interpolate module attributes
  • Loading branch information
wata727 authored Apr 23, 2017
2 parents 727fe29 + 846dfbc commit 95a681e
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 11 deletions.
11 changes: 6 additions & 5 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,21 @@ func NewEvaluator(templates map[string]*hclast.File, varfile []*hclast.File, c *
if err != nil {
return nil, err
}
moduleMap, err := detectModules(templates, c)
if err != nil {
return nil, err
}

evaluator := &Evaluator{
Config: hil.EvalConfig{
GlobalScope: &hilast.BasicScope{
VarMap: varMap,
},
},
ModuleConfig: moduleMap,
}

moduleMap, err := evaluator.detectModules(templates, c)
if err != nil {
return nil, err
}
evaluator.ModuleConfig = moduleMap

return evaluator, nil
}

Expand Down
31 changes: 29 additions & 2 deletions evaluator/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"encoding/hex"
"fmt"

"reflect"

"github.com/hashicorp/hcl"
hclast "github.com/hashicorp/hcl/hcl/ast"
"github.com/hashicorp/hil"
Expand All @@ -22,7 +24,7 @@ type hclModule struct {
Templates map[string]*hclast.File
}

func detectModules(templates map[string]*hclast.File, c *config.Config) (map[string]*hclModule, error) {
func (e *Evaluator) detectModules(templates map[string]*hclast.File, c *config.Config) (map[string]*hclModule, error) {
moduleMap := make(map[string]*hclModule)

for file, template := range templates {
Expand Down Expand Up @@ -51,7 +53,11 @@ func detectModules(templates map[string]*hclast.File, c *config.Config) (map[str
varMap := make(map[string]hilast.Variable)
for k, v := range module {
varName := "var." + k
varMap[varName] = parseVariable(v, "")
ev, err := e.evalModuleAttr(k, v)
if err != nil {
return nil, err
}
varMap[varName] = parseVariable(ev, "")
}

moduleMap[moduleKey] = &hclModule{
Expand All @@ -72,6 +78,27 @@ func detectModules(templates map[string]*hclast.File, c *config.Config) (map[str
return moduleMap, nil
}

func (e *Evaluator) evalModuleAttr(key string, val interface{}) (interface{}, error) {
if v, ok := val.(string); ok {
ev, err := e.Eval(v)
if err != nil {
return nil, err
}
if estr, ok := ev.(string); ok && estr == "[NOT EVALUABLE]" {
ev = e
}

// In parseVariable function, map is expected to be in slice.
switch reflect.ValueOf(ev).Kind() {
case reflect.Map:
return []interface{}{ev}, nil
default:
return ev, nil
}
}
return val, nil
}

func moduleKey(name string, source string) string {
base := "root." + name + "-" + source
sum := md5.Sum([]byte(base)) // #nosec
Expand Down
123 changes: 122 additions & 1 deletion evaluator/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,126 @@ module "ec2_instance" {
},
Error: false,
},
{
Name: "detect module with string variable",
Input: map[string]string{
"module.tf": `
variable "ami" {
default = "ami-12345"
}
module "ec2_instance" {
source = "./tf_aws_ec2_instance"
ami = "${var.ami}"
}`,
},
Result: map[string]*hclModule{
"960d94c2f60d34845dc3051edfad76e1": {
Name: "ec2_instance",
Source: "./tf_aws_ec2_instance",
File: "module.tf",
Config: hil.EvalConfig{
GlobalScope: &hilast.BasicScope{
VarMap: map[string]hilast.Variable{
"var.ami": {
Type: hilast.TypeString,
Value: "ami-12345",
},
},
},
},
Templates: map[string]*hclast.File{},
},
},
Error: false,
},
{
Name: "detect module with list variable",
Input: map[string]string{
"module.tf": `
variable "amis" {
default = ["ami-12345", "ami-54321"]
}
module "ec2_instance" {
source = "./tf_aws_ec2_instance"
ami = "${var.amis}"
}`,
},
Result: map[string]*hclModule{
"960d94c2f60d34845dc3051edfad76e1": {
Name: "ec2_instance",
Source: "./tf_aws_ec2_instance",
File: "module.tf",
Config: hil.EvalConfig{
GlobalScope: &hilast.BasicScope{
VarMap: map[string]hilast.Variable{
"var.ami": {
Type: hilast.TypeList,
Value: []hilast.Variable{
{
Type: hilast.TypeString,
Value: "ami-12345",
},
{
Type: hilast.TypeString,
Value: "ami-54321",
},
},
},
},
},
},
Templates: map[string]*hclast.File{},
},
},
Error: false,
},
{
Name: "detect module with map variable",
Input: map[string]string{
"module.tf": `
variable "ami_info" {
default = {
name = "awesome image"
value = "ami-12345"
}
}
module "ec2_instance" {
source = "./tf_aws_ec2_instance"
ami = "${var.ami_info}"
}`,
},
Result: map[string]*hclModule{
"960d94c2f60d34845dc3051edfad76e1": {
Name: "ec2_instance",
Source: "./tf_aws_ec2_instance",
File: "module.tf",
Config: hil.EvalConfig{
GlobalScope: &hilast.BasicScope{
VarMap: map[string]hilast.Variable{
"var.ami": {
Type: hilast.TypeMap,
Value: map[string]hilast.Variable{
"name": {
Type: hilast.TypeString,
Value: "awesome image",
},
"value": {
Type: hilast.TypeString,
Value: "ami-12345",
},
},
},
},
},
},
Templates: map[string]*hclast.File{},
},
},
Error: false,
},
{
Name: "invalid source",
Input: map[string]string{
Expand Down Expand Up @@ -148,7 +268,8 @@ module "ec2_instances" {
for k, v := range tc.Input {
templates[k], _ = parser.Parse([]byte(v))
}
result, err := detectModules(templates, config.Init())
evaluator, _ := NewEvaluator(templates, []*hclast.File{}, config.Init())
result, err := evaluator.detectModules(templates, config.Init())
if tc.Error && err == nil {
t.Fatalf("\nshould be happen error.\n\ntestcase: %s", tc.Name)
continue
Expand Down
10 changes: 7 additions & 3 deletions evaluator/variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,13 @@ func parseVariable(val interface{}, varType string) hilast.Variable {
// Correct:
//
// []map[string]string{
// map[string]string{
// "name": "test",
// "value": "hcl",
// {
// "key": []map[string]string{
// {
// "name": "test",
// "value": "hcl",
// },
// },
// },
// }
//
Expand Down

0 comments on commit 95a681e

Please sign in to comment.