Ansible "until" response from Jira API - ansible

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

Related

Ansible playbook for installing cyberpanel stops execution

Greetings for the day,
I was trying to install cyberpanel using Ansible by writing a playbook.
The playbook was this
---
- name: Installing cybepanel
hosts: ansible_client
user: ubuntu
become: yes
become_user: root
become_method: sudo
tasks:
- name: Installing screen
apt:
name: screen
state: present
- name: Download the script
get_url:
url=https://cyberpanel.net/install.sh
dest=/root/installer.sh
- name: Execute the script
become: yes
become_method: su
become_user: root
become_exe: sudo su -
expect:
command:
screen -S cyberpanel-installation
sh installer.sh
echo: yes
responses:
(.*) Please enter the number(>*): "1"
'Full installation \[Y/n\]:': "Y"
(.*) Remote MySQL(.*): "N"
(.*)Enter specific version such as:(.*): ""
(.*)Choose(.*)password(.*): "r"
'Please select \[Y/n\]:': "Y"
(.*)Please type Yes or no(.*): "no"
'Would you like to restart your server now? \[y/N\]:': "y"
async: 1800
poll: 5
register: output
- name: 'Checking the status'
async_status:
jid: "{{ output.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 150
delay: 60
- name: debugging
debug:
var=output
The playbook doesn't have any error or conflicts.
The playbook works fine and the cyberpanel is installing with in 20-30 mins(As there is screen in the playbook. The screen stays detached in the destination server and after attaching it (when the playbook stops execution) in the destination server we could see that the installation in progress And successfully completes with in 20-30 mins.
The issue is that the playbook stops execution after 1 minutes of execution with a return code(rc)=0.
This is the output of playbook.
As you can see i am using the async method with poll=0 and poll>0 for long time execution of the script. It is not working the playbook still timesout.
I also increased the SSH timeout to check whether any ssh timeout takes place or not and there is no ssh timeout too.
Also tried using the timeout attribute instead of async method that also don't worked for me.
Anybody with a helping hand is well appreciated.

Ansible is not accepting customer fail module

- 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.

Ansible Playbook creating BitBucket Repository

I am trying to create a BitBucket Repository via Ansible Playbook.
However, running the following command using RestAPI works fine:
curl -u user:Password \
-d '#data.json' \
-X POST \
-H "Content-Type: application/json" \
http:// https://api.bitbucket.org/1.0/projects/SUN/repos
JSON includes the following:
{"name": "my-repo",
"scmId": "git",
"forkable": true}
I tried all kind of ways to convert this curl command to an ansible playbook but it`s always failing with different errors.
- hosts: localhost
tasks:
- name: Create a Bitbucket Repo
uri:
url: https://api.bitbucket.org/1.0/projects/SUN/repos
method: POST
user: user
password: password
src: data.json
force_basic_auth: yes
status_code: 201
body_format: json
When leaving "tasks" it says playbook needs to be a list of plays.
When removing tasks it says "uri" is not valid attribute.
Can anyone advise on the structure the playbook should have in this example?
Thanks a lot
The "tasks needs to be a list" message generally means you either
forgot a - (dash) before a task
- hosts: localhost
tasks
name: # no dash here.
uri:
# ...
misindented something.
I Re-formatted your code. It looks OK to me, as reformatted. Double check what you have in your playbook. But you do need the tasks: keyword or you will get the second error message you mention for sure.

Ansible: Can we run an include playbook Asynchronously?

I'm interested to learn if Ansible can run an included playbook asynchronously?
Basically what I'm trying to do is run a task "Fire and forget, check on it later." When I check on it later I also want to send a slack notification with the result.
However I've notice the included playbook for slack notification takes a little longer than expected to complete and hence it holds up the rest of the playbook.
What I want is to async the included playbook for slack notification so that the current playbook continues.
For instance I have a playbook.yml file that looks like:
- hosts: localhost
tasks:
- name: Fire and forget task
shell: some_task.sh
chdir=/tmp/
register: fire_and_forget_task
async: 3600
poll: 0
- name: Check on fire and forget task
async_status: jid={{ fire_and_forget_task.ansible_job_id }}
register: task_status
until: task_status.finished
retries: 100
ignore_errors: yes
- name: Send slack success msg
include: slack.yml msg="Fire and forget task SUCCESS"
when: task_status.stdout is defined and
'SUCCESS' in fire_and_forget_task.stdout
async: 3600
poll: 0
- name: Send slack failed msg
include: slack.yml msg="Fire and forget task FAILED"
when: task_status.stdout is defined and
'FAILED' in fire_and_forget_task.stdout
async: 3600
poll: 0
My slack.yml file looks like:
- name: Send notification message via Slack
local_action:
module: slack
token: <REDACTED>
attachments:
- text: "{{ msg }}"
color: "#83F52C"
title: "Ansible Status {{ lookup('pipe','date') }}"
With the above playbook, the "Send slack success msg" task takes an awfully long time to execute for a simple task like that. It seems its not running asynchronously even though I have explicitly stated it should.
What is the best way to achieve the desired outcome?
Thank you.
include can't use async keyword.
If your slack.yml is that simple, just replace your include stuff with a single call:
- name: Send notification message via Slack
local_action:
module: slack
token: <REDACTED>
attachments:
- text: "Task result {{ (task_status.stdout is defined and 'SUCCESS' in task_status.stdout) | ternary('SUCCESS','FAILURE') }}"
color: "#83F52C"
title: "Ansible Status {{ lookup('pipe','date') }}"
async: 3600
poll: 0
P.S. but I don't understand how is single Slack HTTP-call slowing down your playbook if you have a long-running task (with high async and retries numbers) just before it...

Ansible integer variables in YAML

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.

Resources