Ansible pull data из ответа API
Я пытаюсь использовать ответ JSON от API для поиска 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"
}
],
}
Я могу получить UUID, который совпадает с именем хоста со следующим фрагментом Ansible, однако я не могу заставить код работать при переключении переменной "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 в факт или переменную для меня?
Спасибо!
1 ответ
Похоже, что вы хотите извлечь 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}}