Skip to content

Commit

Permalink
hcldec: Allow body-derived values to be marked
Browse files Browse the repository at this point in the history
Similar to the previously-added UnknownBody, the new optional interface
MarkedBody allows hcl.Body implementations to suggest a set of marks that
ought to be applied to any value that's generated to represent the content
of that body.

The dynblock extension then uses this to get hcldec to mark the whole
object representing any block that was generated by a dynamic block whose
for_each was marked, for a better representation of the fact that a
block's existence was decided based on a marked value.
  • Loading branch information
apparentlymart committed May 9, 2024
1 parent 9a64c17 commit 318bbfe
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 2 deletions.
5 changes: 5 additions & 0 deletions ext/dynblock/expand_body.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,8 @@ func (b *expandBody) JustAttributes() (hcl.Attributes, hcl.Diagnostics) {
func (b *expandBody) MissingItemRange() hcl.Range {
return b.original.MissingItemRange()
}

// hcldec.MarkedBody impl
func (b *expandBody) BodyValueMarks() cty.ValueMarks {
return b.valueMarks
}
2 changes: 1 addition & 1 deletion ext/dynblock/expand_body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ func TestExpandMarkedForEach(t *testing.T) {
cty.ObjectVal(map[string]cty.Value{
"val0": cty.StringVal("static c 1").Mark("boop"),
"val1": cty.StringVal("hey").Mark("boop"),
}),
}).Mark("boop"),
})
got, diags := hcldec.Decode(dynBody, decSpec, nil)
if diags.HasErrors() {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7
github.com/spf13/pflag v1.0.2
github.com/zclconf/go-cty v1.13.0
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167
golang.org/x/tools v0.6.0
)
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b h1:FosyBZYxY34Wul7O/MSKey3txpPYyCqVO5ZyceuQJEI=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
github.com/zclconf/go-cty-debug v0.0.0-20240417160409-8c45e122ae1a h1:/o/Emn22dZIQ7AhyA0aLOKo528WG/WRAM5tqzIoQIOs=
github.com/zclconf/go-cty-debug v0.0.0-20240417160409-8c45e122ae1a/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0=
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
Expand Down
19 changes: 19 additions & 0 deletions hcldec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ type UnknownBody interface {
Unknown() bool
}

// MarkedBody can be optionally implemented by an hcl.Body instance to
// indicate that a value created from it ought to be marked.
type MarkedBody interface {
BodyValueMarks() cty.ValueMarks
}

func (s ObjectSpec) visitSameBodyChildren(cb visitFunc) {
for _, c := range s {
cb(c)
Expand Down Expand Up @@ -473,6 +479,7 @@ func (s *BlockListSpec) decode(content *hcl.BodyContent, blockLabels []blockLabe

val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)
diags = append(diags, childDiags...)
val = prepareBodyVal(val, childBlock.Body)

if u, ok := childBlock.Body.(UnknownBody); ok {
if u.Unknown() {
Expand Down Expand Up @@ -635,6 +642,7 @@ func (s *BlockTupleSpec) decode(content *hcl.BodyContent, blockLabels []blockLab

val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)
diags = append(diags, childDiags...)
val = prepareBodyVal(val, childBlock.Body)

if u, ok := childBlock.Body.(UnknownBody); ok {
if u.Unknown() {
Expand Down Expand Up @@ -758,6 +766,7 @@ func (s *BlockSetSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel

val, _, childDiags := decode(childBlock.Body, labelsForBlock(childBlock), ctx, s.Nested, false)
diags = append(diags, childDiags...)
val = prepareBodyVal(val, childBlock.Body)

if u, ok := childBlock.Body.(UnknownBody); ok {
if u.Unknown() {
Expand Down Expand Up @@ -928,6 +937,7 @@ func (s *BlockMapSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel

childLabels := labelsForBlock(childBlock)
val, _, childDiags := decode(childBlock.Body, childLabels[len(s.LabelNames):], ctx, s.Nested, false)
val = prepareBodyVal(val, childBlock.Body)
targetMap := elems
for _, key := range childBlock.Labels[:len(s.LabelNames)-1] {
if _, exists := targetMap[key]; !exists {
Expand Down Expand Up @@ -1082,6 +1092,7 @@ func (s *BlockObjectSpec) decode(content *hcl.BodyContent, blockLabels []blockLa

childLabels := labelsForBlock(childBlock)
val, _, childDiags := decode(childBlock.Body, childLabels[len(s.LabelNames):], ctx, s.Nested, false)
val = prepareBodyVal(val, childBlock.Body)
targetMap := elems
for _, key := range childBlock.Labels[:len(s.LabelNames)-1] {
if _, exists := targetMap[key]; !exists {
Expand Down Expand Up @@ -1720,3 +1731,11 @@ func (s noopSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel
Filename: "noopSpec",
}
}

func prepareBodyVal(decodeResult cty.Value, body hcl.Body) cty.Value {
if m, ok := body.(MarkedBody); ok {
marks := m.BodyValueMarks()
return decodeResult.WithMarks(marks)
}
return decodeResult
}

0 comments on commit 318bbfe

Please sign in to comment.