Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(parser): Supports lists in for_each #117

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions pkg/scanners/terraform/parser/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,24 +241,24 @@ func validateForEachArg(arg cty.Value) error {
return nil
}

if !(ty.IsSetType() || ty.IsObjectType() || ty.IsMapType()) {
return fmt.Errorf("%s type is not supported: arg is not set or map", ty.FriendlyName())
if !(ty.IsListType() || ty.IsSetType() || ty.IsObjectType() || ty.IsMapType()) {
return fmt.Errorf("%s type is not supported: arg is not set, map, or list", ty.FriendlyName())
}

if ty.IsSetType() {
if ty.IsListType() || ty.IsSetType() {
if !ty.ElementType().Equals(cty.String) {
return errors.New("arg is not set of strings")
return errors.New("arg is not set or list of strings")
}

it := arg.ElementIterator()
for it.Next() {
key, _ := it.Element()
if key.IsNull() {
return errors.New("arg is set of strings, but contains null")
return errors.New("arg is set or list of strings, but contains null")
}

if !key.IsKnown() {
return errors.New("arg is set of strings, but contains unknown value")
return errors.New("arg is set or list of strings, but contains unknown value")
}
}
}
Expand Down Expand Up @@ -292,14 +292,22 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks) terraform.Bloc
clones := make(map[string]cty.Value)
_ = forEachAttr.Each(func(key cty.Value, val cty.Value) {

if !key.Type().Equals(cty.String) {
if !(key.Type().Equals(cty.String) || key.Type().Equals(cty.Number)) {
e.debug.Log(
`Invalid "for-each" argument: map key (or set value) is not a string, but %s`,
`Invalid "for-each" argument: key is not a string or number, but %s`,
key.Type().FriendlyName(),
)
return
}

var keyString string

if key.Type().Equals(cty.String) {
keyString = key.AsString()
} else {
keyString = key.AsBigFloat().Text('f', -1)
}

clone := block.Clone(key)

ctx := clone.Context()
Expand All @@ -315,7 +323,7 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks) terraform.Bloc
forEachFiltered = append(forEachFiltered, clone)

values := clone.Values()
clones[key.AsString()] = values
clones[keyString] = values
e.ctx.SetByDot(values, clone.GetMetadata().Reference())
})

Expand Down
8 changes: 4 additions & 4 deletions pkg/scanners/terraform/parser/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,22 @@ func TestValidateForEachArg(t *testing.T) {
{
name: "set of non-strings",
arg: cty.SetVal([]cty.Value{cty.NumberIntVal(1), cty.NumberIntVal(2)}),
expectedError: "is not set of strings",
expectedError: "is not set or list of strings",
},
{
name: "set with null",
arg: cty.SetVal([]cty.Value{cty.StringVal("val1"), cty.NullVal(cty.String)}),
expectedError: "arg is set of strings, but contains null",
expectedError: "arg is set or list of strings, but contains null",
},
{
name: "set with unknown",
arg: cty.SetVal([]cty.Value{cty.StringVal("val1"), cty.UnknownVal(cty.String)}),
expectedError: "arg is set of strings, but contains unknown",
expectedError: "arg is set or list of strings, but contains unknown",
},
{
name: "set with unknown",
arg: cty.SetVal([]cty.Value{cty.StringVal("val1"), cty.UnknownVal(cty.String)}),
expectedError: "arg is set of strings, but contains unknown",
expectedError: "arg is set or list of strings, but contains unknown",
},
{
name: "non empty map",
Expand Down