Ansible 在任务中注册变量并在模板中使用它
Ansible register variable in task and use it in template
在 Ansible 任务中,如何注册变量以便我可以将其用作模板中的检查语句。任务是:
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
- name: Create vhost from template
template: "src={{ vhost_conf }} dest=/etc/nginx/conf/vhost.conf"
在虚拟主机模板中,listen 80
始终可用,我只想在证书可用时为 listen 443
添加块:
server {
listen 80;
........
}
{% if ssl_cert_check == True %} # This doesn't issue error but doesn't work either
server {
listen 443;
..............
}
{% endif %}
当我运行上述情况时,第二个服务器块没有被执行,这意味着虚拟主机配置中只打印了服务器监听80。
但是,如果我删除 True for if
语句并在模板中添加 stat.exists
,则会出现错误:
# This issues error
{% if ssl_cert_check.stat.exists %}
server {
listen 443;
..............
}
{% endif %}
错误是:
"msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'stat'
尽管我在注册变量之前使用了 stat 模块。
有没有其他方法可以传递Ansible任务中定义的变量并在Jinja2模板中使用它?
Create vhost from template
之前的 - debug: var=ssl_cert_check
任务显示的值为:
"ssl_cert_check": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/etc/nginx/ssl/abc.pem"
},
"module_name": "stat"
},
"item": {
........
},
"stat": {
"exists": false
}
}
]
}
如果你查看你拥有的 ssl_cert_check
,你会注意到布尔键 exists
存储在 results
列表下的 stat
字典中,所以实际上您应该遍历模板内列表中的项目。
如果您发布的是一个一致的示例,您可以使用以下方式引用列表中的第一项:
{% if ssl_cert_check.results[0].stat.exists %}
然而,在您的案例中创建 ssl_cert_check
的方式很可能意味着:
- 你的代码中有某种循环
sitename
不是标量值,而是列表本身
如果循环 运行 次,或者您在 sitename
上有多个项目,您的结果可能不一致。
您应该解决根本原因,而不是使用 results[0]
解决方法。
注意:跳过的任务仍会注册变量:
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
when: nonexistent is defined
在这种情况下,寄存器的值为:
"ssl_cert_check": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
最好为每个寄存器使用唯一的名称?
在 Ansible 任务中,如何注册变量以便我可以将其用作模板中的检查语句。任务是:
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
- name: Create vhost from template
template: "src={{ vhost_conf }} dest=/etc/nginx/conf/vhost.conf"
在虚拟主机模板中,listen 80
始终可用,我只想在证书可用时为 listen 443
添加块:
server {
listen 80;
........
}
{% if ssl_cert_check == True %} # This doesn't issue error but doesn't work either
server {
listen 443;
..............
}
{% endif %}
当我运行上述情况时,第二个服务器块没有被执行,这意味着虚拟主机配置中只打印了服务器监听80。
但是,如果我删除 True for if
语句并在模板中添加 stat.exists
,则会出现错误:
# This issues error
{% if ssl_cert_check.stat.exists %}
server {
listen 443;
..............
}
{% endif %}
错误是:
"msg": "AnsibleUndefinedVariable: 'dict object' has no attribute 'stat'
尽管我在注册变量之前使用了 stat 模块。
有没有其他方法可以传递Ansible任务中定义的变量并在Jinja2模板中使用它?
Create vhost from template
之前的 - debug: var=ssl_cert_check
任务显示的值为:
"ssl_cert_check": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/etc/nginx/ssl/abc.pem"
},
"module_name": "stat"
},
"item": {
........
},
"stat": {
"exists": false
}
}
]
}
如果你查看你拥有的 ssl_cert_check
,你会注意到布尔键 exists
存储在 results
列表下的 stat
字典中,所以实际上您应该遍历模板内列表中的项目。
如果您发布的是一个一致的示例,您可以使用以下方式引用列表中的第一项:
{% if ssl_cert_check.results[0].stat.exists %}
然而,在您的案例中创建 ssl_cert_check
的方式很可能意味着:
- 你的代码中有某种循环
sitename
不是标量值,而是列表本身
如果循环 运行 次,或者您在 sitename
上有多个项目,您的结果可能不一致。
您应该解决根本原因,而不是使用 results[0]
解决方法。
注意:跳过的任务仍会注册变量:
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
- name: Check if certificate file exists
stat: path=/etc/nginx/ssl/{{ sitename }}.pem
register: ssl_cert_check
when: nonexistent is defined
在这种情况下,寄存器的值为:
"ssl_cert_check": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
最好为每个寄存器使用唯一的名称?