How to check if PID is running in ansible and if not then fail the task? - ansible

I have ansible playbook which does 3 things:
a) Start up a flask server
b) Waits for 10 seconds for it to start
c) Checks if the PID is running
- name: "execute script to start flask"
shell: nohup python main.py &
args:
chdir: /home/ubuntu/flask
executable: /bin/bash
- pause: seconds=10
- name: "verify that the server has started"
command: ?????
Manually I do this to get PID
pgrep -f /'main.py'
Which returns a PID lets say...
8212
How do I do step(c) in ansible playbook, and to make sure if PID is not found, task will fail?

I would not work with pause, it slows down your playbook unnecessarily. You could simply work with the pids Ansible-Module and until
Pids: https://docs.ansible.com/ansible/latest/modules/pids_module.html
Loop-Until: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#retrying-a-task-until-a-condition-is-met
Example checking every 5 seconds for 10 retries, if the Pid from main.py is not available then, the playbook will fail.
---
- hosts: localhost
tasks:
- name: check the pid of main.py
pids:
name: main.py
register: pid
until: pid.pids | length > 0
delay: 5
retries: 10
- debug: var=pid

Related

Ansible Cron special time "You must specify time and date fields or special time." error

I am trying to add a cron job to an ansible playbook. This job takes a long time and I need to run it during normal server off time. The script is as follows:
- name: Set scheduled run
cron:
name: "cron run"
special_time: reboot
minute: "0"
hour: "20"
user: root
job: "/path/to/script"
This works okay without the special_time: reboot but when that is added i get the following error:
"You must specify time and date fields or special time."
In order to achieve what you are looking for, you need two cron jobs:
The first one will reboot the server at a given time
The second one will be executed at reboot — with the #reboot mechanism of the crontab
Mind that the side effect of this is that your script will be executed at each reboot of that node, might it be during night, when the first cron reboots the node, or whenever the node reboots.
This will give this playbook:
- name: Scheduled reboot
cron:
name: "Reboot to launch /path/to/script"
minute: "0"
hour: "20"
user: root
job: "/sbin/reboot"
- name: Launch script after reboot
cron:
name: "Launch /path/to/script after reboot"
special_time: reboot
user: root
job: "/path/to/script"
What you could do to be extra sure that the script is not executed in the middle of the day, though, is to verify the hour at the beginning of it, something like:
#!/usr/bin/env sh
if [ "$(date +%H)" -lt 20 ]; then
exit 0
fi

Ansible: wait for user action or timeout

How can I wait for 30sec OR a user interaction in Ansible?
I have the following playbook at the moment:
- name: "Test"
hosts: localhost
tasks:
- name: wait
wait_for:
timeout: 30
but you can't press return to cancel the waiting time.
I also have unsuccessfully try the following solution:
- name: "Test"
hosts: localhost
tasks:
- name: wait
wait_for:
pause:
prompt: Press return to continue. Press Ctrl+c and then "a" to abort
timeout: 30
but pause is not a valide option for wait_for.
the documentation says:
You can use ctrl+c if you wish to advance a pause earlier than it is set to expire or if you need to abort a playbook run entirely. To continue early press ctrl+c and then c. To abort a playbook press ctrl+c and then a.

Ansible does not cancel a job after running into fata error (awx)

I have the following issue concerning ansible (awx):
When a Job fails with fatal: [IP]: FAILED!, ansible does not cancel this job and awx keeps displaying "Running" forever. I need to cancel those jobs manual which is quite annoying.
The reason why ansible fails does not matter here.
I've tried to solve this problem by adding
- name: Fail task when the command error output prints FAILED
ansible.builtin.command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
at the top of the playbook, but it won't work.
If you have any ideas...
Thanks!
Playbooks support asynchronous mode, if you need stablish a timeout for your task you can use it. Ansible waits until the tasks either completes, fails or timeout. For this you should use async and poll parameters, async stablishs the timeout for the task and poll stablishs the time in wich ansible checks the status of the task. Both must be in seconds.
You could try as below
- name: Fail task when the command error output prints FAILED
ansible.builtin.command: /usr/bin/example-command -x -y -z
register: command_result
async: 60
poll: 15
For more information:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html#asynchronous-playbook-tasks

Running task periodically in Docker container without cancellation issues on endless loop

I'm Dockerizing ssh-key-authority and made an Apache2 container that serves the PHP application. To sync users, the script scripts/ldap_update.php should run periodically every xx min. So I created a second container in my docker-compose.yml file that reuses the Apache image containing phps binary:
version: '2'
services:
ska:
image: ska
build:
context: .
args:
# Allow fetching packages from the internet in corporate environments
http_proxy: ${http_proxy}
env_file: docker.env
ports:
- 80:80
ska-db:
image: mariadb:10.5
env_file: docker.env
cron:
image: ska
volumes_from:
- ska
env_file: docker.env
depends_on:
- ska-db
entrypoint: |
bash -c '
./prepare-docker-configs.sh
# Wait for DB connection
sleep 10
while true
do
echo Running update task
php /ska/scripts/ldap_update.php
sleep 10
done'
10s are for testing only. Productive I'd increase this to lets say 1800 (30 min). While this works, it has a problem: Docker couldn't stop this while true loop, e.g. when executing docker-compose down. As result, Docker waits 10s and then kill the container process.
This causes delays during development and it seems not to be a clean way for handling this. I found trap, which worked well outside Docker using this script:
#!/bin/bash
trap 'kill -TERM -s SIGKILL $PID' SIGINT SIGTERM
PID=$$
echo pid: $PID
while true
do
echo sleep run
sleep 10
done
Result:
$ ./trap.sh
pid: 26135
sleep run
^CKilled
But when trying this in the ENTRYPOINT (even with exec), the container just exited:
entrypoint: |
bash -c '
./prepare-docker-configs.sh
set -x
PID=$$
exec "trap 'kill -TERM -s SIGKILL $PID' SIGINT SIGTERM"
echo "pid is $$"
while true
do
sleep 10
echo sync ldap users
php /ska/scripts/ldap_update.php
done'
The only alternative I see is installing cron and running it in the foreground, but that seems a bit overkill to me.
If you want to kill container process and not wait for 10 seconds, try:
docker-compose kill -s SIGINT
SIGTERM only reaches bash whereas SIGINT reaches sleep

How can I slow down ansible?

Is there a way to slow down ansible by placing a "sleep 5 seconds" between every server run.
For example, I would require something like that:
# --sleep-in-between is a hypothetical flag that would easily explain what I'm looking for
ansible production_servers -a "systemctl restart network" -f 1 --sleep-in-between 5secs
So, if production_servers is a group of servers: server_1, server_2, server_3 then the above command will perform the following:
Output:
server_1: Executing systemctl restart network
sleep 5 seconds
server_2: Executing systemctl restart network
sleep 5 seconds
server_3: Executing systemctl restart network
sleep 5 seconds
I need automation to take place slowly so that I can observe the system for any glitches taking place in the monitoring system while ansible is running.
Q: "Is there a way to slow down ansible by placing a "sleep 5 seconds" between every server run?"
A: Yes. It is. Use wait_for module and set serial to 1. For example
shell> cat playbook.yml
- hosts: all
serial: 1
tasks:
- debug:
msg: systemctl restart network
- wait_for:
timeout: "{{ sleep_in_between|default(5) }}"
By default, each host will wait 5 seconds before termination. It's possible to set it from the command line. For example, sleep for 10 seconds
shell> ansible-playbook -e "sleep_in_between=10" playbook.yml

Resources