development

Ansible에서 이중 중괄호 이스케이프

big-blog 2021. 1. 9. 11:28
반응형

Ansible에서 이중 중괄호 이스케이프


Ansible 1.9.2에서 이중 중괄호를 이스케이프하는 방법은 무엇입니까?

예를 들어, 다음 쉘 명령에서 이중 중괄호를 어떻게 이스케이프 할 수 있습니까?

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

다음은 docker --inspect중괄호 에 의존하지 않는 대부분 깨끗하고 Ansible 기본 해결 방법 입니다. 이전에 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','') }}"

이제 Variable에 Docker 컨테이너의 IP가 _container_ip있습니다. 또한이 해결 방법을 내 기사 The Marriage of Ansible with Docker 에 게시했습니다 .

[Update 2015-11-03] 컨테이너 쿼리의 stdout 공백을 제거했습니다.

[Update 2015-11-04] BTW, 공식 Ansible 저장소에 두 개의 pull 요청이 있었는데 Docker 모듈에서 반환 한 사실을 복구하여이 ​​해결 방법을 불필요하게 만들었습니다. 따라서 .NET을 통해 도커 컨테이너의 IP에 액세스 할 수 docker_containers[0].NetworkSettings.IPAddress있습니다. 따라서 해당 풀 요청에 투표하십시오.


Ansible에서 충돌하는 문자에 문제가있을 때마다 경험상의 규칙은 Jinja 표현식의 문자열로 출력하는 것입니다.

따라서 대신 {{다음을 사용합니다 {{ '{{' }}.

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

Jinja2 문서의 "Escaping"주제.


이:

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

작동해야

또 다른 방법은 백 슬래시를 사용하는 것입니다. \{\{ .NetworkSettings.IPAddress \}\}

도움이되기를 바랍니다.


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의 새로운 기능은 값을 안전하지 않은 유형으로 지정하는 기능입니다.

귀하의 예에서 다음을 수행 할 수 있습니다.

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

자세한 내용은 문서 를 참조하십시오.


작은 스크립트를 사용하여 내 문제를 해결했습니다.

#!/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이 이중 중괄호 이스케이프를 허용하지 않는다는 것은 매우 놀라운 일입니다!


비슷한 문제가 있습니다. 다음과 같은 일부 go 템플릿 변수 (예, 알고 있습니다.

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

템플릿의이 부분을

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

템플릿과 변수 대체를 두 번 실행하는 일종의 마법이 ansible에 있기 때문에 작동하지 않았습니다.

You end up with "undefined variable service_name" when trying to use the template...

So i ended up using a combination of !unsafe and {% raw %} ... {% endraw %} to define a fact that's later used in the template.

- 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') }}"

the template contains this:

    "ROOT_DOMAIN":"{{__rancher_init_root_domain}}",
    "ROUTE53_ZONE_ID":"",
    "NAME_TEMPLATE":"{{__rancher_init_name_template }}",
    "HEALTH_CHECK":"10000",

and the output is ok:

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

Here's a shorter alternative to udondan's answer; surround the whole string with double brackets:

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

I was unable to get @Ben's answer to work (shell: !unsafe ...)

What follows here is a complete (and working!) answer to the OP's question, updated for 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                                                                                                          

outputs: ([WARNINGS] removed)

# 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

ReferenceURL : https://stackoverflow.com/questions/32279519/escaping-double-curly-braces-in-ansible

반응형