in hcl_block.go [67:135]
func (hb *HclBlock) ExpandDynamicBlocks(evalContext *hcl.EvalContext) (*HclBlock, error) {
newHb := &HclBlock{
Block: hb.Block,
wb: hb.wb,
ForEach: hb.ForEach,
attributes: hb.attributes,
blocks: []*HclBlock{},
}
var newNestedBlocks []*hclsyntax.Block
for _, block := range hb.blocks {
if block.Type != "dynamic" {
expandedBlock, err := block.ExpandDynamicBlocks(evalContext)
if err != nil {
return nil, err
}
if err = expandedBlock.evaluateAttributes(evalContext); err != nil {
return nil, err
}
newHb.blocks = append(newHb.blocks, expandedBlock)
newNestedBlocks = append(newNestedBlocks, expandedBlock.Block)
continue
}
forEachAttr, ok := block.Attributes()["for_each"]
if !ok {
return nil, fmt.Errorf("`dynamic` block must have `for_each` attribute")
}
forEachValue, diag := forEachAttr.Expr.Value(evalContext)
if diag.HasErrors() {
return nil, diag
}
if !forEachValue.CanIterateElements() {
return nil, fmt.Errorf("incorrect type for `for_each`, must be a collection")
}
iterator := forEachValue.ElementIterator()
for iterator.Next() {
_, value := iterator.Element()
newContext := evalContext.NewChild()
newContext.Variables = map[string]cty.Value{
block.Labels[0]: cty.ObjectVal(map[string]cty.Value{
"value": value,
}),
}
for _, innerBlock := range block.blocks {
innerBlock = CloneHclBlock(innerBlock)
if innerBlock.Type != "content" {
return nil, fmt.Errorf("`dynamic` block should contain `content` block only")
}
expandedInnerBlock, err := innerBlock.ExpandDynamicBlocks(newContext)
if err != nil {
return nil, err
}
expandedInnerBlock.Type = block.Labels[0]
if err = expandedInnerBlock.evaluateAttributes(newContext); err != nil {
return nil, err
}
newHb.blocks = append(newHb.blocks, expandedInnerBlock)
newNestedBlocks = append(newNestedBlocks, expandedInnerBlock.Block)
}
}
}
newHb.Body.Blocks = newNestedBlocks
return newHb, nil
}