'Conditionally add argument to argv
I want to conditionally pass --detach into argv like this:
- name: run docker container with service
command:
args:
argv:
- docker
- run
- "{{ '' if wait else '--detach' }}"
- "--restart=always"
- "--network=host"
- --log-driver
- fluentd
- --log-opt
- fluentd-async-connect=true
- --log-opt
- fluentd-sub-second-precision=true
- --log-opt
- mode=non-blocking
But it doesn't work because empty argv arguments are incorrectly passed to docker. Is there any workaround?
Solution 1:[1]
I found a way to modify the solution from Frenchy so that there is no need to create a custom filter. Instead of difference we can use reject('equalto', ...) like this:
- name: run docker container with service
command:
args:
argv: "{{ command_args | reject('equalto', omit) | list }}"
vars:
command_args:
- docker
- run
- "{{ omit if wait is defined and wait else '--detach' }}"
- "--network=host"
- --log-driver
- fluentd
- --log-opt
- fluentd-async-connect=true
- --log-opt
- fluentd-sub-second-precision=true
- --log-opt
- mode=non-blocking
Solution 2:[2]
i have had same problem so, i suggest you to use omit with a little tips because omit is not very well changed in arguments:
- name: echo test
command:
args:
argv: "{{ command_args | difference(omit) }}"
vars:
command_args:
- docker
- run
- "{{ omit if wait else '--detach' }}"
- "--restart=always"
- "--network=host"
i have read that somewhere but impossible to remember the post
if you have same options defined more times, the solution above is not functional, you could use a custom filter named here extractarg:
#!/usr/bin/python
class FilterModule(object):
def filters(self):
return {
'extractarg': self.extractarg
}
def extractarg(self, args):
result = []
print(args)
for k in args:
if not k.startswith('__omit_place'):
result.append(k)
return result
and you change the lines
args:
argv: "{{ command_args | difference(omit) }}"
by
args:
argv: "{{ command_args | extractarg }}"
if you dont like custom filter, you could use just jinja loop :
- name: echo test
command:
args:
argv: "{{ _argv }}"
vars:
command_args:
- docker
- run
- "{{ omit if wait else '--detach' }}"
- "--restart=always"
- "--network=host"
_argv: >-
{%- set ns = namespace() -%}
{%- set ns.result = [] -%}
{%- for v in command_args if not v.startswith('__omit_place') -%}
{%- set ns.result = ns.result + [v] -%}
{%- endfor -%}
{{ ns.result }}
Solution 3:[3]
Just don't use the command module when there are dedicated modules to achieve what you need — in this case docker_container.
Then, your issue become trivial, since the detach parameter expects a boolean. In your case, then it would just be not wait.
So, your task become:
- docker_container:
detach: "{{ not wait }}"
restart: yes
restart_policy: always
log_driver: fluentd
log_options:
fluentd-async-connect: true
fluentd-sub-second-precision: true
mode: non-blocking
Solution 4:[4]
Create a switch on your own. For example, as a hint, the playbook below
shell> cat pb.yml
- hosts: localhost
tasks:
- debug:
var: argv
vars:
argv: "{{ command_args|zip(switch)|
selectattr('1')|
map(attribute='0')|list }}"
switch:
- true
- true
- "{{ wait|d(false)|bool }}"
- true
command_args:
- docker
- run
- --detach
- --restart=always
gives (abridged)
shell> ansible-playbook pb.yml
...
argv:
- docker
- run
- --restart=always
shell> ansible-playbook pb.yml -e wait=true
...
argv:
- docker
- run
- --detach
- --restart=always
Fit the lists to your needs.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Vlad |
| Solution 2 | |
| Solution 3 | |
| Solution 4 |
