#!/bin/bash -eu SCRIPTDIR="$(readlink -f "$(dirname "$0")")" TOPDIR="$(readlink -f "${SCRIPTDIR}/..")" # shellcheck source=utils/shfun . "${SCRIPTDIR}/shfun" # shellcheck source=utils/shcontainer . "${SCRIPTDIR}/shcontainer" # shellcheck source=utils/shansible . "${SCRIPTDIR}/shansible" usage() { local prog="${0##*/}" cat <<EOF usage: ${prog} [-h] [-l] [-e] [-K] [-A|-a ANSIBLE] [-p INTERPRETER] [-c CONTAINER] [-s TESTS_SUITE] [-x] [-S SEED.GRP] [-i IMAGE] [-m MEMORY] [-v...] [TEST...] ${prog} runs playbook(s) TEST using an ansible-freeipa testing image. EOF } help() { usage echo -e "$(cat <<EOF positional arguments: TEST A list of playbook tests to be executed. Either a TEST or a MODULE must be provided. optional arguments: -h display this message and exit -a ANSIBLE Ansible version to use, e.g. "ansible-core==2.16.0" (default: latest ansible-core for the python version) -A Do not install Ansible, use host's provided one. -c CONTAINER use container CONTAINER to run tests -K keep container, even if tests succeed -l list available images -e force recreation of the virtual environment -i IMAGE select image to run the tests (default: fedora-latest) -m MEMORY container memory, in GiB (default: 3) -p INTERPRETER Python interpreter to use on target container -s TEST_SUITE run all playbooks for test suite, which is a directory under ${WHITE}tests${RST} -S SEED.GROUP Replicate Azure's test group and seed (seed is YYYYMMDD) -v Increase Ansible verbosity (can be used multiple times) -x Stop on first error. EOF )" } # Defaults verbose="" engine="${engine:-"podman"}" CONTINUE_ON_ERROR="" STOP_CONTAINER="Y" STOP_VIRTUALENV="N" declare -a ENABLED_MODULES declare -a ENABLED_TESTS read -r -a ENABLED_MODULES <<< "${IPA_ENABLED_MODULES:-""}" read -r -a ENABLED_TESTS <<< "${IPA_ENABLED_MODULES:-""}" IMAGE_TAG="fedora-latest" scenario="freeipa-tests" MEMORY=3 IPA_HOSTNAME="ipaserver.test.local" SEED="$(date "+%Y%m%d")" GROUP=1 SPLITS=0 ANSIBLE_COLLECTIONS=${ANSIBLE_COLLECTIONS:-"${engine_collection}"} SKIP_ANSIBLE="" ansible_interpreter="/usr/bin/python3" EXTRA_OPTIONS="" unset ANSIBLE_VERSION # Process command options while getopts ":ha:Ac:ei:Klm:p:s:S:vx" option do case "$option" in h) help && exit 0 ;; A) [ -n "${ANSIBLE_VERSION:-""}" ] && die "Can't use -A with '-a'" SKIP_ANSIBLE="YES" ;; a) [ "${SKIP_ANSIBLE:-"no"}" == "YES" ] && die "Can't use -A with '-a'" ANSIBLE_VERSION="${OPTARG}" ;; c) scenario="${OPTARG}" ;; e) FORCE_ENV="Y" ;; i) IMAGE_TAG="${OPTARG}" ;; K) STOP_CONTAINER="N" ;; l) "${SCRIPTDIR}"/setup_test_container.sh -l && exit 0 || exit 1 ;; m) MEMORY="${OPTARG}" ;; p) ansible_interpreter="${OPTARG}" ;; s) [ ${SPLITS} -ne 0 ] && die -u "Can't use '-S' with '-s'" if [ -d "${TOPDIR}/tests/${OPTARG}" ] then ENABLED_MODULES+=("${OPTARG}") else log error "Invalid suite: ${OPTARG}" fi ;; S) [ ${#ENABLED_MODULES[@]} -eq 0 ] || die -u "Can't use '-A' with '-s'" SEED="$(cut -d. -f1 <<< "${OPTARG}" | tr -d "-")" GROUP="$(cut -d. -f2 <<< "${OPTARG}")" if [ -z "${SEED}" ] || [ -z "${GROUP}" ] then die -u "Seed for '-A' must have the format YYYYMMDD.N" fi SPLITS=3 ;; v) verbose=${verbose:--}${option} ;; x) EXTRA_OPTIONS="$EXTRA_OPTIONS --exitfirst" ;; *) die -u "Invalid option: ${OPTARG}" ;; esac done for test in "${@:${OPTIND}}" do # shellcheck disable=SC2207 if stat "$test" >/dev/null 2>&1 then [ ${SPLITS} -ne 0 ] && die -u "Can't define tests and use '-A'" ENABLED_TESTS+=($(basename "${test}" .yml)) else log error "Test not found: ${test}" fi done [ ${SPLITS} -eq 0 ] && [ ${#ENABLED_MODULES[@]} -eq 0 ] && [ ${#ENABLED_TESTS[@]} -eq 0 ] && die -u "No test defined." export STOP_CONTAINER FORCE_ENV STOP_VIRTUALENV ansible_interpreter # Ensure $python is set [ -z "${python}" ] && python="python3" log info "Controller Python executable: ${python}" ${python} --version # Prepare virtual environment start_virtual_environment log info "Installing dependencies from 'requirements-tests.txt'" pip install --upgrade -r "${TOPDIR}/requirements-tests.txt" [ -z "${SKIP_ANSIBLE}" ] && install_ansible "${ANSIBLE_VERSION:-"ansible-core"}" # Ansible configuration export ANSIBLE_ROLES_PATH="${TOPDIR}/roles" export ANSIBLE_LIBRARY="${TOPDIR}/plugins" export ANSIBLE_MODULE_UTILS="${TOPDIR}/plugins/module_utils" # Start container "${SCRIPTDIR}/setup_test_container.sh" -e "${engine}" -m "${MEMORY}" -p "${ansible_interpreter}" -i "${IMAGE_TAG}" -n "${IPA_HOSTNAME}" -a "${scenario}" || die "Failed to setup test container" # run tests RESULT=0 export RUN_TESTS_IN_DOCKER=${engine} export IPA_SERVER_HOST="${scenario}" # Ensure proper ansible_python_interpreter is used by pytest. export IPA_PYTHON_PATH="${ansible_interpreter}" if [ ${SPLITS} -ne 0 ] then EXTRA_OPTIONS="${EXTRA_OPTIONS} --splits=${SPLITS} --group=${GROUP} --randomly-seed=${SEED}" log info "Running tests for group ${GROUP} of ${SPLITS} with seed ${SEED}" else # shellcheck disable=SC2086 joined="$(printf "%s," "${ENABLED_MODULES[@]}")" # shelcheck disable=SC2178 IPA_ENABLED_MODULES="${joined%,}" joined="$(printf "%s," "${ENABLED_TESTS[@]}")" # shelcheck disable=SC2178 IPA_ENABLED_TESTS="${joined%,}" export IPA_ENABLED_MODULES IPA_ENABLED_TESTS [ -n "${IPA_ENABLED_MODULES}" ] && log info "Test suites: ${IPA_ENABLED_MODULES}" [ -n "${IPA_ENABLED_TESTS}" ] && log info "Individual tests: ${IPA_ENABLED_TESTS}" fi IPA_VERBOSITY="${verbose}" [ -n "${IPA_VERBOSITY}" ] && export IPA_VERBOSITY # shellcheck disable=SC2086 if ! pytest -m "playbook" --verbose --color=yes --suppress-no-test-exit-code --junit-xml=TEST-results-group-${GROUP:-1}.xml ${EXTRA_OPTIONS} then RESULT=2 log error "Container not stopped for verification: ${scenario}" log info "Container: $(${engine} ps -f "name=${scenario}" --format "{{.Names}} - {{.ID}}")" fi [ -z "${CONTINUE_ON_ERROR}" ] && [ $RESULT -ne 0 ] && die "Stopping on test failure." # cleanup environment cleanup "${scenario}" "${engine}"