Evilham
1af7e960fa
Amongst other things compressed files can be of a type other than .tar.gz (it remains the default) and we now properly support runit services, FreeBSD and Devuan.
288 lines
7.9 KiB
Bash
Executable file
288 lines
7.9 KiB
Bash
Executable file
#!/bin/sh -e
|
|
SERVICE_NAME="${__object_id}"
|
|
|
|
OS="$(cat "${__global}/explorer/os")"
|
|
|
|
case "${OS}" in
|
|
debian|devuan)
|
|
SUPER_USER_GROUP=root
|
|
ETC_DIR="/etc"
|
|
;;
|
|
*bsd)
|
|
SUPER_USER_GROUP=wheel
|
|
ETC_DIR="/usr/local/etc"
|
|
;;
|
|
*)
|
|
echo "Your OS '${OS}' is currently not supported." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
INIT="$(cat "${__global}/explorer/init")"
|
|
|
|
case "${INIT}" in
|
|
systemd)
|
|
service_definition_require="__systemd_unit/${SERVICE_NAME}.service"
|
|
service_command="service ${SERVICE_NAME} %s"
|
|
;;
|
|
runit|sysvinit)
|
|
# We will use runit to manage these services
|
|
__runit
|
|
export require="__runit"
|
|
service_definition_require="__runit_service/${SERVICE_NAME}"
|
|
service_command="sv %s ${SERVICE_NAME}"
|
|
;;
|
|
*)
|
|
echo "Init system ${INIT}' is currently not supported." >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
BIN_DIR="/usr/local/bin"
|
|
|
|
# Ensure the target bin dir exists
|
|
# Care, we never want to remove it :-D
|
|
__directory "${BIN_DIR}" \
|
|
--state "exists" \
|
|
--mode 0755
|
|
export require="${require} __directory${BIN_DIR}"
|
|
|
|
STATE="$(cat "${__object}/parameter/state")"
|
|
USER="$(cat "${__object}/parameter/user")"
|
|
GROUP="$(cat "${__object}/parameter/group" 2>/dev/null || true)"
|
|
if [ -z "${GROUP}" ]; then
|
|
if [ "${USER}" != "root" ]; then
|
|
GROUP="${USER}"
|
|
else
|
|
GROUP="${SUPER_USER_GROUP}"
|
|
fi
|
|
fi
|
|
|
|
|
|
BINARY="$(cat "${__object}/parameter/binary" 2>/dev/null || true)"
|
|
if [ -z "${BINARY}" ]; then
|
|
BINARY="${SERVICE_NAME}"
|
|
fi
|
|
EXTRA_BINARIES="$(cat "${__object}/parameter/extra-binary" 2>/dev/null || true)"
|
|
# This only makes sense for file archives
|
|
if [ -n "${EXTRA_BINARIES}" ] && [ -f "${__object}/parameter/unpack" ]; then
|
|
cat >&2 <<-EOF
|
|
You cannot specify extra binaries without the --unpack argument.
|
|
Make sure that the --url argument points to a file archive.
|
|
EOF
|
|
fi
|
|
|
|
SERVICE_EXEC="$(cat "${__object}/parameter/service-exec" 2>/dev/null || true)"
|
|
if [ -z "${SERVICE_EXEC}" ]; then
|
|
SERVICE_EXEC="${BIN_DIR}/${BINARY}"
|
|
fi
|
|
SERVICE_ARGS="$(cat "${__object}/parameter/service-args")"
|
|
SERVICE_EXEC="${SERVICE_EXEC} ${SERVICE_ARGS}"
|
|
|
|
SERVICE_DESCRIPTION="$(cat "${__object}/parameter/service-description" \
|
|
2>/dev/null || true)"
|
|
if [ -z "${SERVICE_DESCRIPTION}" ]; then
|
|
SERVICE_DESCRIPTION="cdist-managed '${SERVICE_NAME}' service"
|
|
fi
|
|
|
|
SERVICE_DEFINITION="$(cat "${__object}/parameter/service-definition" 2>/dev/null || true)"
|
|
|
|
WORKING_DIRECTORY_PATH="$(cat "${__object}/parameter/working-directory" 2>/dev/null || true)"
|
|
if [ -n "${WORKING_DIRECTORY_PATH}" ]; then
|
|
WORKING_DIRECTORY_SYSTEMD="WorkingDirectory=${WORKING_DIRECTORY_PATH}"
|
|
WORKING_DIRECTORY_RUNIT="cd '${WORKING_DIRECTORY_PATH}'"
|
|
fi
|
|
|
|
DOWNLOAD_URL="$(cat "${__object}/parameter/url")"
|
|
CHECKSUM="$(cat "${__object}/parameter/checksum")"
|
|
SHOULD_VERSION="$(cat "${__object}/parameter/version")"
|
|
|
|
# Create a user for the service if it is not root
|
|
USER_HOME_DIR="/root"
|
|
if [ "${USER}" != "root" ] && \
|
|
[ ! -f "${__object}/parameter/do-not-manage-user" ]; then
|
|
if [ "${STATE}" = "absent" ]; then
|
|
# When removing, ensure user is not being used
|
|
user_require="${service_definition_require}"
|
|
fi
|
|
USER_HOME_DIR="$(cat "${__object}/parameter/user-home-dir")"
|
|
if [ "${USER_HOME_DIR}" != "/nonexistent" ]; then
|
|
USER_CREATE_HOME="--create-home"
|
|
fi
|
|
require="${require} ${user_require}" __user "${USER}" \
|
|
--system \
|
|
--state "${STATE}" \
|
|
--home "${USER_HOME_DIR}" \
|
|
--comment "cdist-managed ${SERVICE_NAME} user" \
|
|
${USER_CREATE_HOME}
|
|
# Track dependencies
|
|
service_require="${service_require} __user/${USER}"
|
|
fi
|
|
|
|
# Place config file if necessary
|
|
CONFIG_FILE_DEST="${ETC_DIR}/${SERVICE_NAME}.conf"
|
|
CONFIG_FILE_SOURCE="$(cat "${__object}/parameter/config-file-source" 2>/dev/null || true)"
|
|
if [ "${CONFIG_FILE_SOURCE}" = "-" ]; then
|
|
CONFIG_FILE_SOURCE="${__object}/stdin"
|
|
fi
|
|
if [ -n "${CONFIG_FILE_SOURCE}" ] && [ "${STATE}" = "present" ]; then
|
|
require="${require} __user/${USER}" __file \
|
|
"${CONFIG_FILE_DEST}" \
|
|
--owner "${USER}" \
|
|
--group "${GROUP}" \
|
|
--mode "0440" \
|
|
--source "${CONFIG_FILE_SOURCE}"
|
|
service_require="${service_require} __file${CONFIG_FILE_DEST}"
|
|
fi
|
|
|
|
|
|
|
|
# This should setup the object in $service_definition_require
|
|
# See above.
|
|
case "${INIT}" in
|
|
systemd)
|
|
if [ -z "${SERVICE_DEFINITION}" ]; then
|
|
SERVICE_DEFINITION="$(cat <<EOF
|
|
[Unit]
|
|
Description=${SERVICE_DESCRIPTION}
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
|
|
User=${USER}
|
|
Group=${GROUP}
|
|
ExecStart=${SERVICE_EXEC}
|
|
Restart=always
|
|
${WORKING_DIRECTORY_SYSTEMD}
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
)"
|
|
fi
|
|
__systemd_unit "${SERVICE_NAME}.service" \
|
|
--source "-" \
|
|
--state "${STATE}" \
|
|
--enablement-state "enabled" <<EOF
|
|
${SERVICE_DEFINITION}
|
|
EOF
|
|
;;
|
|
runit|sysvinit)
|
|
if [ -z "${SERVICE_DEFINITION}" ]; then
|
|
SERVICE_DEFINITION="$(cat <<EOF
|
|
#!/bin/sh -e
|
|
${WORKING_DIRECTORY_RUNIT}
|
|
export HOME="\$(getent passwd '${USER}' | cut -d: -f6)"
|
|
export USER="${USER}"
|
|
export GROUP="${GROUP}"
|
|
exec chpst -u "${USER}:${GROUP}" ${SERVICE_EXEC}
|
|
EOF
|
|
)"
|
|
fi
|
|
__runit_service "${SERVICE_NAME}" \
|
|
--state "${STATE}" \
|
|
--log \
|
|
--source - <<EOF
|
|
${SERVICE_DEFINITION}
|
|
EOF
|
|
;;
|
|
esac
|
|
service_require="${service_require} ${service_definition_require}"
|
|
|
|
# Proceed after user and service description have been prepared
|
|
export require="${require} ${service_require}"
|
|
|
|
VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version"
|
|
IS_VERSION="$(cat "${__object}/explorer/explorer-version")"
|
|
|
|
|
|
if [ "${STATE}" = "absent" ]; then
|
|
# Perform cleanup of generated files
|
|
for bin_file in ${BINARY} ${EXTRA_BINARIES}; do
|
|
__file "${BIN_DIR}/${bin_file}" --state "absent"
|
|
done
|
|
__file "${VERSION_FILE}" --state "absent"
|
|
__file "${CONFIG_FILE_DEST}" --state "absent"
|
|
fi
|
|
|
|
if [ "${STATE}" != "present" ]; then
|
|
exit
|
|
fi
|
|
|
|
sv_cmd() {
|
|
# This is intentional
|
|
# shellcheck disable=SC2059
|
|
printf "${service_command}" "$1"
|
|
}
|
|
|
|
if [ "${SHOULD_VERSION}" != "${IS_VERSION}" ]; then
|
|
# We are installing the service and there has been a version change
|
|
# (or it is first-time install)
|
|
TMP_PATH="/tmp/${SERVICE_NAME}-${SHOULD_VERSION}"
|
|
|
|
# This is what will stop the service, replace the binaries and
|
|
# start the service again
|
|
perform_service_upgrade="$(cat <<EOF
|
|
$(sv_cmd stop) || true
|
|
if [ -f '${TMP_PATH}' ]; then
|
|
chown root:${SUPER_USER_GROUP} '${TMP_PATH}'
|
|
chmod 0555 '${TMP_PATH}'
|
|
cp -af '${TMP_PATH}' '${BIN_DIR}/${BINARY}'
|
|
else
|
|
for bin_file in ${BINARY} ${EXTRA_BINARIES}; do
|
|
bin_path="${TMP_PATH}/\${bin_file}"
|
|
chown root:${SUPER_USER_GROUP} "\${bin_path}"
|
|
chmod 0555 "\${bin_path}"
|
|
cp -af "\${bin_path}" "${BIN_DIR}/\${bin_file}"
|
|
done
|
|
fi
|
|
$(sv_cmd start) || true
|
|
EOF
|
|
)"
|
|
|
|
if [ -f "${__object}/parameter/unpack" ]; then
|
|
UNPACK_EXTENSION="$(cat "${__object}/parameter/unpack-extension")"
|
|
UNPACK_ARGS="$(cat "${__object}/parameter/unpack-args" \
|
|
2>/dev/null || true)"
|
|
# Download packed file
|
|
__download "${TMP_PATH}${UNPACK_EXTENSION}" \
|
|
--url "${DOWNLOAD_URL}" \
|
|
--download remote \
|
|
--sum "${CHECKSUM}"
|
|
|
|
# Unpack file and also perform service upgrade
|
|
# shellcheck disable=SC2086
|
|
require="__download${TMP_PATH}${UNPACK_EXTENSION}" \
|
|
__unpack "${TMP_PATH}${UNPACK_EXTENSION}" \
|
|
${UNPACK_ARGS} \
|
|
--destination "${TMP_PATH}"
|
|
version_bump_require="__unpack${TMP_PATH}${UNPACK_EXTENSION}"
|
|
else
|
|
# Create temp directory
|
|
__directory "${TMP_PATH}"
|
|
# Download binary directoy to the temp directory with the
|
|
# specified binary name
|
|
require="__directory${TMP_PATH}" __download \
|
|
"${TMP_PATH}/${BINARY}" \
|
|
--url "${DOWNLOAD_URL}" \
|
|
--download remote \
|
|
--sum "${CHECKSUM}"
|
|
version_bump_require="__download${TMP_PATH}/${BINARY}"
|
|
fi
|
|
|
|
# Perform update of cdist-managed version file
|
|
# And also perform service upgrade
|
|
# This is a bug if service_upgrade fails >,<
|
|
printf "%s" "${SHOULD_VERSION}" | \
|
|
require="${version_bump_require}" __file \
|
|
"${VERSION_FILE}" \
|
|
--onchange "${perform_service_upgrade}" \
|
|
--source "-"
|
|
else
|
|
# We only restart here if there was a config change
|
|
# but there was not a version change
|
|
require="${service_require}" __check_messages \
|
|
"single_binary_service_${__object_id}" \
|
|
--pattern "^__file${CONFIG_FILE_DEST}" \
|
|
--execute "$(sv_cmd restart)"
|
|
fi
|