hcl icon indicating copy to clipboard operation
hcl copied to clipboard

How to create an array of non-quoted identifiers

Open zfLQ2qx2 opened this issue 8 months ago • 1 comments

I am trying to create this structure:

resource "aws_network_acl" "main-private" {
  vpc_id     = aws_vpc.main.id
  subnet_ids = [aws_subnet.a.id, aws_subnet.b.id, aws_subnet.c.id, aws_subnet.d.id, aws_subnet.e.id, aws_subnet.f.id]
  tags {
    Name = "main-private"
  }
}

I'm not sure what is the best way to create the array of non-quoted identifiers - this works but I'm not sure if its optimal, and I'm thinking the tokens should wrap at some point but hclwriite doesn't seem to be doing it.

subnetIds := []string{"aws_subnet.a.id", "aws_subnet.b.id", "aws_subnet.c.id", "aws_subnet.d.id", "aws_subnet.e.id", "aws_subnet.f.id"}
var subnetTokens []hclwrite.Tokens
for _, id := range subnetIds {
        tokens := hclwrite.TokensForIdentifier(id)
        subnetTokens = append(subnetTokens, tokens)
}
privateNACLBody.SetAttributeRaw("subnet_ids", hclwrite.TokensForTuple(subnetTokens))

I had also come up with this which is easier on the eyes but the identifiers are quoted which they should not be:

	resourceBody.SetAttributeValue("subnet_ids", cty.ListVal([]cty.Value{
		cty.StringVal("aws_subnet.x.id"),
		cty.StringVal("aws_subnet.y.id"),
		cty.StringVal("aws_subnet.z.id"),
	}),
	)

zfLQ2qx2 avatar Jun 16 '25 15:06 zfLQ2qx2

An expression like aws_subnet.a.id is called a "traversal" in HCL's terminology: it "traverses" through symbols in the current scope.

Therefore you can construct tokens for an expression like that using hcl.TokensForTraversal. This API is a little weird because the hcl.Traversal type was designed primarily to represent a parsing result rather than as input to a code generator, but you can leave the various "source range" fields unpopulated when you are constructing a traversal purely for use with hclwrite.

aws_subnet.a.id is a traversal with three steps:

You can use the hclwrite.TokensForTraversal results with hclwrite.TokensForTuple to assemble the final result.

hclwrite's auto-formatting does not currently ever introduce new line breaks that were not present in the input; it focuses only on "horizontal" whitespace and alignment, such as indenting nested blocks. I don't think there is currently any "TokensFor..." function that will produce a tuple where each element is wrapped onto a separate line, so producing that particular layout would require constructing a custom hclwrite.Tokens to use for the outer tuple.

apparentlymart avatar Jun 16 '25 15:06 apparentlymart

@apparentlymart Thank you!

zfLQ2qx2 avatar Jun 21 '25 06:06 zfLQ2qx2