Example 1: Run Ansible playbooks in cron
Run ssh-agent
ssh-agent
is needed to provide the ssh connection plugin with the
password to the private key, when used. The script below is executed
by the command interpreter for login shells
1shell> cat /home/admin/.profile
2if [ -n "$BASH_VERSION" ]; then
3 if [ -f "$HOME/.bashrc" ]; then
4 . "$HOME/.bashrc"
5 fi
6 if [ -f "$HOME/.bashrc_ssh" ]; then
7 . "$HOME/.bashrc_ssh"
8 fi
9fi
10if [ -d "$HOME/bin" ] ; then
11 PATH="$HOME/bin:$PATH"
12fi
and will start ssh-agent
on login and prepare SSH_ENV (5)
1shell> cat /home/admin/.bashrc_ssh
2SSH_ENV="$HOME/.ssh/environment"
3function start_agent {
4 echo "Initializing new SSH agent..."
5 /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
6 echo succeeded
7 chmod 600 "${SSH_ENV}"
8 . "${SSH_ENV}" > /dev/null
9 /usr/bin/ssh-add;
10}
11if [ -f "${SSH_ENV}" ]; then
12 . "${SSH_ENV}" > /dev/null
13 #ps ${SSH_AGENT_PID} doesn't work under cywgin
14 ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
15 start_agent;
16 }
17else
18 start_agent;
19fi
Example of .ssh/environment created by ssh-agent
shell> cat /home/admin/.ssh/environment
SSH_AUTH_SOCK=/tmp/ssh-8fUkZ7qOzVPs/agent.5214; export SSH_AUTH_SOCK;
SSH_AGENT_PID=5216; export SSH_AGENT_PID;
#echo Agent pid 5216;
Run gpg-agent
Start gpg-agent
manually by running gpg
. gpg-agent
is needed to provide
gpg
with the password to the private gpg key, when used. For
example, to sign or encrypt emails, or to configure user’s passwords
with help of the passwordstore
. The configuration below enables
gpg-agent
also within a ssh session. In particular, no-grab (2)
allows cut&paste, no-allow-external-cache (3) disables any keyrings
and pinentry-curses (4) asks for the password in the terminal
instead of default pinentry asking in the remote (in the case of
ssh) desktop window. The time to live ttl (5,6) is set to 24
hours. This way, it’s not necessary to re-enter the password when the
cron
, which invokes the play with gpg-agent
, is run daily.
1shell> cat ~/.gnupg/gpg-agent.conf
2no-grab
3no-allow-external-cache
4pinentry-program /usr/bin/pinentry-curses
5default-cache-ttl 86400
6max-cache-ttl 86400
See also
Wrapper ansible-runner
Wrapper of ansible-runner will source .ssh/environment (42) and run the playbook from the project (44)
1#!/bin/bash
2
3# All rights reserved (c) 2020, Vladimir Botka <vbotka@gmail.com>
4# Simplified BSD License, https://opensource.org/licenses/BSD-2-Clause
5
6version="1.0.0"
7runner=$HOME/bin/ansible-runner
8project=$PWD/$2
9param=${3:-all.yml}
10usage="$(basename "$0") ver $version
11
12Usage:
13 $(basename "$0") <cmd> project [param]
14
15Where:
16 cmd ....... One of the commands: run, runid, stdout, custom, clean, test
17 project ... Private data directory. See ansible-runner.
18 param ..... Command specific parameter. See commands.
19
20Commands:
21 run project playbook.yml ......... Run playbook.yml in project
22 runid project playbook.yml ....... The same as run plus display artifact id
23 stdout project id ................ Display project/id/stdout
24 custom project id ................ Display custom stat from project/id/stdout
25 clean project .................... Delete project/artifacts
26 test project playbook.yml ........ Test playbook.yml in project
27
28Examples:
29 arwrapper run priv9 t9.yml ....... Run playbook t9.yml in priv9
30 arwrapper test priv9 t9.yml ...... Test playbook t9.yml in priv9
31 arwrapper clean priv9 ............ Delete pri9/artifacts
32 arwrapper stdout priv9 id1 ....... Display priv9/artifacts/id1/stdout
33 arwrapper custom priv9 id1........ Display custom stat from stdout\n"
34
35case "$1" in
36 test)
37 echo $(date '+%Y-%m-%d %H:%M:%S') $runner run $project -p $param
38 ;;
39 run|runid)
40 echo $(date '+%Y-%m-%d %H:%M:%S') $0
41 if [ -f "$HOME/.ssh/environment" ]; then
42 source $HOME/.ssh/environment
43 fi
44 $runner run $project -p $param
45 if [ "$1" = "runid" ]; then
46 ls -t $project/artifacts | head -1
47 fi
48 ;;
49 stdout)
50 cat $project/artifacts/$param/stdout
51 ;;
52 custom)
53 cat $project/artifacts/$param/stdout | \
54 sed -n '/PLAY RECAP/,$p' | \
55 sed -n '/CUSTOM STATS/,$p' | \
56 tail -n +2 | \
57 cut -d ":" -f2-
58 ;;
59 clean)
60 rm -rf $project/artifacts
61 ;;
62 *)
63 printf "$usage\n"
64 exit 1
65 ;;
66esac
67exit
Command for cron
The script below will use arwrapper.bash (5) to run the playbook pb-01.yml in the projects test_01, test_02, and test_03 (11-13). If the command (18) succeeds the script will print [OK] report (23). If you don’t want to receive email on success remove this line. Optionally enable/disable the cleaning of the artifacts (24).
1shell> cat /home/admin/bin/ansible-cron-test.bash
2#!/bin/bash
3
4cmd=$HOME/bin/arwrapper.bash
5subcmd=${1:-run}
6rc=0
7
8typeset -A projects
9projects=(
10 [test_01]="pb-01.yml"
11 [test_02]="pb-01.yml"
12 [test_03]="pb-01.yml"
13)
14
15for project in "${!projects[@]}"; do
16 for playbook in ${projects[$project]}; do
17 out=$("$cmd" "$subcmd" "$project" "$playbook" 2>&1)
18 if [ "$?" -eq "0" ]; then
19 if [ "$subcmd" = "test" ]; then
20 printf '%s\n' "[DRY] $out"
21 fi
22 printf '%s\n' "[OK] "$project" "$playbook" PASSED"
23 $cmd clean $project
24 else
25 printf '%s\n' "[ERR] $out"
26 rc=1
27 fi
28 done
29 done
30 exit $rc
Crontab
Schedule the script in cron
shell> whoami
admin
cntrlr> crontab -l
MAILTO=admin
#Ansible: Ansible runner daily test
50 20 * * * $HOME/bin/ansible-cron-test.bash
See also
Ansible role’s task FreeBSD postinstall cron.yml
Ansible role’s task Linux postinstall cron.yml
Email sent by cron
In our case the /etc/aliases redirect the emails for root to the user admin. Cron will report the result of the scpript ansible-cron-test.bash. If you want to receive email on a failure only remove the [OK] report from the script and optionally clean the artifacts. The artifacts will be available for a review if the script fails
Date: Tue, 7 Jul 2020 20:50:06 +0200 (CEST)
From: Cron Daemon <root@cntrlr.example.com>
To: admin@cntrlr.example.com
Subject: Cron <admin@cntrlr> $HOME/bin/ansible-cron-test.bash
[OK] test_01 pb-01.yml PASSED
[OK] test_02 pb-01.yml PASSED
[OK] test_03 pb-01.yml PASSED
Project
Example of the project’s directory without the artifacts. The artifacts will be created by ansible-runner
shell> tree /home/admin/.ansible/runner/test_01
/home/admin/.ansible/runner/test_01
├── env
├── inventory
│ └── hosts
└── project
├── ansible.cfg
├── group_vars
├── host_vars
└── pb-01.yml
Note
It’s necessary to provide ansible-playbook with the vault password if any data were encrypted. Use env/cmdline. For example,
shell> cat /home/admin/.ansible/runner/test_01/env/cmdline
--vault-password-file $HOME/.vault-psswd
See also
Example playbook how to create projects pb_create_runner_private.yml
Playbook
Example of a playbook used in the test
shell> cat /home/admin/.ansible/runner/test_01/project/pb-01.yml
- hosts: test_01
remote_user: admin
gather_facts: false
tasks:
- debug:
msg: TEST
Artifacts
Example of the project’s artifacts
shell> tree /home/admin/.ansible/runner/test_01/artifacts/
/home/admin/.ansible/runner/test_01/artifacts
└── aaa5d36e-e8d4-432a-ab52-b69062c85311
├── command
├── fact_cache
├── job_events
│ ├── 1-2b5c9412-f0c4-45dc-a425-5c8c29e37ec0.json
│ ├── 2-5ce0c5a2-1f02-cdab-8869-00000000001f.json
│ ├── 3-5ce0c5a2-1f02-cdab-8869-000000000021.json
│ ├── 4-28749e27-409a-46c4-9551-7ce80c02be83.json
│ ├── 5-997d90c1-6357-45c6-8df9-437c2940c74e.json
│ └── 6-6e41cf27-8c1e-4266-9ffb-8a54375bd4cc.json
├── rc
├── status
└── stdout