逃避Ansible中的双花括号

时间:2015-08-28 20:46:41

标签: docker jinja2 ansible

如何在Ansible 1.9.2中跳过双花括号?

例如,如何在以下shell命令中转义双花括号?

- name: Test 
  shell: "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"

10 个答案:

答案 0 :(得分:77)

每当你在Ansible中遇到冲突字符的问题时,经验法则是将它们作为Jinja表达式中的字符串输出。

因此,您将使用{{代替{{ '{{' }}

- debug: msg="docker inspect --format '{{ '{{' }} .NetworkSettings.IPAddress {{ '}}' }}' instance1"

Topic "Escaping" in the Jinja2 docs.

答案 1 :(得分:34)

此:

- name: Test 
  shell: "docker inspect --format {% raw %}'{{ .NetworkSettings.IPAddress }}' {% endraw %} instance1"

应该工作

另一种方法是使用\{\{ .NetworkSettings.IPAddress \}\}

之类的反斜杠

希望有所帮助

答案 2 :(得分:19)

尝试使用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{{'}}'}}"

反斜杠' \'似乎不起作用

答案 3 :(得分:3)

我设法使用一个小脚本解决了我的问题:

#!/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不允许逃避双花括号,这是非常令人惊讶的!

答案 4 :(得分:3)

Ansible 2.0中的新功能是将值指定为unsafe类型。

在您的示例中,您可以这样做:

- name: Test 
  shell: !unsafe "docker inspect --format '{{ .NetworkSettings.IPAddress }}' instance1"

See the docs了解详情。

答案 5 :(得分:2)

这里是udondan's answer的更短替代方案;用双括号将整个字符串括起来:

orderBy

答案 6 :(得分:2)

已经提到了使用raw的解决方案,但不幸的是,答案中的命令对我不起作用。

没有旁白:

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

答案 7 :(得分:1)

我有一个类似的问题:我需要发布一个由jinja2模板制作的JSON文档,其中包含一些go模板变量(是的,我知道:-P),例如

"NAME_TEMPLATE": %{{service_name}}.%{{stack_name}}.%{{environment_name}}

试图在

之间围住模板的这一部分

{% raw %} ... {% endraw %}

没有工作,因为在ansible中存在某种魔法,它将运行模板和变量替换两次(我不确定,但它明确地看起来像这样)

你最终得到了#34;未定义变量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}}",

答案 8 :(得分:0)

我无法获得@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

答案 9 :(得分:-4)

这是一个大多数干净且安全的本机解决方法,不依赖于带有花括号的docker --inspect。我们假设我们刚刚使用 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。我还在我的文章The Marriage of Ansible with Docker上发布了此解决方法。

[更新2015-11-03]删除了容器查询的标准输出空间。

[更新2015-11-04]顺便说一句,在官方的Ansible存储库中有两个pull请求,这将通过恢复Docker模块返回的事实使这个解决方法变得不必要。因此,您可以通过docker_containers[0].NetworkSettings.IPAddress访问docker容器的IP。所以请投票给那些拉动请求: