I have a ansible playbook with below tasks and when I run it, I get an error:
tasks:
- shell: timeout 5 ps aux | grep app
register: result
ignore_errors: True
- name: Run your shell command
shell: "(ssh -o StrictHostKeyChecking=no abc.com 'ls -1 /var/lib/jenkins/workspace/copy/stuff/*' | parallel -j20 'scp -o StrictHostKeyChecking=no abc.com:{} /data/records/')"
when: result.rc != 124 && result.rc != 0
Error is:
{"msg": "The conditional check 'result.rc != 124 && result.rc != 0' failed. The error was: template error while templating string: unexpected char u'&' at 23. String: {% if result.rc != 124 && result.rc != 0 %} True {% else %} False {% endif %}\n\nThe error appears to have been in '/var/lib/jenkins/workspace/proc/test.yml': line 10, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: copy files\n ^ here\n"}
Any idea what wrong I am doing here?
Correct syntax is
when:
- result.rc != 124
- result.rc != 0
or
when: (result.rc != 124) and (result.rc != 0)
Related
Could you please help me with identifying the error
'dict object' has no attribute 'stdout'
which I am getting while running an Ansible playbook. Please see the error below:
{"msg": "The conditional check '(result.stdout == 1) and (ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat')' failed. The error was: error while evaluating conditional ((result.stdout == 1) and (ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat')): 'dict object' has no attribute 'stdout'\n\nThe error appears to be in '/etc/ansible/playbooks/dev_patching_security_upgrade_version2.yml': line 47, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Reboot CentOS Server if Necessary\n ^ here\n"}
I am pasting the relevant part of the code below:
- name: check to see if we need a reboot in Centos
shell:
"needs-restarting; echo $?"
register: result
ignore_errors: yes
when: ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat'
- name: display result
debug:
var: result.stdout
when: ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat'
- name: Reboot CentOS Server if Necessary
command: shutdown -r now "Ansible Updates Triggered reboot"
become: true
async: 30
poll: 0
when: (result.stdout == 1) and (ansible_distribution == 'CentOS' or ansible_distribution == 'RedHat')
Thanks in advance
This is because the result set might not have a dictionary key stdout. To debug a result set you may use
- name: Show result
debug:
var: result
Since the shell module already provides the return code within the Return Values, reboot checks are simple as
- name: Check if reboot_required
shell:
cmd: "needs-restarting -r"
changed_when: false
failed_when: reboot_required.rc != 0 and reboot_required.rc != 1
check_mode: false
register: reboot_required
- name: Report reboot_required
debug:
msg: "{{ reboot_required.rc | bool }} "
changed_when: reboot_required.rc == 1
check_mode: false
and resulting into an output of in example
TASK [Report reboot_required] **************************************************
ok: [test1.example.com] => {
"msg": "True "
}
ok: [test2.example.com] => {
"msg": "False "
}
You could dense down the tasks to one by using one
needs-restarting -r || /usr/sbin/shutdown -r now "Ansible Updates Triggered reboot"
Further Q&A
How to determine if system needs a reboot?
Ansible - How to reboot the server based on condition?
Guys I have code like:
- name: Running ccache for {{ SOMETHING }}
shell: "{{ item }}"
loop:
- command1
- command2
- command3
when: stat_result.stat.exists
failed_when: >
(rc != 0) or
(rc != 8)
I tried to get the following logic work:
"If command's exit code is not 0 or 8 , then success."
However only thing I get from this is:
[0;31mfatal: [someIPhere]: FAILED! => {"msg": "The conditional check '(rc != 0) or (rc != 8)' failed. The error was: error while evaluating conditional ((rc != 0) or (rc != 8)): 'rc' is undefined"}[0m
Any advices?
You need to register a variable to contain the results of the commands. This variable will contain values for each item in the loop, including rc.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#registering-variables
- name: Running ccache for {{ TENANT }}
shell: "{{ item }}"
loop:
- touch /tmp/test
- touch /tmp/test
- touch /tmp/test
when: stat_result.stat.exists
register: command_result
failed_when: command_result.rc not in [ 0, 68 ]
Team,
I am trying to verify if sdd exists in mount command output. so when there is any, i am fine but when there is none, my task is simply failing instead of just telling me that no mounts exists. any hint how to tackle this? I don't want my task to fail but to report what is the state.
when status code is 0 am good but when status code is 1 am just seeing failure instead of a helpful message that mounds sdd don't exist.
"mount | grep sdd"
- name: "Verify LVP Mounts sdd exists on CPU Nodes for mount_device"
shell: "mount | grep sdd"
register: lvp_mount
ignore_errors: yes
failed_when: False
delegate_to: "{{ item }}"
with_items: "{{ groups['kube-cpu-node'] }}"
- name: "Report status of mounts"
fail:
msg: |
Mounts sdd not found
Output of `mount | grep sdd`:
{{ lvp_mount.stdout }}
{{ lvp_mount.stderr }}
when: lvp_mount | failed
output:
fatal: [localhost]: FAILED! => {"msg": "The conditional check 'lvp_mount | failed' failed. The error was: template error while templating string: no filter named 'failed'. String: {% if lvp_mount | failed %} True {% else %} False {% endif %}\n\nThe error appears to be in '/k8s/baremetal/roles/maglev-services-pre-install-checks/tasks/main.yml': line 111, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n with_items: \"{{ groups['kube-cpu-node'] }}\"\n - name: \"Report status of mounts\"\n ^ here\n"}
expected output:
if lvp_mount.rc == 0
msg: mount sdd exists
if lvp_mount.rc == 1
msg: mount sdd does not exists
if lvp_mount.rc not in [0, 1]
msg: mount exec errir
The error is telling you that there is no filter named failed. To check for a failed result in a conditional, use this instead:
when: lvp_mount is failed
Alternatively, to check for a successful result, use:
when: lvp_mount is succeeded
Getting error when using an if/else condition to set a variable in a playbook on Red Hat.
I tried a few different permutations of quotes, brackets etc.
Executed as "ansible-playbook -e env=dev playbook.yaml"
Set Vars:
vars:
certenv: "{{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}"
Task
- name: Update server.xml Cert
lineinfile:
dest: "{{tomcat}}/conf/server.xml"
regexp: '^(.*)certificateFile(.*)$'
line: 'certificateFile="{{tomcat}}/webapps/{{appwar}}/certificates/app{{certenv}}domain.cer"'
Error
fatal: [localhost]: FAILED! => {"msg": "An unhandled exception occurred while templating '{{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}'.
Error was a <class 'ansible.errors.AnsibleError'>, original message: template error while templating string: expected token ':', got '}'. String: {{ '-eng.dev.' if {{env}} == 'eng' else '.dev.' if {{env}} == 'dev' else '.uat.' if {{env}} == 'stg' else '.prd.' if {{env}} == 'prd' }}"}
Expecting the certenv variable to be set as ".dev." for example.
As per comments: Modify your variable to
certenv: "{{ '-eng.dev.' if env == 'eng' else '.dev.' if env == 'dev' else '.uat.' if env == 'stg' else '.prd.' if env == 'prd' }}"
and run your playbook with:
ansible-playbook myplaybook.yml -e "env=dev".
For jinja2, the syntax is:
vars:
certenv: "{% if env == 'eng' %}-eng.dev.{% elif env == 'dev' %}.dev.{% elif env == 'stg' %}.uat.{% elif env == 'prd' %}.prd.{% endif %}"
You do not need to put the variables in {{...}} because they are inside the jinja2 markers {%...%}.
You can also make it more readable:
vars:
certenv:
"{% if env == 'eng' %}
-eng.dev.
{% elif env == 'dev' %}
.dev.
{% elif env == 'stg' %}
.uat.
{% elif env == 'prd' %}
.prd.
{% endif %}"
An option would be to use selectattr and map. The play below
vars:
cert_options:
eng: "-eng.dev."
dev: ".dev."
stg: ".uat."
prd: ".prd."
env: "stg"
tasks:
- set_fact:
certenv: "{{ cert_options|dict2items|selectattr('key', 'match', env)|map(attribute='value')|list }}"
- debug:
var: item
loop: "{{ certenv }}"
gives:
"item": ".uat."
This hint might help to solve the problem.
The fixed syntax of the code is below. (not tested)
- name: Update server.xml Cert
lineinfile:
dest: "{{ tomcat }}/conf/server.xml"
regexp: "^(.*)certificateFile(.*)$"
line: "certificateFile={{ tomcat }}/webapps/{{ appwar }}/certificates/app{{ certenv }}domain.cer"
I am trying to write a task which runs a list of ldapmodify statements and only want it to fail if any of the return codes are not 0 or 68 (object allready existed):
- name: add needed LDAP infrastructure
action: command ldapmodify -x -D '{{ ADMINDN }}' -w '{{ LDAPPW }}' -H {{ LDAPURI }} -c -f {{ item }}
register: result
failed_when: "result.results | rejectattr('rc', 'sameas', 0) | rejectattr('rc', 'sameas', 68) | list | length > 0"
# ignore_errors: true
with_items:
- a.ldif
- b.ldif
Does not work, producing the error:
error while evaluating conditional: result.results | rejectattr('rc', 'sameas', 0) | rejectattr('rc', 'sameas', 68) | list | length > 0
However if I comment the failed_when and use ignore_errors, the following tasks produce the correct results. While I can use this workaround to solve my problem, I would like to understand why the failed_when version is not working, as I would find that more elegant.
- debug: var="result.results | rejectattr('rc', 'sameas', 0) | rejectattr('rc', 'sameas', 68) | list | length > 0"
- fail: msg="failure during ldapmodify"
when: "result.results | rejectattr('rc', 'sameas', 0) | rejectattr('rc', 'sameas', 68) | list | length > 0"
Sidenote sameas might be equalto in other versions of jinja2, in case you are wondering.
Well, it turns out I was going about it much too complicated. The problem was: Ansible runs failed_when after every iteration of the loop. As such I simply need to access result.rc:
- name: add needed LDAP infrastructure
action: command ldapmodify -x -D '{{ ADMINDN }}' -w '{{ LDAPPW }}' -H {{ LDAPURI }} -c -f {{ item }}
register: result
# As per comment from user "ypid"
failed_when: ( result.rc not in [ 0, 68 ] )
# failed_when: ( result.rc != 0 ) and ( result.rc != 68 )
with_items:
- a.ldif
- b.ldif
produces the wanted result.
After the loop the variable result is filled with a summary dictionary which has the details of each item in the results key.
But since I was not able to find any examples of using result.results with filter chains I will just leave this question up, hoping someone else might find it useful. ( I'm sure I will eventually want to look it up again some day ;) )
Thanks to sivel on #ansible for pointing this out.