0

I am trying to run an ansible "uri" task that fetches the status in an "until" loop till the status returned is either SUCCESS or FAILED. My task looks like this:

- name: Fetching recycle status
  uri:
    url: "http://{{ restarter }}/status?job_id={{ item }}"
    method: GET
    body_format: json
    headers:
      Accept: 'application/json'
    return_content: yes
  register: restart_status
  with_items:
     - 14502414
     - 14552415
  until: (restart_status.results|json_query('[*].json')| json_query('[*][*].status')|flatten) in ['SUCCESS', 'FAILED']

restart_status is a variable that contains the json payload that is returned and it looks like this:

{
        "changed": false,
        "results": [
            {
                "_ansible_ignore_errors": null,
                "item": 14502414,
                "json": [
                    {
                        "created_date": 1635348569000,
                        "job": {
                            "application_name": "testapp",
                            "id": 14552414,
                            "user": "gui"
                        },
                        "status": "FAILED"
                    }
                ],
                "vary": "Accept-Encoding"
            },
            {
                "_ansible_ignore_errors": null,
                "item": 14552415,
                "json": [
                    {
                        "created_date": 1635348569000,
                        "job": {
                            "application_name": "testapp",
                            "id": 14502415,
                            "user": "gui"
                        },
                        "status": "FAILED"
                    }
                ],
                "vary": "Accept-Encoding"
            }
        ]
    }

The output of (restart_status.results|json_query('[].json')| json_query('[][*].status')|flatten) is

ok: [localhost] => {
    "msg": [
        "FAILED",
        "FAILED"
    ]
}

I somehow cant seem to get the until clause to work.I have tried multiple things like "contain", "in" ,"not in", ==, but none of it is working. This is the error that is thrown.

TASK [Fetching recycle status] **************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "The conditional check '(restart_status.results|json_query('[*].json')| json_query('[*][*].status')|flatten) not in ['INIT', 'PROGRESS']' failed. The error was: Unexpected templating type error occurred on ({% if (restart_status.results|json_query('[*].json')| json_query('[*][*].status')|flatten) not in ['INIT', 'PROGRESS'] %} True {% else %} False {% endif %}): 'NoneType' object is not iterable"}

Any help or pointer to what I am doing wrong is greatly appreciated.

isherwood
  • 58,414
  • 16
  • 114
  • 157
sdhir
  • 41
  • 7
  • *until* is testing the condition on each iteration, i.e. you have to test *restart_status*. Do not test *restart_status.results* which is the cumulative list of all results. Test it on a simpler example first. – Vladimir Botka Oct 27 '21 at 16:33
  • You say that you want to run the task ``" till the status returned is either SUCCESS or FAILED"``. Both iterations in the *results* are *FAILED*. Just to be sure, is this the expected result? – Vladimir Botka Oct 27 '21 at 16:43
  • yes. That is expected. It can be both successes, both failures or a combination of the two. – sdhir Oct 27 '21 at 17:18

2 Answers2

0

Since the JSON response you receive contains a list in json[].status as shown in debug output, the multiple (dynamic) items of that list cannot be matched with in ['SUCCESS', 'FAILED'].

However matching the desired status would work, like 'SUCCESS' in ['SUCCESS', 'FAILED']. If we want to match multiple statuses, we can use and/or combination.

Something like:

    - debug:
        msg: Fetching recycle status
      until: |
        'SUCCESS' in restart_status.results | json_query('[].json[].status') or
        'FAILED' in restart_status.results | json_query('[].json[].status')
seshadri_c
  • 6,906
  • 2
  • 10
  • 24
  • Thank you so much for your response. I still get the same error with the code below - name: Fetching recycle status uri: url: "http://{{ restarter }}/status?job_id={{ item }}" method: GET body_format: json headers: Accept: 'application/json' return_content: yes register: restart_status with_items: - 14502414 - 14552415 until: | 'FAILED' in restart_status.results|json_query('[].json[].status') – sdhir Oct 27 '21 at 18:06
  • The error posted in question relates to using conditions with `NoneType`, which is not what the `debug` output shows. Using the same data structure, I'm able to match these conditions. Is it the same error as before? – seshadri_c Oct 28 '21 at 03:53
0

Do not test the cumulative results. Using until you have to test the registered variable in each iteration, e.g.

- hosts: localhost
  tasks:
    - command: echo FAILED
      register: status
      loop: [1,2,3]
      until: status.stdout in ['FAILED', 'SUCCESS']
    - debug:
        msg: "{{ status.results|json_query('[].stdout') }}"

This trivial example will pass the iterations. Change the command to e.g. "echo XXX". You'll see the until condition in action.


In your case, the condition might be

      until: restart_status.json.0.status in ['FAILED', 'SUCCESS']

, but I'm not sure why the attribute json is a list. Maybe it keeps the results from all attempts? Anyway, to be on the safe side, the condition below should work also with multiple items in the list

      until: restart_status.json|
             json_query('[].status')|unique|
             intersect(['FAILED', 'SUCCESS'])|length > 0
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63