podmanRunWrapper 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #!/usr/bin/env bash
  2. # shellcheck disable=SC1090,SC2004
  3. podmanRunWrapper () {
  4. ########################
  5. ###### FUNCTIONS #######
  6. ########################
  7. _printHelpAndExit () {
  8. if [[ -z $_debug ]]; then
  9. cat <<-'EOF'
  10. USAGE
  11. Argument mode:
  12. podman-run-wrapper -m MODE -o OPTIONS -i IMAGE [-n CONTAINER_NAME]
  13. [--help] [--silent] [--debug] [COMMANDS [ARGS...]]
  14. Array mode (bash >= 4.3):
  15. podman-run-wrapper -a ARRAY
  16. EXAMPLE
  17. podman-run-wrapper -m ephemeral -o "-it -v $PWD:$PWD -w $PWD" -i "php:latest" -c "php ./script.php"
  18. ARRAY=( "-m" "ephemeral" "-o" "--rm -it -v $PWD:$PWD -w $PWD" "-i" "php:latest" "-c" "php ./script.php")
  19. podman-run-wrapper -a ARRAY
  20. COMMANDS
  21. COMMANDS to run in the container (e.g. the current active file, an external build script, a
  22. program residing in the container, etc.)
  23. Can be empty (run default container entrypoint)
  24. OPTIONS
  25. --mode, -m MODE
  26. MODE can be any of the following:
  27. 1. ephemeral
  28. 2. persistent
  29. 3. recreate-persistent
  30. 4. remove-persistent
  31. --options, -o OPTIONS
  32. OPTIONS to pass directly to `podman run` or `podman exec` depending on the mode or
  33. container state
  34. --image, -i IMAGE
  35. IMAGE used to create the container
  36. --array, -a ARRAY
  37. Read arguments array named ARRAY (bash >= 4.3)
  38. This is useful to reduce parsing errors and recommended for build-wrapper plugins
  39. --optionsarray OPTIONS_ARRAY
  40. Read podman options from array named OPTIONS_ARRAY (bash >= 4.3)
  41. This is useful to reduce parsing errors and recommended for build-wrapper plugins
  42. --commandsarray COMMANDS_ARRAY
  43. Read container commands from array named COMMANDS_ARRAY (bash >= 4.3)
  44. This is useful to reduce parsing errors and recommended for build-wrapper plugins
  45. --name, -n CONTAINER_NAME
  46. Use the CONTAINER_NAME base to name containers (should be unique to each project)
  47. Default: Container name will be set based on a concatenation of the image and commands
  48. --selinuxfix
  49. A temporary hack to grant SELinux write access on $PWD until a better fix is found
  50. --silent, -s
  51. Only print errors
  52. --debug, -d
  53. Print debugging
  54. --help, -h
  55. Print this help message and exit
  56. EOF
  57. fi
  58. # Exit using passed exit code
  59. [[ -z $1 ]] && exit 0 || exit "$1"
  60. }
  61. # Parse input
  62. _parseInput () {
  63. unset _mode _cmds_arr _opts_arr _options _prw_opts_arr _image _name _array _selinux_fix
  64. # Use getopt to print help
  65. if INPUT=$(getopt -o +m:o:i:x:n:a:sdh -l mode:,options:,image:,name:,array:,optionsarray:,commandsarray:,selinuxfix,silent,debug,help -- "$@"); then
  66. eval set -- "$INPUT"
  67. while true; do
  68. case "$1" in
  69. --mode|-m)
  70. shift
  71. _mode="$1"
  72. ;;
  73. --options|-o)
  74. shift
  75. _options+=("$1")
  76. ;;
  77. --image|-i)
  78. shift
  79. _image="$1"
  80. ;;
  81. --name|-n)
  82. shift
  83. _name="$1"
  84. ;;
  85. --array|-a)
  86. shift
  87. _array="$1"
  88. ;;
  89. --optionsarray)
  90. shift
  91. _opts_arr="$1"
  92. ;;
  93. --commandsarray)
  94. shift
  95. _cmds_arr="$1"
  96. ;;
  97. --selinuxfix)
  98. _selinux_fix="1"
  99. ;;
  100. --help|-h)
  101. _printHelpAndExit 0
  102. ;;
  103. --silent|-s)
  104. _silent="1"
  105. ;;
  106. --debug|-d)
  107. _debug="1"
  108. echo "Debugging on!"
  109. ;;
  110. --)
  111. shift
  112. break
  113. ;;
  114. esac
  115. shift
  116. done
  117. else
  118. echo "Incorrect options provided!"
  119. _printHelpAndExit 1
  120. fi
  121. # If array mode, load and parse input array
  122. if [[ -n $_array ]]; then
  123. checkBashVersion
  124. local _n_array
  125. declare -n _n_array="$_array"
  126. _parseInput "${_n_array[@]}"
  127. return
  128. fi
  129. # Parse podman options from --optionsarray
  130. if [[ -n $_opts_arr ]]; then
  131. # namerefs are awesome
  132. declare -gn _prw_opts_arr="$_opts_arr"
  133. # If no array given, parse input from options
  134. elif [[ ${#_options[@]} -ge 1 ]]; then
  135. declare -ga _prw_opts_arr=("${_options[@]}")
  136. else
  137. echo "Must provide --options or the name of an existing --optionsarray"
  138. _printHelpAndExit 1
  139. fi
  140. # Parse commands
  141. if [[ -n $_cmds_arr ]]; then
  142. declare -gn _prw_cmds_arr="$_cmds_arr"
  143. else
  144. # Create COMMANDS array from remaining arguments
  145. # shift getopt parameters away
  146. shift $((OPTIND - 1))
  147. # create array
  148. declare -ga _prw_cmds_arr
  149. _prw_cmds_arr=("$@")
  150. if [[ ${#_prw_cmds_arr[@]} -lt 1 ]]; then
  151. [[ -z $_silent ]] && echo "Warning: running container without any commands"
  152. fi
  153. fi
  154. [[ -n $_debug ]] && echo "_prw_opts_arr:" "${_prw_opts_arr[@]}"
  155. [[ -n $_debug ]] && echo "_prw_cmds_arr:" "${_prw_cmds_arr[@]}"
  156. }
  157. _addCName () {
  158. # autogenerate _name if missing
  159. [[ -z $_name ]] && _name="${_image}${_prw_cmds_arr[*]}"
  160. # sanitize container name
  161. _name="${_name//_/}" && _name="${_name// /}" && \
  162. _name="${_name//[^a-zA-Z0-9_]/}" && _name="${_name,,}"
  163. # append flag
  164. if [[ "$_mode" == "ephemeral" ]]; then
  165. _cname="prw-e-$_name"
  166. else
  167. _cname="prw-p-$_name"
  168. fi
  169. _prw_opts_arr+=("--name" "$_cname")
  170. }
  171. _removeContainer () {
  172. if podman container exists "$_cname"; then
  173. [[ -z $_silent ]] && echo "Removing container: $_cname"
  174. [[ -n $_debug ]] && echo "podman rm -v -f $_cname"
  175. podman rm -v -f "$_cname"
  176. fi
  177. }
  178. _runContainer () {
  179. # Run _remove_container first to not run in existing container
  180. if podman container exists "${_cname}"; then
  181. [[ -z $_silent ]] && echo "Reusing container: $_cname"
  182. [[ -n $_debug ]] && echo podman exec "$_cname" sh -c "${_prw_cmds_arr[@]}"
  183. podman exec "$_cname" sh -c "${_prw_cmds_arr[@]}"
  184. exit $?
  185. else
  186. [[ -z $_silent ]] && echo "Running in container: $_cname"
  187. [[ -n $_debug ]] && echo "Command: podman run" "${_prw_opts_arr[@]}" "$_image" sh -c "${_prw_cmds_arr[@]}"
  188. podman run "${_prw_opts_arr[@]}" "$_image" "${_prw_cmds_arr[@]}"
  189. exit $?
  190. fi
  191. }
  192. #########################
  193. ####### EXECUTE #########
  194. #########################
  195. _execute () {
  196. # Get input
  197. _parseInput "$@"
  198. # Set container name
  199. _addCName
  200. # SELinux fix
  201. [[ -n $_selinux_fix ]] && fixPermissions "$PWD"
  202. # Execute podman
  203. if [[ $_mode == "ephemeral" || $_mode == "recreate-persistent" ]]; then
  204. _removeContainer
  205. _runContainer
  206. elif [[ $_mode == "remove-persistent" ]]; then
  207. _removeContainer
  208. elif [[ $_mode == "persistent" ]]; then
  209. _runContainer
  210. else
  211. echo "Unknown mode!"
  212. _printHelpAndExit 1
  213. fi
  214. }
  215. # Allow this function to be executed directly
  216. _execute "$@"
  217. }
  218. # Allow script to be called directly
  219. if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
  220. # No imported functions
  221. #source-functions
  222. podmanRunWrapper "$@"
  223. fi