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
}

最好为每个寄存器使用唯一的名称?