Reputation: 3306
The Question - Why does jq generate lines with values, instead of generating the built-in json array? (I've tried using [.[]]
with no success)
The code snippet @ jqplay.org - https://jqplay.org/s/IDhVa5KID8
The Challenge - Generate an array of allowed Actions (Effect == Allow
).
IAM Policy (input)
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "cloudformation:UpdateStack",
"Resource": "arn:aws:cloudformation:eu-west-1:123456789012:stack/sokker-stack-dev/*",
"Effect": "Allow"
},
{
"Action": [
"lambda:UpdateFunctionConfiguration",
"lambda:InvokeFunction"
],
"Resource": "arn:aws:lambda:eu-west-1:123456789012:function:sokker-api-dev-GetApiKeyValueFunction-MYDISTRIBID",
"Effect": "Allow"
},
{
"Action": [
"cloudfront:GetDistribution",
"cloudfront:UpdateDistribution"
],
"Resource": "arn:aws:cloudfront::*:distribution/MYDISTRIBID",
"Effect": "Allow"
},
{
"Action": [
"apigateway:GET",
"apigateway:HEAD",
"apigateway:OPTIONS",
"apigateway:PUT",
"iam:GetRole",
"iam:PassRole",
"lambda:GetFunctionConfiguration"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
My Solution (not good enough):
jq '.Statement | map(select(.Effect == "Allow"))[].Action | if type == "string" then . else .[] end' iampolicy.json
My Solution's Output:
# Why is it a list of values? Why isn't it a json array?
"cloudformation:UpdateStack"
"lambda:UpdateFunctionConfiguration"
"lambda:InvokeFunction"
"cloudfront:GetDistribution"
"cloudfront:UpdateDistribution"
"apigateway:GET"
"apigateway:HEAD"
"apigateway:OPTIONS"
"apigateway:PUT"
"iam:GetRole"
"iam:PassRole"
"lambda:GetFunctionConfiguration"
Desired output:
[
"cloudformation:UpdateStack",
"lambda:UpdateFunctionConfiguration",
"lambda:InvokeFunction",
"cloudfront:GetDistribution",
"cloudfront:UpdateDistribution",
"apigateway:GET",
"apigateway:HEAD",
"apigateway:OPTIONS",
"apigateway:PUT",
"iam:GetRole",
"iam:PassRole",
"lambda:GetFunctionConfiguration"
]
Upvotes: 0
Views: 656
Reputation: 116780
The last part of your jq pipeline is:
| .[]
This results in the stream that you don't want. One solution therefore would be to enclose your entire expression in square brackets; one of several better alternatives would be:
.Statement
| [.[]
| select(.Effect == "Allow")
| .Action
| if type == "string" then . else .[] end ]
Upvotes: 3
Reputation: 3306
Ok that was silly, surrounding my final output with []
did the trick
.Statement | [map(select(.Effect == "Allow"))[].Action | if type == "string" then . else .[] end]
Upvotes: 1