From f2143633c58ab5eaeb5c26213869086393e831b8 Mon Sep 17 00:00:00 2001 From: cryobry <38270216+cryobry@users.noreply.github.com> Date: Thu, 16 Apr 2020 14:50:26 -0400 Subject: [PATCH] Add toolboxRun plugin --- plugins/toolboxRun/toolboxRun | 247 ++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 plugins/toolboxRun/toolboxRun diff --git a/plugins/toolboxRun/toolboxRun b/plugins/toolboxRun/toolboxRun new file mode 100644 index 0000000..5aeb764 --- /dev/null +++ b/plugins/toolboxRun/toolboxRun @@ -0,0 +1,247 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1090 + +toolboxRun () { + + _printHelpAndExit () { + + cat <<-'EOF' +USAGE + toolboxRun -c NAME [-i NAME] [-r RELEASE] [--no-sh] [-h] [-s] [-d] [COMMANDS [ARGS...]] + +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 (default entrypoint) + +OPTIONS + + --container NAME, -c NAME + Assign a different NAME to the toolbox container. This is useful for creating multiple + toolbox containers from the same base image, or for entirely customized containers from + custom-built base images. + + If the toolbox container NAME already exists, the command passed to toolboxRun will be + executed in the existing toolbox. If toolbox container NAME does not exist, it will be + created and the COMMAND will then be run in it. + + --image NAME, -i NAME + Change the NAME of the base image used to create the toolbox container. This is useful for + creating containers from custom-built base images. + + --release RELEASE, -r RELEASE + Create a toolbox container for a different operating system RELEASE than the host. + + --ephemeral + The toolbox will be removed after the COMMAND is executed + + --recreate + If the toolbox NAME already exists, it will first be removed and recreated + + --no-sh, -n + Makes the first argument of COMMANDS executable and runs it directly + + --debug, -d + Display debugging output + + --array, -a ARRAY + Read arguments from an existing or new ARRAY (bash >= 4.3) + This is useful to reduce parsing errors and recommended for build-wrapper plugins + + --silent, -s + Don't output anything from this program (container output will still be passed to stdout + if -it option is used instead of -d, see `man podman run` for more information) + + --help, -h + Print this help message and exit (overrides --silent) + +EOF + + # Exit using passed exit code + [[ -z $1 ]] && exit 0 || exit "$1" + } + + + _runDebug () { + + [[ -n $_debug ]] && echo "Running: " "$@" + } + + + _parseInput () { + + _runDebug "${FUNCNAME[0]}" "$@" + + # Unset vars + unset _array + + # Parse input and set switches using getopt + if _input=$(getopt -o +c:i:r:a:ndsh -l container:,image:,release:,ephemeral,recreate,no-sh,debug,array:,silent,help -- "$@"); then + eval set -- "$_input" + while true; do + case "$1" in + --container|-c) + shift && _cname="$1" + ;; + --image|-i) + shift && _image=("-i" "$1") + ;; + --release|-r) + shift && _release=("-r" "$1") + ;; + --ephemeral) + _ephemeral="true" + ;; + --recreate) + _recreate="true" + ;; + --no-sh) + _no_sh="true" + ;; + --debug) + _debug="true" + echo "Debugging on!" + ;; + --array|-a) + shift && _array="$1" + break + ;; + --silent) + #_silent="true" + ;; + --help|-h) + _printHelpAndExit 0 + ;; + --) + shift + break + ;; + esac + shift + done + else + echo "Incorrect options provided" + _printHelpAndExit 1 + fi + + # If array mode, load input array, reparse input, and return + if [[ -n $_array ]]; then + checkBashVersion + local _n_array + declare -n _n_array="$_array" + _parseInput "${_n_array[@]}" + return + fi + + # Create _pre_commands_array from remaining arguments + # shift getopt parameters away + shift $((OPTIND - 1)) + # create array + declare -a _cmd_array + _program="$1" + _cmd_array=("$@") + + [[ -n $_debug ]] && echo "_cmd_array:" "${_cmd_array[@]}" + } + + + _shWrap () { + + _runDebug "${FUNCNAME[0]}" + + if [[ -z $_no_sh ]]; then + _cmd_array=("sh" "-c" "${_cmd_array[@]}") + fi + } + + + _toolboxExists () { + + _runDebug "${FUNCNAME[0]}" + + toolbox list -c | cut -d ' ' -f 3 | grep -w "$_cname" + } + + + _toolboxRemove () { + + _runDebug "${FUNCNAME[0]}" + + toolbox rm "$_cname" + } + + + _toolboxRun () { + + _runDebug "${FUNCNAME[0]}" + + toolbox run -c "$_cname" "${_cmd_array[@]}" + } + + + _toolboxCreate () { + + _runDebug "${FUNCNAME[0]}" + + toolbox create -c "$_cname" "${_image[@]}" "${_release[@]}" + } + + + __main () { + + # Get input + _parseInput "$@" + + # Make sure the first argument is executable + chmod +x "$_program" + + # Wrap command with `sh -c` by default + _shWrap + + # Check if container exists + if _toolboxExists; then + [[ -n $_recreate ]] && _toolboxRemove + else + _toolboxCreate + fi + + _toolboxRun + + [[ -n $_ephemeral ]] && _toolboxRemove + + } + + # Allow this function to be executed directly + __main "$@" +} + + +# Allow this file to be executed directly if not being sourced +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + + # The following functions are usually handled by build-wrapper + + _getBaseDir () { + # Get base directory name of where this script resides + # https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself#comment54598418_246128 + _basedir=$(dirname "$(readlink -f "$0")") + } + + + _sourceFunctions () { + # Get the location of this file + _getBaseDir + # Go up two directories + ff="${_basedir%/*/*}/functions" + # Source functions file + if [[ -f "$ff" ]]; then + source "$ff" + else + echo "Cannot find functions file: ${ff}" + fi + } + + _sourceFunctions + toolboxRun "$@" +fi