Ansible - 循环和 json_query 的问题

Ansible - issue with loop and json_query's

问题

我需要从 GET 中获取 ID,因为 PUT 任务中的 URL 需要它来编辑特定的“输入”条目。我正在使用 Ansible URI 与 REST API 对话来管理它。

剧本

*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

get 显示的注册变量如下

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

运行 比赛结果

循环 1 - 这需要与标题匹配,因此获得 ID“61015085eca1554750236084”

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

循环 2

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

欢迎大家的帮助!

  1. (不相关)您不需要 json_decode 结果 get_graylog_inputs.content。如果那边的服务器发送了正确的 Content-type: application/json header,你应该有一个 get_graylog_inputs.json 条目包含已经解码的 json 结果。
  2. 你不需要循环两次。删除第一个文件中的 set_fact 循环(无论如何都不正确),并在第二个循环中直接使用寄存器中的值。
  3. 您没有显示任何输入数据的示例,所以我不得不从您的 jmespath 表达式中猜测一些...但您基本上根本不需要 json_query 并且可以坚持使用通用核心ansible 过滤器。

这是我在第一个 cleaned-up 第一个文件中看到的解决方案:

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

您可能必须调试和调整表达式才能获得输入 ID,因为我自己无法根据示例数据结构完成此操作。