0

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. I'm using the Ansible URI to talk to a REST API to manage this.

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

The registered var from the get show's the following

{
    "json": {
        "inputs": [
            {
                "attributes": {
                    "allow_override_date": "False",
                    "bind_address": "0.0.0.0",
                    "expand_structured_data": "False",
                    "force_rdns": "False",
                    "number_worker_threads": 8,
                    "override_source": "",
                    "port": 5999,
                    "recv_buffer_size": "",
                    "store_full_message": "True"
                },
                "content_pack": null,
                "created_at": "2021-07-30T15:21:47.590Z",
                "creator_user_id": "triple_admin",
                "global": false,
                "id": "6104170beca15547502665d6",
                "name": "Syslog UDP",
                "node": "ba52ad48-0b13-419d-b957-d47d8911b413",
                "static_fields": {},
                "title": "test_input_api",
                "type": "org.graylog2.inputs.syslog.udp.SyslogUDPInput"
            },

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

Results of running the play

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

All help is welcome !

balpoint
  • 17
  • 4

1 Answers1

0
  1. (not related) You don't need to json_decode the result get_graylog_inputs.content. If the server on the over side sends the correct Content-type: application/json header, you should have a get_graylog_inputs.json entry containing the already decoded json result.
  2. You don't need to loop twice. Remove the set_fact loop (which is not correct anyway) in your first file and use the value from your register directly in the second loop.
  3. You did not show any example of your input data so I have to guess a bit here from your jmespath expression... but you basically don't need json_query at all and can stick to generic core ansible filters.

Here is how I see the solution in the second file once you cleaned-up the first:

---
  - name: "API PUT System Inputs"
    vars:
      get_input_id: "{{ get_graylog_inputs.json.inputs | selectattr('title', '==', input.title) | map(attribute='id') | first }}"
    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

You will probably have to debug and tune the expression to get the input id as I could not do it myself against an example data structure.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • Hi @Zeitounator , i posted the registered var *get_graylog_inputs* in the following pastebin: https://pastebin.com/eAwZz9pr I cannot get the id value with the given suggestion as the mapping goes one level deeper into attributes, while id is on the same level as title – balpoint Jul 30 '21 at 21:58
  • Please add that in a code block as an edit to your question, not in an external link in a volatile comment. Don't pour the full variable dunno: the json structure is enough. While you are adding this necessary info, review your question and remove the sea of text that does not add any valuable precision for people to answer. Read [how to create an MCVE](/help/mcve) and hold on those two words: minimal **and** complete. I edited my answer. Of this still does not work as expected. Edit your question again with what you tried and the error you get. – Zeitounator Jul 31 '21 at 06:36
  • Hi, thanks for the feedback i will keep that in mind for future issue's, as far as a sollution , i've got you're proposed solution to work in my use case just needed to step back and look at the json data structure, also came up with a work around ( not as elegant but still learnt something ). – balpoint Jul 31 '21 at 07:40
  • Please do enhance your question now. This is a q&a site. Your question and the possible answers are supposed to help others, not just fix your own problem just at the moment. – Zeitounator Jul 31 '21 at 08:03