Skip to content

Commit

Permalink
exit condition for ResolveStrRef recursive calls
Browse files Browse the repository at this point in the history
  • Loading branch information
patilpankaj212 committed Apr 26, 2021
1 parent 59fd279 commit 2545350
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 46 deletions.
15 changes: 5 additions & 10 deletions pkg/iac-providers/terraform/commons/local-references.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func getLocalName(localRef string) (string, string) {
}

// ResolveLocalRef returns the local value as configured in IaC config in module
func (r *RefResolver) ResolveLocalRef(localRef string) interface{} {
func (r *RefResolver) ResolveLocalRef(localRef, callerRef string) interface{} {

// get local name from localRef
localName, localExpr := getLocalName(localRef)
Expand Down Expand Up @@ -89,16 +89,11 @@ func (r *RefResolver) ResolveLocalRef(localRef string) interface{} {
if reflect.TypeOf(val).Kind() == reflect.String {
valStr := val.(string)
resolvedVal := strings.Replace(localRef, localExpr, valStr, 1)
// when the resolved reference value, contains the value resolved for the
// expression, we would need to return the value resolved for the expression
// to break the recursion.
// We cannot send 'localExpr', as it would again form a non breaking recursion call
if localRef != localExpr && strings.Contains(resolvedVal, valStr) {
zap.S().Debugf("resolved local variable ref refers to self: '%v'", valStr)
return valStr
if callerRef != "" && strings.Contains(resolvedVal, callerRef) {
zap.S().Debugf("resolved str local value ref: '%v', value: '%v'", localRef, resolvedVal)
return resolvedVal
}
zap.S().Debugf("resolved str local value ref: '%v', value: '%v'", localRef, resolvedVal)
return r.ResolveStrRef(resolvedVal)
return r.ResolveStrRef(resolvedVal, localRef)
}

// return extracted value
Expand Down
6 changes: 3 additions & 3 deletions pkg/iac-providers/terraform/commons/lookup-references.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ func getLookupName(lookupRef string) (string, string, string) {
}

// ResolveLookupRef returns the lookup value as configured in IaC config in module
func (r *RefResolver) ResolveLookupRef(lookupRef string) interface{} {
func (r *RefResolver) ResolveLookupRef(lookupRef, callerRef string) interface{} {

// get lookup name from lookupRef
table, key, _ := getLookupName(lookupRef)

// resolve key, if it is a reference
resolvedKey := r.ResolveStrRef(key)
resolvedKey := r.ResolveStrRef(key, callerRef)

// check if key is still an unresolved reference
if reflect.TypeOf(resolvedKey).Kind() == reflect.String && isRef(resolvedKey.(string)) {
Expand All @@ -71,7 +71,7 @@ func (r *RefResolver) ResolveLookupRef(lookupRef string) interface{} {
}

// resolve table, if it is a ref
lookup := r.ResolveStrRef(table)
lookup := r.ResolveStrRef(table, callerRef)

// check if lookup is a map
if reflect.TypeOf(lookup).String() != "map[string]interface {}" {
Expand Down
9 changes: 6 additions & 3 deletions pkg/iac-providers/terraform/commons/module-references.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func getModuleVarName(moduleRef string) (string, string, string) {
}

// ResolveModuleRef tries to resolve cross module references
func (r *RefResolver) ResolveModuleRef(moduleRef string,
func (r *RefResolver) ResolveModuleRef(moduleRef, callerRef string,
children map[string]*hclConfigs.Config) interface{} {

// get module and variable name
Expand Down Expand Up @@ -108,8 +108,11 @@ func (r *RefResolver) ResolveModuleRef(moduleRef string,
zap.S().Debugf("resolved str variable ref refers to self: '%v'", moduleRef)
return moduleRef
}
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", moduleRef, resolvedVal)
return r.ResolveStrRef(resolvedVal)
if callerRef != "" && strings.Contains(resolvedVal, callerRef) {
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", moduleRef, resolvedVal)
return resolvedVal
}
return r.ResolveStrRef(resolvedVal, moduleRef)
}
return val
}
20 changes: 10 additions & 10 deletions pkg/iac-providers/terraform/commons/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (r *RefResolver) ResolveRefs(config jsonObj) jsonObj {

// case 1: config value is a string; in resource config, refs
// are of the type string
config[k] = r.ResolveStrRef(v.(string))
config[k] = r.ResolveStrRef(v.(string), "")

case vType == "tfv12.jsonObj" && vKind == reflect.Map:

Expand All @@ -86,7 +86,7 @@ func (r *RefResolver) ResolveRefs(config jsonObj) jsonObj {
// references
if len(sConfig) > 0 && reflect.TypeOf(sConfig[0]).Kind() == reflect.String {
for i, c := range sConfig {
sConfig[i] = r.ResolveStrRef(c.(string))
sConfig[i] = r.ResolveStrRef(c.(string), "")
}
config[k] = sConfig
}
Expand Down Expand Up @@ -115,23 +115,23 @@ func (r *RefResolver) ResolveRefs(config jsonObj) jsonObj {
// ResolveStrRef tries to resolve a string reference. Reference can be a
// variable "${var.foo}", cross module variable "${module.foo.bar}", local
// value "${local.foo}"
func (r *RefResolver) ResolveStrRef(ref string) interface{} {
func (r *RefResolver) ResolveStrRef(ref, callerRef string) interface{} {

switch {
case isModuleRef(ref):

// resolve cross module references
return r.ResolveModuleRef(ref, r.Config.Children)
return r.ResolveModuleRef(ref, callerRef, r.Config.Children)

case isLocalRef(ref):

// resolve local value references
return r.ResolveLocalRef(ref)
return r.ResolveLocalRef(ref, callerRef)

case isLookupRef(ref):

// resolve lookup references
return r.ResolveLookupRef(ref)
return r.ResolveLookupRef(ref, callerRef)

case isVarRef(ref):

Expand All @@ -144,7 +144,7 @@ func (r *RefResolver) ResolveStrRef(ref string) interface{} {
*/

// 1. resolve variables initialized in parent module call
val := r.ResolveVarRefFromParentModuleCall(ref)
val := r.ResolveVarRefFromParentModuleCall(ref, callerRef)

if reflect.TypeOf(val).Kind() == reflect.String {

Expand All @@ -163,17 +163,17 @@ func (r *RefResolver) ResolveStrRef(ref string) interface{} {
case isVarRef(valStr):

// resolve variable reference
return r.ResolveVarRef(valStr)
return r.ResolveVarRef(valStr, ref)

case isModuleRef(valStr):

// resolve cross module reference in parent module
return r.ResolveModuleRef(valStr, r.Config.Parent.Children)
return r.ResolveModuleRef(valStr, ref, r.Config.Parent.Children)

case isRef(valStr):

// some other reference
return r.ResolveStrRef(valStr)
return r.ResolveStrRef(valStr, ref)
}
}

Expand Down
18 changes: 12 additions & 6 deletions pkg/iac-providers/terraform/commons/variable-references.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func getVarName(varRef string) (string, string) {
}

// ResolveVarRef returns the variable value as configured in IaC config in module
func (r *RefResolver) ResolveVarRef(varRef string) interface{} {
func (r *RefResolver) ResolveVarRef(varRef, callerRef string) interface{} {

// get variable name from varRef
varName, varExpr := getVarName(varRef)
Expand Down Expand Up @@ -94,8 +94,11 @@ func (r *RefResolver) ResolveVarRef(varRef string) interface{} {
zap.S().Debugf("resolved str variable ref refers to self: '%v'", varRef)
return varRef
}
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", varRef, resolvedVal)
return r.ResolveStrRef(resolvedVal)
if callerRef != "" && strings.Contains(resolvedVal, callerRef) {
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", varRef, string(resolvedVal))
return resolvedVal
}
return r.ResolveStrRef(resolvedVal, varRef)
}
return val
}
Expand All @@ -104,7 +107,7 @@ func (r *RefResolver) ResolveVarRef(varRef string) interface{} {
// ModuleCall from parent module. The resolved value can be an absolute value
// (string, int, bool etc.) or it can also be another reference, which may
// need further resolution
func (r *RefResolver) ResolveVarRefFromParentModuleCall(varRef string) interface{} {
func (r *RefResolver) ResolveVarRefFromParentModuleCall(varRef, callerRef string) interface{} {

zap.S().Debugf("resolving variable ref %q in parent module call", varRef)

Expand Down Expand Up @@ -152,8 +155,11 @@ func (r *RefResolver) ResolveVarRefFromParentModuleCall(varRef string) interface
zap.S().Debugf("resolved str variable ref refers to self: '%v'", varRef)
return resolvedVal
}
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", varRef, string(resolvedVal))
return r.ResolveStrRef(resolvedVal)
if callerRef != "" && strings.Contains(resolvedVal, callerRef) {
zap.S().Debugf("resolved str variable ref: '%v', value: '%v'", varRef, string(resolvedVal))
return resolvedVal
}
return r.ResolveStrRef(resolvedVal, varRef)
}

// return extracted value
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"aws_iam_user": [
{
"id": "aws_iam_user.lb",
"name": "lb",
"source": "dummy/main.tf",
"line": 13,
"type": "aws_iam_user",
"config": {
"name": "${lower(var.bar != null ? var.bar : var.foo)}"
},
"skip_rules": null
}
]
}
"aws_iam_user": [
{
"id": "aws_iam_user.lb",
"name": "lb",
"source": "dummy/main.tf",
"line": 13,
"type": "aws_iam_user",
"config": {
"name": "${lower(${local.foo} != null ? var.bar : var.foo)}"
},
"skip_rules": null
}
]
}

0 comments on commit 2545350

Please sign in to comment.