#!/bin/bash -eu trap interrupt_exception SIGINT RST="\033[0m" RED="\033[31m" # BRIGHTRED="\033[31;1m" # GREEN="\033[32m" BRIGHTGREEN="\033[32;1m" # BROWN="\033[33m" YELLOW="\033[33;1m" # NAVY="\033[34m" BLUE="\033[34;1m" # MAGENTA="\033[35m" # BRIGHTMAGENTA="\033[35;1m" # DARKCYAN="\033[36m" # CYAN="\033[36;1m" # BLACK="\033[30m" # DARKGRAY="\033[30;1m" # GRAY="\033[37m" WHITE="\033[37;1m" TOPDIR="$(readlink -f "$(dirname "$0")/..")" interrupt_exception() { trap - SIGINT log warn "User interrupted test execution." cleanup exit 1 } usage() { local prog="${0##*/}" cat </dev/null 2>&1 } in_python_virtualenv() { local script read -r -d "" script <"${playbook}" ansible-playbook -i "${inventory}" "${playbook}" err=$? rm "${playbook}" return ${err} } die() { usg="N" if [ "${1}" == "-u" ] then usg="Y" shift 1 fi log error "${*}" STOP_CONTAINER="N" cleanup [ "${usg}" == "Y" ] && usage exit 1 } make_inventory() { local scenario=$1 engine=${2:-podman} inventory="${test_env}/inventory" log info "Inventory file: ${inventory}" cat << EOF > "${inventory}" [ipaserver] ${scenario} ansible_connection=${engine} [ipaserver:vars] ipaserver_domain = test.local ipaserver_realm = TEST.LOCAL EOF } stop_container() { local scenario=${1} engine=${2:-podman} echo "Stopping container..." quiet "${engine}" stop "${scenario}" echo "Removing container..." quiet "${engine}" rm "${scenario}" } cleanup() { if [ $# -gt 0 ] then if [ "${STOP_CONTAINER}" != "N" ] then stop_container "${1}" "${2}" rm "${inventory}" else log info "Keeping container: $(podman ps --format "{{.Names}} - {{.ID}}" --filter "name=${1}")" fi fi if [ "${STOP_VIRTUALENV}" == "Y" ] then echo "Deactivating virtual environment" deactivate fi } list_images() { local quay_api="https://quay.io/api/v1/repository/ansible-freeipa/upstream-tests/tag" echo -e "${WHITE}Available images:" curl --silent -L "${quay_api}" | jq '.tags[]|.name' | tr -d '"'| sort | uniq | sed "s/.*/ &/" echo -e "${RST}" } # Defaults ANSIBLE_VERSION=${ANSIBLE_VERSION:-'ansible-core>=2.12,<2.13'} verbose="" FORCE_ENV="N" CONTINUE_ON_ERROR="" STOP_CONTAINER="Y" STOP_VIRTUALENV="N" declare -a ENABLED_MODULES declare -a ENABLED_TESTS ENABLED_MODULES=() ENABLED_TESTS=() test_env="${TESTENV_DIR:-${VIRTUAL_ENV:-/tmp/ansible-freeipa-tests}}" engine="podman" IMAGE_REPO="quay.io/ansible-freeipa/upstream-tests" IMAGE_TAG="fedora-latest" scenario="" MEMORY=3 hostname="ipaserver.test.local" ANSIBLE_COLLECTIONS=${ANSIBLE_COLLECTIONS:-"containers.podman"} # Process command options while getopts ":hc:ei:Klms:v" option do case "$option" in h) help && exit 0 ;; c) scenario="${OPTARG}" ;; e) FORCE_ENV="Y" ;; i) IMAGE_TAG="${OPTARG}" ;; K) STOP_CONTAINER="N" ;; l) list_images && exit 0 || exit 1;; m) MEMORY="${OPTARG}" ;; s) if [ -d "${TOPDIR}/tests/${OPTARG}" ] then ENABLED_MODULES+=("${OPTARG}") else log error "Invalid suite: ${OPTARG}" fi ;; v) verbose=${verbose:--}${option} ;; *) die -u "Invalid option: ${OPTARG}" ;; esac done for test in "${@:${OPTIND}}" do # shellcheck disable=SC2207 if stat "$test" >/dev/null 2>&1 then ENABLED_TESTS+=($(basename "${test}" .yml)) else log error "Test not found: ${test}" fi done [ ${#ENABLED_MODULES[@]} -eq 0 ] && [ ${#ENABLED_TESTS[@]} -eq 0 ] && die -u "No test defined." # Prepare virtual environment VENV=$(in_python_virtualenv && echo Y || echo N) if [ "${FORCE_ENV}" == "Y" ] then [ "${VENV}" == "Y" ] && deactivate VENV="N" rm -rf "$test_env" log info "Virtual environment will be (re)created." fi if [ "$VENV" == "N" ] then log info "Preparing virtual environment: ${test_env}" if [ ! -d "${test_env}" ] then log info "Creating virtual environment: ${test_env}..." if ! python3 -m venv "${test_env}" then die "Cannot create virtual environment." fi fi if [ -f "${test_env}/bin/activate" ] then log info "Starting virtual environment: ${test_env}" # shellcheck disable=SC1091 . "${test_env}/bin/activate" || die "Cannot activate environment." STOP_VIRTUALENV="Y" else die "Cannot activate environment." fi log info "Installing required tools." log none "Upgrading: pip setuptools wheel" pip install --quiet --upgrade pip setuptools wheel log info "Installing dependencies from 'requirements-tests.txt'" pip install --quiet -r "${TOPDIR}/requirements-tests.txt" log info "Installing Ansible: ${ANSIBLE_VERSION}" pip install --quiet "${ANSIBLE_VERSION}" log debug "Ansible version: $(ansible --version | sed -n "1p")${RST}" if [ -n "${ANSIBLE_COLLECTIONS}" ] then log warn "Installed collections will not be removed after execution." log none "Installing: Ansible Collection ${ANSIBLE_COLLECTIONS}" # shellcheck disable=SC2086 quiet ansible-galaxy collection install ${ANSIBLE_COLLECTIONS} || die "Failed to install Ansible collections." fi else log info "Using current virtual environment." fi # Ansible configuration export ANSIBLE_ROLES_PATH="${TOPDIR}/roles" export ANSIBLE_LIBRARY="${TOPDIR}/plugins:${TOPDIR}/molecule" export ANSIBLE_MODULE_UTILS="${TOPDIR}/plugins/module_utils" # Prepare container container_id="" container_status=("-f" "status=created" "-f" "status=running") [ -n "${scenario}" ] && container_id="$(${engine} ps --all -q -f "name=${scenario}" "${container_status[@]}")" if [ -z "${container_id}" ] then # Retrieve image and start container. log info "Pulling FreeIPA image '${IMAGE_REPO}:${IMAGE_TAG}'..." img_id=$(${engine} pull -q "${IMAGE_REPO}:${IMAGE_TAG}") log info "Creating container..." CONFIG="--hostname ${hostname} --memory ${MEMORY}g --memory-swap -1 --dns none --add-host ipaserver.test.local:127.0.0.1" [ -n "${scenario}" ] && CONFIG="${CONFIG} --name ${scenario}" # shellcheck disable=SC2086 container_id=$(${engine} create ${CONFIG} "${img_id}" || die "Cannot create container") echo "CONTAINER: ${container_id}" fi scenario="${scenario:-$(${engine} ps -q --format "{{.Names}}" --filter "id=${container_id}" "${container_status[@]}")}" log debug "Using container: ${scenario}" # Start container make_inventory "${scenario}" log info "Starting container for ${scenario}..." quiet ${engine} start "${scenario}" # create /etc/resolve.conf run_inline_playbook <