如何用jq合并多个输出对象为单个对象及解析Terraform状态文件
Hey there! Let's break down how to parse your Terraform state file and combine all module outputs into a single object using jq.
First, let's make your state file easier to read (formatted properly):
{ "version": 3, "terraform_version": "0.9.3", "serial": 0, "lineage": "ae1f2572-8fa6-4977-be73-3deac7529eff", "modules": [ { "path": [ "root" ], "outputs": { "elb_dns_name": { "sensitive": false, "type": "string", "value": "web-elb-1019323532.us-east-1.elb.amazonaws.com" } }, "resources": {}, "depends_on": [] }, { "path": [ "root", "elb" ], "outputs": { "dns_name": { "sensitive": false, "type": "string", "value": "web-elb-1019323532.us-ea..." } } } ] }
基础合并:保留完整输出结构
To merge all the outputs objects from every module into one, use this jq command:
jq '.modules | map(.outputs) | reduce .[] as $item ({}; . * $item)' terraform.tfstate
Let's break down what each part does:
.modules: Targets the array of modules in your state filemap(.outputs): Extracts just theoutputsobject from each modulereduce .[] as $item ({}; . * $item): Iterates over each extracted output object, merging them into a single empty starting object. The*operator combines objects, with later keys overriding earlier ones if there's a name conflict (which shouldn't happen with properly named Terraform outputs).
Running this on your state file will give you:
{ "elb_dns_name": { "sensitive": false, "type": "string", "value": "web-elb-1019323532.us-east-1.elb.amazonaws.com" }, "dns_name": { "sensitive": false, "type": "string", "value": "web-elb-1019323532.us-ea..." } }
简化合并:只提取输出值
If you don't need the full metadata (like sensitive or type) and just want the actual output values, tweak the command to extract the value field directly:
jq '.modules | map(.outputs | with_entries(.value = .value.value)) | reduce .[] as $item ({}; . * $item)' terraform.tfstate
The with_entries(.value = .value.value) part transforms each output entry to replace the full object with just its value property. The result will be:
{ "elb_dns_name": "web-elb-1019323532.us-east-1.elb.amazonaws.com", "dns_name": "web-elb-1019323532.us-ea..." }
注意事项
- If you have duplicate output keys across modules, the later module's output will overwrite the earlier one (this is how jq's object merge works). If you need to handle duplicates (e.g., collect values into an array), you'd need a slightly more complex reduce logic, but that's rarely necessary for Terraform setups.
内容的提问来源于stack exchange,提问作者Levi

