本文介绍了Ansible with_dict模板使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下任务:

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

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

And I've also added the containers dictionary in my group_vars

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

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

Finally here is the relevant snippet from server.xml

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

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

What I want to happen is that the relevant http_port gets used in the template module. But instead I get and error:

致命:[localhost] => {'msg': AnsibleUndefinedVariable:一个或多个未定义变量:'http_port'未定义, 'failed':True}

fatal: [localhost] => {'msg': "AnsibleUndefinedVariable: One or more undefined variables: 'http_port' is undefined", 'failed': True}

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

Is this possible? How do I leverage an item's values for variable substitution?

推荐答案

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

Using {{ item.value.http_port }} is exactly the right solution.

当您传递with_dict时,它将循环执行任务,将容器字典中的每个项目传递为 {{item}} ,其中该项目具有一个键,而词典项目包含的任何值-在您的情况下,键/值对为键,其中键为http_port,值为这两个不同的整数-但是您可以传递非常复杂的嵌套字典,在其中变得更重要的是使用出现的 {{item.value.http_port}} 语法访问内容

When you pass with_dict, it loops through the task passing each of the items in your containers dictionary as {{ item }}, where the item has a key and whatever values that dictionary item contains - in your case, key/value pairs where the keys are http_port and the values are those two different integers - but you can pass seriously complex nested dictionaries where it gets even more important to access things with the {{ item.value.http_port }} syntax you came up with.

在使用更复杂的模板时要警惕的是,如何混合使用内容并设置默认值,并在有其他多余内容时使用if语句

The thing to be wary of as you get to more complex template usage is how to mix stuff up and set defaults and use if-statements when you have some extra variables to template for one host (or container, or whatever) but not another.

要掌握一个主机(或容器,或其他任何东西)的模板变量,请读u p在Jinja2上,Ansible语言会用它来解释模板。一个很好的例子是在此处通过SSL在前端(而不是后端)上提供文件。使用类似 {{foo | default('bar')}} ,以避免Ansible惹恼您尝试使用未定义的变量和if语句,以确保您只是模板化所需的东西。

To get to grips on it, read up on Jinja2, the language Ansible interprets templates in. A good example would be something like serving files over SSL on your frontend here, but not the backend. Use syntax like {{ foo | default('bar') }} to avoid Ansible getting angry about you trying to use undefined variables, and if-statements so as to make sure you're only templating the stuff you need.

一个粗略的草图-说过:

A rough sketch - say you had:

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

在这种情况下,想象您要复制一个任务该密钥库在需要时移到文件系统上,您可以使用以下方式:

In that case, imagining you'd had a task to copy that keystore over onto the filesystem when needed, you could use something along the lines of:

<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 %}

模板很高兴!

这篇关于Ansible with_dict模板使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-12 17:41