One section of my config gathers a bunch of local variables in a module and puts them in a mapping, so that they can all be dumped to Parameter Store. At first thought I’ve tried to do:
locals {
store_keys = ["aws_region", "ami", "sqs_arn", "vpc_id", "scheduler_subnet", "compute_subnets", "security_group", "ec2_access_key", "efs_dns_name", "efs_mount_ip"]
store_params = { for attr in local.store_keys : attr => local[attr] }
}
However this did not pass validation, Terraform basically complained that local
cannot be accessed like a map. In the end I’ve resorted to doing:
locals {
store_params = {
aws_region = local.aws_region
sqs_arn = local.sqs_arn
ami = local.ami
vpc_id = local.vpc_id
scheduler_subnet = local.scheduler_subnet
compute_subnets = local.compute_subnets
security_group = local.security_group
ec2_access_key = local.ec2_access_key
efs_dns_name = local.efs_dns_name
efs_mount_ip = local.efs_mount_ip
}
}
This works, but I’m thinking that surely there must be a better way to gather a large number of local variables? Is there something obvious that I’m missing?
For what it’s worth, I find the second version much more readable and understandable. Thinking about the people who need to read this code in the future, including you in a month or two, you may find this version preferable as well
1 Like
Indeed, this is the best way to write it if indeed you do need them both as individual local values and in the map, because Terraform uses those references to understand that local.store_params
depends on each of those other local values. As @kpfleming noted, it could also allow future readers to more easily understand what’s going on, but of course that’s subjective. The Terraform language design generally optimizes for the future reader over the initial author when their needs are in conflict, on the assumption that most configurations will be written once but read many times.
One way to simplify this further would be to remove the separate local values altogether and just put them literally inside the map:
locals {
store_params = {
aws_region = "us-west-2"
sqs_arn = "aws:arn:etc,etc"
ami = "ami-abc123"
}
}
Then elsewhere in the configuration you could say local.store_params.aws_region
instead of just local.aws_region
. Whether it’s more important to have a smaller locals
block or to have more direct references to the values inside is a design tradeoff; I’d personally do this only if those values are here only to be used as “store params”, and not as part of anything else.
Thanks a lot for the response guys. It’s nice to gain some insight into the design ethos of the config language.