docker - tag - Escapar de llaves dobles en Ansible
docker image version (9)
Aquí hay una alternativa más corta a la respuesta de udondan ; rodea toda la cuerda con corchetes dobles:
shell: "docker inspect --format {{ ''{{ .NetworkSettings.IPAddress }}'' }} instance1"
¿Cómo escapar de llaves dobles en Ansible 1.9.2?
Por ejemplo, ¿cómo puedo escapar de llaves dobles en el siguiente comando de shell?
- name: Test
shell: "docker inspect --format ''{{ .NetworkSettings.IPAddress }}'' instance1"
Aquí hay una solución nativa en su mayoría limpia y Ansible que no depende de la
docker --inspect
con llaves.
Asumimos que acabamos de hacer referencia a un contenedor con el
módulo acoplable Ansible
antes:
- 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'','''') }}"
Ahora tiene la IP del contenedor Docker en la Variable
_container_ip
.
También publiqué esta solución en mi artículo
The Marriage of Ansible with Docker
.
[Actualización 2015-11-03] Se eliminaron los espacios en blanco de la salida estándar de la consulta del contenedor.
[Actualización 2015-11-04] Por cierto, hubo dos solicitudes de extracción en el repositorio oficial de Ansible, que haría innecesaria esta solución al recuperar los hechos devueltos por el módulo Docker.
Para que pueda acceder a la IP de un contenedor acoplable a través de
docker_containers[0].NetworkSettings.IPAddress
.
Entonces, vote por esas solicitudes de extracción:
Esta:
- name: Test
shell: "docker inspect --format {% raw %}''{{ .NetworkSettings.IPAddress }}'' {% endraw %} instance1"
Deberia trabajar
Otra forma de hacerlo es usar barras invertidas como
/{/{ .NetworkSettings.IPAddress /}/}
Espero eso ayude
Me las arreglé para solucionar mi problema usando un pequeño script:
#!/usr/bin/env bash
docker inspect --format ''{{ .NetworkSettings.IPAddress }}'' "$1"
Y la siguiente obra de 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
Sin embargo, es muy sorprendente que Ansible no permita escapar de llaves dobles.
No pude obtener la respuesta de @ Ben para trabajar (
shell: !unsafe ...
)
Lo que sigue aquí es una respuesta completa (¡y funciona!) A la pregunta del OP, actualizada para 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
salidas: ([ADVERTENCIAS] eliminadas)
# 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
Nuevo en Ansible 2.0 es la capacidad de especificar un valor como tipo inseguro.
En tu ejemplo podrías hacer:
- name: Test
shell: !unsafe "docker inspect --format ''{{ .NetworkSettings.IPAddress }}'' instance1"
Ver los documentos para más detalles.
Probado con ansible 2.1.1.0
El bloque {% raw%} ... {% endraw%} parece el camino claro
- name: list container images and name date on the server
shell: docker ps --format {%raw%}"{{.Image}} {{.Names}}"{%endraw%}
Solo necesita escapar de los principales ''{{''
tasks:
- name: list container images and names
shell: docker ps --format "{{''{{''}}.Image}} {{''{{''}}.Names}}"
No hay daño para escapar de la cola ''}}'', excepto que es más difícil de leer.
tasks:
- name: list container images and names
shell: docker ps --format "{{''{{''}}.Image{{''}}''}} {{''{{''}}.Names{{''}}''}}"
La barra invertida ''/' parece no funcionar
Siempre que tenga problemas con los caracteres en conflicto en Ansible, una regla general es generarlos como una cadena en una expresión Jinja.
Entonces, en lugar de
{{
usarías
{{ ''{{'' }}
:
- debug: msg="docker inspect --format ''{{ ''{{'' }} .NetworkSettings.IPAddress {{ ''}}'' }}'' instance1"
Tengo un problema similar: necesito publicar un documento JSON hecho a partir de una plantilla jinja2 que contiene algunas variables de plantillas go (sí, lo sé :-P), como
"NAME_TEMPLATE": %{{service_name}}.%{{stack_name}}.%{{environment_name}}
Intentando cercar esta parte de la plantilla entre
{% raw %} ... {% endraw %}
no funcionó porque hay algún tipo de magia en ansible que ejecutará la plantilla y la subposición variable dos veces (no estoy seguro de eso, pero definitivamente se ve así)
Terminas con "variable indefinida
service_name
" cuando intentas usar la plantilla ...
Así que terminé usando una combinación de
!unsafe
y
{% raw %} ... {% endraw %}
para definir un hecho que luego se usará en la plantilla.
- 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'') }}"
la plantilla contiene esto:
"ROOT_DOMAIN":"{{__rancher_init_root_domain}}",
"ROUTE53_ZONE_ID":"",
"NAME_TEMPLATE":"{{__rancher_init_name_template }}",
"HEALTH_CHECK":"10000",
y la salida está bien:
"NAME_TEMPLATE": "%{{service_name}}.%{{stack_name}}.%{{environment_name}}",