Initial commit

This commit is contained in:
cryobry
2020-04-01 18:35:44 -04:00
commit 0829962d22
8 changed files with 769 additions and 0 deletions

20
.atom-build.yml Executable file
View File

@@ -0,0 +1,20 @@
cmd: 'echo "Pick a command (see .atom-build.yml)"'
name: ''
targets:
# Fedora
Run silently in fedora:
cmd: 'buildWrapper podmanRunEasy -m ephemeral -i fedora:latest -n bw-fedora-test -w {FILE_ACTIVE_PATH} --silent --mkexec {FILE_ACTIVE}'
Run debug in fedora:
cmd: 'buildWrapper podmanRunEasy -m ephemeral -i fedora:latest -n bw-fedora-test -w {FILE_ACTIVE_PATH} --debug --mkexec {FILE_ACTIVE}'
# PHP
Run silently with php:
cmd: 'buildWrapper podmanRunEasy -m ephemeral -i php:latest -n bw-php-test -w {FILE_ACTIVE_PATH} --silent --mkexec {FILE_ACTIVE}'
Run debug with php:
cmd: 'buildWrapper podmanRunEasy -m ephemeral -i php:latest -n bw-php-test -w {FILE_ACTIVE_PATH} --debug --mkexec {FILE_ACTIVE}'
# Jekyll
Run jekyll serve:
cmd: 'buildWrapper podmanRunWrapper -m ephemeral -o "-it -p 4000:4000 -v {FILE_ACTIVE_PATH}:/srv/jekyll -v {FILE_ACTIVE_PATH}/vendor/bundle:/usr/local/bundle" -i jekyll/jekyll -n "bw-jekyll-serve-test" "bundle exec jekyll serve --watch --drafts"'
# Bundle
Run bundle update:
cmd: 'buildWrapper podmanRunWrapper -m ephemeral -o "-it -v {FILE_ACTIVE_PATH}:/srv/jekyll -v {FILE_ACTIVE_PATH}/vendor/bundle:/usr/local/bundle" -i jekyll/jekyll -n "bw-jekyll-bundle-update-test" --selinuxfix "chmod a+w /srv/jekyll/Gemfile.lock && bundle update --all"'
# Please add more!

1
README.md Normal file
View File

@@ -0,0 +1 @@
Coming soon, this program is still in development

51
buildWrapper Executable file
View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
########################
###### FUNCTIONS #######
########################
source functions
_printHelpAndExit () {
cat <<-'EOF'
USAGE
buildWrapper plugin [command]
EXAMPLES
buildWrapper podmanRunEasy --mode 0 ./myscript.sh -d -b
buildWrapper podmanRunEasy --mode 1 bundle exec jekyll build --watch
buildWrapper podmanRunWrapper -m ephemeral -o "--rm -it -v $PWD:$PWD -w $PWD" -i "php:latest" -c "php ./script.php"
ARGUMENTS
plugin
Plugin to run (found in plugins/plugin_group/plugin)
command
Command to be passed to the plugin
EOF
# Exit using passed exit code
[[ -z $1 ]] && exit 0 || exit "$1"
}
########################
####### EXECUTE ########
########################
# check if bash version supports nameref
checkBashVersion
# source all plugins
sourcePlugins
# make sure that the chosen plugin exists
pluginExists "$1"
# Create a new named array with the arguments to be passed to the function
# We will access this array by name using a nameref (-n attribute) in our functions
# shellcheck disable=SC2034
declare -a _BW_ARGS=("${@:2}")
# Pass the name of the array to the function
"${1}" -a _BW_ARGS

107
functions Normal file
View File

@@ -0,0 +1,107 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2034
checkBashVersion () {
if ! declare -n _assoc; then
echo "You must use bash >= 4.3 (supports namerefs) to use build-wrapper"
echo "You can still call most functions directly using arguments instead of arrays."
_printHelpAndExit 1
fi
}
getOS () {
if [[ -e /etc/os-release ]]; then
source /etc/os-release
else
echo "No /etc/os-release found!"
echo "Your OS is unsupported"
_printHelpAndExit 1
fi
}
installPackage () {
# We will add packages to this array if their command is not available
local -a _pkg_array
# parse commands
for _pkg in "$@"; do
_pkg=$(packageOverrides "$_pkg")
# Insert the package name to test if already installed one element from the end
# and silence output
if ! "${_pkg_query_cmd[@]}" "$_pkg" > /dev/null 2>&1; then
_pkg_array+=("$_pkg")
else
echo "$_pkg is already installed!"
fi
done
if [[ ${#_pkg_array[@]} -ge 1 ]]; then
[[ -n $_debug ]] && echo "${_install_cmd[@]}" "${_pkg_array[@]}"
"${_install_cmd[@]}" "${_pkg_array[@]}"
fi
}
packageOverrides () {
if [[ "$ID" == "ubuntu" || "$ID" == "debian" ]]; then
if [[ "$1" == "rpm-build" ]]; then
echo "rpm"
elif [[ "$1" == "createrepo_c" ]]; then
echo "createrepo"
else
echo "$1"
fi
else
echo "$1"
fi
}
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")")
}
sourcePlugin () {
getBaseDir
_plugin="$_basedir/plugins/$1"
if [[ -f "$_plugin" ]]; then
source "$_plugin"
else
echo "Plugin $_plugin does not exist!"
fi
}
sourcePlugins () {
getBaseDir
for _file in "$_basedir"/plugins/*/*; do
[[ -f "$_file" ]] && source "$_file"
done
}
pluginExists () {
if [[ $# -lt 1 || ! $(type -t "$1") == "function" ]]; then
echo "Plugin not found"
_printHelpAndExit 1
fi
}
fixPermissions () {
# Allow container access to the workdir (SELinux)
chcon -t container_file_t -R "$1"
}

304
plugins/podman/podmanRunEasy Executable file
View File

@@ -0,0 +1,304 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2004
podmanRunEasy () {
sourcePlugin "podman/podmanRunWrapper"
########################
####### DEFAULTS #######
########################
# Can be overridden using environment variables
[[ -z $_image ]] && _image="fedora:latest"
[[ -z $_mode ]] && _mode="ephemeral"
[[ -z $_workdir ]] && _workdir="$PWD"
_smartDefaults () {
echo ""
### UNDER CONSTRUCTION ###
# I would like to handle some options automatically to reduce the number of configuration
# options necessary to run podman and also make it easy for users to define defaults based
# on file extension, command, shebang, etc
# check the basename for defaults
#[[ -z $COMMAND_DEF ]] \
# && COMMAND_BASENAME="${COMMAND_ARR[0]##*/}" \
# && _set_defaults "${COMMAND_BASENAME}"
# check the extension for defaults
#[[ -z $COMMAND_DEF ]] \
# && COMMAND_EXT="${COMMAND_BASENAME##*.}" \
# && _set_defaults "${COMMAND_EXT}"
# add defaults to the string
#if [[ -n $COMMAND_DEF ]]; then
# [[ -z $_silent ]] && echo "Loaded command defaults, executing with \"${COMMAND_DEF}\""
# COMMAND_STR="${COMMAND_DEF} ${COMMAND_STR}"
#else
# [[ -z $_silent ]] && echo "Could not find command defaults from name or extension"
# [[ -z $_silent ]] && echo "Executing script directly"
#fi
}
########################
###### FUNCTIONS #######
########################
_printHelpAndExit () {
cat <<-'EOF'
USAGE
podman-run-easy [-m _mode] [-w PATH] [-d PATH] [-i _image] [--systemd] [--mkexec] [--help]
[--silent] [--debug] [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
--mode, -m MODE
MODE can be any of the following:
1. ephemeral
2. persistent
3. recreate-persistent
4. remove-persistent
--workdir, -w PATH
The directory in the container where we execute the COMMANDS
Default: The present working directory
--maskdir, -d PATH
Hide this directory from the host OS, store contents in the container only
--image, -i IMAGE
IMAGE used to create the container
Default: fedora:latest
--mkexec, -x
Makes the first argument of COMMANDS executable
--name, -n CONTAINER_NAME
This will form the base of the container name and should be unique to each project
Default: Container name will be set based on a concatenation of the image and commands
--systemd
Force container to init with systemd (--systemd=always)
Default: --systemd=true (systemd will only start if CMD is systemd, /usr/sbin/init or
/sbin/init)
--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"
}
_parseInput () {
[[ -n $_debug ]] && echo "$@"
# Unset array variable when reparsing array
unset _array
# Parse input and set switches using getopt
if _input=$(getopt -o +m:w:d:i:a:n:xsh -l mode:,workdir:,maskdir:,image:,array:,name:,mkexec,systemd,silent,debug,help -- "$@"); then
eval set -- "$_input"
while true; do
case "$1" in
--mode|-m)
shift
_mode="$1"
;;
--workdir|-w)
shift
_workdir="$1"
;;
--maskdir|-d)
shift
_maskdir="$1"
;;
--image|-i)
shift
_image="$1"
;;
--name|-n)
shift
_name="$1"
;;
--array|-a)
shift
_array="$1"
break
;;
--mkexec|-x)
_mkexec="true"
;;
--systemd|-s)
_systemd="true"
;;
--silent)
_silent="true"
;;
--debug)
_debug="true"
echo "Debugging on!"
;;
--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 -ga _pre_commands_array
_pre_commands_array=("$@")
[[ -n $_debug ]] && echo "_pre_commands_array:" "${_pre_commands_array[@]}"
# Sanitize mode numbers
[[ "$_mode" == "1" ]] && _mode="ephemeral"
[[ "$_mode" == "2" ]] && _mode="persistent"
[[ "$_mode" == "3" ]] && _mode="recreate-persistent"
[[ "$_mode" == "4" ]] && _mode="remove-persistent"
# build the podman options array
declare -ga _pre_options_array
_pre_options_array+=("-it")
#[[ "$_mode" == "ephemeral" ]] && _pre_options_array+=("--rm")
_pre_options_array+=("-v" "${_workdir}:${_workdir}")
_pre_options_array+=("-w" "${_workdir}")
[[ -n $_maskdir ]] && _pre_options_array+=("-v" "${_maskdir}")
[[ -n $_systemd ]] && _pre_options_array+=("--systemd=always")
[[ -n $_debug ]] && echo "_pre_options_array:" "${_pre_options_array[@]}"
}
_makeExec () {
# make executable
if [[ -n $_mkexec ]]; then
# assume script/program is the first argument in the command and break on whitespace
_program="${_pre_commands_array[0]}"
# make executable on the host
chmod +x "${_program}"
# make executable in the container
#COMMAND="chmod 755 ${_program} && $COMMAND"
fi
}
_sanityChecks () {
# If missing, create workdir
if ! [[ -d "$_workdir" ]]; then
[[ -z $_silent ]] && echo "--workdir does not exist!"
[[ -z $_silent ]] && echo "Creating ${_workdir} now..."
mkdir -p "${_workdir}"
fi
# Grant container SELinux access to the _workdir
fixPermissions "${_workdir}"
}
_runPodmanRunWrapper() {
_makeExec
local _prw_array
_prw_array=("-m" "${_mode}" "--optionsarray" "_pre_options_array" "-i" "${_image}" "-n" "${_name}" "--commandsarray" "_pre_commands_array")
[[ -n $_debug ]] && _prw_array+=("--debug")
[[ -n $_silent ]] && _prw_array+=("--silent")
if [[ -n $_debug ]]; then
echo -n "PRE->PRW argument array: "
printf '"%s" ' "${_prw_array[@]}"
echo ""
fi
podmanRunWrapper -a _prw_array
}
#########################
####### EXECUTE #########
#########################
_execute () {
# Get input
_parseInput "$@"
# Call podman-run-wrapper
_runPodmanRunWrapper
}
# Allow this function to be executed directly
_execute "$@"
}
# 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
podmanRunEasy "$@"
fi

277
plugins/podman/podmanRunWrapper Executable file
View File

@@ -0,0 +1,277 @@
#!/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

6
tests/scripts/script.php Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/bin/env php
<?php
print("Hello World");
?>

3
tests/scripts/script.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env bash
echo "Hello World"