#json #ansible #jmespath
#json #ansible #jmespath
Вопрос:
У меня есть Ansible playbook, который запрашивает API инвентаризации устройств и возвращает результат JSON, который содержит много записей в этом формате:
{
"service_level": "Test",
"tags": [
"Application:MyApp1"
],
"fqdn": "matestsvcapp1.vipcustomers.com",
"ip": "172.20.11.237",
"name": "matestsvcapp1.vipcustomers.com"
}
Затем я перебираю эти задачи ansible, чтобы запросить результат JSON для каждого из интересующих меня IP-адресов:
- name: Set JMESQuery
set_fact:
jmesquery: "Devices[?ip_addresses[?ip.contains(@,'{{ ip_to_query }}' )]].{ip: '{{ ip_to_query }}', tags: tags[], , service_level: service_level }"
- name: Store values
set_fact:
inven_results: "{{ (inven_results| default([])) (existing_device_info.json | to_json | from_json | json_query(jmesquery)) }}"
Затем я продолжаю выполнять другие задачи в ansible, перенося эти данные в другие системы, и все работает нормально.
Однако я только что получил запрос от руководства о том, что они хотели бы видеть «уровень обслуживания», представленный в виде тега в некоторых системах, в которые я загружаю эти данные. Поэтому мне нужно объединить элементы ‘tags’ и ‘service_level’, в результате чего получится нечто, похожее на это:
{
"tags": [
"Application:MyApp1",
"service_level:Test"
],
"fqdn": "matestsvcapp1.vipcustomers.com",
"ip": "172.20.11.237",
"name": "matestsvcapp1.vipcustomers.com"
}
Я попытался изменить запрос JMESpath, чтобы объединить результаты вместе с помощью функции join, и попытался сделать это способом ‘ansible’, используя combine или map, но я также не смог заставить ни один из них работать.
Есть мысли о правильном способе справиться с этим? Заранее спасибо!
Примечание: ‘tags’ — это список строк, и хотя он написан в формате key:value, на самом деле это просто строка.
Комментарии:
1. Я не совсем понимаю, как выглядят ваши данные. Можете ли вы опубликовать минимальный сборник задач, включающий образцы данных, которые полностью воспроизводят проблему, которую вы пытаетесь решить?
Ответ №1:
чтобы добавить два массива, вы используете
оператор, подобный этому:
ansible localhost -m debug -a 'msg="{{ b ["String3"] }}"' -e '{"b":["String1", "String2"]}'
Результат:
localhost | SUCCESS => {
"msg": [
"String1",
"String2",
"String3"
]
}
Итак, если я возьму ваш код json, test.json
который вы могли бы запустить
ansible localhost -m debug -a 'msg="{{ tags ["service_level:" ~ service_level ] }}"' -e @test.json
Результат:
localhost | SUCCESS => {
"msg": [
"Application:MyApp1",
"service_level:Test"
]
}
Зная это, вы можете использовать set_fact, чтобы поместить этот новый массив в переменную для последующего использования.
Комментарии:
1. Это был не точный ответ, но он привел меня по пути. Я в основном узнал, что вы не можете обновить существующий элемент, но вам нужно зарегистрировать новый. Позже в моем сборнике я объединил несколько значений, и добавление
tags ["service_level:" ~ service_level ]
раздела к этому позволило мне объединить нужные мне элементы. Спасибо!