Skip to content

Commit

Permalink
Merge pull request #656 from hashicorp/improve-dynamic-block-error-me…
Browse files Browse the repository at this point in the history
…ssage

prefer iterator error over for_each
  • Loading branch information
DanielMSchmidt committed Feb 14, 2024
2 parents 1e1a6b8 + d72c32f commit 772d004
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 22 deletions.
78 changes: 78 additions & 0 deletions ext/dynblock/expand_body_test.go
Expand Up @@ -709,3 +709,81 @@ func TestExpandUnknownBodies(t *testing.T) {
})

}

func TestExpandInvalidIteratorError(t *testing.T) {
srcBody := hcltest.MockBody(&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "dynamic",
Labels: []string{"b"},
LabelRanges: []hcl.Range{hcl.Range{}},
Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"for_each": hcltest.MockExprLiteral(cty.ListVal([]cty.Value{
cty.StringVal("dynamic b 0"),
cty.StringVal("dynamic b 1"),
})),
"iterator": hcltest.MockExprLiteral(cty.StringVal("dyn_b")),
}),
Blocks: hcl.Blocks{
{
Type: "content",
Body: hcltest.MockBody(&hcl.BodyContent{
Blocks: hcl.Blocks{
{
Type: "c",
Body: hcltest.MockBody(&hcl.BodyContent{
Attributes: hcltest.MockAttrs(map[string]hcl.Expression{
"val0": hcltest.MockExprLiteral(cty.StringVal("static c 1")),
"val1": hcltest.MockExprTraversalSrc("dyn_b.value"),
}),
}),
},
},
}),
},
},
}),
},
},
})

dynBody := Expand(srcBody, nil)

t.Run("Decode", func(t *testing.T) {
decSpec := &hcldec.BlockListSpec{
TypeName: "b",
Nested: &hcldec.BlockListSpec{
TypeName: "c",
Nested: &hcldec.ObjectSpec{
"val0": &hcldec.AttrSpec{
Name: "val0",
Type: cty.String,
},
"val1": &hcldec.AttrSpec{
Name: "val1",
Type: cty.String,
},
},
},
}

var diags hcl.Diagnostics
_, diags = hcldec.Decode(dynBody, decSpec, nil)

if len(diags) < 1 {
t.Errorf("Expected diagnostics, got none")
}
if len(diags) > 1 {
t.Errorf("Expected one diagnostic message, got %d", len(diags))
for _, diag := range diags {
t.Logf("- %s", diag)
}
}

if diags[0].Summary != "Invalid expression" {
t.Errorf("Expected error subject to be invalid expression, instead it was %q", diags[0].Summary)
}
})

}
46 changes: 24 additions & 22 deletions ext/dynblock/expand_spec.go
Expand Up @@ -38,6 +38,29 @@ func (b *expandBody) decodeSpec(blockS *hcl.BlockHeaderSchema, rawSpec *hcl.Bloc
return nil, diags
}

//// iterator attribute

iteratorName := blockS.Type
if iteratorAttr := specContent.Attributes["iterator"]; iteratorAttr != nil {
itTraversal, itDiags := hcl.AbsTraversalForExpr(iteratorAttr.Expr)
diags = append(diags, itDiags...)
if itDiags.HasErrors() {
return nil, diags
}

if len(itTraversal) != 1 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic iterator name",
Detail: "Dynamic iterator must be a single variable name.",
Subject: itTraversal.SourceRange().Ptr(),
})
return nil, diags
}

iteratorName = itTraversal.RootName()
}

//// for_each attribute

eachAttr := specContent.Attributes["for_each"]
Expand Down Expand Up @@ -80,28 +103,7 @@ func (b *expandBody) decodeSpec(blockS *hcl.BlockHeaderSchema, rawSpec *hcl.Bloc
return nil, diags
}

//// iterator attribute

iteratorName := blockS.Type
if iteratorAttr := specContent.Attributes["iterator"]; iteratorAttr != nil {
itTraversal, itDiags := hcl.AbsTraversalForExpr(iteratorAttr.Expr)
diags = append(diags, itDiags...)
if itDiags.HasErrors() {
return nil, diags
}

if len(itTraversal) != 1 {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid dynamic iterator name",
Detail: "Dynamic iterator must be a single variable name.",
Subject: itTraversal.SourceRange().Ptr(),
})
return nil, diags
}

iteratorName = itTraversal.RootName()
}
//// labels attribute

var labelExprs []hcl.Expression
if labelsAttr := specContent.Attributes["labels"]; labelsAttr != nil {
Expand Down

0 comments on commit 772d004

Please sign in to comment.