voipp
voipp

Reputation: 1461

How to properly escape symbols in ansible command?

I want to execute the command on each node:

docker ps --format '{{.Names}}' -a | egrep -v '^k8s.*$'

I tried millions of variants to execute command in ansible, including:

- hosts: kubernetes
  tasks:
    - name: check docker
      command:
        cmd: docker ps --format '{{.Names}}' -a | egrep -v '^k8s.*$'
      register: doc

    - debug: var=doc.stdout_lines

I tried to escape characters. But nothing works. So, how to make ansible execute the my docker command on each host?

PS I want to list containers that ain't controlled by k8s

Upvotes: 1

Views: 53

Answers (1)

phanaz
phanaz

Reputation: 1632

You have several problems with your task:

  1. you are using the command module with shell syntax (pipelining multiple commands)

    The error in this case:

    unknown shorthand flag: 'v' in -v See 'docker ps --help'.

    As you can see, the pipe is ignored and the -v parameter is passed to the Docker command.

  2. double curly braces in a string. Double curly braces are interpreted as Jinja2 syntax in Ansible and attempts to templatize.

    The error in this case:

    template error while templating string: unexpected '.'.

Solution for problem 1

  • You can use the shell module, here you can execute all commands that are possible in a shell.

  • Alternatively, you can simply execute the Docker command with the command module and filter the resulting data in Ansible.

See below for examples.

Solution for problem 2

  • Define the curly brackets as variables and insert them at the appropriate place.

    - name: check docker
      command:
        cmd: "docker ps --format '{{ cbo }} .Names {{ cbc }}' -a"
      vars:
        cbo: "{{ '{{' }}"  # curly braces open
        cbc: "{{ '}}' }}"  # curly braces close
      register: doc
    
  • You can define the entire string as raw string with marker !unsafe. Then it is not templated by Ansible with Jinja2, but then you can't templatize other variables in this string.

    - name: check docker
      command:
        cmd: !unsafe "docker ps --format '{{.Names}}' -a"
      register: doc
    

Final resulting task

  • using command module, filter data in Ansible and !unsafe marker

    - name: check docker
      command:
        cmd: !unsafe "docker ps --format '{{.Names}}' -a"
      register: doc
    
    - name: filter docker container names
      set_fact:
        container_names: "{{ doc.stdout_lines | reject('match', '^k8s') }}"
    
    - debug: var=container_names
    

    With the reject filter, all list elements that match ^k8s are discarded.

  • using shell module and !unsafe marker

    - name: check docker
      shell:
        cmd: !unsafe "docker ps --format '{{.Names}}' -a | egrep -v '^k8s.*$'"
      register: doc
    
    - debug: var=doc.stdout_lines
    

Upvotes: 3

Related Questions