From 3b8059f2daca80d967635e04d8d81e9abb755a4d Mon Sep 17 00:00:00 2001 From: Georg Lauterbach <44545919+georglauterbach@users.noreply.github.com> Date: Tue, 21 Sep 2021 08:51:59 +0200 Subject: [PATCH] make setup.sh completely non-interactive (#2201) Co-authored-by: Brennan Kinney <5098581+polarathene@users.noreply.github.com> --- setup.sh | 206 ++++++++++++++++++++-------------------- test/linting/.ecrc.json | 1 - 2 files changed, 101 insertions(+), 106 deletions(-) diff --git a/setup.sh b/setup.sh index 6d8708d6..6184f6f8 100755 --- a/setup.sh +++ b/setup.sh @@ -4,7 +4,20 @@ # executed manually / via Make # task wrapper for various setup scripts +DIR="$(pwd)" +CONFIG_PATH= +CONTAINER_NAME= +CRI= +DEFAULT_CONFIG_PATH= +DESIRED_CONFIG_PATH= +DMS_CONFIG='/tmp/docker-mailserver' +IMAGE_NAME= +INFO= +PODMAN_ROOTLESS=false SCRIPT='setup.sh' +USE_SELINUX= +USE_TTY= +VOLUME= set -euEo pipefail trap '__err "${FUNCNAME[0]:-?}" "${BASH_COMMAND:-?}" "${LINENO:-?}" "${?:-?}"' ERR @@ -13,12 +26,13 @@ function __err { [[ ${4} -gt 1 ]] && exit 1 - local ERR_MSG='--- \e[31m\e[1mUNCHECKED ERROR\e[0m' + local ERR_MSG='\n--- \e[31m\e[1mUNCHECKED ERROR\e[0m' ERR_MSG+="\n - script = ${SCRIPT:-${0}}" - ERR_MSG+="\n - function = ${1} / ${2}" + ERR_MSG+="\n - function = ${1}" + ERR_MSG+="\n - command = ${2}" ERR_MSG+="\n - line = ${3}" ERR_MSG+="\n - exit code = ${4}" - ERR_MSG+='\n' + ERR_MSG+='\n\nThis should not have happened. Please file a bug report.\n' echo -e "${ERR_MSG}" } @@ -41,7 +55,8 @@ function _show_local_usage Provides the name of the running container. -p PATH - Provides the config folder path to the temporary container (does not work if docker-mailserver container already exists). + Provides the local path of the config folder to the temporary container instance. + Does not work if an existing docker-mailserver container is already running. ${LBLUE}SELinux${RESET} -z @@ -52,7 +67,16 @@ function _show_local_usage Allows container access to the bind mount content that is private and unshared with other containers on a SELinux-enabled host. -${ORANGE}EXIT STATUS${RESET} + ${LBLUE}Podman${RESET} + -R + Accept running in Podman rootless mode. Ignored when using Docker / Docker Compose. + +" + + [[ ${1:-} == 'no-exit' ]] && return 0 + + # shellcheck disable=SC2059 + printf "${ORANGE}EXIT STATUS${RESET} Exit status is 0 if the command was successful. If there was an unexpected error, an error message is shown describing the error. In case of an error, the script will exit with exit status 1. @@ -62,13 +86,14 @@ ${ORANGE}EXIT STATUS${RESET} function _get_absolute_script_directory { - if [[ "$(uname)" == "Darwin" ]] + if [[ "$(uname)" == 'Darwin' ]] then readlink() { # requires coreutils greadlink "${@:+$@}" } fi + if dirname "$(readlink -f "${0}")" &>/dev/null then DIR="$(dirname "$(readlink -f "${0}")")" @@ -77,100 +102,107 @@ function _get_absolute_script_directory DIR="$(realpath -e -L "${0}")" DIR="${DIR%/setup.sh}" fi + + DEFAULT_CONFIG_PATH="${DIR}/config" } -DIR="$(pwd)" -_get_absolute_script_directory - -CRI= -CONFIG_PATH= -CONTAINER_NAME= -DEFAULT_CONFIG_PATH="${DIR}/config" -IMAGE_NAME= -INFO= -USE_TTY= -USE_SELINUX= -VOLUME= -WISHED_CONFIG_PATH= - -function _check_root +function _handle_config_path { - if [[ ${EUID} -ne 0 ]] + if [[ -z ${DESIRED_CONFIG_PATH} ]] then - echo "Curently, DMS doesn't support podman's rootless mode. -Please run this script as root user." + # no desired config path + if [[ -n ${CONTAINER_NAME} ]] + then + VOLUME=$(${CRI} inspect "${CONTAINER_NAME}" \ + --format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \ + grep "${DMS_CONFIG}$" 2>/dev/null || :) + fi - exit 1 + if [[ -n ${VOLUME} ]] + then + CONFIG_PATH=$(echo "${VOLUME}" | awk '{print $1}') + fi + + if [[ -z ${CONFIG_PATH} ]] + then + CONFIG_PATH=${DEFAULT_CONFIG_PATH} + fi + else + CONFIG_PATH=${DESIRED_CONFIG_PATH} fi } -function _update_config_path -{ - if [[ -n ${CONTAINER_NAME} ]] - then - VOLUME=$(${CRI} inspect "${CONTAINER_NAME}" \ - --format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \ - grep "/tmp/docker-mailserver$" 2>/dev/null || :) - fi - - if [[ -n ${VOLUME} ]] - then - CONFIG_PATH=$(echo "${VOLUME}" | awk '{print $1}') - fi -} - -function _docker_image_exists -{ - ${CRI} history -q "${1}" &>/dev/null - return ${?} -} - -function _docker_image +function _run_in_new_container { # start temporary container with specified image - if ! _docker_image_exists "${IMAGE_NAME}" + if ! ${CRI} history -q "${IMAGE_NAME}" &>/dev/null then echo "Image '${IMAGE_NAME}' not found. Pulling ..." ${CRI} pull "${IMAGE_NAME}" fi ${CRI} run --rm "${USE_TTY}" \ - -v "${CONFIG_PATH}:/tmp/docker-mailserver${USE_SELINUX}" \ + -v "${CONFIG_PATH}:${DMS_CONFIG}${USE_SELINUX}" \ "${IMAGE_NAME}" "${@:+$@}" } -function _docker_container -{ - if [[ -n ${CONTAINER_NAME} ]] - then - ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@:+$@}" - else - # if no container is running, run a temporary one: - # https://github.com/docker-mailserver/docker-mailserver/pull/1874#issuecomment-809781531 - _docker_image "${@:+$@}" - fi -} - function _main { + _get_absolute_script_directory + + local OPTIND + while getopts ":c:i:p:zZR" OPT + do + case ${OPT} in + ( i ) IMAGE_NAME="${OPTARG}" ;; + ( z | Z ) USE_SELINUX=":${OPT}" ;; + ( c ) CONTAINER_NAME="${OPTARG}" ;; + ( R ) PODMAN_ROOTLESS=true ;; + ( p ) + case "${OPTARG}" in + ( /* ) DESIRED_CONFIG_PATH="${OPTARG}" ;; + ( * ) DESIRED_CONFIG_PATH="${DIR}/${OPTARG}" ;; + esac + + if [[ ! -d ${DESIRED_CONFIG_PATH} ]] + then + echo "Specified directory '${DESIRED_CONFIG_PATH}' doesn't exist" >&2 + exit 1 + fi + ;; + + ( * ) + echo "Invalid option: '-${OPTARG}'" >&2 + echo -e "Use './setup.sh help' to get a complete overview.\n" >&2 + _show_local_usage 'no-exit' + exit 1 + ;; + + esac + done + shift $(( OPTIND - 1 )) + if command -v docker &>/dev/null then CRI=docker elif command -v podman &>/dev/null then CRI=podman - _check_root + if ! ${PODMAN_ROOTLESS} && [[ ${EUID} -ne 0 ]] + then + read -r -p "You are running Podman in rootless mode. Continue? [Y/n] " + [[ -n ${REPLY} ]] && [[ ${REPLY} =~ (n|N) ]] && exit 0 + fi else - echo "No supported Container Runtime Interface detected." + echo 'No supported Container Runtime Interface detected.' exit 1 fi INFO=$(${CRI} ps --no-trunc --format "{{.Image}};{{.Names}}" --filter \ label=org.opencontainers.image.title="docker-mailserver" | tail -1) - IMAGE_NAME=${INFO%;*} CONTAINER_NAME=${INFO#*;} - + [[ -z ${IMAGE_NAME} ]] && IMAGE_NAME=${INFO%;*} if [[ -z ${IMAGE_NAME} ]] then IMAGE_NAME=${NAME:-docker.io/mailserver/docker-mailserver:latest} @@ -186,51 +218,15 @@ function _main USE_TTY="-t" fi - local OPTIND - while getopts ":c:i:p:zZ" OPT - do - case ${OPT} in - ( i ) IMAGE_NAME="${OPTARG}" ;; - ( z | Z ) USE_SELINUX=":${OPTARG}" ;; - ( c ) CONTAINER_NAME="${OPTARG}" ;; + _handle_config_path - ( p ) - case "${OPTARG}" in - ( /* ) WISHED_CONFIG_PATH="${OPTARG}" ;; - ( * ) WISHED_CONFIG_PATH="${DIR}/${OPTARG}" ;; - esac - - if [[ ! -d ${WISHED_CONFIG_PATH} ]] - then - echo "Specified directory '${WISHED_CONFIG_PATH}' doesn't exist" >&2 - exit 1 - fi - ;; - - ( * ) - echo "Invalid option: -${OPT}" >&2 - exit 1 - ;; - - esac - done - - shift $(( OPTIND - 1 )) - - if [[ -z ${WISHED_CONFIG_PATH} ]] + if [[ -n ${CONTAINER_NAME} ]] then - # no wished config path - _update_config_path - - if [[ -z ${CONFIG_PATH} ]] - then - CONFIG_PATH=${DEFAULT_CONFIG_PATH} - fi + ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" setup "${@:+$@}" else - CONFIG_PATH=${WISHED_CONFIG_PATH} + _run_in_new_container setup "${@:+$@}" fi - _docker_container setup "${@:+$@}" [[ ${1} == 'help' ]] && _show_local_usage return 0 diff --git a/test/linting/.ecrc.json b/test/linting/.ecrc.json index ac50331a..d9abd2f6 100644 --- a/test/linting/.ecrc.json +++ b/test/linting/.ecrc.json @@ -7,7 +7,6 @@ "Exclude": [ "^test/", "\\.git.*", - "\\.bats$", "\\.cf$", "\\.conf$", "\\.init$",