Skip to content

Commit

Permalink
fix(misconf): properly expand dynamic blocks (#7612)
Browse files Browse the repository at this point in the history
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io>
Co-authored-by: Simar <simar@linux.com>
  • Loading branch information
nikpivkin and simar7 authored Oct 19, 2024
1 parent c225883 commit 8d5dbc9
Show file tree
Hide file tree
Showing 5 changed files with 409 additions and 214 deletions.
2 changes: 1 addition & 1 deletion pkg/iac/scanners/terraform/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ resource "something" "else" {
for_each = toset(["true"])
content {
ok = each.value
ok = blah.value
}
}
}
Expand Down
49 changes: 7 additions & 42 deletions pkg/iac/scanners/terraform/parser/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,48 +260,28 @@ func (e *evaluator) evaluateSteps() {
}

func (e *evaluator) expandBlocks(blocks terraform.Blocks) terraform.Blocks {
return e.expandDynamicBlocks(e.expandBlockForEaches(e.expandBlockCounts(blocks), false)...)
return e.expandDynamicBlocks(e.expandBlockForEaches(e.expandBlockCounts(blocks))...)
}

func (e *evaluator) expandDynamicBlocks(blocks ...*terraform.Block) terraform.Blocks {
for _, b := range blocks {
e.expandDynamicBlock(b)
}
return blocks
}

func (e *evaluator) expandDynamicBlock(b *terraform.Block) {
for _, sub := range b.AllBlocks() {
e.expandDynamicBlock(sub)
}
for _, sub := range b.AllBlocks().OfType("dynamic") {
if sub.IsExpanded() {
continue
}
blockName := sub.TypeLabel()
expanded := e.expandBlockForEaches(terraform.Blocks{sub}, true)
for _, ex := range expanded {
if content := ex.GetBlock("content"); content.IsNotNil() {
_ = e.expandDynamicBlocks(content)
b.InjectBlock(content, blockName)
}
}
if len(expanded) > 0 {
sub.MarkExpanded()
if err := b.ExpandBlock(); err != nil {
e.logger.Error(`Failed to expand dynamic block.`,
log.String("block", b.FullName()), log.Err(err))
}
}
return blocks
}

func isBlockSupportsForEachMetaArgument(block *terraform.Block) bool {
return slices.Contains([]string{
"module",
"resource",
"data",
"dynamic",
}, block.Type())
}

func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool) terraform.Blocks {
func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks) terraform.Blocks {

var forEachFiltered terraform.Blocks

Expand Down Expand Up @@ -348,7 +328,7 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool
// is the value of the collection. The exception is the use of for-each inside a dynamic block,
// because in this case the collection element may not be a primitive value.
if (forEachVal.Type().IsCollectionType() || forEachVal.Type().IsTupleType()) &&
!forEachVal.Type().IsMapType() && !isDynamic {
!forEachVal.Type().IsMapType() {
stringVal, err := convert.Convert(val, cty.String)
if err != nil {
e.logger.Error(
Expand All @@ -374,22 +354,7 @@ func (e *evaluator) expandBlockForEaches(blocks terraform.Blocks, isDynamic bool

ctx.Set(eachObj, "each")
ctx.Set(eachObj, block.TypeLabel())

if isDynamic {
if iterAttr := block.GetAttribute("iterator"); iterAttr.IsNotNil() {
refs := iterAttr.AllReferences()
if len(refs) == 1 {
ctx.Set(idx, refs[0].TypeLabel(), "key")
ctx.Set(val, refs[0].TypeLabel(), "value")
} else {
e.logger.Debug("Ignoring iterator attribute in dynamic block, expected one reference",
log.Int("refs", len(refs)))
}
}
}

forEachFiltered = append(forEachFiltered, clone)

clones[idx.AsString()] = clone.Values()
})

Expand Down
Loading

0 comments on commit 8d5dbc9

Please sign in to comment.