Skip to content

Instantly share code, notes, and snippets.

@mjanser
Forked from geerlingguy/ansible-role-test.sh
Created May 3, 2018 05:57
Show Gist options
  • Select an option

  • Save mjanser/8e2ea2f84b8c828267c86d9745d175dd to your computer and use it in GitHub Desktop.

Select an option

Save mjanser/8e2ea2f84b8c828267c86d9745d175dd to your computer and use it in GitHub Desktop.
Ansible Role Test Shim Script
#!/bin/bash
#
# Ansible role test shim.
#
# Usage: [OPTIONS] ./tests/test.sh
#
# Options are defined as environment variables:
# - DISTRO: a supported Docker distro version (default = "centos")
# - RELEASE: the release of the distro to use (default = "7")
# - ANSIBLE: version of Ansible to use (default = "2.5")
# - PLAYBOOK: a playbook in the tests directory (default = "test.yml")
# - ROLE_DIR: the directory where the role exists (default = $PWD)
# - CLEANUP: whether to remove the Docker container (default = 1)
# - TEST_IDEMPOTENCE: whether to test playbook's idempotence (default = 1)
# - ALLOW_ERRORS: whether to allow errors in playbook (default = 0)
# - ALLOW_WARNINGS: whether to allow warnings in playbook (default = 0)
#
# If you place a requirements.yml file in tests/requirements.yml, the
# requirements listed inside that file will be installed via Ansible Galaxy
# prior to running tests.
#
# License: MIT
# Pretty colors.
RED='\033[0;31m'
GREEN='\033[0;32m'
NEUTRAL='\033[0m'
# Allow environment variables to override defaults.
DISTRO=${DISTRO:-"centos"}
RELEASE=${RELEASE:-"7"}
ANSIBLE=${ANSIBLE:-"2.5"}
PLAYBOOK=${PLAYBOOK:-"test.yml"}
ROLE_DIR=${ROLE_DIR:-"$PWD"}
CLEANUP=${CLEANUP:-1}
TEST_IDEMPOTENCE=${TEST_IDEMPOTENCE:-1}
ALLOW_ERRORS=${ALLOW_ERRORS:-0}
ALLOW_WARNINGS=${ALLOW_WARNINGS:-0}
CONTAINER_CREATED=0
## Set up vars for Docker setup.
case "${DISTRO}" in
"centos")
IMAGE="geerlingguy/docker-${DISTRO}${RELEASE}-ansible:latest"
INIT="/usr/lib/systemd/systemd"
OPTS="--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
if [ "${RELEASE}" -lt 7 ]; then
INIT="/sbin/init"
OPTS="--privileged"
fi
;;
"debian")
IMAGE="geerlingguy/docker-${DISTRO}${RELEASE}-ansible:latest"
INIT="/lib/systemd/systemd"
OPTS="--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
;;
"ubuntu")
IMAGE="geerlingguy/docker-${DISTRO}${RELEASE}-ansible:latest"
INIT="/lib/systemd/systemd"
OPTS="--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
if [ "${RELEASE}" -lt 1604 ]; then
INIT="/sbin/init"
OPTS="--privileged"
fi
;;
"fedora")
IMAGE="geerlingguy/docker-${DISTRO}${RELEASE}-ansible:latest"
INIT="/usr/lib/systemd/systemd"
OPTS="--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro"
;;
*)
printf ${RED}"Specified distro ""${DISTRO}"" is not supported!"${NEUTRAL}\n
exit 1
;;
esac
error() {
printf ${RED}"FAILED!"${NEUTRAL}" See above for the error...\n"
cleanup
exit 1
}
abort() {
cleanup
exit
}
cleanup() {
# Remove the Docker container (if configured).
if [ "${CLEANUP}" -eq 1 -a "${CONTAINERID}" != "" -a $CONTAINER_CREATED -eq 1 ]; then
printf "Removing Docker container ${CONTAINERID}...\n"
docker rm -f $CONTAINERID || true
fi
}
trap error ERR
trap abort SIGHUP
trap abort SIGINT
trap abort SIGTERM
# Run the container using the supplied OS.
CONTAINERID=$(date +%s)
printf ${GREEN}"Starting Docker container: ${IMAGE}, id: ${CONTAINERID}."${NEUTRAL}"\n"
docker pull $IMAGE
docker run --detach --volume="$ROLE_DIR":/etc/ansible/roles/role_under_test:rw --name $CONTAINERID $OPTS $IMAGE $INIT
CONTAINER_CREATED=1
printf "\n"
# Install ansible.
printf ${GREEN}"Installing Ansible version ${ANSIBLE}."${NEUTRAL}"\n"
docker exec --tty $CONTAINERID env TERM=xterm pip install ansible~=${ANSIBLE}.0
printf "\n"
# Install requirements if `requirements.yml` is present.
if [ -f "${ROLE_DIR}/tests/requirements.yml" ]; then
printf ${GREEN}"Requirements file detected; installing dependencies."${NEUTRAL}"\n"
docker exec --tty $CONTAINERID env TERM=xterm ansible-galaxy install -r /etc/ansible/roles/role_under_test/tests/requirements.yml
fi
printf "\n"
# Test Ansible syntax.
printf ${GREEN}"Checking Ansible playbook syntax."${NEUTRAL}
docker exec --tty $CONTAINERID env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/$PLAYBOOK --syntax-check
printf "\n"
# Run Ansible playbook.
printf ${GREEN}"Running command: docker exec $CONTAINERID env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/$PLAYBOOK"${NEUTRAL}
log=$(mktemp)
docker exec $CONTAINERID env TERM=xterm env ANSIBLE_FORCE_COLOR=1 ansible-playbook /etc/ansible/roles/role_under_test/tests/$PLAYBOOK 2>&1 | tee -a $log
if [ "$ALLOW_ERRORS" -eq 0 ]; then
# Look for errors in log output.
grep 'ERROR\|FAILED' $log \
&& { printf ${RED}'Errors test: fail'${NEUTRAL}"\n"; error; } \
|| { printf ${GREEN}'Errors test: pass'${NEUTRAL}"\n"; }
fi
if [ "$ALLOW_WARNINGS" -eq 0 ]; then
# Look for warnings in log output.
grep 'WARNING' $log \
&& { printf ${RED}'Warnings test: fail'${NEUTRAL}"\n"; error; } \
|| { printf ${GREEN}'Warnings test: pass'${NEUTRAL}"\n"; }
fi
if [ "$TEST_IDEMPOTENCE" -eq 1 ]; then
# Run Ansible playbook again (idempotence test).
printf ${GREEN}"Running playbook again: idempotence test"${NEUTRAL}
idempotence=$(mktemp)
docker exec $CONTAINERID ansible-playbook /etc/ansible/roles/role_under_test/tests/$PLAYBOOK | tee -a $idempotence
tail $idempotence \
| grep -q 'changed=0.*failed=0' \
&& { printf ${GREEN}'Idempotence test: pass'${NEUTRAL}"\n"; } \
|| { printf ${RED}'Idempotence test: fail'${NEUTRAL}"\n"; error; }
fi
cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment