首页 > 解决方案 > 从 API 响应中提取数据

问题描述

我正在尝试使用来自 API 的 JSON 响应来查找我尝试使用主机名备份的 VM 的 UUID。API 返回一个哈希列表,其中包括该主机名的主机名和 UUID。当我提供主机名时,我想让 Ansible 返回机器的 UUID。

这是来自 API 的响应示例,我将其存储在 networker_vms

    {
        "networker_vms.json.vms": [
            {
                "hostname": ""
            },
            {
                "hostname": ""
            },
            {
                "hostname": "server1.company.com",
                "uuid": "1ef92350-a5e3-8df3-6106-208a88aad352"
            },
            {
                "hostname": "server2.company.com",
                "uuid": "5003006d-23f4-a515-3722-181238489896"
            },
            {
                "hostname": "server3.company.com",
                "uuid": "50640076-07ae-571d-5e69-2183db42d2ee"
            },
            {
                "hostname": "server4.company.com",
                "uuid": "500410b1-505a-7539-5efd-89131d671b0a"
            },
            {
                "hostname": "server5.company.com",
                "uuid": "5024014b-e788-12a9-bcf6-5475ae50bf7c"
            },
            {
                "hostname": "server6.company.com",
                "uuid": "51462200-1abf-1c09-5007-fa72f76854fc"
            }
      ],
}

我能够获得与具有以下 Ansible 片段的主机名一致的 UUID,但是当将“mynames”变量切换为 {{ ansible_hostname }} 之类的东西时,我无法让代码工作 - 我收到错误“意外失败期间模块执行”。我猜这与花括号的堆叠有关,但我不确定....

- name: debug my_uuid
  debug:
    msg: "{{ mynames | map('extract', dict(networker_vms.json | json_query('vms[].[hostname,uuid]'))) }}"
  vars:
    mynames:
      - server2.company.com

对我来说,搜索特定主机名的 API 调用结果并让 Ansible 将相应的 uuid 放入事实或变量中的最佳方法是什么?

谢谢!

标签: ansiblejson-query

解决方案


听起来您想提取当前主机的 UUID,由ansible_hostname变量标识。你可以这样做:

- name: debug using ansible_hostname
  debug:
    msg: >-
      {{ [ansible_hostname] |
      map('extract', dict(networker_vms.json |
      json_query('vms[].[hostname,uuid]'))) | first }}

这只是mynames在您的示例中替换了一个列表,[ansible_hostname]它也是一个列表(由单个值组成,的内容ansible_hostname)。这提供了map过滤器所需的列表上下文。

但是,如果您只有一个值,则不需要使用map过滤器;你可以这样做:

- name: debug using ansible_hostname
  debug:
    msg: >-
      {{ (networker_vms.json.vms |
      selectattr('hostname', 'eq', ansible_hostname)|first).uuid }}

更新

如果您混合了合格和不合格的主机名,则可以执行以下操作:

- name: get my uuid
  set_fact:
    my_uuid: "{{ host_to_addr[item] }}"
  when: my_uuid is not defined and item in host_to_addr
  vars:
    host_to_addr: "{{ dict(networker_vms.json | json_query('vms[].[hostname,uuid]')) }}"
  loop:
    - "{{ ansible_hostname }}"
    - "{{ ansible_fqdn }}"

- debug:
    var: my_uuid

这将遍历主机名列表,并将my_uuid事实设置为首先匹配的任何一个。

您还可以为json_query过滤器编写一个稍微复杂一点的表达式:

- name: get my uuid
  debug:
    msg: >-
      {{ networker_vms.json.vms |
      json_query('[?hostname == `%s` || hostname == `%s`].[uuid]|[]' % (
      ansible_hostname, ansible_fqdn))|
      first}}

推荐阅读