123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #!/usr/bin/env bash
- #
- # 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 (default) (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 (usually not necessary)
- #[[ "$_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
|