Search code examples
ansiblejinja2json-query

Loop ansible json_query in Ansible


So, I'm fetching Grafana alerts and I want to get a list of the alerts that don't end with two specific strings:

grafana_alerts_exclusion_list: "['one', 'three']"

Here's how I'm fetching all the Grafana alerts:

- name: Get Grafana alerts
   URI:
    url: "{{ grafana_endpoint }}/api/alerts"
    method: GET
    headers:
      Authorization: "Bearer {{ grafana_api_token }}"
    body_format: json
  register: alerts_output

And here I'm trying to use json_query to exclude the grafana_alerts_exclusion_list alerts:

- set_fact:
    alerts: "{{ alerts + [ alerts_output.json | to_json | from_json | json_query(query) ] }}"
  with_items: "{{ grafana_alerts_exclusion_list }}"
  vars:
    alerts: []
    query: "[?!ends_with(name, '{{ item }}')]"

The problem I'm getting is that it runs the json_query once for string "one" and then it runs it again against the initial "alerts_output.json" for string "three", and not against the results from string "one". How do I get the output without strings "one" and "three" (grafana_alerts_exclusion_list)?

Here's my "alerts_output":

{
    "cache_control": "no-cache",
    "changed": false,
    "connection": "Close",
    "content_length": "3175",
    "content_type": "application/json",
    "cookies": {},
    "cookies_string": "",
    "date": "Tue, 09 Aug 2022 14:52:07 GMT",
    "elapsed": 0,
    "expires": "-1",
    "failed": false,
    "json": [
        {
            "dashboardId": 238,
            "evalData": {
                "noData": true
            },
            "evalDate": "0001-01-01T00:00:00Z",
            "executionError": "",
            "id": 94,
            "name": "Something one",
            "newStateDate": "2022-08-09T14:48:48Z",
            "panelId": 4,
            "state": "no_data"
        },
        {
            "dashboardId": 238,
            "evalData": {
                "noData": true
            },
            "evalDate": "0001-01-01T00:00:00Z",
            "executionError": "",
            "id": 93,
            "name": "Something two",
            "newStateDate": "2022-08-09T14:48:28Z",
            "panelId": 3,
            "state": "no_data"
        },
        {
            "dashboardId": 238,
            "evalData": {
                "noData": true
            },
            "evalDate": "0001-01-01T00:00:00Z",
            "executionError": "",
            "id": 95,
            "name": "Something three",
            "newStateDate": "2022-08-09T14:48:48Z",
            "panelId": 7,
            "state": "no_data"
        },
        {
            "dashboardId": 238,
            "evalData": {
                "noData": true
            },
            "evalDate": "0001-01-01T00:00:00Z",
            "executionError": "",
            "id": 96,
            "name": "Something four",
            "newStateDate": "2022-08-09T14:48:16Z",
            "panelId": 10,
            "state": "no_data"
        }
    ],
    "msg": "OK (3175 bytes)",
    "pragma": "no-cache",
    "redirected": false,
    "status": 200,
    "x_content_type_options": "nosniff",
    "x_frame_options": "deny",
    "x_xss_protection": "1; mode=block"
}

Solution

  • You don't need json_query nor loop and not even set_fact. Just filter out the relevant alerts from your list, e.g.

    - vars:
        reject_regex: "({{ grafana_alerts_exclusion_list | map('regex_escape') | join('|') }})$"
      debug:
        msg: "{{ alerts_output.json | rejectattr('name', 'regex', reject_regex) }}"