Skip to content

Commit 5cb436c

Browse files
authored
fix: nested maps not rendered if no value attribute is present. (#1957)
## What this PR does / why we need it: The nested `map` blocks are not rendered if the `value` block do not contain attributes. ## Which issue(s) this PR fixes: none ## Special notes for your reviewer: ## Does this PR introduce a user-facing change? ``` yes, fixes a bug. ```
2 parents dca70c8 + 1e232c3 commit 5cb436c

File tree

3 files changed

+129
-19
lines changed

3 files changed

+129
-19
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ Given a version number `MAJOR.MINOR.PATCH`, we increment the:
2626

2727
- Add `terramate.stack.parent.id` metadata to stacks that are part of a parent-child hierarchy.
2828

29+
### Fixed
30+
31+
- Nested `map` blocks not rendered if the `value` block contain no attributes.
32+
2933
## v0.11.1
3034

3135
### Added

globals/globals_map_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,109 @@ func TestGlobalsMap(t *testing.T) {
736736
),
737737
},
738738
},
739+
{
740+
name: "regression test: nested map not rendered with no flat attribute",
741+
layout: []string{"s:stack"},
742+
configs: []hclconfig{
743+
{
744+
path: "/",
745+
add: Globals(
746+
Expr("lst", `[
747+
{
748+
val: "a",
749+
lst: [1, 2, 3]
750+
},
751+
{
752+
val: "b",
753+
lst: [4, 5, 6]
754+
},
755+
{
756+
val: "c",
757+
lst: [7, 8, 9]
758+
}
759+
]`),
760+
Map(
761+
Labels("var"),
762+
Expr("for_each", `global.lst`),
763+
Expr("key", "element.new.val"),
764+
765+
Value(
766+
Map(
767+
Labels("var"),
768+
Expr("for_each", "element.new.lst"),
769+
Expr("key", "tm_tostring(el.new)"),
770+
Expr("value", "el.new"),
771+
Expr("iterator", "el"),
772+
),
773+
Map(
774+
Labels("var2"),
775+
Expr("for_each", "element.new.lst"),
776+
Expr("key", "tm_tostring(el2.new)"),
777+
Expr("value", "el2.new"),
778+
Expr("iterator", "el2"),
779+
),
780+
),
781+
),
782+
),
783+
},
784+
},
785+
want: map[string]*hclwrite.Block{
786+
"/stack": Globals(
787+
EvalExpr(t, "lst", `[
788+
{
789+
val: "a",
790+
lst: [1, 2, 3]
791+
},
792+
{
793+
val: "b",
794+
lst: [4, 5, 6]
795+
},
796+
{
797+
val: "c",
798+
lst: [7, 8, 9]
799+
}
800+
]`),
801+
EvalExpr(t, "var", `{
802+
a = {
803+
var = {
804+
"1" = 1
805+
"2" = 2
806+
"3" = 3
807+
}
808+
var2 = {
809+
"1" = 1
810+
"2" = 2
811+
"3" = 3
812+
}
813+
}
814+
b = {
815+
var = {
816+
"4" = 4
817+
"5" = 5
818+
"6" = 6
819+
}
820+
var2 = {
821+
"4" = 4
822+
"5" = 5
823+
"6" = 6
824+
}
825+
}
826+
c = {
827+
var = {
828+
"7" = 7
829+
"8" = 8
830+
"9" = 9
831+
}
832+
var2 = {
833+
"7" = 7
834+
"8" = 8
835+
"9" = 9
836+
}
837+
}
838+
}`),
839+
),
840+
},
841+
},
739842
} {
740843
testGlobals(t, tc)
741844
}

mapexpr/map.go

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
type MapExpr struct {
2020
Origin info.Range
2121
Attrs Attributes
22-
Children []*MapExpr
22+
Children []varMap
2323
}
2424

2525
// Attributes of the MapExpr block.
@@ -31,9 +31,14 @@ type Attributes struct {
3131
ValueBlock *ast.MergedBlock
3232
}
3333

34+
type varMap struct {
35+
Name string
36+
Map *MapExpr
37+
}
38+
3439
// NewMapExpr creates a new MapExpr instance.
3540
func NewMapExpr(block *ast.MergedBlock) (*MapExpr, error) {
36-
children := []*MapExpr{}
41+
children := []varMap{}
3742
var valueBlock *ast.MergedBlock
3843
for _, subBlock := range block.Blocks {
3944
if valueBlock != nil {
@@ -49,7 +54,10 @@ func NewMapExpr(block *ast.MergedBlock) (*MapExpr, error) {
4954
if err != nil {
5055
return nil, errors.E(err, "creating nested `map` expression")
5156
}
52-
children = append(children, m)
57+
children = append(children, varMap{
58+
Name: childBlock.Labels[0],
59+
Map: m,
60+
})
5361
}
5462
}
5563

@@ -167,23 +175,18 @@ func (m *MapExpr) Value(ctx *hhcl.EvalContext) (cty.Value, hhcl.Diagnostics) {
167175
}
168176

169177
valueMap[attr.Name] = attrVal
178+
}
170179

171-
for _, subBlock := range m.Attrs.ValueBlock.Blocks {
172-
childEvaluator := evaluator.Copy()
173-
// only `map` block allowed inside `value` block.
174-
subMap, err := NewMapExpr(subBlock)
175-
if err != nil {
176-
mapErr = errors.E(err, "evaluating nested %q map block", subBlock.Labels[0])
177-
return true
178-
}
179-
val, diags := subMap.Value(childEvaluator.Unwrap())
180-
if diags.HasErrors() {
181-
mapErr = errors.E(diags, "evaluating nested %q map block", subBlock.Labels[0])
182-
return true
183-
}
184-
185-
valueMap[subBlock.Labels[0]] = val
180+
for _, subMap := range m.Children {
181+
childEvaluator := evaluator.Copy()
182+
183+
val, diags := subMap.Map.Value(childEvaluator.Unwrap())
184+
if diags.HasErrors() {
185+
mapErr = errors.E(diags, "evaluating nested %q map block", subMap.Name)
186+
return true
186187
}
188+
189+
valueMap[subMap.Name] = val
187190
}
188191

189192
valVal = cty.ObjectVal(valueMap)
@@ -238,7 +241,7 @@ func (m *MapExpr) Variables() []hhcl.Traversal {
238241
}
239242

240243
for _, childMap := range m.Children {
241-
appendVars(childMap.Variables())
244+
appendVars(childMap.Map.Variables())
242245
}
243246
}
244247
return allvars

0 commit comments

Comments
 (0)