From af21c8559ac725cbca8f0a9ad866fba109f9a9cc Mon Sep 17 00:00:00 2001 From: cryobry <38270216+cryobry@users.noreply.github.com> Date: Sun, 10 May 2020 10:19:00 -0400 Subject: [PATCH] Initial commit --- podmanRun | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100755 podmanRun diff --git a/podmanRun b/podmanRun new file mode 100755 index 0000000..1985d9f --- /dev/null +++ b/podmanRun @@ -0,0 +1,221 @@ +#!/usr/bin/env bash +# shellcheck disable=SC1090,SC2004 +# +# This script/function is a wrapper for podman run/exec that will automatically handle container +# creation, removal, and reuse +# +# MIT License +# Copyright (c) 2020 Bryan Roessler +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +podmanRun() { + + ######################## + ###### FUNCTIONS ####### + ######################## + + _printHelpAndExit() { + + if [[ -z $_debug ]]; then + cat <<-'EOF' +USAGE + podmanRun -m MODE -o OPTIONS -c COMMANDS [--help] [--debug] + +COMMANDS + COMMANDS to run in the container + +OPTIONS + --mode, -m MODE + 1. recreate (remove container if it already exists and create a new one) + 2. persistent (reuse existing container if it exists) + --options, -o OPTIONS + OPTIONS to pass to podman run/exec + Can be passed multiple times + Final option should be the name of the container image + --commands, -c COMMANDS + COMMANDS to execute in the container designated by OPTIONS + Can be passed multiple times + --debug, -d + Print debugging + --help, -h + Print this help message and exit + +EXAMPLES + Note: IDE examples are using Atom Build package placeholders. + + Run an ephemeral PHP webserver container using the current directory as webroot: + podmanRun -o "-p=8000:80" -o "--name=php_script" -o "-v=$PWD:/var/www/html:z" -o "php:7.3-apache" + Run an ephemeral PHP webserver container using the current directory as webroot using IDE: + podmanRun -o "-p=8000:80" -o "--name=php_{FILE_ACTIVE_NAME_BASE}" \ + -o "-v={FILE_ACTIVE_PATH}:/var/www/html:z" -o "php:7.3-apache" + Run an ephemeral bash script: + podmanRun -o "--name=bash_script" -o "-v=$PWD:$PWD:z" -o "-w=$PWD" + -o "debian:testing" -c "./script.sh" + Run an ephemeral bash script using IDE: + podmanRun -o "--name=bash_{FILE_ACTIVE_NAME_BASE}" \ + -o "-v={FILE_ACTIVE_PATH}:{FILE_ACTIVE_PATH}:z" -o "-w={FILE_ACTIVE_PATH}" \ + -o "debian:testing" -c "{FILE_ACTIVE}" +EOF + fi + + # Exit using passed exit code + [[ -z $1 ]] && exit 0 || exit "$1" + } + + + # Parse input + _parseInput() { + + declare -g _mode _debug + declare -ga _opts_arr _cmds_arr + local INPUT + + # Use getopt to print help + if INPUT=$(getopt -o +m:o:c:dh -l mode:,options:,commands:,debug,help -- "$@"); then + eval set -- "$INPUT" + while true; do + case "$1" in + --mode|-m) + shift + _mode="$1" + ;; + --options|-o) + shift + _opts_arr+=("$1") + ;; + --command|-c) + shift + _cmds_arr+=("$1") + ;; + --help|-h) + _printHelpAndExit 0 + ;; + --debug|-d) + _debug="1" + echo "Debugging on!" + ;; + --) + shift + break + ;; + esac + shift + done + else + err "Incorrect options provided!" + _printHelpAndExit 1 + fi + + # Mode + # Set default + [[ -z $_mode ]] && _mode="recreate" + # Allow mode numbers + [[ "$_mode" == "1" ]] && _mode="recreate" + [[ "$_mode" == "2" ]] && _mode="persistent" + # Sanity checks + [[ ! "$_mode" =~ ^(recreate|persistent)$ ]] && err "Bad --mode" && _printHelpAndExit 1 + + debug "_opts_arr:" "${_opts_arr[@]}" + debug "_cmds_arr:" "${_cmds_arr[@]}" + } + + + debug() { [[ -n $_debug ]] && echo "debug: " "$@"; } + err() { echo "error: $*" >&2; } + + + _setContainerName() { + + debug "${FUNCNAME[0]}" + + export _cname + local index _name + + # Get user-specified container name by parsing the options array for --name + for ((index=0; index <= ${#_opts_arr[@]}; index++)); do + if [[ "${_opts_arr[index]}" == "--name" ]]; then + _name="${_opts_arr[index+1]}" + elif [[ "${_opts_arr[index]}" =~ ^--name ]]; then + _name="${_opts_arr[index]}" + _name="${_name#--name=}" + fi + done + + # If no container name is specified, then generate one using the opts and cmds arrays + [[ -z $_name ]] && _name="${_opts_arr[*]}${_cmds_arr[*]}" + + # Sanitize container name + _name="${_name//_/}" && _name="${_name// /}" && \ + _name="${_name//[^a-zA-Z0-9_]/}" && _name="${_name,,}" + + # Our finished container name + _cname="$_name" + debug "_cname: $_cname" + } + + + _containerExists() { debug "${FUNCNAME[0]} $1"; podman container exists "$1"; } + + _removeContainer() { debug "${FUNCNAME[0]} $1"; _containerExists "$1" && podman rm -vf "$1"; } + + _runContainer() { + + debug "${FUNCNAME[0]} $1" + + if _containerExists "$1"; then + debug "podman exec $1 sh -c" "${_cmds_arr[@]}" + podman exec "$1" "${_cmds_arr[@]}" + else + debug "podman run" "${_opts_arr[@]}" "${_cmds_arr[@]}" + podman run "${_opts_arr[@]}" "${_cmds_arr[@]}" + fi + } + + +######################### +####### EXECUTE ######### +######################### + + __main() { + + # Get input + _parseInput "$@" + + # Set container name + _setContainerName + + # Remove container if necessary + [[ "$_mode" == "recreate" ]] && _containerExists "$_cname" && _removeContainer "$_cname" + + # Run or execute container + _runContainer "$_cname" + + # Cleanup more reliably + [[ "$_mode" == "recreate" ]] && _containerExists "$_cname" && _removeContainer "$_cname" + } + + # Allow this function to be executed directly + __main "$@" + exit $? +} + +# Allow script to be called directly +if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then + podmanRun "$@" +fi