$ terraform -v
Terraform v0.13.2
aws_vpc_endpoint_service, exporting single indexed value of base_endpoint_dns_names
output "endpointinfo" {
value = aws_vpc_endpoint_service.epsvc.base_endpoint_dns_names.0
}
https://gist.github.com/tezzigator/42966402f94d12bc8eef573f37c595f2
Expected to see the leading string of that list output
Error: Invalid index
on modules/workload/main.tf line 202, in output "endpointinfo":
202: value = aws_vpc_endpoint_service.epsvc.base_endpoint_dns_names.0
This value does not have any indices.
If I simply export the entire aws_vpc_endpoint_service then I do get an actual list:
orangeendpointsvc = [
"vpce-svc-REDACTED.us-east-1.vpce.amazonaws.com",
]
But that comma there concerns me - seems like it shouldnt be there; I supposed that could be causing all this?
base_endpoint_dns_names is a set (an unordered collection) so it can't be indexed. If you want to use an index, you can call tolist():
output "endpointinfo" {
value = tolist(aws_vpc_endpoint_service.epsvc.base_endpoint_dns_names)[0]
}
I would caution you that it's safer to process all names returned in whatever code is using the output. Your particular example is returning a single end point, but since it's a set that's not guaranteed behavior.
@tezzigator Thanks for raising this.
As you suspect, the underlying cause is mis-documentation of the dns_names attribute as "list" rather than "set".
There are many other such related issues (just a sample):
@ewbankkit I don't see base_endpoint_dns_names documented as a list or a set explicitly. I agree the documentation should be better about showing the expected types though.
I'd like to contribute to this, is there any concensus on the best way to handle this? I think I can work around the problem by adding a code example using tolist () to the documentation about base_endpoint_dns_names.
I'm not sure it's recommended to do so, so I'm not sure the documentation should include that as an example. Generally, if an item is a set, it means the ordering isn't relevant or guaranteed from the API. So converting it to a list and processing items by an index can result in unnecessary resource modification/recreation if the ordering changes. I think the recommended way to process a set is with the for_each directive.
More specifically in the use case here, the user may be assuming that there's only a single name to process and is trying to index into the set to get access to that name as a string. While that may be a way to meet their goal at a tactical level, I don't think it's a strategy that should be encouraged as it's fragile.
Would a valid solution be to make it standard to include the type being returned in the docs under Attributes Reference?
eg:
In addition to all arguments above, the following attributes are exported:
acceptance_required - bool - Whether or not VPC endpoint connection requests to the service must be accepted by the service owner - true or false.arn - string - The Amazon Resource Name (ARN) of the VPC endpoint service.availability_zones - list(string) - The Availability Zones in which the service is available.base_endpoint_dns_names - set(string) - The DNS names for the service.Personally I'd like that. I feel like it would be good if it was a terraform wide standard change, so I'm not sure what the protocol is for changing the format just in the AWS provider. But I've had more than one occasion where I've had to lookup the return type because it's not obvious, so I think this is desirable.
I agree. I think it is desirable that the return type is documented.