I am attempting to use jq to parse a AWS CloudFront configuration JSON file and change a few values so that I can then issue an update statement with that configuration.
The Document
The document format snippet that matters, with redacted values, is:
{
"ETag": "REDACTED",
"DistributionConfig": {
"Origins": {
"Quantity": 2,
"Items": [
{
"Id": "redacted-1",
"DomainName": "redacted1.us-east-1.amazonaws.com",
"OriginPath": "/redacted"
},
{
"Id": "redacted-2",
"DomainName": "redacted2.s3.amazonaws.com",
"OriginPath": ""
}
]
}
}
}
What I'm trying to do
I want to output the entire document, but:
- I want to set the
ETag
value to""
- On the 2nd item in the items array, I want to set the
OriginPath
to a value of my choosing
(this is to support our CI/CD process being able to point the CloudFront distribution to a new folder of just-deployed code within an S3 bucket. I want to modify the existing configuration in those specific ways but leave the rest in-tact.)
Something that works...sort of
A jq filter of . | (.DistributionConfig.Origins.Items[1].OriginPath = "Hello") | .ETag = ""
does what I need it to do, resulting in:
{
"ETag": "", // correctly updated
"DistributionConfig": {
"Origins": {
"Quantity": 2, // correctly retained
"Items": [
{
"Id": "redacted-1",
"DomainName": "redacted1.us-east-1.amazonaws.com",
"OriginPath": "/redacted"
},
{
"Id": "redacted-2",
"DomainName": "redacted2.s3.amazonaws.com",
"OriginPath": "Hello" // correctly updated
}
]
}
}
}
Where I'm having trouble
The solution above works...as long as I'm referring to the 2nd item in the array. But I'm not always sure it will be the second item in the array.
So instead, I'd like to match based on the Id
property.
Any solutions I've been able to find that do this seem to filter the document to that section of JSON, rather than matching and updating the value as part of outputting the document.
Question
How can I filter an array for a field that has a certain value, and still output the whole document?
Or put another way -- given the document above, how can I change:
. | (.DistributionConfig.Origins.Items[1].OriginPath = "Hello") | .ETag = ""
To something that lets me refer to .Id="redaacted-2"
rather than Items[1]
?
A link to a demo
Demo of the script at https://jqplay.org/s/ZQ7XcM5-BY in case anyone wants to try an answer.