Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

jq: how to select entries containing element in a mixed (scalar/list) value

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

$ 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 ?

>Solution :

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

Demo

Actually, there is a built-in shortcut to select(type=="array") called arrays, so this is equivalent:

.Statement[].Action | arrays[] | contains("s3:GetObject")

Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading