如何在Terragrunt中用for_each动态执行依赖块实现多环境DRY?
问题描述
你当前在多环境Terragrunt配置中面临重复定义依赖块和硬编码环境信息的问题,现有重复的依赖块如下:
dependency "development" { config_path = "../../development/mandatory_resources" } dependency "production" { config_path = "../../production/mandatory_resources" }
同时在inputs中硬编码环境映射:
inputs = { projects = { "dev" = dependency.development.outputs.shared_resources_project_id, "prod" = dependency.production.outputs.shared_resources_project_id, } }
你已经有来自前置阶段的环境映射dependency.retrospect.outputs.available_environments,结构如下:
{ "dev" = "development", "prod" = "production", }
希望找到无需重复编写依赖块、硬编码环境,且支持扩展N个环境的优雅实现方式,询问Terragrunt是否支持类似for_each的指令。
解决方案
Terragrunt完全支持这种动态化需求,你可以通过generate blocks配合遍历逻辑来动态生成依赖块,再结合Terraform内置函数构建动态inputs,实现完全的DRY配置。
1. 动态生成依赖块
使用generate "dependency"块,遍历前置阶段输出的环境映射,自动生成对应名称的依赖块:
generate "dependency" { path = "dependencies.hcl" if_exists = "overwrite" contents = <<EOF ${join("\n\n", [ "dependency \"${env_name}\" {", " config_path = \"../../${env_name}/mandatory_resources\"", "}" for _, env_name in values(dependency.retrospect.outputs.available_environments) ])} EOF }
这段代码会遍历available_environments的所有值(如"development"、"production"),为每个值生成对应的dependency块,并写入到dependencies.hcl文件中,Terragrunt会自动加载该文件。
2. 动态构建inputs中的projects映射
不再硬编码环境映射,而是通过遍历available_environments动态生成projects对象:
inputs = { projects = { for short_name, env_name in dependency.retrospect.outputs.available_environments : short_name => dependency[env_name].outputs.shared_resources_project_id } }
这里使用Terraform的for表达式,遍历环境映射的键值对,将短名称(如"dev")作为键,对应依赖块的输出值作为值,自动构建完整的projects映射。
3. 扩展支持N个环境
后续只需在前置阶段的available_environments中添加新的环境映射(比如"staging" = "staging"),上述配置会自动生成对应的依赖块并更新projects输入,无需手动修改当前配置文件,完全实现可扩展的多环境支持。
内容的提问来源于stack exchange,提问作者Gabriele B

