[__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.
This commit is contained in:
parent
3e77fbbb43
commit
1af7e960fa
6 changed files with 152 additions and 74 deletions
|
@ -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
|
|
||||||
|
|
27
man.rst
27
man.rst
|
@ -23,10 +23,8 @@ binaries in `/usr/local/bin`.
|
||||||
If a `--config-file-source` is provided, it will be placed under:
|
If a `--config-file-source` is provided, it will be placed under:
|
||||||
`/etc/${__object_id}.conf`.
|
`/etc/${__object_id}.conf`.
|
||||||
|
|
||||||
TODO (patches welcome!):
|
This type supports services managed by `__runit(7)` when `systemd` is not
|
||||||
- It currently only supports `.tar.gz` archives.
|
the init system being used.
|
||||||
- It currently only supports systemd units.
|
|
||||||
- Does not handle properly BSD-systems (wheel group, /usr/local/etc, systemd)
|
|
||||||
|
|
||||||
|
|
||||||
REQUIRED PARAMETERS
|
REQUIRED PARAMETERS
|
||||||
|
@ -72,6 +70,13 @@ user
|
||||||
If this user is not `root` and `--do-not-manage-user` is not present,
|
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.
|
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
|
group
|
||||||
The group under which the service will run. Defaults to `--user`.
|
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
|
Defaults to `/usr/local/bin/BINARY_NAME` where `BINARY_NAME` is the
|
||||||
resulting value of `--binary`.
|
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
|
service-description
|
||||||
The service description to be used in, e.g. the systemd unit file.
|
The service description to be used in, e.g. the systemd unit file.
|
||||||
Defaults to `cdist-managed '${__object_id}' service`.
|
Defaults to `cdist-managed '${__object_id}' service`.
|
||||||
|
@ -106,6 +118,13 @@ unpack-args
|
||||||
subdirectories; that can be worked around with
|
subdirectories; that can be worked around with
|
||||||
`--unpack-args '--tar-strip 1'`.
|
`--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
|
OPTIONAL MULTIPLE PARAMETERS
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
137
manifest
137
manifest
|
@ -1,22 +1,43 @@
|
||||||
#!/bin/sh -e
|
#!/bin/sh -e
|
||||||
|
SERVICE_NAME="${__object_id}"
|
||||||
|
|
||||||
OS="$(cat "${__global}/explorer/os")"
|
OS="$(cat "${__global}/explorer/os")"
|
||||||
|
|
||||||
case "${OS}" in
|
case "${OS}" in
|
||||||
debian)
|
debian|devuan)
|
||||||
SUPER_USER_GROUP=root
|
SUPER_USER_GROUP=root
|
||||||
|
ETC_DIR="/etc"
|
||||||
;;
|
;;
|
||||||
*bsd)
|
*bsd)
|
||||||
SUPER_USER_GROUP=wheel
|
SUPER_USER_GROUP=wheel
|
||||||
|
ETC_DIR="/usr/local/etc"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Your OS '${OS}' is currently not supported." >&2
|
echo "Your OS '${OS}' is currently not supported." >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
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"
|
BIN_DIR="/usr/local/bin"
|
||||||
ETC_DIR="/etc"
|
|
||||||
|
|
||||||
# Ensure the target bin dir exists
|
# Ensure the target bin dir exists
|
||||||
# Care, we never want to remove it :-D
|
# Care, we never want to remove it :-D
|
||||||
|
@ -29,10 +50,13 @@ STATE="$(cat "${__object}/parameter/state")"
|
||||||
USER="$(cat "${__object}/parameter/user")"
|
USER="$(cat "${__object}/parameter/user")"
|
||||||
GROUP="$(cat "${__object}/parameter/group" 2>/dev/null || true)"
|
GROUP="$(cat "${__object}/parameter/group" 2>/dev/null || true)"
|
||||||
if [ -z "${GROUP}" ]; then
|
if [ -z "${GROUP}" ]; then
|
||||||
|
if [ "${USER}" != "root" ]; then
|
||||||
GROUP="${USER}"
|
GROUP="${USER}"
|
||||||
|
else
|
||||||
|
GROUP="${SUPER_USER_GROUP}"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SERVICE_NAME="${__object_id}"
|
|
||||||
|
|
||||||
BINARY="$(cat "${__object}/parameter/binary" 2>/dev/null || true)"
|
BINARY="$(cat "${__object}/parameter/binary" 2>/dev/null || true)"
|
||||||
if [ -z "${BINARY}" ]; then
|
if [ -z "${BINARY}" ]; then
|
||||||
|
@ -62,22 +86,34 @@ fi
|
||||||
|
|
||||||
SERVICE_DEFINITION="$(cat "${__object}/parameter/service-definition" 2>/dev/null || true)"
|
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")"
|
DOWNLOAD_URL="$(cat "${__object}/parameter/url")"
|
||||||
CHECKSUM="$(cat "${__object}/parameter/checksum")"
|
CHECKSUM="$(cat "${__object}/parameter/checksum")"
|
||||||
SHOULD_VERSION="$(cat "${__object}/parameter/version")"
|
SHOULD_VERSION="$(cat "${__object}/parameter/version")"
|
||||||
|
|
||||||
# Create a user for the service if it is not root
|
# Create a user for the service if it is not root
|
||||||
|
USER_HOME_DIR="/root"
|
||||||
if [ "${USER}" != "root" ] && \
|
if [ "${USER}" != "root" ] && \
|
||||||
[ ! -f "${__object}/parameter/do-not-manage-user" ]; then
|
[ ! -f "${__object}/parameter/do-not-manage-user" ]; then
|
||||||
if [ "${STATE}" = "absent" ]; then
|
if [ "${STATE}" = "absent" ]; then
|
||||||
# When removing, ensure user is not being used
|
# 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
|
fi
|
||||||
require="${require} ${user_require}" __user "${USER}" \
|
require="${require} ${user_require}" __user "${USER}" \
|
||||||
--system \
|
--system \
|
||||||
--state "${STATE}" \
|
--state "${STATE}" \
|
||||||
--home /nonexistent \
|
--home "${USER_HOME_DIR}" \
|
||||||
--comment "cdist-managed ${SERVICE_NAME} user"
|
--comment "cdist-managed ${SERVICE_NAME} user" \
|
||||||
|
${USER_CREATE_HOME}
|
||||||
# Track dependencies
|
# Track dependencies
|
||||||
service_require="${service_require} __user/${USER}"
|
service_require="${service_require} __user/${USER}"
|
||||||
fi
|
fi
|
||||||
|
@ -100,8 +136,8 @@ fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INIT="$(cat "${__global}/explorer/init")"
|
# This should setup the object in $service_definition_require
|
||||||
# TODO: Support non-systemd
|
# See above.
|
||||||
case "${INIT}" in
|
case "${INIT}" in
|
||||||
systemd)
|
systemd)
|
||||||
if [ -z "${SERVICE_DEFINITION}" ]; then
|
if [ -z "${SERVICE_DEFINITION}" ]; then
|
||||||
|
@ -117,6 +153,7 @@ User=${USER}
|
||||||
Group=${GROUP}
|
Group=${GROUP}
|
||||||
ExecStart=${SERVICE_EXEC}
|
ExecStart=${SERVICE_EXEC}
|
||||||
Restart=always
|
Restart=always
|
||||||
|
${WORKING_DIRECTORY_SYSTEMD}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
@ -129,14 +166,28 @@ EOF
|
||||||
--enablement-state "enabled" <<EOF
|
--enablement-state "enabled" <<EOF
|
||||||
${SERVICE_DEFINITION}
|
${SERVICE_DEFINITION}
|
||||||
EOF
|
EOF
|
||||||
service_require="${service_require} __systemd_unit/${SERVICE_NAME}.service"
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
*)
|
runit|sysvinit)
|
||||||
echo "Init system ${INIT}' is currently not supported." >&2
|
if [ -z "${SERVICE_DEFINITION}" ]; then
|
||||||
exit 1
|
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
|
esac
|
||||||
|
service_require="${service_require} ${service_definition_require}"
|
||||||
|
|
||||||
# Proceed after user and service description have been prepared
|
# Proceed after user and service description have been prepared
|
||||||
export require="${require} ${service_require}"
|
export require="${require} ${service_require}"
|
||||||
|
@ -144,8 +195,27 @@ export require="${require} ${service_require}"
|
||||||
VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version"
|
VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version"
|
||||||
IS_VERSION="$(cat "${__object}/explorer/explorer-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
|
# We are installing the service and there has been a version change
|
||||||
# (or it is first-time install)
|
# (or it is first-time install)
|
||||||
TMP_PATH="/tmp/${SERVICE_NAME}-${SHOULD_VERSION}"
|
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
|
# This is what will stop the service, replace the binaries and
|
||||||
# start the service again
|
# start the service again
|
||||||
perform_service_upgrade="$(cat <<EOF
|
perform_service_upgrade="$(cat <<EOF
|
||||||
service ${SERVICE_NAME} stop || 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
|
for bin_file in ${BINARY} ${EXTRA_BINARIES}; do
|
||||||
bin_path="${TMP_PATH}/\${bin_file}"
|
bin_path="${TMP_PATH}/\${bin_file}"
|
||||||
chown root:${SUPER_USER_GROUP} "\${bin_path}"
|
chown root:${SUPER_USER_GROUP} "\${bin_path}"
|
||||||
chmod 0555 "\${bin_path}"
|
chmod 0555 "\${bin_path}"
|
||||||
cp -af "\${bin_path}" "${BIN_DIR}/\${bin_file}"
|
cp -af "\${bin_path}" "${BIN_DIR}/\${bin_file}"
|
||||||
done
|
done
|
||||||
service ${SERVICE_NAME} start || true
|
fi
|
||||||
|
$(sv_cmd start) || true
|
||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
if [ -f "${__object}/parameter/unpack" ]; then
|
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" \
|
UNPACK_ARGS="$(cat "${__object}/parameter/unpack-args" \
|
||||||
2>/dev/null || true)"
|
2>/dev/null || true)"
|
||||||
# Download packed file
|
# Download packed file
|
||||||
__download "${TMP_PATH}.tar.gz" \
|
__download "${TMP_PATH}${UNPACK_EXTENSION}" \
|
||||||
--url "${DOWNLOAD_URL}" \
|
--url "${DOWNLOAD_URL}" \
|
||||||
--download remote \
|
--download remote \
|
||||||
--sum "${CHECKSUM}"
|
--sum "${CHECKSUM}"
|
||||||
|
|
||||||
# Unpack file and also perform service upgrade
|
# Unpack file and also perform service upgrade
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
require="__download${TMP_PATH}.tar.gz" \
|
require="__download${TMP_PATH}${UNPACK_EXTENSION}" \
|
||||||
__unpack "${TMP_PATH}.tar.gz" \
|
__unpack "${TMP_PATH}${UNPACK_EXTENSION}" \
|
||||||
${UNPACK_ARGS} \
|
${UNPACK_ARGS} \
|
||||||
--destination "${TMP_PATH}"
|
--destination "${TMP_PATH}"
|
||||||
version_bump_require="__unpack${TMP_PATH}.tar.gz"
|
version_bump_require="__unpack${TMP_PATH}${UNPACK_EXTENSION}"
|
||||||
else
|
else
|
||||||
# Create temp directory
|
# Create temp directory
|
||||||
__directory "${TMP_PATH}"
|
__directory "${TMP_PATH}"
|
||||||
|
@ -196,18 +272,17 @@ EOF
|
||||||
|
|
||||||
# Perform update of cdist-managed version file
|
# Perform update of cdist-managed version file
|
||||||
# And also perform service upgrade
|
# And also perform service upgrade
|
||||||
|
# This is a bug if service_upgrade fails >,<
|
||||||
printf "%s" "${SHOULD_VERSION}" | \
|
printf "%s" "${SHOULD_VERSION}" | \
|
||||||
require="${version_bump_require}" __file \
|
require="${version_bump_require}" __file \
|
||||||
"${VERSION_FILE}" \
|
"${VERSION_FILE}" \
|
||||||
--onchange "${perform_service_upgrade}" \
|
--onchange "${perform_service_upgrade}" \
|
||||||
--source "-"
|
--source "-"
|
||||||
fi
|
else
|
||||||
|
# We only restart here if there was a config change
|
||||||
if [ "${STATE}" = "absent" ]; then
|
# but there was not a version change
|
||||||
# Perform cleanup of generated files
|
require="${service_require}" __check_messages \
|
||||||
for bin_file in ${BINARY} ${EXTRA_BINARIES}; do
|
"single_binary_service_${__object_id}" \
|
||||||
__file "${BIN_DIR}/${bin_file}" --state "absent"
|
--pattern "^__file${CONFIG_FILE_DEST}" \
|
||||||
done
|
--execute "$(sv_cmd restart)"
|
||||||
__file "${VERSION_FILE}" --state "absent"
|
|
||||||
__file "${CONFIG_FILE_DEST}" --state "absent"
|
|
||||||
fi
|
fi
|
||||||
|
|
1
parameter/default/unpack-extension
Normal file
1
parameter/default/unpack-extension
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.tar.gz
|
1
parameter/default/user-home-dir
Normal file
1
parameter/default/user-home-dir
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/nonexistent
|
|
@ -7,4 +7,7 @@ service-args
|
||||||
service-exec
|
service-exec
|
||||||
service-description
|
service-description
|
||||||
service-definition
|
service-definition
|
||||||
|
unpack-extension
|
||||||
unpack-args
|
unpack-args
|
||||||
|
user-home-dir
|
||||||
|
working-directory
|
||||||
|
|
Loading…
Reference in a new issue