Score:0

Ansible - issue with loop and json_query's

gb flag

I am using the ansible URI module to talk to a REST api. I have a task to perform a GET to get me some data that i want to use later on. I want to be able to match a certain variable from the GET to create the path to do a PUT on the REST api. My code is as followed

playbook

*host_vars/host.yml *

---
inputs:
  - title: "test_input_api"
    type: "org.graylog2.inputs.syslog.udp.SyslogUDPInput"
    global: false
    configuration:
      allow_override_date: false
      bind_address: "0.0.0.0"
      expand_structured_data: false
      force_rdns: false
      number_worker_threads: 8
      override_source: null
      port: 5999
      recv_buffer_size: null
      store_full_message: true
  - title: "test_input_api_2"
    type: "org.graylog2.inputs.syslog.udp.SyslogUDPInput"
    global: false
    configuration:
      allow_override_date: false
      bind_address: "0.0.0.0"
      expand_structured_data: false
      force_rdns: false
      number_worker_threads: 8
      override_source: null
      port: 5998
      recv_buffer_size: null
      store_full_message: true

playbook.yml

---
- name: Configure system
  hosts: graylog
  connection: local
  gather_facts: no
  roles:
    - graylog/inputs

roles/graylog/inputs/tasks/main.yml

---
- include_tasks: get_inputs.yml
- include_tasks: put_inputs.yml

roles/graylog/inputs/tasks/get_inputs.yml

--- 
- name: "API GET System Inputs"
    uri:
      url: http://{{ ansible_host }}:9000/api/system/inputs
      url_username : "{{ system.users.triple_admin.api_token }}"
      url_password: token
      method: GET
      return_content: yes
    register: get_graylog_inputs

- name: Set Fact
  set_fact:
    get_input_id: "{{ get_graylog_inputs.content | from_json | json_query('inputs[?title == `{}`] | [0].id '.format(input.title)) }}"
  loop: "{{ inputs }}"
  loop_control:
    loop_var: input

roles/graylog/inputs/tasks/put_inputs.yml

---
  - name: "API PUT System Inputs"
    uri:
      url: http://{{ ansible_host }}:9000/api/system/inputs/{{ get_input_id }}
      url_username : "{{ system.users.triple_admin.api_token }}"
      url_password: token
      headers:
        X-Requested-By: X-Ansible
      method: PUT
      body_format: json
      body: "{{ lookup('template', 'templates/post_template.j2') }}"
      status_code: 201
      return_content: yes
    loop: "{{ inputs }}"
    loop_control:
      loop_var: input

possible issue

A double loop statement within the play

As you can see in the get_inputs.yml I do a loop over the inputs dict in the host_vars within the set_fact task to get the ID from the REST api for each input entry that is defined in the host_vars that matches the title.

The idea behind this is when i want to change something about the input entry i can do a PUT that builds a path within the task put_inputs.yml the variable URL to the input with the id that is gathered with the GET and set to fact by the get_facts task and then play the PUT task to the rest api and adjust some parameter.

But i also need do a loop over the same inputs dict in the host_vars within the put_inputs.yml because if there are changes to multiple entries i want to loop the PUT.

The issue is that the get_facts get's both the id values as show below only the last one is being registered as the fact because it's a loop and they get the same name.

    "ansible_facts": {
        "get_input_id": "61015085eca1554750236084",
        "get_input_titles": "test_input_api"
    },
    "ansible_facts": {
        "get_input_id": "610282d0eca155475024ac91",
        "get_input_titles": "test_input_api_2"

So when the put_inputs.yml task is played ( after the get_inputs.yml) I end up with the following response from the play which in short is that both times te task is being played ( as per loop ) i get the same get_input_id value.

loop 1 - this needs to be matched to the title and therefor get id "61015085eca1554750236084"

        "title": "test_input_api",
            "url": "http://192.168.21.82:9000/api/system/inputs/610282d0eca155475024ac91",

loop 2

        "title": "test_input_api_2",
            "url": "http://192.168.21.82:9000/api/system/inputs/610282d0eca155475024ac91",

Question

I need to get the ID from the GET because it's needed in the URL in the PUT task to edit a specific "input" entry. But because i need to match the ID to the Title i need to do a loop but this as I said previously results in only getting one ID value as a fact which is being used in the PUT loop for all items in the inputs dict this is not what i need because i need to be able to edit every entry separately based on ID.

All help is welcome !

Zeitounator avatar
fr flag
Hi. Please do not cross post [the same question](https://stackoverflow.com/questions/68587692/ansible-issue-with-loop-and-json-querys) on different stackexchange sites. Choose the one that is the most appropriate.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.