@ -1,22 +1,43 @@
#!/bin/sh -e
SERVICE_NAME="${__object_id}"
OS="$(cat "${__global}/explorer/os")"
case "${OS}" in
debian)
SUPER_USER_GROUP=root
;;
*bsd)
SUPER_USER_GROUP=wheel
;;
*)
echo "Your OS '${OS}' is currently not supported." >&2
exit 1
;;
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"
ETC_DIR="/etc"
# Ensure the target bin dir exists
# Care, we never want to remove it :-D
@ -29,10 +50,13 @@ STATE="$(cat "${__object}/parameter/state")"
USER="$(cat "${__object}/parameter/user")"
GROUP="$(cat "${__object}/parameter/group" 2>/dev/null || true)"
if [ -z "${GROUP}" ]; then
GROUP="${USER}"
if [ "${USER}" != "root" ]; then
GROUP="${USER}"
else
GROUP="${SUPER_USER_GROUP}"
fi
fi
SERVICE_NAME="${__object_id}"
BINARY="$(cat "${__object}/parameter/binary" 2>/dev/null || true)"
if [ -z "${BINARY}" ]; then
@ -62,22 +86,34 @@ 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="__systemd_unit/${SERVICE_NAME}.service"
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 /nonexistent \
--comment "cdist-managed ${SERVICE_NAME} user"
--home "${USER_HOME_DIR}" \
--comment "cdist-managed ${SERVICE_NAME} user" \
${USER_CREATE_HOME}
# Track dependencies
service_require="${service_require} __user/${USER}"
fi
@ -100,8 +136,8 @@ fi
INIT="$(cat "${__global}/explorer/init")"
# TODO: Support non-systemd
# This should setup the object in $service_definition_require
# See above.
case "${INIT}" in
systemd)
if [ -z "${SERVICE_DEFINITION}" ]; then
@ -117,6 +153,7 @@ User=${USER}
Group=${GROUP}
ExecStart=${SERVICE_EXEC}
Restart=always
${WORKING_DIRECTORY_SYSTEMD}
[Install]
WantedBy=multi-user.target
@ -129,14 +166,28 @@ EOF
--enablement-state "enabled" <<EOF
${SERVICE_DEFINITION}
EOF
service_require="${service_require} __systemd_unit/${SERVICE_NAME}.service"
;;
*)
echo "Init system ${INIT}' is currently not supported." >&2
exit 1
;;
;;
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}"
@ -144,8 +195,27 @@ export require="${require} ${service_require}"
VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version"
IS_VERSION="$(cat "${__object}/explorer/explorer-version")"
if [ "${SHOULD_VERSION}" != "${IS_VERSION}" ] && \
[ "${STATE}" = "present" ]; then
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}"
@ -153,34 +223,40 @@ if [ "${SHOULD_VERSION}" != "${IS_VERSION}" ] && \
# This is what will stop the service, replace the binaries and
# start the service again
perform_service_upgrade="$(cat <<EOF
service ${SERVICE_NAME} stop || true
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
service ${SERVICE_NAME} start || true
$(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
# TODO: Support files other than .tar.gz
UNPACK_EXTENSION="$(cat "${__object}/parameter/unpack-extension")"
UNPACK_ARGS="$(cat "${__object}/parameter/unpack-args" \
2>/dev/null || true)"
# Download packed file
__download "${TMP_PATH}.tar.gz " \
__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}.tar.gz " \
__unpack "${TMP_PATH}.tar.gz " \
require="__download${TMP_PATH}${UNPACK_EXTENSION} " \
__unpack "${TMP_PATH}${UNPACK_EXTENSION} " \
${UNPACK_ARGS} \
--destination "${TMP_PATH}"
version_bump_require="__unpack${TMP_PATH}.tar.gz "
version_bump_require="__unpack${TMP_PATH}${UNPACK_EXTENSION} "
else
# Create temp directory
__directory "${TMP_PATH}"
@ -196,18 +272,17 @@ EOF
# 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 "-"
fi
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"
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