Перебор вложенного списка/словаря с использованием шаблонов Jinja2
Я пытаюсь динамически настроить несколько серверов NFS в своей системе, создав их файлы /etc/exports с помощью Ansible. Я надеюсь, что смогу сделать это с помощью шаблона jinja2. Это шаблон jinja2, который я не могу понять, судя по моему списку экспорта.
В моей роли nfs определены следующие переменные:
site_nfs_servers: ['ansibletarget1', 'ansibletarget2']
exports:
- server: "ansibletarget1"
shares:
- path: "/my/first/share/path"
client: "*"
options: "rw,sync"
- path: "/my/second/share/path"
client: "*"
options: "rw,sync,root_squash"
- server: "ansibletarget2"
shares:
- path: "/another/shared/path/different/server"
client: "*"
options: "ro,sync"
Затем у меня есть следующая игра для создания шаблона:
- name: Generate the exports file.
template:
src: exports.j2
dest: /etc/exports
owner: root
group: root
mode: '0750'
Мой шаблон на данный момент выглядит так:
{% for export in exports %}
{% if ansible_hostname in export.server %}
{% for share in shares %}
{{ share.path }} {{ share.client }} {{ share.options }}
{% endfor %}
{% endif %}
{% endfor %}
Я не думаю, что я близок к созданию правильной структуры шаблона. Как, черт возьми, можно перебирать этот список?
2 ответа
Вам не хватает ссылки наexport
в вашем втором цикле.
{% for export in exports %}
{% if ansible_hostname in export.server %}
{% for share in export.shares %}
{{ share.path }} {{ share.client }} {{ share.options }}
{% endfor %}
{% endif %}
{% endfor %}
Однако было бы лучше определить доли в переменных хоста, как показано в ответе Владимира.
Создать инвентарь
shell> cat hosts
[site_nfs_servers]
ansibletarget1
ansibletarget2
и поместите общие ресурсы в хост_vars
shell> cat host_vars/ansibletarget1.yml
shares:
- path: "/my/first/share/path"
client: "*"
options: "rw,sync"
- path: "/my/second/share/path"
client: "*"
options: "rw,sync,root_squash"
shell> cat host_vars/ansibletarget2.yml
shares:
- path: "/another/shared/path/different/server"
client: "*"
options: "ro,sync"
Создайте упрощенную роль для тестирования
shell> tree roles/my_nfs_role/
roles/my_nfs_role/
├── tasks
│ └── main.yml
└── templates
└── exports.j2
2 directories, 2 files
shell> cat roles/my_nfs_role/tasks/main.yml
- template:
src: exports.j2
dest: /etc/exports.test
shell> cat roles/my_nfs_role/templates/exports.j2
{% for share in shares %}
{{ share.path }} {{ share.client }} {{ share.options }}
{% endfor %}
Затем используйте группу инвентаря и роль в сборнике сценариев.
shell> cat playbook.yml
- hosts: site_nfs_servers
roles:
- my_nfs_role
Запустите playbook и создайте файлы
shell> ansible-playbook -i hosts playbook.yml
PLAY [site_nfs_servers] ************************************************
TASK [my_nfs_role : template] ******************************************
changed: [ansibletarget1]
changed: [ansibletarget2]
...
shell> ssh admin@ansibletarget1 cat /etc/exports.test
/my/first/share/path * rw,sync
/my/second/share/path * rw,sync,root_squash
shell> ssh admin@ansibletarget2 cat /etc/exports.test
/another/shared/path/different/server * ro,sync
См. Пример настройки Ansible .
Если вы хотите сохранить общие ресурсы в одном объекте, поместите список в groups_vars. Чтобы упростить код, преобразуйте список в словарь. Например, вы можете использовать Community.general.groupby_as_dict
shell> cat group_vars/all.yml
exports:
- server: "ansibletarget1"
shares:
- path: "/my/first/share/path"
client: "*"
options: "rw,sync"
- path: "/my/second/share/path"
client: "*"
options: "rw,sync,root_squash"
- server: "ansibletarget2"
shares:
- path: "/another/shared/path/different/server"
client: "*"
options: "ro,sync"
exports_dict: "{{ exports|community.general.groupby_as_dict('server') }}"
дает
exports_dict:
ansibletarget1:
server: ansibletarget1
shares:
- client: '*'
options: rw,sync
path: /my/first/share/path
- client: '*'
options: rw,sync,root_squash
path: /my/second/share/path
ansibletarget2:
server: ansibletarget2
shares:
- client: '*'
options: ro,sync
path: /another/shared/path/different/server
Затем измените шаблон. Это должно создать те же файлы, что и раньше.
shell> cat roles/my_nfs_role/templates/exports.j2
{% for share in exports_dict[inventory_hostname]['shares'] %}
{{ share.path }} {{ share.client }} {{ share.options }}
{% endfor %}