commit 4bb2ba9cbe45f99b6dd197b6aa6cd79a936fb5d7 Author: bryan Date: Sun May 10 13:39:41 2020 -0400 Initial commit diff --git a/.atom-build.yml b/.atom-build.yml new file mode 100644 index 0000000..d20a211 --- /dev/null +++ b/.atom-build.yml @@ -0,0 +1,5 @@ +cmd: './podmanRun -o "--name=bash_{FILE_ACTIVE_NAME_BASE} -v={FILE_ACTIVE_PATH}:{FILE_ACTIVE_PATH}:z -w={FILE_ACTIVE_PATH} ubuntu:latest" test.sh "hello world!"' +name: 'Test podmanRun' +targets: + Test podmanRun w/ debug: + cmd: './podmanRun --debug -o "--name=bash_{FILE_ACTIVE_NAME_BASE} -v={FILE_ACTIVE_PATH}:{FILE_ACTIVE_PATH}:z -w={FILE_ACTIVE_PATH} ubuntu:latest" test.sh "hello world!"' diff --git a/README.md b/README.md new file mode 100644 index 0000000..f9dbbcd --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +```text +USAGE + podmanRun [-m MODE] [-o OPTIONS] [COMMANDS [ARGS]...] [--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 to concatenate + Will be split on whitespace + Final option should be the name of the container image + --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 --name=php_script -v=$PWD:/var/www/html:z php:7.3-apache" + + Run an ephemeral PHP webserver container using the current directory as webroot using IDE: + podmanRun -o "-p=8000:80 --name=php_{FILE_ACTIVE_NAME_BASE} \ + -v={FILE_ACTIVE_PATH}:/var/www/html:z php:7.3-apache" + + Run an ephemeral bash script: + podmanRun -o "--name=bash_script -v=$PWD:$PWD:z -w=$PWD debian:testing" ./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" \ + {FILE_ACTIVE} arg1 arg2 +``` diff --git a/podmanRun b/podmanRun new file mode 100755 index 0000000..9eb246d --- /dev/null +++ b/podmanRun @@ -0,0 +1,223 @@ +#!/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() { + + _printHelpAndExit() { + + if [[ -z $_debug ]]; then + cat <<-'EOF' +USAGE + podmanRun [-m MODE] [-o OPTIONS] [COMMANDS [ARGS]...] [--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 to concatenate + Will be split on whitespace + Final option should be the name of the container image + --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 --name=php_script -v=$PWD:/var/www/html:z php:7.3-apache" + + Run an ephemeral PHP webserver container using the current directory as webroot using IDE: + podmanRun -o "-p=8000:80 --name=php_{FILE_ACTIVE_NAME_BASE} \ + -v={FILE_ACTIVE_PATH}:/var/www/html:z php:7.3-apache" + + Run an ephemeral bash script: + podmanRun -o "--name=bash_script -v=$PWD:$PWD:z -w=$PWD debian:testing" ./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" \ + {FILE_ACTIVE} arg1 arg2 +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:dh -l mode:,options:,debug,help -- "$@"); then + eval set -- "$INPUT" + while true; do + case "$1" in + --mode|-m) + shift + _mode="$1" + ;; + --options|-o) + shift + # + _opts_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 + + # Load remaining arguments into the commands array + shift $((OPTIND - 1)) + _cmds_arr=("$@") + + # Set default mode + [[ -z $_mode ]] && _mode="recreate" + # Allow mode numbers + [[ "$_mode" == "1" ]] && _mode="recreate" + [[ "$_mode" == "2" ]] && _mode="persistent" + # Sanity check + [[ ! "$_mode" =~ ^(recreate|persistent)$ ]] && err "Bad --mode" && _printHelpAndExit 1 + + # Split options on whitespace + # This assumes that podman options are properly formatted + # https://unix.stackexchange.com/a/519917/382539 + readarray -td' ' _opts_arr < <(printf '%s' "${_opts_arr[*]}") + + 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 + + _sanitize() { + local i="$*"; i="${i// /}" && i="${i//[^a-zA-Z0-9_]/}" && i="${i,,}"; echo "$i" ; + } + + # If no --name is specified, then generate one using the opts and cmds arrays + if [[ -z $_name ]]; then + _cname="$(_sanitize "${_opts_arr[*]}${_cmds_arr[*]}")" + else + _cname="$(_sanitize "$_name")" + [[ "$_name" != "$_cname" ]] && err "You must provide a valid --name" && exit 1 + fi + + 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 + } + + + __main() { + + # Get input + _parseInput "$@" + + # Set _cname (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 diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..8629c24 --- /dev/null +++ b/test.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo "$@"