从 Jinja2 模板为多个主机生成单个配置
Generate single configuration for multiple hosts from Jinja2 template
问题: 考虑到 Ansible 的性质,我有 2 个任务按预期顺序执行。据我了解,每个任务只能执行一个模块。
任务 1 - 从网络设备收集事实信息(序列号、版本等)。
任务 2 - 使用任务 1 中收集的信息渲染模板
理想结果: 由于我正在遍历大量网络设备,因此我的理想结果是一次选择一个设备,从中收集信息,然后呈现一个带有该信息的模板,接下来转到循环中的其他设备,依此类推。
方法: 我想保持相同的语法,在任务 1 中将事实保存在文件 (.json) 中,在任务 2 中,阅读JSON 文件并获取我感兴趣的变量。
有没有更好的方法呢? (可能不止一个)
我目前得到的内容不符合我的目的,因为当模板呈现时,它只包含有关最后一个设备的信息:
任务:roles/juniper.junos/tasks/main.yaml
- name: 1 - Gathering Facts
junos_get_facts:
host: "{{ inventory_hostname}}"
user: ""
passwd: ""
savedir: "~/Ansible/Ouput/Facts"
ignore_errors: True
register: junos
- name: 2 - Creating the template
template:
src="~/Ansible/roles/juniper.junos/templates/template.j2"
dest="~/Ansible/Ouput/Facts/Device_facts.yml"
模板:~/Ansible/roles/juniper.junos/templates/template.j2
{% for host in groups['OOB_AMS'] %}
ANSIBLE NAME: {{ inventory_hostname}}
HOSTNAME: {{ junos.facts.hostname }}
MODEL: {{ junos.facts.model }}
SERIAL: {{ junos.facts.serialnumber }}
VERSION: {{ junos.facts.model }}
UP TIME: {{ junos.facts.RE0.up_time }}
{% endfor %}
理想输出:"~/Ansible/Ouput/Facts/Device_facts.yml"
ANSIBLE NAME: DEVICE 1
HOSTNAME: DEVICE 1 HOSTNAME
MODEL: DEVICE 1 MODEL
SERIAL: DEVICE 1 SERIAL
VERSION: DEVICE 1 VERSION
UP TIME: DEVICE 1 UP TIME
ANSIBLE NAME: DEVICE 2
HOSTNAME: DEVICE 2 HOSTNAME
MODEL: DEVICE 2 MODEL
SERIAL: DEVICE 2 SERIAL
VERSION: DEVICE 2 VERSION
UP TIME: DEVICE 2 UP TIME
ANSIBLE NAME: DEVICE 3
HOSTNAME: DEVICE 3 HOSTNAME
MODEL: DEVICE 3 MODEL
SERIAL: DEVICE 3 SERIAL
VERSION: DEVICE 3 VERSION
UP TIME: DEVICE 3 UP TIME
你用 host
变量写了一个 for
循环,但一次都没用过。
将模板更改为:
{% for host in ansible_play_hosts %}
ANSIBLE NAME: {{ hostvars[host].inventory_hostname}}
HOSTNAME: {{ hostvars[host].junos.facts.hostname }}
MODEL: {{ hostvars[host].junos.facts.model }}
SERIAL: {{ hostvars[host].junos.facts.serialnumber }}
VERSION: {{ hostvars[host].junos.facts.model }}
UP TIME: {{ hostvars[host].junos.facts.RE0.up_time }}
{% endfor %}
循环遍历 groups['OOB_AMS']
还不错,但硬编码组名对于您的情况似乎没有必要。相反,您可以使用:ansible_play_hosts
(2.2 版之前的play_hosts
)。
另外,为了清晰起见,您可以将 run_once: true
添加到 template
任务中。这并不关键,因为模板在每次迭代中都会产生相同的输出,所以后面的运行无论如何都会跳过,但没有必要多次这样做。
问题: 考虑到 Ansible 的性质,我有 2 个任务按预期顺序执行。据我了解,每个任务只能执行一个模块。
任务 1 - 从网络设备收集事实信息(序列号、版本等)。
任务 2 - 使用任务 1 中收集的信息渲染模板
理想结果: 由于我正在遍历大量网络设备,因此我的理想结果是一次选择一个设备,从中收集信息,然后呈现一个带有该信息的模板,接下来转到循环中的其他设备,依此类推。
方法: 我想保持相同的语法,在任务 1 中将事实保存在文件 (.json) 中,在任务 2 中,阅读JSON 文件并获取我感兴趣的变量。
有没有更好的方法呢? (可能不止一个)
我目前得到的内容不符合我的目的,因为当模板呈现时,它只包含有关最后一个设备的信息:
任务:roles/juniper.junos/tasks/main.yaml
- name: 1 - Gathering Facts
junos_get_facts:
host: "{{ inventory_hostname}}"
user: ""
passwd: ""
savedir: "~/Ansible/Ouput/Facts"
ignore_errors: True
register: junos
- name: 2 - Creating the template
template:
src="~/Ansible/roles/juniper.junos/templates/template.j2"
dest="~/Ansible/Ouput/Facts/Device_facts.yml"
模板:~/Ansible/roles/juniper.junos/templates/template.j2
{% for host in groups['OOB_AMS'] %}
ANSIBLE NAME: {{ inventory_hostname}}
HOSTNAME: {{ junos.facts.hostname }}
MODEL: {{ junos.facts.model }}
SERIAL: {{ junos.facts.serialnumber }}
VERSION: {{ junos.facts.model }}
UP TIME: {{ junos.facts.RE0.up_time }}
{% endfor %}
理想输出:"~/Ansible/Ouput/Facts/Device_facts.yml"
ANSIBLE NAME: DEVICE 1
HOSTNAME: DEVICE 1 HOSTNAME
MODEL: DEVICE 1 MODEL
SERIAL: DEVICE 1 SERIAL
VERSION: DEVICE 1 VERSION
UP TIME: DEVICE 1 UP TIME
ANSIBLE NAME: DEVICE 2
HOSTNAME: DEVICE 2 HOSTNAME
MODEL: DEVICE 2 MODEL
SERIAL: DEVICE 2 SERIAL
VERSION: DEVICE 2 VERSION
UP TIME: DEVICE 2 UP TIME
ANSIBLE NAME: DEVICE 3
HOSTNAME: DEVICE 3 HOSTNAME
MODEL: DEVICE 3 MODEL
SERIAL: DEVICE 3 SERIAL
VERSION: DEVICE 3 VERSION
UP TIME: DEVICE 3 UP TIME
你用 host
变量写了一个 for
循环,但一次都没用过。
将模板更改为:
{% for host in ansible_play_hosts %}
ANSIBLE NAME: {{ hostvars[host].inventory_hostname}}
HOSTNAME: {{ hostvars[host].junos.facts.hostname }}
MODEL: {{ hostvars[host].junos.facts.model }}
SERIAL: {{ hostvars[host].junos.facts.serialnumber }}
VERSION: {{ hostvars[host].junos.facts.model }}
UP TIME: {{ hostvars[host].junos.facts.RE0.up_time }}
{% endfor %}
循环遍历 groups['OOB_AMS']
还不错,但硬编码组名对于您的情况似乎没有必要。相反,您可以使用:ansible_play_hosts
(2.2 版之前的play_hosts
)。
另外,为了清晰起见,您可以将 run_once: true
添加到 template
任务中。这并不关键,因为模板在每次迭代中都会产生相同的输出,所以后面的运行无论如何都会跳过,但没有必要多次这样做。