Як уникнути подвійних фігурних дужок в Ansible 1.9.2?
Наприклад, як я можу уникнути подвійних фігурних дужок у такій команді оболонки?
- name: Test
shell: "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
Як уникнути подвійних фігурних дужок в Ansible 1.9.2?
Наприклад, як я можу уникнути подвійних фігурних дужок у такій команді оболонки?
- name: Test
shell: "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
inspect
команда клієнта docker бере на введення шаблон go, який використовує подвійні фігурні дужки як jinja2. Мені потрібен спосіб отримати фігурні дужки до останньої команди Ansile, запущеної на цільових серверах. Див. Docs.docker.com/reference/commandline/inspect -
Відповіді:
Кожного разу, коли у вас виникають проблеми з конфліктуючими символами в Ansible, основним правилом є виведення їх у вигляді рядка у виразі Jinja.
Отже, замість {{
вас ви б використовували {{ '{{' }}
:
- debug: msg="docker inspect --format '{{ '{{' }} .NetworkSettings.IPAddress {{ '}}' }}' instance1"
changed: [docker-server.local] => {"changed": true, "cmd": "docker inspect --format '{# .NetworkSettings.IPAddress #}' glance-api.os-in-a-box", "delta": "0:00:00.029344", "end": "2015-08-29 17:36:37.962143", "rc": 0, "start": "2015-08-29 17:36:37.932799", "stderr": "", "stdout": "172.17.1.6", "warnings": []}
raw_var: '{{ '{{' }}something{{ '}}' }}'
та посилаєтесь на неї в іншому місці, command: "{{ raw_var }}"
ви отримаєте Error: something is undefined
.
raw_var: "{{ '{{' }}something{{ '}}' }}"
?
Це:
- name: Test
shell: "docker inspect --format {% raw %}'{{ .NetworkSettings.IPAddress }}' {% endraw %} instance1"
Має працювати
Інший спосіб зробити це - використовувати зворотні скісні риски типу \{\{ .NetworkSettings.IPAddress \}\}
Сподіваюся, це допоможе
{ raw }...{% endraw %}
працює для мене. Втеча, хоча насправді не працює. Це призведе до\\{\\{ .NetworkSettings.IPAddress \\}\\}
fatal: [docker-server.local] => Failed to template {{test}}: Failed to template docker inspect --format '{{ .NetworkSettings.IPAddress }}' glance-api.os-in-a-box: template error while templating string: unexpected '.'
- name: Find ipv6 of of some-host shell: docker inspect -f "{% raw %} {{ .NetworkSettings.GlobalIPv6Address }} {% endraw %}" {{some.host}} > tmp.txt - command: cat tmp.txt register: result - debug: msg="{{ result.stdout }}"
Пробував з ansible 2.1.1.0
Блок {% raw%} ... {% endraw%} здається зрозумілим
- name: list container images and name date on the server
shell: docker ps --format {%raw%}"{{.Image}} {{.Names}}"{%endraw%}
Потрібно уникнути лише провідного "{{"
tasks:
- name: list container images and names
shell: docker ps --format "{{'{{'}}.Image}} {{'{{'}}.Names}}"
Не шкодить уникнути хвоста '}}', окрім складнішого для читання.
tasks:
- name: list container images and names
shell: docker ps --format "{{'{{'}}.Image{{'}}'}} {{'{{'}}.Names{{'}}'}}"
Зворотний слеш '\', здається, не працює
Новим у Ansible 2.0 є можливість оголосити значення як небезпечне з !unsafe
тегом.
У вашому прикладі ви можете зробити:
- name: Test
shell: !unsafe "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
!unsafe 'docker inspect --format "{{ .NetworkSettings.IPAddress }}" instance1'
У мене схожа проблема: мені потрібно опублікувати документ JSON, зроблений із шаблону jinja2, що містить деякі змінні шаблонів go (так, я знаю :-P), наприклад
"NAME_TEMPLATE": %{{service_name}}.%{{stack_name}}.%{{environment_name}}
Спроба огородити цю частину шаблону між
{% raw %} ... {% endraw %}
не спрацював, оскільки в ansible є якась магія, яка двічі запустить підрозділ шаблону та змінної (я не впевнений у цьому, але це остаточно виглядає так)
У вас з’являється "невизначена змінна service_name
" при спробі використовувати шаблон ...
Тож я в кінцевому підсумку використав комбінацію !unsafe
та, {% raw %} ... {% endraw %}
щоб визначити факт, який пізніше буде використаний у шаблоні.
- set_fact:
__rancher_init_root_domain: "{{ rancher_root_domain }}"
#!unsafe: try to trick ansible into not doing substitutions in that string, then use %raw% so the value won't substituted another time
__rancher_init_name_template: !unsafe "{%raw%}%{{service_name}}.%{{stack_name}}.%{{environment_name}}{%endraw%}"
- name: build a template for a project
set_fact:
__rancher_init_template_doc: "{{ lookup('template', 'templates/project_template.json.j2') }}"
шаблон містить це:
"ROOT_DOMAIN":"{{__rancher_init_root_domain}}",
"ROUTE53_ZONE_ID":"",
"NAME_TEMPLATE":"{{__rancher_init_name_template }}",
"HEALTH_CHECK":"10000",
і результат нормальний:
"NAME_TEMPLATE": "%{{service_name}}.%{{stack_name}}.%{{environment_name}}",
Мені вдалося обійти свою проблему за допомогою невеликого сценарію:
#!/usr/bin/env bash
docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$1"
І наступна п’єса Ansible
- copy:
src: files/get_docker_ip.sh
dest: /usr/local/bin/get_docker_ip.sh
owner: root
group: root
mode: 0770
- shell: "/usr/local/bin/get_docker_ip.sh {{ SWIFT_ACCOUNT_HOSTNAME }}"
register: swift_account_info
Тим не менше, дуже дивно, що Ansible не дозволяє втекти подвійним фігурним дужкам!
Рішення за допомогою raw
вже було згадано, але команда у відповіді раніше, на жаль, не спрацювала для мене.
Без ансамблю:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker_instance_name
З ансиблем:
- name: Get ip of db container
shell: "{% raw %}docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker_instance_name{% endraw %}"
register: db_ip_addr
- debug:
var: db_ip_addr.stdout
Мені не вдалося отримати відповідь @ Ben на роботу ( shell: !unsafe ...
)
Далі йде повна (і діюча!) Відповідь на запитання OP, оновлена для Ansible> 2.0
---
# file: play.yml
- hosts: localhost
connection: local
gather_facts: no
vars:
# regarding !unsafe, please see:
# https://docs.ansible.com/ansible/latest/user_guide/playbooks_advanced_syntax.html
#
- NetworkSettings_IPAddress: !unsafe "{{.NetworkSettings.IPAddress}}"
tasks:
- shell: "docker inspect --format '{{NetworkSettings_IPAddress}}' instance1"
register: out
- debug: var="{{item}}"
with_items:
- out.cmd
- out.stdout
виходи: ([ПОПЕРЕДЖЕННЯ] видалено)
# ansible-playbook play.yml
PLAY [localhost] ***************************************************************
TASK [shell] *******************************************************************
changed: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] => (item=out.cmd) => {
"item": "out.cmd",
"out.cmd": "docker inspect --format '{{.NetworkSettings.IPAddress}}' instance1"
}
ok: [localhost] => (item=out.stdout) => {
"item": "out.stdout",
"out.stdout": "172.17.0.2"
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
# ansible --version | head -1
ansible 2.6.1
Ось переважно чисте та відповідне місцеве рішення, не залежно від docker --inspect
фігурних дужок. Припускаємо, що ми щойно посилалися на один контейнер з модулем докерів Ansible :
- name: query IP of client container
shell: "docker exec {{ docker_containers[0].Id }} hostname -I"
register: _container_query
- name: get IP of query result
set_fact:
_container_ip: "{{ _container_query.stdout | regex_replace('\\s','') }}"
Тепер у вас є IP-адреса контейнера Docker у змінній _container_ip
. Я також опублікував цей обхідний шлях у своїй статті "Шлюб Ансібеля з Докером" .
[Оновлення 03.11.2015] Видалено пробіли stdout запиту контейнера.
[Оновлення 04.11.2015] До речі, в офіційному сховищі Ansible було два запити на витяг, що зробило б цей спосіб непотрібним, відновлюючи факти, повернуті модулем Docker. Таким чином, ви можете отримати доступ до IP контейнера докера через docker_containers[0].NetworkSettings.IPAddress
. Тож, будь ласка, проголосуйте за ці запити на витяг: