- name: "Waiting for URL to come up."
uri:
url: "{{ url }}/libs/granite/core/content/login.html"
status_code: 200
register: result
until: result.status == 200
retries: 10
delay: 10
fail:
msg: "Service was not available after 10 minutes. Files were installed except for the ones that required AEM to be available"
I'm adding the fail message so when the task fails we will have a meaningful output.
However I receive an error:
line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: \"Waiting for URL to come up.\"\n ^ here\n"}[0
I checked at the documentation and it seems that is the right way to do. What am I missing?
If you look at the documentation for the uri module, you will
note that there is no fail parameter. There is, however, a separate
fail module. If you'd like to use that, you will need to
rewrite your uri task such that it does not cause Ansible fail, but
instead records the task result so that you can use it in a subsequent
fail action.
- name: "Waiting for URL to come up."
uri:
url: "{{ url }}/libs/granite/core/content/login.html"
status_code: 200
until: result.status == 200
retries: 10
delay: 10
register: uri_result
ignore_errors: true
- name: fail with custom message
when: uri_result is failed
fail:
msg: >-
Service was not available after 10 minutes. Files
were installed except for the ones that required AEM
to be available.
Related
This should be a very simple task but I'm unable to get past a syntax error.
In the below playbook, the first task gets the capabilities of Python and registers it in python_capability where python_capability.stdout becomes /usr/bin/python3.10 cap_sys_nice=ep.
In the next task, I split this string and set capabilities to everything following after the 0th item. In this case, capabilities becomes [cap_sys_nice=ep].
Then, I want to check the length of the above list and fail if it's > 1.
- hosts: tests
become: yes
pre_tasks:
- block:
- name: Ensure Python has CAP_SYS_NICE privileges
capabilities:
path: /usr/bin/python3.10
capability: cap_sys_nice+ep
state: present
register: python_capability
rescue:
- name: RESCUE | Get Python capabilities
set_fact:
capabilities: "{{ python_capability.stdout.split()[1:] }}"
- name: Get length
set_fact:
num_capabilities: "{{ capabilities | length }}"
- name: Failed when
failed_when: num_capabilities | int > 1
But I get the below syntax related error:
ERROR! no module/action detected in task.
The error appears to be in '/test.yml': line 25, column 11, but may
be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: Failed when
^ here
What am I missing?
You need to change the last task to:
- name: Validate number of capabilities
ansible.builtin.fail:
msg: "There are too many capabilities"
when: num_capabilities | int > 1
This will stop the execution if the condition is met.
Following is the piece of code, which is retrieving list of local zones and trying to enter rescue block if any one of the local zones is not in RUNNING state.
But the rescue block is failing, at 'Check if the zones are in running state'
Expectation is to send an email with the task name. But it is working well with other failed tasks.Can anyone please guide?
FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'item' is undefined\n\nThe error appears to be in '/etc/ansible/playbooks/misc/test1404.yml': line 23, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n rescue:\n - name: Sending an e-mail from Ansible controller node\n ^ here\n"}
- '{{ host }}'
tasks:
- block:
- name: Retrieve list of local zones
shell: /usr/sbin/zoneadm list | grep -v global
register: lzones
tags:
- local_zone_list
- debug:
msg: "{{ item }}"
with_items: "{{lzones.stdout_lines}}"
- name: Check if the zones are in running state
shell: /usr/sbin/zoneadm list | grep -v global | grep "{{ item }}" | awk '{print$3}'
register: status
with_items: "{{lzones.stdout_lines}}"
failed_when: status.stdout.find('running') == -1
< few other tasks>
rescue:
- name: Sending an e-mail from Ansible controller node
mail:
host: localhost
port: 25
to: xyz#abc.com
subject: Reboot Failed
body: Reboot FAILED at TASK - {{ ansible_failed_task.name }} with ERROR {{ ansible_failed_result }}
delegate_to: localhost
Well that was an absolutely fascinating rabbit hole.
Because in ansible jinja2 templates are rendered recursively, when it tries to render the failed message, which contains the failed template, it tries to re-render the failed template again, re-causing the error
This appears to be impacting you by the inclusion of the ansible_failed_task variable, since -- inexplicably -- it appears to be safe to include ansible_failed_result in the body
As best I can tell by experimenting with ansible 2.9.6, one must determine if it is possible to safely output the a*_task flavor variable before touching it, because I was wholly unable to find any combination of | string or |regex_replace or anything that allowed jinja2 to touch that variable so long as it contains the bogus variable reference:
- block:
- debug:
msg: this explodes {{ nope_not_a_var }}
rescue:
- set_fact:
is_undefined_error: '{{ "undefined variable" in ansible_failed_result.msg }}'
- name: variable is unsafe version
debug:
msg: >-
failed task action has an undefined variable in the task,
so we cannot show you the task, but here is the result: {{ ansible_failed_result }}
when: is_undefined_error
- name: variable is safe to output version
debug:
msg: Reboot FAILED at TASK - {{ ansible_failed_task.name }} with ERROR {{ ansible_failed_result }}
when: not is_undefined_error
It may be safe to inline that test of "..." in ansible_failed_result.msg into the when: lines directly, but since it (should) produce the same answer both times, there's no really good reason to evaluate it twice
This appears to me to be an ansible bug, but I don't have the emotional energy to take it up with their community -- however, I encourage you to file a bug with them
I am installing some plugins and then checking the status in a command loop. I want to check the result of the status of the command and if the plugins are not installed I want to install it again with the help of retry module.
- name: install plugins
command: "run {{ item }}"
with_items:
- install plugins
- status
register: result
until: result.stdout.find("InstallPlugin1 and InstallPlugin2") != -1
retries: 5
delay: 10
I am using register to save the result and I know register saves the result in results and in this case it will save the result in "results" dict. Now I want to check a string in result of status command in until, which should be the 2nd value of results dictionary but I am not able to grab it.
when I use
debug: msg="{{ result['results'][1]['stdout'] }}"
I can see the output of the status command but I dont know how to use this in until module. whenever I use results there it gives an error. I want to use something like
until: result['results'][1]['stdout'].find("all systems go") != -1
If both run install plugins and run status return something like
installed: InstallPlugin1, InstallPlugin2
the task below will do the job
- name: install plugins
command: "run {{ item }}"
loop:
- install plugins
- status
register: result
until:
- result.stdout is search('InstallPlugin1')
- result.stdout is search('InstallPlugin2')
retries: 5
delay: 10
It's not possible to use the loop if only run status returns the confirmation, because the until statement is evaluated in each iteration. An option would be to concatenate the commands. For example
- name: install plugins
command: "run install plugins; run status"
register: result
until:
- result.stdout is search('InstallPlugin1')
- result.stdout is search('InstallPlugin2')
retries: 5
delay: 10
It's possible to test the registered result in each loop. After the loop is done the variable result will keep accumulated result.results. It might be worth to review it.
- debug:
var: result
I think this is what you're looking for:
until: "all systems go" in item['stdout']
The register statement you have there will be a list of the aggregate results from all irritations in the with_items loop and what you want to conditional on is the item itself. Depending on what what you're doing, you might not even need to register that variable.
Im trying to schedule an ansible playbook to re-index Jira, Id also like our dev to be able to kick this off ad-hoc is needed which they would be able to do via AWX, I am able to start a re-index but would like a notification when the re-index is complete.
Here are my CLI commands and outputs:
[root#devjira02 ~]# curl -u admin:admin123! -X GET https://devjira.comapny.com/rest/api/2/reindex/progress
{"progressUrl":"/secure/admin/jira/IndexProgress.jspa?taskId=12720","currentProgress":35,"currentSubTask":"Currently working on: Issue index","type":"BACKGROUND","submittedTime":"2019-04-01T14:23:50.971+0100","startTime":"2019-04-01T14:23:50.973+0100","success":false}
[root#devjira02 ~]# curl -u admin:admin123! -X GET https://devjira.company.com/rest/api/2/reindex/progress
{"progressUrl":"/secure/admin/jira/IndexProgress.jspa?taskId=12720","currentProgress":100,"type":"BACKGROUND","submittedTime":"2019-04-01T14:23:50.971+0100","startTime":"2019-04-01T14:23:50.973+0100","finishTime":"2019-04-01T14:24:33.922+0100","success":true}
My Playbook:
- name: DEV Jira Re-index
become: true
become_method: sudo
become_user: root
hosts: DEVJIRA02
gather_facts: yes
tasks:
- name: Jira Re-index
uri:
url: https://devjira.company.com/rest/api/2/reindex?type=BACKGROUND_PREFERRED
method: POST
user: admin
password: admin123!
force_basic_auth: yes
status_code: [201, 202]
- name: Wait until re-index completes
uri:
url: https://devjira.company.com/rest/api/2/reindex/progress
method: GET
user: admin
password: admin123!
force_basic_auth: yes
status_code: [201, 202]
return_content: yes
body_format: json
register: result
until: result.json.success == true
retries: 180
delay: 30
Id like the second part to retry until success == true at which point AWX can send a notification email. Running the playbook manually will start the re-index but the retry will just retry even though the re-index has finished
Edit after user comment:
Although my below proposition is still good practice and will prevent some possible future headaches, it proved not to be the issue in this case.
I didn't pay attention at first that your are requesting the url call to return a 201 or 202 status while the jira documentation specifies you will receive a 200.
You should either:
Change the expected return code: status: 200
Drop the status option completely and change your condition: until: response.status == 200 and (result.json.success | bool)
Original proposition (does not fix but still good practice)
It is generally a bad idea in ansible to test against a literal true or false because ansible/yaml is quite permissive about the values you can use for that (yes, true, Y, 1, 234, no, false, 0, ...) and also because the values can sometimes be interpreted as pure strings rather that booleans (try with vars_prompt to understant the problem if you have some time).
Ansible provides a filter to test the boolean representation of a value. I'm not 100% sure this will fix your current problem but I would try with until: result.json.success | bool
I'm using Ansible to deploy a webapp. I'd like to wait for the application to be running by checking that a given page returns a JSON with a given key/value.
I want the task to be tried a few times before failing. I'm therefore using the combination of until/retries/delay keybwords.
Issue is, I want the number of retries to be taken from a variable. If I write :
retries: {{apache_test_retries}}
I fall into the usual Yaml Gotcha (http://docs.ansible.com/YAMLSyntax.html#gotchas).
If, instead, I write:
retries: "{{apache_test_retries}}"
I'm being said the value is not an integer.
ValueError: invalid literal for int() with base 10: '{{apache_test_retries}}'
Here is my full code:
- name: Wait for the application to be running
local_action:
uri
url=http://{{webapp_url}}/health
timeout=60
register: res
sudo: false
when: updated.changed and apache_test_url is defined
until: res.status == 200 and res['json'] is defined and res['json']['status'] == 'UP'
retries: "{{apache_test_retries}}"
delay: 1
Any idea on how to work around this issue? Thanks.
I had the same issue and tried a bunch of things that didn't work so for some time I just worked around without using a variable but found the answer so for everyone who has it.
Daniels solution indeed should work:
retries: "{{ apache_test_retries | int }}"
However, if you are running a little older version of Ansible it won't work. So make sure you update Ansible. I tested on 1.8.4 and it works and it doesn't on 1.8.2
This was the original bug on ansible:
https://github.com/ansible/ansible/issues/5865
You should be able to convert it to an integer with the int filter:
retries: "{{ apache_test_retries | int }}"
I had the same problem and the solutions suggested here didn't work. I didn't try Tim Diels' suggestion though.
Here's what worked for me:
vars:
capacity: "{{ param_capacity | default(16) }}"
tasks:
- name: some task
...
when: item.usage < (capacity | int)
loop:
...
And here's what I was trying to do:
vars:
capacity: "{{ (param_capacity | default(16)) | int }}"
tasks:
- name: some task
...
when: item.usage < capacity
loop:
...
I found this issue on GitHub, about this same problem, and actually the intended way to use this filter is applying it where you use the variable, not where you declare it.
I have faced a similar issue, in my case I wanted to restart celeryd service. It sometimes takes a very long time to restart and I wanted to give it max 30 seconds for a soft restart, then force-restart it. I used async for this (polling for restart result every 5 seconds).
celery/handlers/main.yml
- name: restart celeryd
service:
name=celeryd
state=restarted
register: celeryd_restart_result
ignore_errors: true
async: "{{ async_val | default(30) }}"
poll: 5
- name: check celeryd restart result and force restart if needed
shell: service celeryd kill && service celeryd start
when: celeryd_restart_result|failed
And then I use above in the playbook as handlers to a task (restart celeryd is always first in notify list)
In your case something like below could possibly work. Haven't checked whether it does but it might give you some hack idea to solve it in a different way. Also since you will be ignoring errors in the 1st task, you need to make sure that things are fine in 2nd:
- name: Poll to check if the application is running
local_action:
uri
url=http://{{webapp_url}}/health
timeout=60
register: res
sudo: false
when: updated.changed and apache_test_url is defined
failed_when: res.status != 200 and res['json'] is not defined and not res['json']['status'] == 'UP'
ignore_errors: true
async: "{{ apache_test_retries | default(60) }}"
poll: 1
# Task above will exit as early as possible on success
# It will keep trying for 60 secs, polling every 1 sec
# You need to make sure it's fine **again** because it has ignore_errors: true
- name: Final UP check
local_action:
uri
url=http://{{webapp_url}}/health
timeout=60
register: res
sudo: false
when: updated.changed and apache_test_url is defined
failed_when: res.status != 200 and res['json'] is not defined and not res['json']['status'] == 'UP'
Hope it helps you solve the issue with a bug in retries.