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")
