Ansible with_dict模板使用

时间:2014-09-24 15:10:18

标签: ansible ansible-template

我有以下任务:

- name: copy server.xml
  template: src=server.xml dest=/var/containers/{{ item.key }}/conf
  with_dict: containers

我还在group_vars中添加了容器字典

containers:
  frontend:
    http_port: 8080
  backend:
    http_port: 8081

最后,这是server.xml的相关代码段

<Connector port="{{ http_port }}" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

我想要发生的是在模板模块中使用相关的http_port。但相反,我得到了错误:

致命:[localhost] =&gt; {'msg':“AnsibleUndefinedVariable:一个或多个未定义的变量:'http_port'未定义”,'失败':真}

这可能吗?如何利用项目的值进行变量替换?

1 个答案:

答案 0 :(得分:5)

使用{{ item.value.http_port }}是正确的解决方案。

当您传递with_dict时,它循环执行任务,将容器字典中的每个项目传递为{{ item }},其中项目具有键和字典项目包含的任何值 - 在您的情况下,键/值密钥为http_port且值为两个不同整数的对 - 但是您可以通过认真复杂的嵌套字典传递更重要的内容,使用您提出的{{ item.value.http_port }}语法来访问它们。

当你得到更复杂的模板使用时要警惕的是如何混合填充和设置默认值并使用if语句当你有一些额外的变量模板用于一个主机(或容器,或其他)但不是另一个。

要掌握它,请阅读Jinja2,Ansible语言解释模板。一个很好的例子就像在前端提供SSL上的文件,而不是后端。使用类似{{ foo | default('bar') }}的语法来避免Ansible对您尝试使用未定义的变量和if语句感到生气,以确保您只是模板化您需要的东西。

粗略草图 - 说你有:

containers:
  frontend:
    http_port: 8080
    https_port: 8443
    ssl_cert: ./files/keystore
    ssl_pass: "{{ vaulted_vars.ssl_pass }}" 
  backend:
    http_port: 8081

在这种情况下,想象你有一个任务是在需要时将密钥库复制到文件系统上,你可以使用以下内容:

<Connector port="{{ item.value.http_port }}" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="{{ item.value.https_port | default('8443')" />
           {% if item.value.ssl_cert is defined %} 
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="${user.home}/.keystore" keystorePass="{{ item.value.ssl_pass }}"
           clientAuth="false" sslProtocol="TLS"/>
           {% endif %}

快乐的模板!