From 51d0b817fe0e56a733cd1b445b81321831b0c4f3 Mon Sep 17 00:00:00 2001 From: Evilham Date: Fri, 18 Jun 2021 20:52:58 +0200 Subject: [PATCH 1/6] [__single_binary_service] Type to manage very simple services. --- explorer/explorer-version | 10 +++ manifest | 158 +++++++++++++++++++++++++++++++++ parameter/boolean | 1 + parameter/default/service-args | 0 parameter/default/state | 1 + parameter/default/user | 1 + parameter/optional | 8 ++ parameter/optional_multiple | 1 + parameter/required | 3 + 9 files changed, 183 insertions(+) create mode 100755 explorer/explorer-version create mode 100755 manifest create mode 100644 parameter/boolean create mode 100644 parameter/default/service-args create mode 100644 parameter/default/state create mode 100644 parameter/default/user create mode 100644 parameter/optional create mode 100644 parameter/optional_multiple create mode 100644 parameter/required diff --git a/explorer/explorer-version b/explorer/explorer-version new file mode 100755 index 0000000..690cc5f --- /dev/null +++ b/explorer/explorer-version @@ -0,0 +1,10 @@ +#!/bin/sh -e + +BIN_PREFIX="/usr/local/bin" +SERVICE_NAME="${__object_id}" + +VERSION_FILE="${BIN_PREFIX}/.${SERVICE_NAME}.cdist.version" + +if [ -f "${VERSION_FILE}" ]; then + cat "${VERSION_FILE}" +fi diff --git a/manifest b/manifest new file mode 100755 index 0000000..d5df410 --- /dev/null +++ b/manifest @@ -0,0 +1,158 @@ +#!/bin/sh -e + +BIN_DIR="/usr/local/bin" + +# Ensure the target bin dir exists +__directory "${BIN_DIR}" \ + --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 + GROUP="${USER}" +fi + +SERVICE_NAME="${__object_id}" + +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 >> /dev/stderr <<-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_EXEC="${SERVICE_EXEC} $(cat "${__object}/parameter/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 + +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 +if [ "${USER}" != "root" ]; then + __user "${USER}" \ + --system \ + --state "${STATE}" \ + --home /nonexistent \ + --comment "cdist-managed ${SERVICE_NAME} user" + # Track dependencies + service_require="${service_require} __user/${USER}" +fi + +# TODO: Support non-systemd +__systemd_unit "${SERVICE_NAME}.service" \ + --source "-" \ + --state "${STATE}" \ + --enablement-state "enabled" </dev/null || true)" + # Download packed file + __download "${TMP_PATH}.tar.gz" \ + --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" \ + ${UNPACK_ARGS} \ + --destination "${TMP_PATH}" \ + --onchange "$(cat < Date: Fri, 18 Jun 2021 22:01:45 +0200 Subject: [PATCH 2/6] [__single_binary_service] Add manpage, config-file and better absent With these changes the type is good for general consumption (modulo the limitations mentioned in the manpage under TODO). --- man.rst | 169 +++++++++++++++++++++++++++++++++++++++++++++ manifest | 39 ++++++++++- parameter/boolean | 1 + parameter/optional | 1 + 4 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 man.rst diff --git a/man.rst b/man.rst new file mode 100644 index 0000000..8f384bf --- /dev/null +++ b/man.rst @@ -0,0 +1,169 @@ +cdist-type__evilham_single_binary_service(7) +============================================ + +NAME +---- +cdist-type__evilham_single_binary_service - Setup a single-binary service + + +DESCRIPTION +----------- +This type is designed to easily deploy and configure a single-binary service +named `${__object_id}`. + +A good example of this are Prometheus exporters. + +This type makes certain assumptions that might not be correct on your system. +If you need more flexibility, please get in touch and provide a use-case +(and hopefully a backwards-compatible patch). + +This type will place the downloaded binary and, if requested, other extra +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) + + +REQUIRED PARAMETERS +------------------- +checksum + This will be passed verbatim to `__download(7)`. + Use something like `sha256:...`. + +url + This will be passed verbatim to `__download(7)`. + +version + This type will use a thumbstone file with a "version" number to track + whether or not a service must be updated. + This thumbstone file is placed under + `/usr/local/bin/.${__object_id}.cdist.version`. + + +BOOLEAN PARAMETERS +------------------ +unpack + If present, the contents of `--url` will be treated as an archive to be + unpacked with `__unpack(7)`. + See also `--unpack-args` and `--extra-binary`. + +do-not-manage-user + Always considered present when `--user` is `root`. + If present, the user in `--user` will not be managed by this type with + `__user`, this means it *must* exist beforehand when installing the service + and it will not be removed by this type. + + +OPTIONAL PARAMETERS +------------------- +config-file-source + If present, this file's contents will be placed under + `/etc/${__object_id}.conf` with permissions `0440` and ownership assigned to + `--user` and `--group`. + If `-` is passed, this type's `stdin` will be used. + +user + The user under which the service will run. Defaults to `root`. + 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. + +group + The group under which the service will run. Defaults to `--user`. + +state + Whether the service is to be `present` (default) or `absent`. + When `absent`, this type will clean any binaries listed in `--extra-binary` + and also the config file as described in `--config-file-source`. + +binary + This will be the binary name. Defaults to `${__object_id}`. + If `--unpack` is used, a binary with this name must be unpacked. + Otherwise, the contents of `--url` will be placed under this binary name. + +service-args + Any extra arguments to pass along with `--service-exec`. + +service-exec + The executable to use for this service. + Defaults to `/usr/local/bin/BINARY_NAME` where `BINARY_NAME` is the + resulting value of `--binary`. + +service-description + The service description to be used in, e.g. the systemd unit file. + Defaults to `cdist-managed '${__object_id}' service`. + +unpack-args + Only has an effect if `--unpack` is used. + These arguments will be passed verbatim to `__unpack(7)`. + Very useful as this type assumes the archive does not have the binaries in + subdirectories; that can be worked around with + `--unpack-args '--tar-strip 1'`. + + +OPTIONAL MULTIPLE PARAMETERS +---------------------------- +extra-binary + Only useful with `--unpack`. + If passed, these binaries will also be installed when `--state` is `present` + and removed when `--state` is `absent`. + Handle with care :-). + + +EXAMPLES +-------- + +.. code-block:: sh + + # Install and enable the ipmi_exporter service + # The variables are defined in the manifest previously + __evilham_single_binary_service ipmi_exporter \ + --user "${USER}" \ + --service-args ' --config.file=/etc/ipmi_exporter.conf' \ + --version "${SHOULD_VERSION}" \ + --checksum "${CHECKSUM}" \ + --url "${DOWNLOAD_URL}" \ + --state "present" \ + --unpack \ + --unpack-args "--tar-strip 1" \ + --config-file-source '-' <<-EOF + # Remotely managed, changes will be lost + # [...] config contents goes here + EOF + + # Remove the ipmi_exporter service along with the user and its config + __evilham_single_binary_service ipmi_exporter \ + --user "${USER}" \ + --version "${SHOULD_VERSION}" \ + --checksum "${CHECKSUM}" \ + --url "${DOWNLOAD_URL}" \ + --state "absent" + + # Same, but the service was using my user! Let's not delete that! + __evilham_single_binary_service ipmi_exporter \ + --user "evilham" \ + --do-not-manage-user \ + --version "${SHOULD_VERSION}" \ + --checksum "${CHECKSUM}" \ + --url "${DOWNLOAD_URL}" \ + --state "absent" + + +SEE ALSO +-------- +- `__download(7)` +- `__unpack(7)` + + +AUTHORS +------- +Evilham + + +COPYING +------- +Copyright \(C) 2021 Evilham. diff --git a/manifest b/manifest index d5df410..e279a05 100755 --- a/manifest +++ b/manifest @@ -1,9 +1,12 @@ #!/bin/sh -e BIN_DIR="/usr/local/bin" +ETC_DIR="/etc" # 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}" @@ -46,8 +49,13 @@ CHECKSUM="$(cat "${__object}/parameter/checksum")" SHOULD_VERSION="$(cat "${__object}/parameter/version")" # Create a user for the service if it is not root -if [ "${USER}" != "root" ]; then - __user "${USER}" \ +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" + fi + require="${require} ${user_require}" __user "${USER}" \ --system \ --state "${STATE}" \ --home /nonexistent \ @@ -56,10 +64,29 @@ if [ "${USER}" != "root" ]; then 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_required="${service_required} __file${CONFIG_FILE_DEST}" +fi + + + # TODO: Support non-systemd __systemd_unit "${SERVICE_NAME}.service" \ --source "-" \ --state "${STATE}" \ + --restart \ --enablement-state "enabled" < Date: Wed, 4 Aug 2021 20:27:08 +0200 Subject: [PATCH 3/6] [__single_binary_service] Adapt bug fixes proposed by pedro there are several typos, some style issues and now there is at most one service restart in all cases. Submitted by: pedro --- gencode-remote | 21 ++++++++++++++++ man.rst | 4 ++- manifest | 68 +++++++++++++++++++++++++++++--------------------- 3 files changed, 64 insertions(+), 29 deletions(-) create mode 100644 gencode-remote diff --git a/gencode-remote b/gencode-remote new file mode 100644 index 0000000..fe769fa --- /dev/null +++ b/gencode-remote @@ -0,0 +1,21 @@ +#!/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 8f384bf..804b465 100644 --- a/man.rst +++ b/man.rst @@ -86,7 +86,9 @@ binary Otherwise, the contents of `--url` will be placed under this binary name. service-args - Any extra arguments to pass along with `--service-exec`. + Any extra arguments to pass along with `--service-exec`. Beware that any + service-args having the format `--config=/etc/foo.cfg` should be + represented in the following way `--service-exec='--config=/etc/foo.cfg'` service-exec The executable to use for this service. diff --git a/manifest b/manifest index e279a05..be967eb 100755 --- a/manifest +++ b/manifest @@ -1,5 +1,20 @@ #!/bin/sh -e +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 + ;; +esac + BIN_DIR="/usr/local/bin" ETC_DIR="/etc" @@ -26,7 +41,7 @@ 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 >> /dev/stderr <<-EOF + cat >&2 <<-EOF You cannot specify extra binaries without the --unpack argument. Make sure that the --url argument points to a file archive. EOF @@ -36,7 +51,8 @@ SERVICE_EXEC="$(cat "${__object}/parameter/service-exec" 2>/dev/null || true)" if [ -z "${SERVICE_EXEC}" ]; then SERVICE_EXEC="${BIN_DIR}/${BINARY}" fi -SERVICE_EXEC="${SERVICE_EXEC} $(cat "${__object}/parameter/service-args")" +SERVICE_ARGS="$(cat "${__object}/parameter/service-args")" +SERVICE_EXEC="${SERVICE_EXEC} ${SERVICE_ARGS}" SERVICE_DESCRIPTION="$(cat "${__object}/parameter/service-description" \ 2>/dev/null || true)" @@ -77,17 +93,19 @@ if [ -n "${CONFIG_FILE_SOURCE}" ] && [ "${STATE}" = "present" ]; then --group "${GROUP}" \ --mode "0440" \ --source "${CONFIG_FILE_SOURCE}" - service_required="${service_required} __file${CONFIG_FILE_DEST}" + service_require="${service_require} __file${CONFIG_FILE_DEST}" fi +INIT="$(cat "${__global}/explorer/init")" # TODO: Support non-systemd -__systemd_unit "${SERVICE_NAME}.service" \ - --source "-" \ - --state "${STATE}" \ - --restart \ - --enablement-state "enabled" <&2 + exit 1 + ;; +esac # Proceed after user and service description have been prepared export require="${require} ${service_require}" -# Perform a service restart if config has changed -if [ "${STATE}" = "present" ]; then - __check_messages "${SERVICE_NAME}_config" \ - --pattern "^__file${CONFIG_FILE_DEST}" \ - --execute "service ${SERVICE_NAME} restart" -fi - VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version" IS_VERSION="$(cat "${__object}/explorer/explorer-version")" @@ -130,8 +148,7 @@ if [ "${SHOULD_VERSION}" != "${IS_VERSION}" ] && \ service ${SERVICE_NAME} stop || true for bin_file in ${BINARY} ${EXTRA_BINARIES}; do bin_path="${TMP_PATH}/\${bin_file}" - # TODO: on the BSDs, the super user group is wheel - chown root:root "\${bin_path}" + chown root:${SUPER_USER_GROUP} "\${bin_path}" chmod 0555 "\${bin_path}" cp -af "\${bin_path}" "${BIN_DIR}/\${bin_file}" done @@ -154,39 +171,34 @@ EOF require="__download${TMP_PATH}.tar.gz" \ __unpack "${TMP_PATH}.tar.gz" \ ${UNPACK_ARGS} \ - --destination "${TMP_PATH}" \ - --onchange "$(cat < Date: Wed, 4 Aug 2021 21:00:52 +0200 Subject: [PATCH 4/6] [__single_binary_service] Support customisation of systemd units Requested by pedro --- manifest | 14 ++++++++++---- parameter/optional | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/manifest b/manifest index be967eb..fe9ef74 100755 --- a/manifest +++ b/manifest @@ -60,6 +60,8 @@ if [ -z "${SERVICE_DESCRIPTION}" ]; then SERVICE_DESCRIPTION="cdist-managed '${SERVICE_NAME}' service" fi +SERVICE_DEFINITION="$(cat "${__object}/parameter/service-definition" 2>/dev/null || true)" + DOWNLOAD_URL="$(cat "${__object}/parameter/url")" CHECKSUM="$(cat "${__object}/parameter/checksum")" SHOULD_VERSION="$(cat "${__object}/parameter/version")" @@ -102,10 +104,8 @@ INIT="$(cat "${__global}/explorer/init")" # TODO: Support non-systemd case "${INIT}" in systemd) - __systemd_unit "${SERVICE_NAME}.service" \ - --source "-" \ - --state "${STATE}" \ - --enablement-state "enabled" < Date: Wed, 4 Aug 2021 21:02:37 +0200 Subject: [PATCH 5/6] [__single_binary_service] Do not use echo echo echo --- manifest | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/manifest b/manifest index fe9ef74..e05b630 100755 --- a/manifest +++ b/manifest @@ -123,10 +123,12 @@ WantedBy=multi-user.target EOF )" fi - echo ${SERVICE_DEFINITION} | __systemd_unit "${SERVICE_NAME}.service" \ + __systemd_unit "${SERVICE_NAME}.service" \ --source "-" \ --state "${STATE}" \ - --enablement-state "enabled" + --enablement-state "enabled" < Date: Sat, 30 Oct 2021 15:36:49 +0200 Subject: [PATCH 6/6] [__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