I need to select values that have lists with a special element in some attributes:
Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:ListBucket
Resource:
- Fn::Join:
- ''
- - 'arn:aws:s3:::'
- bucket*
- Fn::Join:
- ''
- - 'arn:aws:s3:::'
- bucket*
- Effect: Allow
Action: cloudformation:*
Resource:
- Fn::Join:
- ''
- - 'arn:aws:cloudformation:'
- Ref: AWS::Region
- ':'
- Ref: AWS::AccountId
- :stack/
- Ref: AWS::StackName
- /*
In this example, the first element must be selected, because its Action
contains s3:GetObject
.
If I try to use select
here, it does not work, because in the second element, Action
does not contain a list, and contains
can't iterate over it.
$ cat action.yaml | yq -y '.Statement[].Action[]|contains("s3:GetObject")
jq: error (at <stdin>:1): Cannot iterate over string ("cloudforma...)
I can check if the element contains a list, using type
:
$ cat action.yaml | yq -y '.Resources.InstanceRolePolicy.Properties.PolicyDocument.Statement[]|select(.Action|select(type=="array"))'
But how can I combine both checks in our select
?
CodePudding user response:
Put select(type=="array")
after traversing to an element (here .Statement[].Action
) but before trying to iterate over its items ([]
):
.Statement[].Action | select(type=="array")[] | contains("s3:GetObject")
Actually, there is a built-in shortcut to select(type=="array")
called arrays
, so this is equivalent:
.Statement[].Action | arrays[] | contains("s3:GetObject")