Skip to content

Commit

Permalink
Add shell utitily functions for scripts
Browse files Browse the repository at this point in the history
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
  • Loading branch information
rjeffman committed Jul 20, 2024
1 parent 045199e commit d9a9e46
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
118 changes: 118 additions & 0 deletions utils/shfun
Original file line number Diff line number Diff line change
@@ -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"
}

57 changes: 57 additions & 0 deletions utils/shlog
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit d9a9e46

Please sign in to comment.