#!/usr/bin/bash # # Run ansible on all hosts older than the latest git commit. # Use argument "$(date)" to update all machines independent # of the last ansible run. # set -eu ## maximal age of file in minutes: age="15" pbook="lmn-client" logdir="/tmp/collector" debug=false ## date of latest git commit in ansible repository: git_date="$(date --iso-8601=seconds --date="$(git log --date=iso-strict | \ head -3 | sed -nE "s/^Date:\s+(.+)$/\1/p")")" echo "Latest commit in git at: $git_date." if [[ $# = 0 ]] ; then timestamp="$git_date" else timestamp="$(date --iso-8601=seconds --date="$1")" fi echo "Time stamp at: $timestamp." #dir="$(mktemp -d)" dir="/tmp/emitter" mkdir -vp "$dir" touch "$dir/${timestamp//T*/}" hlist="" n=0 running=0 ansible_arg="" find_outdated(){ hlist="" n=0 running=0 ansible_arg="--tags=upgrade" while IFS= read -r -d '' file ; do running=$(( running + 1 )) $debug && echo -n "Processing host '$file' with IP address " d="$(sed -nE "s/^2\s+(\S.+)$/\1/p" "$file")" if [[ -z "$d" ]] || \ [[ $(date --date="$d" +%s) -lt $(date --date="$timestamp" +%s) ]] ; then r='([0-9]{1,3}\.){3}[0-9]{1,3}' ipa="$(sed -nE "s/^3\s+default via.+ src ($r) metric.+/\1/p" "$file")" if [[ -z "$ipa" ]] ; then # FIXME: Outdated report format, try fallback: ipa="$(sed -nE "s|^.+default via.+ src ($r) metric.+|\1|p" "$file" | head -1)" fi $debug && echo "'$ipa'." if ! grep -q "$ipa" "$dir/${timestamp//T*/}" ; then echo "$ipa" >> "$dir/${timestamp//T*/}" hlist="$hlist,$ipa" n=$(( n + 1 )) if [[ $(date --date="$d" +%s) -lt $(date --date="$git_date" +%s) ]] ; then ## ansible run needed at least on one machine, run it on all: echo "Triggering full ansible run!" ansible_arg="" fi else $debug && echo "Host already processed before." fi fi done < <(find "$logdir" -maxdepth 1 -type f -mmin -$age -print0) hlist="${hlist#,}" echo -n "Running hosts: $running, to be upgraded: $n. " } run_ansible(){ local hsts="$1" if [[ -n "$hsts" ]] ; then if ! echo | eval ANSIBLE_RETRY_FILES_ENABLED=1 ANSIBLE_RETRY_FILES_SAVE_PATH="$dir" \ ansible-playbook --vault-password-file ~/.vaultpwd \ -bi inventory.yml "$pbook.yml" "$ansible_arg" -l "$hsts" ; then while IFS= read -r ipa ; do sed -i "/$ipa/d" "$dir/${timestamp//T*/}" echo "IP address '$ipa' removed from '$dir/${timestamp//T*/}'." done < "$dir/$pbook.retry" fi fi } ################# while true ; do date --rfc-3339=seconds find_outdated run_ansible "$hlist" t=$(( 600/(n*n+1) )) echo -n "Sleeping for $t seconds now ... " sleep $t done