2014-09-24 2 views
4

У меня есть следующая задача:анзибль использование шаблона with_dict

- 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 используется в модуле шаблона. Но вместо этого я получаю и ошибка:

со смертельным исходом: [локальный] => { 'сбщ': "AnsibleUndefinedVariable: Один или более неопределенные переменные: 'http_port' не определен", 'не удалось': Правда}

ли это возможно? Как использовать значения элемента для замены переменных?

+0

необходимо указать как минимум фрагмент 'server.xml'; это то, что терпит неудачу. – tedder42

+3

Я не знаю, насколько переносимо это решение, но замена {{http_port}} на {{item.value.http_port}} решает проблему – user1432403

+2

. Я почти уверен, что это стандартный способ сделать это afaik. – jarv

ответ

4

Использование {{ item.value.http_port }} - это правильное решение.

Когда вы проходите через_dict, он проходит через задачу, передающую каждый из элементов в вашем словаре контейнеров, как {{ item }}, где элемент имеет ключ и любые значения, которые содержит элемент словаря - в вашем случае пары ключ/значение, где ключи являются http_port, а значениями являются эти два разных целых числа, но вы можете передать серьезно сложные вложенные словари, где становится еще более важным получить доступ к вещам с помощью синтаксиса {{ item.value.http_port }}, с которым вы столкнулись.

Осторожно, поскольку вы получаете более сложное использование шаблонов, это как смешивать вещи и устанавливать значения по умолчанию и использовать if-statements, когда у вас есть дополнительные переменные для шаблона для одного хоста (или контейнера или что-то еще) но не другой.

Чтобы понять это, прочитайте Jinja2, язык Ansible интерпретирует шаблоны. Хорошим примером может быть что-то вроде файлов для загрузки через SSL на вашем интерфейсе здесь, но не для бэкэнд. Используйте синтаксис, например, {{ foo | default('bar') }}, чтобы избежать Ansible, злитесь на то, что вы пытаетесь использовать неопределенные переменные, и if-statements, чтобы удостовериться, что вы только задумываетесь над тем, что вам нужно.

Грубый эскиз - сказать, что вы были:

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

Happy templating!

Смежные вопросы