使用 Jinja2 模板迭代嵌套列表/字典

dut*_*irf 5 ansible ansible-playbook jinja2

我正在尝试通过使用 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"
Run Code Online (Sandbox Code Playgroud)

然后我有以下 ansible play 来生成模板:

- name: Generate the exports file.
  template:
    src: exports.j2
    dest: /etc/exports
    owner: root
    group: root
    mode: '0750'
Run Code Online (Sandbox Code Playgroud)

我的模板目前如下所示:

{% for export in exports %}
{% if ansible_hostname in export.server %}
{% for share in shares %}
{{ share.path }} {{ share.client }} {{ share.options }}
{% endfor %}
{% endif %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

我认为我还没有接近拥有正确的模板结构。人们到底如何迭代这个列表呢?

Vla*_*tka 3

创建库存

\n
shell> cat hosts\n[site_nfs_servers]\nansibletarget1\nansibletarget2\n
Run Code Online (Sandbox Code Playgroud)\n

并将共享放入host_vars

\n
shell> cat hosts\n[site_nfs_servers]\nansibletarget1\nansibletarget2\n
Run Code Online (Sandbox Code Playgroud)\n
shell> cat host_vars/ansibletarget1.yml \nshares:\n  - path: "/my/first/share/path"\n    client: "*"\n    options: "rw,sync"\n  - path: "/my/second/share/path"\n    client: "*"\n    options: "rw,sync,root_squash"\n
Run Code Online (Sandbox Code Playgroud)\n

创建一个简化的测试角色

\n
shell> cat host_vars/ansibletarget2.yml \nshares:\n  - path: "/another/shared/path/different/server"\n    client: "*"\n    options: "ro,sync"\n
Run Code Online (Sandbox Code Playgroud)\n
shell> tree roles/my_nfs_role/\nroles/my_nfs_role/\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 tasks\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.yml\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 templates\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 exports.j2\n\n2 directories, 2 files\n
Run Code Online (Sandbox Code Playgroud)\n
shell> cat roles/my_nfs_role/templates/exports.j2 \n{% for share in shares %}\n{{ share.path }} {{ share.client }} {{ share.options }}\n{% endfor %}\n
Run Code Online (Sandbox Code Playgroud)\n

然后,使用清单组和剧本中的角色

\n
shell> cat roles/my_nfs_role/tasks/main.yml \n- template:\n    src: exports.j2\n    dest: /etc/exports.test\n
Run Code Online (Sandbox Code Playgroud)\n

运行剧本并创建文件

\n
shell> cat roles/my_nfs_role/templates/exports.j2 \n{% for share in shares %}\n{{ share.path }} {{ share.client }} {{ share.options }}\n{% endfor %}\n
Run Code Online (Sandbox Code Playgroud)\n
shell> cat playbook.yml\n- hosts: site_nfs_servers\n  roles:\n    - my_nfs_role\n
Run Code Online (Sandbox Code Playgroud)\n

请参阅Ansible 设置示例

\n
\n

如果您想将共享保留在一个对象中,请将列表放入groups_vars中。为了简化代码,将列表转换为字典。例如,您可以使用community.general.groupby_as_dict

\n
shell> ansible-playbook -i hosts playbook.yml\n\nPLAY [site_nfs_servers] ************************************************\n\nTASK [my_nfs_role : template] ******************************************\nchanged: [ansibletarget1]\nchanged: [ansibletarget2]\n ...\n
Run Code Online (Sandbox Code Playgroud)\n

给出

\n
shell> ssh admin@ansibletarget1 cat /etc/exports.test\n/my/first/share/path * rw,sync\n/my/second/share/path * rw,sync,root_squash\n\nshell> ssh admin@ansibletarget2 cat /etc/exports.test\n/another/shared/path/different/server * ro,sync\n
Run Code Online (Sandbox Code Playgroud)\n

然后修改模板。这应该创建与以前相同的文件。

\n
shell> cat roles/my_nfs_role/templates/exports.j2 \n{% for share in exports_dict[inventory_hostname][\'shares\'] %}\n{{ share.path }} {{ share.client }} {{ share.options }}\n{% endfor %}\n
Run Code Online (Sandbox Code Playgroud)\n