Можно ли отобразить несколько атрибутов с помощью Jinja/Ansible?
Я хотел бы построить вывод, который показывает ключ и значение переменной.
Следующее работает отлично...
# Format in Ansible
msg="{{ php_command_result.results | map(attribute='item') | join(', ') }}"
# Output
{'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}, {'value': {'svn_tag': '20150702r1_6.36_homeland'}, 'key': 'api'}
Я хотел бы показать вместе key
и svn_tag
следующим образом:
Я могу отображать либо key
, либо svn_tag
, но получение их для совместного использования не работает.
msg="{{ php_command_result.results | map(attribute='item.key') | join(', ') }}"
# Output
ui, api
Однако, это то, что я хочу.
# Desired Output
api - 20150702r1_6.36_homeland
ui - 20150703r1_6.36_homeland
Ответы
Ответ 1
Вы можете сделать это, используя следующие методы:
-
Создайте filter_plugin
. Добавьте filter_plugins = <path to the folder>
в ansible.cfg. Затем создайте файл: my_plugin.py
:
class FilterModule(object):
''' Custom filter '''
def filters(self, my_arg):
return <parse it here......>
Пример:
playbook.yml
---
- hosts: localhost
gather_facts: no
connection: local
tasks:
- set_fact:
php_command_result:
results: {'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}
- debug: msg="Hey look what I got '{{ php_command_result.results | a }}'"
my_plugin.py
import json
class FilterModule(object):
def filters(self):
return {'a': a}
def a(a):
r = '%s - %s' % (a['key'], a['value']['svn_tag'])
return r
-
Быстрый и простой подход: используйте python/php/shell
или что вы предпочитаете с модулем shell
. Что-то вроде этого:
- name: Pars output
shell: python -c "import json; json.loads('{{ php_command_result.results }}') ....
Ответ 2
Использование утверждений дзиндзя:
- set_fact:
php_command_result:
results: [{"value":{"svn_tag":"20150703r1_6.36_homeland"},"key":"ui"},{"value":{"svn_tag":"20150702r1_6.36_homeland"},"key":"api"}]
- debug:
msg: "{% for result in php_command_result.results %}\
{{ result.key }} - {{ result.value.svn_tag }} |
{% endfor %}"
Выходы:
ok: [localhost] => {
"msg": "ui - 20150703r1_6.36_homeland | api - 20150702r1_6.36_homeland | "
}
Если вы хотите получить результаты в отдельных строках:
- debug:
msg: "{% set output = [] %}\
{% for result in php_command_result.results %}\
{{ output.append( result.key ~ ' - ' ~ result.value.svn_tag) }}\
{% endfor %}\
{{ output }}"
Выходы:
ok: [localhost] => {
"msg": [
"ui - 20150703r1_6.36_homeland",
"api - 20150702r1_6.36_homeland"
]
}
При желании любой из них может быть помещен в одну строку:
- debug:
msg: "{% for result in php_command_result.results %}{{ result.key }} - {{ result.value.svn_tag }} | {% endfor %}"
- debug:
msg: "{% set output = [] %}{% for result in php_command_result.results %}{{ output.append( result.key ~ ' - ' ~ result.value.svn_tag) }}{% endfor %}{{ output }}"
Ответ 3
Вот решение без пользовательского фильтра filter_plugin или командной строки. Однако для этого необходимо установить дополнительный факт в цикле with_items (php_fmt).
- hosts: localhost
connection: local
gather_facts: false
tasks:
- set_fact:
php_command_result:
results: '[{"value":{"svn_tag":"20150703r1_6.36_homeland"},"key":"ui"},{"value":{"svn_tag":"20150702r1_6.36_homeland"},"key":"api"}]'
- set_fact:
php_fmt: "{{ php_fmt|default([])|union([item.key+' -- '+item.value.svn_tag ]) }}"
with_items: "{{ php_command_result.results }}"
- debug:
msg: "{{php_fmt|join(',')}}"
Ответ 4
Вот еще один ответ с использованием filter_plugins
, который я нашел очень простым в использовании.
Если кому-то это все еще нужно, вы можете использовать следующий код (поместите в playbooks/filter_plugins/mapattributes.py):
#!/usr/bin/env python
class FilterModule(object):
def filters(self):
return { 'mapattributes': self.mapattributes }
def mapattributes(self, list_of_dicts, list_of_keys):
l = []
for di in list_of_dicts:
newdi = { }
for key in list_of_keys:
newdi[key] = di[key]
l.append(newdi)
return l
И скажем, у вас есть этот список, от которого вам нужны только ключи:
INTERFACES:
- { name: GigabitEthernet1/0/24 , enabled: yes, state: up , description: FRONT }
- { name: GigabitEthernet1/0/9 , enabled: yes, state: up , description: BACK }
Давайте создадим другую переменную, фильтрующую только нужные key:values
test: "{{ INTERFACES | mapattributes(['name', 'description']) }}"
Проверьте вывод
- debug:
var: test
ok: [R1] => {
"test": [
{
"description": "FRONT",
"name": "GigabitEthernet1/0/24"
},
{
"description": "BACK",
"name": "GigabitEthernet1/0/9"
}
]
}
Это позволяет мне иметь большой словарь и выделять только те ключи, которые мне нужно передать ios_interface/aggregate
Спасибо Nee6ione, я нашел его на паллетах /jinja github issue