Ansible

使用 Jinja2 模板遍歷嵌套列表/字典

  • February 1, 2022

我正在嘗試通過使用 Ansible 生成 /etc/exports 文件來動態配置系統中的多個 NFS 伺服器。我希望能夠使用 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"

然後我有以下 ansible play 來生成模板:

- 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 %}

我認為我離正確的模板結構還差得很遠。到底是如何遍歷這個列表的?

創建庫存

shell> cat hosts
[site_nfs_servers]
ansibletarget1
ansibletarget2

並將股份放入host_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

執行劇本並創建文件

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 %}

引用自:https://serverfault.com/questions/1091892