Skip to content

Commit 5bcfcf4

Browse files
committed
chore: fix param hook to correctly set count based block values
1 parent 296359b commit 5bcfcf4

File tree

2 files changed

+82
-2
lines changed

2 files changed

+82
-2
lines changed

hclext/merge.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package hclext
2+
3+
import "github.com/zclconf/go-cty/cty"
4+
5+
func MergeObjects(a, b cty.Value) cty.Value {
6+
output := make(map[string]cty.Value)
7+
8+
for key, val := range a.AsValueMap() {
9+
output[key] = val
10+
}
11+
b.ForEachElement(func(key, val cty.Value) (stop bool) {
12+
k := key.AsString()
13+
old := output[k]
14+
if old.IsKnown() && isNotEmptyObject(old) && isNotEmptyObject(val) {
15+
output[k] = MergeObjects(old, val)
16+
} else {
17+
output[k] = val
18+
}
19+
return false
20+
})
21+
return cty.ObjectVal(output)
22+
}
23+
24+
func isNotEmptyObject(val cty.Value) bool {
25+
return !val.IsNull() && val.IsKnown() && val.Type().IsObjectType() && val.LengthInt() > 0
26+
}

paramhook.go

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"github.com/aquasecurity/trivy/pkg/iac/terraform"
55
tfcontext "github.com/aquasecurity/trivy/pkg/iac/terraform/context"
66
"github.com/zclconf/go-cty/cty"
7+
8+
"github.com/coder/preview/hclext"
79
)
810

911
// ParameterContextsEvalHook is called in a loop, so if parameters affect
@@ -24,6 +26,21 @@ func ParameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks
2426
continue // Wow a value exists?!. This feels like a bug.
2527
}
2628

29+
countAttr, countExists := block.Attributes()["count"]
30+
if countExists {
31+
// Omit count = 0 values!
32+
countVal := countAttr.Value()
33+
if !countVal.Type().Equals(cty.Number) {
34+
continue // Probably unknown
35+
}
36+
v, _ := countVal.AsBigFloat().Int64()
37+
if v < 1 {
38+
// Non-one counts are incorrect
39+
// Zero counts are ignored as the blocks are omitted
40+
continue
41+
}
42+
}
43+
2744
nameAttr := block.GetAttribute("name")
2845
nameVal := nameAttr.Value()
2946
if !nameVal.Type().Equals(cty.String) {
@@ -48,8 +65,44 @@ func ParameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks
4865
}
4966

5067
// Set the default value as the 'value' attribute
51-
path := []string{"data"}
52-
path = append(path, block.Labels()...)
68+
path := []string{
69+
"data",
70+
"coder_parameter",
71+
block.Reference().NameLabel(),
72+
}
73+
if countExists {
74+
// Append to the existing tuple
75+
existing := ctx.Get(path...)
76+
if existing.IsNull() {
77+
continue
78+
}
79+
80+
if !existing.Type().IsTupleType() {
81+
continue
82+
}
83+
84+
if existing.LengthInt() > 1 {
85+
// coder_parameters can only ever have a count of 0 or 1.
86+
// More than that is invalid. So ignore invalid blocks.
87+
continue
88+
}
89+
90+
it := existing.ElementIterator()
91+
if !it.Next() {
92+
continue
93+
}
94+
95+
_, v := it.Element()
96+
merged := hclext.MergeObjects(v, cty.ObjectVal(map[string]cty.Value{
97+
"value": value,
98+
}))
99+
100+
// Since our count can only equal 1, we can safely set the
101+
// value to a tuple of length 1 in all cases.
102+
ctx.Set(cty.TupleVal([]cty.Value{merged}), path...)
103+
continue
104+
}
105+
53106
path = append(path, "value")
54107
// The current context is in the `coder_parameter` block.
55108
// Use the parent context to "export" the value
@@ -104,5 +157,6 @@ func evaluateCoderParameterDefault(b *terraform.Block) (cty.Value, bool) {
104157
if diags.HasErrors() {
105158
return cty.NilVal, false
106159
}
160+
107161
return v, true
108162
}

0 commit comments

Comments
 (0)