[__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).
This commit is contained in:
evilham 2021-06-18 22:01:45 +02:00
parent 51d0b817fe
commit d5b552ddb4
4 changed files with 208 additions and 2 deletions

169
man.rst Normal file
View file

@ -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 <contact@evilham.com>
COPYING
-------
Copyright \(C) 2021 Evilham.

View file

@ -1,9 +1,12 @@
#!/bin/sh -e #!/bin/sh -e
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
__directory "${BIN_DIR}" \ __directory "${BIN_DIR}" \
--state "exists" \
--mode 0755 --mode 0755
export require="${require} __directory${BIN_DIR}" export require="${require} __directory${BIN_DIR}"
@ -46,8 +49,13 @@ 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
if [ "${USER}" != "root" ]; then if [ "${USER}" != "root" ] && \
__user "${USER}" \ [ ! -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 \ --system \
--state "${STATE}" \ --state "${STATE}" \
--home /nonexistent \ --home /nonexistent \
@ -56,10 +64,29 @@ if [ "${USER}" != "root" ]; then
service_require="${service_require} __user/${USER}" service_require="${service_require} __user/${USER}"
fi 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 # TODO: Support non-systemd
__systemd_unit "${SERVICE_NAME}.service" \ __systemd_unit "${SERVICE_NAME}.service" \
--source "-" \ --source "-" \
--state "${STATE}" \ --state "${STATE}" \
--restart \
--enablement-state "enabled" <<EOF --enablement-state "enabled" <<EOF
[Unit] [Unit]
Description=${SERVICE_DESCRIPTION} Description=${SERVICE_DESCRIPTION}
@ -81,6 +108,12 @@ service_require="${service_require} __systemd_unit/${SERVICE_NAME}.service"
# 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}"
# 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" VERSION_FILE="${BIN_DIR}/.${SERVICE_NAME}.cdist.version"
IS_VERSION="$(cat "${__object}/explorer/explorer-version")" IS_VERSION="$(cat "${__object}/explorer/explorer-version")"
@ -149,10 +182,12 @@ EOF
"${VERSION_FILE}" \ "${VERSION_FILE}" \
--source "-" --source "-"
fi fi
if [ "${STATE}" = "absent" ]; then if [ "${STATE}" = "absent" ]; then
# Perform cleanup of generated files # Perform cleanup of generated files
for bin_file in ${BINARY} ${EXTRA_BINARIES}; do for bin_file in ${BINARY} ${EXTRA_BINARIES}; do
__file "${BINARY_PREFIX}/${bin_file}" --state "absent" __file "${BINARY_PREFIX}/${bin_file}" --state "absent"
done done
__file "${VERSION_FILE}" --state "absent" __file "${VERSION_FILE}" --state "absent"
__file "${CONFIG_FILE_DEST}" --state "absent"
fi fi

View file

@ -1 +1,2 @@
do-not-manage-user
unpack unpack

View file

@ -1,3 +1,4 @@
config-file-source
user user
group group
state state