From b0e03a032df9d90283294e6d2b6319c1c1864dd8 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman <rjeffman@redhat.com> Date: Fri, 19 Jul 2024 17:45:47 -0300 Subject: [PATCH] Add shell utitily functions for scripts Add two shell libaries with utilities to write shell scripts. The 'utils/shlog' file provides macro names for ANSI escape sequences to control color output on terminals, a 'log' functions with pre-defined behavior for ERROR, WARN, DEBUG, INFO and SUCCESS level messages, and the 'quiet' function which executes a command and hides its output. The 'utils/shfun' file provides an interruptinon handler for SIGINT, and the following functions: - run_if_exists: run a command if it is available - cleanup: cleanup environment, possibly stopping a container and a Python virtual environment. - start_virtual_environmnt: initiates a Python virtual environment - in_python_virtualenv: test if the script is running inside a Python virtual environment - die: abort the script with an error message end exit code 1 New files: - utils/shlog - utils/shfun --- utils/shfun | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++ utils/shlog | 57 +++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 utils/shfun create mode 100644 utils/shlog diff --git a/utils/shfun b/utils/shfun new file mode 100644 index 00000000..e14b9bd6 --- /dev/null +++ b/utils/shfun @@ -0,0 +1,118 @@ +#!/bin/bash -eu +# This file is meant to be source'd by shell scripts + +SCRIPTDIR="$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")" + +. "${SCRIPTDIR}/shlog" + +[ -n "$(command -v python3)" ] && python="$(command -v python3)" || python="$(command -v python2)" +export python + +trap interrupt_exception SIGINT + +interrupt_exception() { + trap - SIGINT + log warn "User interrupted test execution." + # shellcheck disable=SC2119 + cleanup "${scenario:+${scenario}}" + exit 1 +} + +run_if_exists() { + cmd="${1}" + shift + [ -n "$(command -v "${cmd}")" ] && "${cmd}" "${@}" +} + +# shellcheck disable=SC2120 +cleanup() { + local container container_engine + container="${1:-${scenario:+${scenario}}}" + container_engine="${2:-${engine:-"podman"}}" + if [ "${STOP_CONTAINER:-"Y"}" == "Y" ] && [ -n "${container}" ] + then + run_if_exists stop_container "${container}" "${container_engine}" + [ -f "${inventory:-}" ] && rm "${inventory}" + else + if [ -n "${container}" ] + then + log info "Keeping container: $(${container_engine} ps --format "{{.Names}} - {{.ID}}" --filter "name=${container}")" + fi + fi + if [ "${STOP_VIRTUALENV:-"N"}" == "Y" ] + then + echo "Deactivating virtual environment" + run_if_exists deactivate + fi +} + +start_virtual_environment() { + # options -f + local FORCE_ENV VENV envdirectory + FORCE_ENV="N" + while getopts ":f" option + do + case "$option" in + f) FORCE_ENV="Y" ;; + *) die "prepare_virtual_environment: Invalid option: ${option}" ;; + esac + done + envdirectory="${test_env:-/tmp/ansible-freeipa-tests}" + + # Prepare virtual environment + VENV=$(in_python_virtualenv && echo Y || echo N) + + if [ "${FORCE_ENV}" == "Y" ] + then + run_if_exists 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: ${envdirectory}" + if [ ! -d "${envdirectory}" ] || [ ! -f "${envdirectory}/bin/activate" ] + then + log info "Creating virtual environment: ${envdirectory}..." + log warn "RUN: ${python} -m venv ${envdirectory}" + ${python} -m venv "${envdirectory}" || die "Cannot create virtual environment." + fi + log info "Starting virtual environment: ${envdirectory}" + [ -f "${envdirectory}/bin/activate" ] || die "Failed to create virtual environment." + # shellcheck disable=SC1091 + . "${envdirectory}/bin/activate" || die "Cannot activate virtual environment." + export STOP_VIRTUALENV="Y" + log info "Installing required tools." + log none "Upgrading: pip setuptools wheel" + pip install --quiet --upgrade pip setuptools wheel + else + log info "Using current virtual environment." + fi +} + +die() { + usg="N" + if [ "${1}" == "-u" ] + then + usg="Y" + shift 1 + fi + log error "${*}" + STOP_CONTAINER="N" + cleanup "${scenario:+${scenario}}" + [ "${usg}" == "Y" ] && run_if_exists usage + exit 1 +} + +in_python_virtualenv() { + local script + read -r -d "" script <<EOS +import sys; +base = getattr(sys, "base_prefix", ) or getattr(sys, "real_prefix", ) or sys.prefix +print('yes' if sys.prefix != base else 'no') +EOS + test "$(${python} -c "${script}")" == "yes" +} + diff --git a/utils/shlog b/utils/shlog new file mode 100644 index 00000000..d1b51e83 --- /dev/null +++ b/utils/shlog @@ -0,0 +1,57 @@ +#!/bin/bash -eu +# This file is meant to be source'd by shell scripts + +# shellcheck disable=SC2034 +RST="\033[0m" +# shellcheck disable=SC2034 +RED="\033[31m" +# shellcheck disable=SC2034 +BRIGHTRED="\033[31;1m" +# shellcheck disable=SC2034 +GREEN="\033[32m" +# shellcheck disable=SC2034 +BRIGHTGREEN="\033[32;1m" +# shellcheck disable=SC2034 +BROWN="\033[33m" +# shellcheck disable=SC2034 +YELLOW="\033[33;1m" +# shellcheck disable=SC2034 +NAVY="\033[34m" +# shellcheck disable=SC2034 +BLUE="\033[34;1m" +# shellcheck disable=SC2034 +MAGENTA="\033[35m" +# shellcheck disable=SC2034 +BRIGHTMAGENTA="\033[35;1m" +# shellcheck disable=SC2034 +DARKCYAN="\033[36m" +# shellcheck disable=SC2034 +CYAN="\033[36;1m" +# shellcheck disable=SC2034 +BLACK="\033[30m" +# shellcheck disable=SC2034 +DARKGRAY="\033[30;1m" +# shellcheck disable=SC2034 +GRAY="\033[37m" +# shellcheck disable=SC2034 +WHITE="\033[37;1m" + +log() { + local level="${1^^}" message="${*:2}" + case "${level}" in + ERROR) COLOR="${RED}" ;; + WARN) COLOR="${YELLOW}" ;; + DEBUG) COLOR="${BLUE}" ;; + INFO) COLOR="${WHITE}" ;; + SUCCESS) COLOR="${BRIGHTGREEN}" ;; + *) COLOR="${RST}" ;; + esac + echo -en "${COLOR}" + [ "${level}" == "ERROR" ] && echo -en "${level}:" + echo -e "${message}${RST}" +} + +quiet() { + "$@" >/dev/null 2>&1 +} + -- GitLab