diff --git a/utils/run-tests.sh b/utils/run-tests.sh index e814aed0..140998be 100755 --- a/utils/run-tests.sh +++ b/utils/run-tests.sh @@ -1,38 +1,19 @@ #!/bin/bash -eu -trap interrupt_exception SIGINT +SCRIPTDIR="$(readlink -f "$(dirname "$0")")" +TOPDIR="$(readlink -f "${SCRIPTDIR}/..")" -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 -} +# shellcheck source=utils/shfun +. "${SCRIPTDIR}/shfun" +# shellcheck source=utils/shcontainer +. "${SCRIPTDIR}/shcontainer" +# shellcheck source=utils/shansible +. "${SCRIPTDIR}/shansible" 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'} verbose="" -FORCE_ENV="N" +engine="${engine:-"podman"}" 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" +read -r -a ENABLED_MODULES <<< "${IPA_ENABLED_MODULES:-""}" +read -r -a ENABLED_TESTS <<< "${IPA_ENABLED_MODULES:-""}" IMAGE_TAG="fedora-latest" -scenario="" +scenario="freeipa-tests" MEMORY=3 -hostname="ipaserver.test.local" -SEED="" -GROUP=0 +IPA_HOSTNAME="ipaserver.test.local" +SEED="$(date "+%Y%m%d")" +GROUP=1 SPLITS=0 -ANSIBLE_COLLECTIONS=${ANSIBLE_COLLECTIONS:-"containers.podman"} - +ANSIBLE_COLLECTIONS=${ANSIBLE_COLLECTIONS:-"${engine_collection}"} +SKIP_ANSIBLE="" +ansible_interpreter="/usr/bin/python3" EXTRA_OPTIONS="" +unset ANSIBLE_VERSION # Process command options -while getopts ":hA:c:ei:Klms:vx" option +while getopts ":ha:Ac:ei:Klm:p:s:S:vx" option do case "$option" in h) help && exit 0 ;; A) - [ ${#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 - ;; + [ -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) list_images && exit 0 || exit 1;; + 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 '-A' with '-s'" + [ ${SPLITS} -ne 0 ] && die -u "Can't use '-S' with '-s'" if [ -d "${TOPDIR}/tests/${OPTARG}" ] then ENABLED_MODULES+=("${OPTARG}") @@ -220,6 +101,16 @@ do 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}" ;; @@ -240,155 +131,28 @@ 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 -VENV=$(in_python_virtualenv && echo Y || echo N) +start_virtual_environment +log info "Installing dependencies from 'requirements-tests.txt'" +pip install --upgrade -r "${TOPDIR}/requirements-tests.txt" -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}" -else - log info "Using current virtual environment." -fi - -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 +[ -z "${SKIP_ANSIBLE}" ] && install_ansible "${ANSIBLE_VERSION:-"ansible-core"}" # Ansible configuration export ANSIBLE_ROLES_PATH="${TOPDIR}/roles" -export ANSIBLE_LIBRARY="${TOPDIR}/plugins:${TOPDIR}/molecule" +export ANSIBLE_LIBRARY="${TOPDIR}/plugins" 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 </dev/null 2>&1 || die "Failed to change directory." files_list=$(mktemp) @@ -25,7 +27,7 @@ git diff "${remote}/master" --name-only > "${files_list}" git remote remove ${remote} # Get all modules that should have tests executed -enabled_modules="$(python utils/get_test_modules.py $(cat "${files_list}"))" +enabled_modules="$(${python} utils/get_test_modules.py $(cat "${files_list}"))" [ -z "${enabled_modules}" ] && enabled_modules="None" # Get individual tests that should be executed diff --git a/utils/setup_test_container.sh b/utils/setup_test_container.sh new file mode 100755 index 00000000..0916c27f --- /dev/null +++ b/utils/setup_test_container.sh @@ -0,0 +1,119 @@ +#!/bin/bash -eu + +SCRIPTDIR="$(readlink -f "$(dirname "$0")")" + +# shellcheck source=utils/shcontainer +. "${SCRIPTDIR}/shcontainer" +# shellcheck source=utils/shansible +. "${SCRIPTDIR}/shansible" + +usage() { + local prog="${0##*/}" + cat </dev/null) + # In some configurations, it may not be possible to use another + # directory, so we store the playbook in the current one. + # [ -z "${playbook}" ] && playbook=$(mktemp "ansible-freeipa-test-playbook_ipa.XXXXXXXX") + + inventory="${inventory:-${test_env:-"."}/inventory}" + quiet mkdir -p "${playbookdir}" + cat - >"${playbook}" + # shellcheck disable=SC2086 + run_if_exists ansible-playbook ${ansible_options:-} -i "${inventory}" "${playbook}" + err=$? + rm -f "${playbook}" + return ${err} +} + +make_inventory() { + local scenario pod_engine ansible_interpreter + scenario=$1 + pod_engine="${engine:-${2:-podman}}" + ansible_interpreter="${3:-${ansible_interpreter:-"/usr/bin/python3"}}" + export inventory="${test_env:-"."}/inventory" + log info "Inventory file: ${inventory}" + cat << EOF > "${inventory}" +[ipaserver] +${scenario} ansible_connection=${pod_engine} ansible_python_interpreter=${ansible_interpreter} +[ipaserver:vars] +ipaserver_domain = test.local +ipaserver_realm = TEST.LOCAL +EOF +} + +query_container_installed_software() { + # check image software versions. + run_inline_playbook "${test_env:-"/tmp"}/playbooks" <