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