Search code examples
jsonansiblejinja2jmespath

Multiline var declaration in Ansible


I have a very long json_query that looks like this:

resources[?involvedObject.apiVersion == `v1` && involvedObject.kind == `Pod` && involvedObject.name==`my-name`].{ firstTimestamp: firstTimestamp, lastTimestamp: lastTimestamp, count: count, reason: reason, message: message }

I am using it in set_fact:

- name: Getting events
  set_fact:
    pod_events: " {{ events | json_query(events_query) }} "
  var:
    events_query: "resources[?involvedObject.apiVersion == `v1` && involvedObject.kind == `Pod` && involvedObject.name==`my-name`].{ firstTimestamp: firstTimestamp, lastTimestamp: lastTimestamp, count: count, reason: reason, message: message }"

While this works, I'd like to break the query with some newlines for readability. I tried > as well as >- and |replace('\n',''). No matter what I did the newlines in the query always persisted, leading to a broken json_query.

There has to be a way to break it, right?


Solution

  • After some trials and errors, on which I reproduced an error to the one similar that yours, I guess:

    FAILED! => {"msg": "JMESPathError in json_query filter plugin:\nBad jmespath expression: Unknown token ?:\nresources[ ?\n involvedObject.apiVersion == `v1` && \n involvedObject.kind == `Pod` && \n involvedObject.name==`my-name`\n].{ \n firstTimestamp: firstTimestamp, \n lastTimestamp: lastTimestamp, \n count: count, \n reason: reason, \n message: message \n}\n ^"}

    I went back to the JMESPath documentation about filter expressions to realise that the expression is delimited by [? and ] and this is quite important because is means that the question mark ? and the opening square bracket [ cannot be separated with a new line or a even a space, otherwise you will face the error here above.

    Once you have that in mind, you can do your multiline as you wish.
    Here would be an example of working playbook:

    - hosts: all
      gather_facts: no
      vars:
        events:
          resources:
            - firstTimestamp: '2020-10-27 10:00:00'
              lastTimestamp: '2020-10-27 12:00:00'
              count: 1
              reason: some reason
              message: some message
              involvedObject:
                apiVersion: v1
                kind: Pod
                name: my-name
    
      tasks:
        - set_fact:
            pod_events: "{{ events | json_query(events_query) }}"
          vars:
            events_query: >-
              resources[?
                involvedObject.apiVersion == `v1` && 
                involvedObject.kind == `Pod` && 
                involvedObject.name==`my-name`
              ].{ 
                firstTimestamp: firstTimestamp, 
                lastTimestamp: lastTimestamp, 
                count: count, 
                reason: reason, 
                message: message 
              }
    
        - debug:
            var: pod_events
    

    Yields the recap

    PLAY [all] *******************************************************************************************************
    
    TASK [set_fact] **************************************************************************************************
    ok: [localhost]
    
    TASK [debug] *****************************************************************************************************
    ok: [localhost] => {
        "pod_events": [
            {
                "count": 1,
                "firstTimestamp": "2020-10-27 10:00:00",
                "lastTimestamp": "2020-10-27 12:00:00",
                "message": "some message",
                "reason": "some reason"
            }
        ]
    }
    
    PLAY RECAP *******************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0