#!/usr/bin/env bash # shellcheck disable=SC1090,SC2004 podmanRunWrapper () { ######################## ###### FUNCTIONS ####### ######################## _printHelpAndExit () { if [[ -z $_debug ]]; then cat <<-'EOF' USAGE Argument mode: podman-run-wrapper -m MODE -o OPTIONS -i IMAGE [-n CONTAINER_NAME] [--help] [--silent] [--debug] [COMMANDS [ARGS...]] Array mode (bash >= 4.3): podman-run-wrapper -a ARRAY EXAMPLE podman-run-wrapper -m ephemeral -o "-it -v $PWD:$PWD -w $PWD" -i "php:latest" -c "php ./script.php" ARRAY=( "-m" "ephemeral" "-o" "--rm -it -v $PWD:$PWD -w $PWD" "-i" "php:latest" "-c" "php ./script.php") podman-run-wrapper -a ARRAY COMMANDS COMMANDS to run in the container (e.g. the current active file, an external build script, a program residing in the container, etc.) Can be empty (run default container entrypoint) OPTIONS --mode, -m MODE MODE can be any of the following: 1. ephemeral 2. persistent 3. recreate-persistent 4. remove-persistent --options, -o OPTIONS OPTIONS to pass directly to `podman run` or `podman exec` depending on the mode or container state --image, -i IMAGE IMAGE used to create the container --array, -a ARRAY Read arguments array named ARRAY (bash >= 4.3) This is useful to reduce parsing errors and recommended for build-wrapper plugins --optionsarray OPTIONS_ARRAY Read podman options from array named OPTIONS_ARRAY (bash >= 4.3) This is useful to reduce parsing errors and recommended for build-wrapper plugins --commandsarray COMMANDS_ARRAY Read container commands from array named COMMANDS_ARRAY (bash >= 4.3) This is useful to reduce parsing errors and recommended for build-wrapper plugins --name, -n CONTAINER_NAME Use the CONTAINER_NAME base to name containers (should be unique to each project) Default: Container name will be set based on a concatenation of the image and commands --selinuxfix A temporary hack to grant SELinux write access on $PWD until a better fix is found --silent, -s Only print errors --debug, -d Print debugging --help, -h Print this help message and exit EOF fi # Exit using passed exit code [[ -z $1 ]] && exit 0 || exit "$1" } # Parse input _parseInput () { unset _mode _cmds_arr _opts_arr _options _prw_opts_arr _image _name _array _selinux_fix # Use getopt to print help if INPUT=$(getopt -o +m:o:i:x:n:a:sdh -l mode:,options:,image:,name:,array:,optionsarray:,commandsarray:,selinuxfix,silent,debug,help -- "$@"); then eval set -- "$INPUT" while true; do case "$1" in --mode|-m) shift _mode="$1" ;; --options|-o) shift _options="$1" ;; --image|-i) shift _image="$1" ;; --name|-n) shift _name="$1" ;; --array|-a) shift _array="$1" ;; --optionsarray) shift _opts_arr="$1" ;; --commandsarray) shift _cmds_arr="$1" ;; --selinuxfix) _selinux_fix="1" ;; --help|-h) _printHelpAndExit 0 ;; --silent|-s) _silent="1" ;; --debug|-d) _debug="1" echo "Debugging on!" ;; --) shift break ;; esac shift done else echo "Incorrect options provided!" _printHelpAndExit 1 fi # If array mode, load and parse input array if [[ -n $_array ]]; then checkBashVersion local _n_array declare -n _n_array="$_array" _parseInput "${_n_array[@]}" return fi # Parse podman options if [[ -n $_opts_arr ]]; then # namerefs are awesome declare -gn _prw_opts_arr="$_opts_arr" # If not array mode optionally load podman options from input string elif [[ -n $_options ]]; then declare -ga _prw_opts_arr for _option in $_options; do _prw_opts_arr+=("$_option") done else echo "Must provide --options or the name of an existing --optionsarray" _printHelpAndExit 1 fi # Parse commands if [[ -n $_cmds_arr ]]; then declare -gn _prw_cmds_arr="$_cmds_arr" else # Create COMMANDS array from remaining arguments # shift getopt parameters away shift $((OPTIND - 1)) # create array declare -ga _prw_cmds_arr _prw_cmds_arr=("$@") if [[ ${#_prw_cmds_arr[@]} -lt 1 ]]; then [[ -z $_silent ]] && echo "Warning: running container without any commands" fi fi [[ -n $_debug ]] && echo "_prw_opts_arr:" "${_prw_opts_arr[@]}" [[ -n $_debug ]] && echo "_prw_cmds_arr:" "${_prw_cmds_arr[@]}" } _addCName () { # autogenerate _name if missing [[ -z $_name ]] && _name="${_image}${_prw_cmds_arr[*]}" # sanitize container name _name="${_name//_/}" && _name="${_name// /}" && \ _name="${_name//[^a-zA-Z0-9_]/}" && _name="${_name,,}" # append flag if [[ "$_mode" == "ephemeral" ]]; then _cname="prw-e-$_name" else _cname="prw-p-$_name" fi _prw_opts_arr+=("--name" "$_cname") } _removeContainer () { if podman container exists "$_cname"; then [[ -z $_silent ]] && echo "Removing container: $_cname" [[ -n $_debug ]] && echo "podman rm -v -f $_cname" podman rm -v -f "$_cname" fi } _runContainer () { # Run _remove_container first to not run in existing container if podman container exists "${_cname}"; then [[ -z $_silent ]] && echo "Reusing container: $_cname" [[ -n $_debug ]] && echo podman exec "$_cname" sh -c "${_prw_cmds_arr[@]}" podman exec "$_cname" sh -c "${_prw_cmds_arr[@]}" exit $? else [[ -z $_silent ]] && echo "Running in container: $_cname" [[ -n $_debug ]] && echo "Command: podman run" "${_prw_opts_arr[@]}" "$_image" sh -c "${_prw_cmds_arr[@]}" podman run "${_prw_opts_arr[@]}" "$_image" "${_prw_cmds_arr[@]}" exit $? fi } ######################### ####### EXECUTE ######### ######################### _execute () { # Get input _parseInput "$@" # Set container name _addCName # SELinux fix [[ -n $_selinux_fix ]] && fixPermissions "$PWD" # Execute podman if [[ $_mode == "ephemeral" || $_mode == "recreate-persistent" ]]; then _removeContainer _runContainer elif [[ $_mode == "remove-persistent" ]]; then _removeContainer elif [[ $_mode == "persistent" ]]; then _runContainer else echo "Unknown mode!" _printHelpAndExit 1 fi } # Allow this function to be executed directly _execute "$@" } # Allow script to be called directly if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then # No imported functions #source-functions podmanRunWrapper "$@" fi