From 1af7e960fa882efc7202cad5cc01d3136886fa0a Mon Sep 17 00:00:00 2001 From: Evilham Date: Sat, 30 Oct 2021 15:36:49 +0200 Subject: [PATCH] [__single_binary_service] Many improvements + runit support 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. --- gencode-remote | 21 ---- man.rst | 27 ++++- manifest | 173 +++++++++++++++++++++-------- parameter/default/unpack-extension | 1 + parameter/default/user-home-dir | 1 + parameter/optional | 3 + 6 files changed, 152 insertions(+), 74 deletions(-) delete mode 100644 gencode-remote create mode 100644 parameter/default/unpack-extension create mode 100644 parameter/default/user-home-dir diff --git a/gencode-remote b/gencode-remote deleted file mode 100644 index fe769fa..0000000 --- a/gencode-remote +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -e - -STATE="$(cat "${__object}/parameter/state")" -if [ "${STATE}" != "present" ]; then - exit -fi - -ETC_DIR="/etc" -SERVICE_NAME="${__object_id}" -CONFIG_FILE_DEST="${ETC_DIR}/${SERVICE_NAME}.conf" - -BIN_DIR="/usr/local/bin" -VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version" - -# We only restart here if there was a config change -# but there was not a version change -if grep -qE "^__file${CONFIG_FILE_DEST}" "${__messages_in}" && \ - grep -qvE "^__file${VERSION_FILE}" "${__messages_in}"; then - echo "service ${SERVICE_NAME} restart" -fi - diff --git a/man.rst b/man.rst index 804b465..cb40330 100644 --- a/man.rst +++ b/man.rst @@ -23,10 +23,8 @@ binaries in `/usr/local/bin`. If a `--config-file-source` is provided, it will be placed under: `/etc/${__object_id}.conf`. -TODO (patches welcome!): -- It currently only supports `.tar.gz` archives. -- It currently only supports systemd units. -- Does not handle properly BSD-systems (wheel group, /usr/local/etc, systemd) +This type supports services managed by `__runit(7)` when `systemd` is not +the init system being used. REQUIRED PARAMETERS @@ -72,6 +70,13 @@ user If this user is not `root` and `--do-not-manage-user` is not present, this user will be created or removed as per the `--state` parameter. +user-home-dir + Does not have an effect if `--do-not-manage-user` is used or `--user` is + `root`. + The home directory of the service user. It will be created. + Defaults to `/nonexistent`, in this case the home directory will not be + created. + group The group under which the service will run. Defaults to `--user`. @@ -95,6 +100,13 @@ service-exec Defaults to `/usr/local/bin/BINARY_NAME` where `BINARY_NAME` is the resulting value of `--binary`. +service-definition + The service definition to be used as an override. + Note that this type decides dinammically between runit and systemd, and + you can currently only define either a systemd unit or a runit script here. + Use this parameter only for testing and get in touch to discuss how your + particular use-case can be supported by the type. + service-description The service description to be used in, e.g. the systemd unit file. Defaults to `cdist-managed '${__object_id}' service`. @@ -106,6 +118,13 @@ unpack-args subdirectories; that can be worked around with `--unpack-args '--tar-strip 1'`. +unpack-extension + Only has an effect if `--unpack` is used. + The file extension of the file to unpack, defaults to `.tar.gz`. + +working-directory + If set, the working directory with which the service will be started. + OPTIONAL MULTIPLE PARAMETERS ---------------------------- diff --git a/manifest b/manifest index e05b630..8288b94 100755 --- a/manifest +++ b/manifest @@ -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" <&2 - exit 1 - ;; + ;; + runit|sysvinit) + if [ -z "${SERVICE_DEFINITION}" ]; then + SERVICE_DEFINITION="$(cat </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 diff --git a/parameter/default/unpack-extension b/parameter/default/unpack-extension new file mode 100644 index 0000000..c95e2e9 --- /dev/null +++ b/parameter/default/unpack-extension @@ -0,0 +1 @@ +.tar.gz \ No newline at end of file diff --git a/parameter/default/user-home-dir b/parameter/default/user-home-dir new file mode 100644 index 0000000..4d21ca6 --- /dev/null +++ b/parameter/default/user-home-dir @@ -0,0 +1 @@ +/nonexistent diff --git a/parameter/optional b/parameter/optional index 7c2ca06..7c88cb4 100644 --- a/parameter/optional +++ b/parameter/optional @@ -7,4 +7,7 @@ service-args service-exec service-description service-definition +unpack-extension unpack-args +user-home-dir +working-directory