如何在Ansible 1.9.2中避免双大括号?
例如,在以下shell命令中,如何转义双大括号?
- name: Test
shell: "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"
如果在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": []}
- Davide Guerriraw_var: '{{ '{{' }}something{{ '}}' }}'
并在其他地方引用它 command: "{{ raw_var }}"
,你会得到 Error: something is undefined
。 - Megakoreshraw_var: "{{ '{{' }}something{{ '}}' }}"
- udondan这个:
- name: Test
shell: "docker inspect --format {% raw %}'{{ .NetworkSettings.IPAddress }}' {% endraw %} instance1"
应该有效
另一种方法是使用反斜杠,例如\{\{ .NetworkSettings.IPAddress \}\}
希望能帮到你
{ raw }...{% endraw %}
对我有效。但是转义确实不起作用。它会导致\\{\\{ .NetworkSettings.IPAddress \\}\\}
的结果。 - udondan{{ .NetworkSettings.IPAddress }}
。这是我得到的: changed: [docker-server.local] => {"changed": true, "cmd": "docker inspect --format '{# .NetworkSettings.IPAddress #}' glance-api.os-in-a-box", "delta": "0:00:00.028659", "end": "2015-08-29 17:25:53.416944", "rc": 0, "start": "2015-08-29 17:25:53.388285", "stderr": "", "stdout": "172.17.1.6", "warnings": []}
- Davide Guerri使用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"
- Timmy Chiu我有一个类似的问题:我需要发布一个JSON文档,该文档由一个包含一些go模板变量(是的,我知道:-P)的jinja2模板生成,例如
"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}}",
这里有一个比 udondan 的答案 更简短的替代方案; 将整个字符串用双括号括起来:
shell: "docker inspect --format {{ '{{ .NetworkSettings.IPAddress }}' }} instance1"
已经提到过使用raw
的解决方案,但是很可惜之前答案中的命令对我来说不起作用。
没有ansible:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker_instance_name
使用Ansible:
- 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
#!/usr/bin/env bash
docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$1"
以下是 Ansible play 的代码:
- 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不允许转义双大括号!
我无法让@Ben的答案工作(shell:!unsafe ...
)
以下是完整且可行的答案,针对Ansible >2.0进行了更新,以回答OP的问题
---
# 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原生解决方法。我们假设之前刚引用了一个容器,使用了Ansible docker module。- 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','') }}"
现在你已经在变量_container_ip
中拥有了Docker容器的IP。我还在我的文章 Ansible与Docker的结合中发布了这个解决方法。
[更新2015-11-03] 删除了容器查询的标准输出的空格。
[更新2015-11-04] 顺便说一下,官方Ansible存储库中有两个拉取请求,通过恢复Docker模块返回的事实,这个解决方法就不再需要了。所以你可以通过docker_containers[0].NetworkSettings.IPAddress
访问Docker容器的IP。请投票支持这些拉取请求:
inspect
docker 客户端命令输入一个使用双大括号作为 jinja2 模板的 go 模板。我需要一种方法可以将大括号传递到目标服务器上运行的最终 Ansile 命令中。请参阅 http://docs.docker.com/reference/commandline/inspect。 - Davide Guerri