I have this in my playbook:
- name: Get facts about containers
shell: "docker ps -f name=jenkins --format {%raw%}{{.Names}}{% endraw %}"
register: container
Note, that I inserted the {%raw%} and {%endraw%} so that ansible does not evaulate the '{{'.
If I run this, I get this error:
fatal: [localhost]: FAILED! => {"failed": true, "msg": "{u'cmd': u'docker ps -f name=jenkins --format {{.Names}}', u'end': u'2017-01-19 10:04:27.491648', u'stdout': u'ecs-sde-abn-17-jenkins-ec8eccee8c9eb8e38f01', u'changed': True, u'start': u'2017-01-19 10:04:27.481090', u'delta': u'0:00:00.010558', u'stderr': u'', u'rc': 0, 'stdout_lines': [u'ecs-task-17-jenkins-ec8eccee8c9eb8e38f01'], u'warnings': []}: template error while templating string: unexpected '.'. String: docker ps -f name=jenkins --format {{.Names}}"}
In other words, the command ran succesfully (the output ecs-task-17-jenkins-ec8eccee8c9eb8e38f01 is correct), but than it tries the template the string ... again?
What is going wrong here and how can I fix this?
EDITED
Escaping the {{ like this:
shell: "docker ps -f name=jenkins --format {{ '{' }}{.Names}{{ '}' }}"
results in the same error.
This is a problem introduced in Ansible 2.2.1: https://github.com/ansible/ansible/issues/20400.
Happens when registering variable with {{ inside.
This workaround prevent {{ from appearing in registered variable:
shell: "docker inspect --format '{''{ .NetworkSettings.IPAddress }''}' consul"
Way to reproduce the bug:
- hosts: localhost
gather_facts: no
tasks:
- shell: "echo '{''{.Names}''}'"
register: myvar
- debug: var=myvar
Related
My intention with below playbook is to run a shell command only when it finds any of the value from disk_list. I need help to frame out when condition as told above.
---
- hosts: localhost
connection: local
gather_facts: false
tasks:
- set_fact:
disk_list:
- sda
- sdb
- sdc
- name: Get df -hT output to know XFS file system
shell: df -hT |grep xfs|awk '{print $1}'
register: df_result
- name: Run shell command on each XFS file system
shell: ls -l {{ item }} | awk '{print $1}'
with_items: "{{ df_result.stdout_lines }}"
when: "{{ disk_list.[] }} in {{ item }}"
BTW, in my system, "df_result" variable looks as below:
TASK [debug] ***************************************************************************************************************************************
ok: [localhost] => {
"df_result": {
"changed": true,
"cmd": "df -hT |grep xfs|awk '{print $1}'",
"delta": "0:00:00.017588",
"end": "2019-03-01 23:55:21.318871",
"failed": false,
"rc": 0,
"start": "2019-03-01 23:55:21.301283",
"stderr": "",
"stderr_lines": [],
"stdout": "/dev/sda3\n/dev/sda1",
"stdout_lines": [
"/dev/sda3",
"/dev/sda1"
]
}
}
Please help !
Some notes on the playbook.
For localhost, connection: local is implicit. So there is no technical need to specify this.
set_fact is correct, but in this case I believe is more appropiate to use "vars" at a play level instead of the set_fact module in a task. This also allows you to use "vars_files" for easier use of disk device lists.
I would reccomend to try to keep your task names "easy", as you may want to use the --start-at-task option at some point.
with_items is depricated in favor of "loop".
The conditional "when" works at a task level. So it will execute the task (for all its items) if the condition is met.
Here is a working version of what you need which also reflects the (5) recommendations made:
---
- hosts: localhost
gather_facts: false
vars:
disk_list:
- sda
- sdb
- sdc
tasks:
- name: cleans previous runs
shell: cat /dev/null > /tmp/df_result
- name: creates temporary file
shell: df -hT | grep ext4 | grep -i {{ item }} | awk '{print $1}' >> /tmp/df_result
loop: "{{ disk_list }}"
- name: creates variable
shell: cat /tmp/df_result
register: df_result
- name: shows info
shell: ls -l {{ item }} | awk '{print $1}'
loop: "{{ df_result.stdout_lines }}"
I basically just use a temporary file (/tmp/df_result) with the results you need already filtered by the "grep -i {{ item }}" used in the loop on task "creates temporary file". Then, the loop in "shows info" just iterates over an already clean list of items.
To see the result on screen, you could use "-v" option when running the playbook or if you want to save the result in a file, you could add " >> /tmp/df_final" at the end of the shell line in "shows info" task.
I accidently step on this post, which is kind of old. I'm sure you already fixed this in your environment, maybe you find a better way to do it, hopefully you did.
Regards,
Ansible variables passed via command line are not getting defined in the playbook.
I'm looking to pass external variables via command line to an ansible playbook. It is not working as expected using the -e, which is to call external variables based on the ansible documentation.
ansible-playbook /opt/playbooks/shutdown.yaml -f 10 -i /opt/inventory/hosts -e 'logPath=/my/log/path logName=shutdown.log logDir=shutdown'
---
- name: Transfer and execute a script.
hosts: all
remote_user: ansible
sudo: yes
tasks:
- name: Transfer the script
copy: src=/opt/files/shutdown.sh dest=/tmp/ mode=0777
- name: Execute the script
command: sh /tmp/shutdown.sh logPath logName logDir
- name: cat log output
command: cat logDir
register: myoutput
- name: get stout of execution of script
debug: msg={{ myoutput.stdout_lines }}
Here is my output, I'm expecting LogPath to be defined as the variable using key:value pair
: FAILED! => {"changed": true, "cmd": ["cat", "logPath"], "delta": "0:00:00.005258", "end": "2019-02-06 13:30:03.551631", "failed": true, "rc": 1, "start": "2019-02-06 13:30:03.546373", "stderr": "cat: logPath: No such file or directory", "stderr_lines": ["cat: logPath: No such file or directory"], "stdout": "", "stdout_lines": []}
to retry, use: --limit #/opt/playbooks/shutdown.retry
your command task seems wrong, you need to use curly brackets for ansible to treat the enclosed string as variable (and replace it with its value). Try this syntax:
- name: Execute the script
command: sh /tmp/shutdown.sh {{ logPath }} {{ logName }} {{ logDir }}
hope it helps
these should be passed in JSON notation, which would support passing other data-types than string:
-e '{"log_path":"/my/log/path","log_name":"shutdown.log","log_dir":"shutdown"}'
and then substitute accordingly:
- name: Execute the script
command: sh /tmp/shutdown.sh log_path log_name log_dir
snake-case is rather the default for variable names, than camel-case.
see the documentation.
I have a simple playbook:
---
- name: cat resolv.conf
telnet:
user: "{{ foxuser }}"
password: "{{ foxpass }}"
login_prompt: "login:"
prompts: "#"
command:
- grep 192.168.178.6 /etc/resolv.conf
register: resolv
changed_when: not( resolv.output | join('') | search('nameserver'))
notify: update resolv.conf
This works, but it throws a deprecation warning;
[DEPRECATION WARNING]: Using tests as filters is deprecated. Instead of using `result|search` use `result is search`. This feature will be removed in version 2.9.
I tried:
changed_when: not('nameserver' in resolv.output )
but that always seems to be true, even when nameserver is in resolv.output. Somehow, the join seems an essential part of the expression.
Note that resolv contains:
"resolv": {
"changed": false,
"failed": false,
"output": [
" grep 192.168.178.6 /etc/resolv.conf\r\nnameserver 192.168.178.6\r\n[root#foxboard /root]1068#"
]
}
I cannot seem to find a working solution without the filter. What am I missing?
I believe this should work (simulated test does for me):
- name: cat resolv.conf
telnet:
user: "{{ foxuser }}"
password: "{{ foxpass }}"
login_prompt: "login:"
prompts: "#"
command:
- grep 192.168.178.6 /etc/resolv.conf
register: resolv
changed_when: not ( resolv.output | join('') ) is search('nameserver')
notify: update resolv.conf
Using the search function as part of a filter appears to be what triggers the deprecation warning.
I am pretty much beginner with ansible. I am trying to migrate linux scripts to perform a remote server startup using the nohup command and it does not work properly. The ansible results state change: true, but when I check if the process is up, it doesn't. Thus, I have to restart it manually.
Thanks for your help.
Here what I am doing:
- name: "Performing remote startup on server {{ SERVER }}"
command: nohup {{ JAVA_HOME }}/bin/java {{ DYNATRACE_AGENT_REUS }} -jar -Dengine={{ ENGINE_NAME }} name-{{ ENGINE_JAR_VERSION }}.jar --server.port={{ ENGINE_PORT }} >{{ CONSOLE_LOG }} 2>&1 &
args:
chdir: "{{ SOMEVAR_HOME }}"
async: 75
poll: 0
register: out
- debug:
msg: '{{ out }}'
Results:
TASK [Performing remote startup on server] ***********************************************************************************************************************************************************************************
changed: [servername]
TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [servername] => {
"msg": {
"ansible_job_id": "160551828781.28405",
"changed": true,
"failed": false,
"finished": 0,
"results_file": "/home/admindirectory/.ansible_async/160551828781.28405",
"started": 1
}
}
Try to use shell instead of command module. Bash redirects do not work with command.
P.S. You are using ansible in a strange way. Create a systemd unit (system or user-level) and use systemd module to enable/start it.
I am running a custom command because I haven't found a working module doing what I need, and I want to adjust the changed flag to reflect the actual behaviour:
- name: Remove unused images
shell: '[ -n "$(docker images -q -f dangling=true)" ] && docker rmi $(docker images -q -f dangling=true) || echo Ignoring failure...'
register: command_result
changed_when: "command_result.stdout == 'Ignoring failure...'"
- debug: var="1 {{ command_result.stdout }}"
when: "command_result.stdout != 'Ignoring failure...'"
- debug: var="2 {{ command_result.stdout }}"
when: "command_result.stdout == 'Ignoring failure...'"
(I know the shell command is ugly and could be improved by a more complex script but I don't want to for now)
Running this task on an host where no Docker image can be removed gives the following output:
TASK: [utils.dockercleaner | Remove unused images] ****************************
changed: [cloud-host] => {"changed": true, "cmd": "[ -n \"$(docker images -q -f dangling=true)\" ] && docker rmi $(docker images -q -f dangling=true) || echo Ignoring failure...", "delta": "0:00:00.064451", "end": "2015-07-30 18:37:25.620135", "rc": 0, "start": "2015-07-30 18:37:25.555684", "stderr": "", "stdout": "Ignoring failure...", "stdout_lines": ["Ignoring failure..."], "warnings": []}
TASK: [utils.dockercleaner | debug var="DIFFERENT {{ command_result.stdout }}"] ***
skipping: [cloud-host]
TASK: [utils.dockercleaner | debug var="EQUAL {{ command_result.stdout }}"] ***
ok: [cloud-host] => {
"var": {
"EQUAL Ignoring failure...": "EQUAL Ignoring failure..."
}
}
So, I have this stdout return value "stdout": "Ignoring failure...", and the debug task shows the strings are equal, so why is the task still displayed as "changed"?
I am using ansible 1.9.1.
The documentation I am refering to is this one: http://docs.ansible.com/ansible/playbooks_error_handling.html#overriding-the-changed-result
I think you may have misinterpreted what changed_when does.
changed_when marks the task as changed based on the evaluation of the conditional statement which in your case is:
"command_result.stdout == 'Ignoring failure...'"
So whenever this condition is true, the task will be marked as changed.