diff --git a/deployment/docker/server/Dockerfile b/deployment/docker/server/Dockerfile index 2e0e053e..65a53f5a 100644 --- a/deployment/docker/server/Dockerfile +++ b/deployment/docker/server/Dockerfile @@ -53,7 +53,7 @@ ENV ANSIBLE_VERSION 9.4.0 ARG ANSIBLE_VENV_PATH=/opt/semaphore/apps/ansible/${ANSIBLE_VERSION}/venv RUN apk add --no-cache -U \ - bash curl git gnupg mysql-client openssh-client-default python3 py3-pip rsync sshpass tar tini tzdata unzip wget zip && \ + bash curl git gnupg mysql-client openssh-client-default python3 py3-pip rsync sshpass tar tini tzdata unzip wget zip jq && \ rm -rf /var/cache/apk/* && \ adduser -D -u 1001 -G root semaphore && \ mkdir -p /tmp/semaphore && \ diff --git a/deployment/docker/server/server-wrapper b/deployment/docker/server/server-wrapper index adb04be0..7a05a075 100755 --- a/deployment/docker/server/server-wrapper +++ b/deployment/docker/server/server-wrapper @@ -2,6 +2,9 @@ set -e echoerr() { printf "%s\n" "$*" >&2; } +# +# Read environment variables from file if envrionment variable ${1}_FILE is set +# file_env() { local var="" local fileVar="" @@ -32,19 +35,15 @@ file_env() { } export SEMAPHORE_CONFIG_PATH="${SEMAPHORE_CONFIG_PATH:-/etc/semaphore}" -export SEMAPHORE_TMP_PATH="${SEMAPHORE_TMP_PATH:-/tmp/semaphore}" -export SEMAPHORE_DB_DIALECT="${SEMAPHORE_DB_DIALECT:-mysql}" -export SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}" export SEMAPHORE_DB_PATH="${SEMAPHORE_DB_PATH:-/var/lib/semaphore}" export SEMAPHORE_DB_PORT="${SEMAPHORE_DB_PORT:-}" -export SEMAPHORE_DB="${SEMAPHORE_DB:-semaphore}" -file_env 'SEMAPHORE_DB_USER' 'semaphore' -file_env 'SEMAPHORE_DB_PASS' 'semaphore' -file_env 'SEMAPHORE_ADMIN' 'admin' +file_env 'SEMAPHORE_DB_USER' +file_env 'SEMAPHORE_DB_PASS' +file_env 'SEMAPHORE_ADMIN' export SEMAPHORE_ADMIN_EMAIL="${SEMAPHORE_ADMIN_EMAIL:-admin@localhost}" export SEMAPHORE_ADMIN_NAME="${SEMAPHORE_ADMIN_NAME:-Semaphore Admin}" -file_env 'SEMAPHORE_ADMIN_PASSWORD' 'semaphorepassword' +file_env 'SEMAPHORE_ADMIN_PASSWORD' export SEMAPHORE_LDAP_ACTIVATED="${SEMAPHORE_LDAP_ACTIVATED:-no}" export SEMAPHORE_LDAP_HOST="${SEMAPHORE_LDAP_HOST:-}" export SEMAPHORE_LDAP_PORT="${SEMAPHORE_LDAP_PORT:-}" @@ -56,10 +55,6 @@ export SEMAPHORE_LDAP_MAPPING_FULLNAME="${SEMAPHORE_LDAP_MAPPING_FULLNAME:-cn}" export SEMAPHORE_LDAP_MAPPING_EMAIL="${SEMAPHORE_LDAP_MAPPING_EMAIL:-mail}" file_env 'SEMAPHORE_ACCESS_KEY_ENCRYPTION' -[ -d "${SEMAPHORE_TMP_PATH}" ] || mkdir -p "${SEMAPHORE_TMP_PATH}" || { - echo "Can't create Semaphore tmp path ${SEMAPHORE_TMP_PATH}." - exit 1 -} [ -d "${SEMAPHORE_CONFIG_PATH}" ] || mkdir -p "${SEMAPHORE_CONFIG_PATH}" || { echo "Can't create Semaphore config path ${SEMAPHORE_CONFIG_PATH}." @@ -71,7 +66,27 @@ file_env 'SEMAPHORE_ACCESS_KEY_ENCRYPTION' exit 1 } -# Check if $SEMAPHORE_DB_HOST contains port number. + +# +# Extract database host and port from config.json if they are not set +# +if [ -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then + if [ -z "${SEMAPHORE_DB_DIALECT}" ]; then + SEMAPHORE_DB_DIALECT=$(cat "${SEMAPHORE_CONFIG_PATH}/config.json" | jq ".dialect" -r) + fi + + if [ -z "${SEMAPHORE_DB_HOST}" ]; then + SEMAPHORE_DB_HOST=$(cat "${SEMAPHORE_CONFIG_PATH}/config.json" | jq ".${SEMAPHORE_DB_DIALECT}.host" -r) + fi +fi + +export SEMAPHORE_DB_DIALECT="${SEMAPHORE_DB_DIALECT:-mysql}" +export SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST:-0.0.0.0}" + + +# +# Remove port number from SEMAPHORE_DB_HOST and put it to SEMAPHORE_DB_PORT +# case "$SEMAPHORE_DB_HOST" in *:*) SEMAPHORE_DB_PORT=$(echo "$SEMAPHORE_DB_HOST" | cut -d ':' -f 2) @@ -80,6 +95,10 @@ case "$SEMAPHORE_DB_HOST" in *) esac + +# +# Set SEMAPHORE_DB_PORT if it is not set +# if [ -z "${SEMAPHORE_DB_PORT}" ]; then case ${SEMAPHORE_DB_DIALECT} in mysql) @@ -97,9 +116,12 @@ if [ -z "${SEMAPHORE_DB_PORT}" ]; then esac fi + +# # Ping database if it is not BoltDB +# if [ "${SEMAPHORE_DB_DIALECT}" != 'bolt' ]; then - echoerr "Attempting to connect to database ${SEMAPHORE_DB} on ${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT} with user ${SEMAPHORE_DB_USER} ..." + echoerr "Pinging database on ${SEMAPHORE_DB_HOST} port ${SEMAPHORE_DB_PORT}..." TIMEOUT=30 @@ -116,47 +138,64 @@ if [ "${SEMAPHORE_DB_DIALECT}" != 'bolt' ]; then done fi -if [ -n "${SEMAPHORE_DB_PORT}" ]; then - SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT}" -fi - -case ${SEMAPHORE_DB_DIALECT} in - mysql) - SEMAPHORE_DB_DIALECT_ID=1 - ;; - bolt) - SEMAPHORE_DB_DIALECT_ID=2 - SEMAPHORE_DB_HOST=${SEMAPHORE_DB_PATH}/database.boltdb - ;; - postgres) - SEMAPHORE_DB_DIALECT_ID=3 - ;; - *) - echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}" - exit 1 - ;; -esac +# +# Generate new config.json if it does not exist +# if [ ! -f "${SEMAPHORE_CONFIG_PATH}/config.json" ]; then - echoerr "Generating ${SEMAPHORE_TMP_PATH}/config.stdin ..." - cat << EOF > "${SEMAPHORE_TMP_PATH}/config.stdin" + echoerr "Generating setup file ${TMP_STDIN_CONFIG_FILE} ..." + + TMP_STDIN_CONFIG_FILE=$(mktemp) + + + SEMAPHORE_TMP_PATH=${SEMAPHORE_TMP_PATH:-/tmp/semaphore} + [ -d "${SEMAPHORE_TMP_PATH}" ] || mkdir -p "${SEMAPHORE_TMP_PATH}" || { + echo "Can't create Semaphore tmp path ${SEMAPHORE_TMP_PATH}." + exit 1 + } + + + if [ -n "${SEMAPHORE_DB_PORT}" ]; then + SEMAPHORE_DB_HOST="${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT}" + fi + + + case ${SEMAPHORE_DB_DIALECT} in + mysql) + SEMAPHORE_DB_DIALECT_ID=1 + ;; + bolt) + SEMAPHORE_DB_DIALECT_ID=2 + SEMAPHORE_DB_HOST=${SEMAPHORE_DB_PATH}/database.boltdb + ;; + postgres) + SEMAPHORE_DB_DIALECT_ID=3 + ;; + *) + echoerr "Unknown database dialect: ${SEMAPHORE_DB_DIALECT}" + exit 1 + ;; + esac + + + cat << EOF > "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_DB_DIALECT_ID} EOF if [ "${SEMAPHORE_DB_DIALECT}" = "bolt" ]; then - cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin" + cat << EOF >> "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_DB_HOST} EOF else - cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin" + cat << EOF >> "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_DB_HOST}:${SEMAPHORE_DB_PORT} ${SEMAPHORE_DB_USER} ${SEMAPHORE_DB_PASS} -${SEMAPHORE_DB} +${SEMAPHORE_DB:-semaphore} EOF fi - cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin" + cat << EOF >> "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_TMP_PATH} ${SEMAPHORE_WEB_ROOT:-} no @@ -168,7 +207,7 @@ ${SEMAPHORE_LDAP_ACTIVATED} EOF if [ "${SEMAPHORE_LDAP_ACTIVATED}" = "yes" ]; then - cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin" + cat << EOF >> "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_LDAP_HOST}:${SEMAPHORE_LDAP_PORT} ${SEMAPHORE_LDAP_NEEDTLS:-no} ${SEMAPHORE_LDAP_DN_BIND} @@ -182,7 +221,7 @@ ${SEMAPHORE_LDAP_MAPPING_EMAIL} EOF fi; - cat << EOF >> "${SEMAPHORE_TMP_PATH}/config.stdin" + cat << EOF >> "${TMP_STDIN_CONFIG_FILE}" ${SEMAPHORE_CONFIG_PATH} ${SEMAPHORE_ADMIN} ${SEMAPHORE_ADMIN_EMAIL} @@ -190,14 +229,21 @@ ${SEMAPHORE_ADMIN_NAME} ${SEMAPHORE_ADMIN_PASSWORD} EOF + echoerr "Executing semaphore setup" if test "$#" -ne 1; then - /usr/local/bin/semaphore setup - < "${SEMAPHORE_TMP_PATH}/config.stdin" + /usr/local/bin/semaphore setup - < "${TMP_STDIN_CONFIG_FILE}" else - "$1" setup - < "${SEMAPHORE_TMP_PATH}/config.stdin" + "$1" setup - < "${TMP_STDIN_CONFIG_FILE}" fi + + rm -f "${TMP_STDIN_CONFIG_FILE}" fi + +# +# Install additional python dependencies +# if test -f "${SEMAPHORE_CONFIG_PATH}/requirements.txt"; then echoerr "Installing additional python dependencies" pip3 install --upgrade \ @@ -206,6 +252,10 @@ else echoerr "No additional python dependencies to install" fi + +# +# Start Semaphore server +# echoerr "Starting semaphore server" if test "$#" -ne 1; then exec /usr/local/bin/semaphore server --config "${SEMAPHORE_CONFIG_PATH}/config.json" diff --git a/util/config.go b/util/config.go index b1fb6927..3426ee6f 100644 --- a/util/config.go +++ b/util/config.go @@ -36,10 +36,10 @@ const ( type DbConfig struct { Dialect string `json:"-"` - Hostname string `json:"host,omitempty" env:"SEMAPHORE_DB_HOST"` + Hostname string `json:"host,omitempty" env:"SEMAPHORE_DB_HOST" default:"0.0.0.0"` Username string `json:"user,omitempty" env:"SEMAPHORE_DB_USER"` Password string `json:"pass,omitempty" env:"SEMAPHORE_DB_PASS"` - DbName string `json:"name,omitempty" env:"SEMAPHORE_DB"` + DbName string `json:"name,omitempty" env:"SEMAPHORE_DB" default:"semaphore"` Options map[string]string `json:"options,omitempty" env:"SEMAPHORE_DB_OPTIONS"` }