From 2cf44c66d46435e859fe0528d4b414dafd8b468a Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 15 Jan 2020 19:00:30 +0100 Subject: [PATCH 01/32] [__directory] Add --state exists and --state pre-exists --- cdist/conf/type/__directory/gencode-remote | 17 ++++++++++++++--- cdist/conf/type/__directory/man.rst | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cdist/conf/type/__directory/gencode-remote b/cdist/conf/type/__directory/gencode-remote index 374db47a..e1ab69d7 100755 --- a/cdist/conf/type/__directory/gencode-remote +++ b/cdist/conf/type/__directory/gencode-remote @@ -3,6 +3,7 @@ # 2011-2013 Nico Schottelius (nico-cdist at schottelius.org) # 2013 Steven Armstrong (steven-cdist armstrong.cc) # 2014 Daniel Heule (hda at sfs.biz) +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -21,8 +22,8 @@ # destination="/$__object_id" -state_should="$(cat "$__object/parameter/state")" -type="$(cat "$__object/explorer/type")" +state_should=$(cat "$__object/parameter/state") +type=$(cat "$__object/explorer/type") stat_file="$__object/explorer/stat" # variable to keep track if we have to set directory attributes @@ -72,7 +73,7 @@ set_mode() { } case "$state_should" in - present) + present|exists) if [ "$type" != "directory" ]; then set_attributes=1 if [ "$type" != "none" ]; then @@ -83,6 +84,10 @@ case "$state_should" in fi echo "mkdir $mkdiropt '$destination'" echo "create" >> "$__messages_out" + elif [ "$state_should" = 'exists' ]; then + # The type is directory and --state exists. We are done and do not + # check or set the attributes. + exit 0 fi # Note: Mode - needs to happen last as a chown/chgrp can alter mode by @@ -103,6 +108,12 @@ case "$state_should" in fi done ;; + pre-exists) + if [ "$type" != "directory" ]; then + echo "Directory \"$destination\" does not exist" >&2 + exit 1 + fi + ;; absent) if [ "$type" = "directory" ]; then echo "rm -rf '$destination'" diff --git a/cdist/conf/type/__directory/man.rst b/cdist/conf/type/__directory/man.rst index 74b00afe..7755334c 100644 --- a/cdist/conf/type/__directory/man.rst +++ b/cdist/conf/type/__directory/man.rst @@ -19,7 +19,18 @@ None. OPTIONAL PARAMETERS ------------------- state - 'present' or 'absent', defaults to 'present' + 'present', 'absent', 'exists' or 'pre-exists', defaults to 'present' where: + + present + the directory exists and the given attributes are set. + absent + the directory does not exist. + exists + the directory exists, but its attributes are not altered if it already + existed. + pre-exists + check that the directory exists and is indeed a directory, but do not + create or modify it. group Group to chgrp to. @@ -36,7 +47,7 @@ BOOLEAN PARAMETERS parents Whether to create parents as well (mkdir -p behaviour). Warning: all intermediate directory permissions default - to whatever mkdir -p does. + to whatever mkdir -p does. Usually this means root:root, 0700. From de1a421b68edeb2bf3660f2ed98e109db93e8d88 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 2 Oct 2019 15:39:30 +0200 Subject: [PATCH 02/32] [explorer/init] Support for Darwin and more BusyBox combinations --- cdist/conf/explorer/init | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index a8a7857e..829d6ab8 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -23,14 +23,22 @@ # for example at linux this value is "init" or "systemd" in most cases # -uname_s="$(uname -s)" - -case "$uname_s" in +case $(uname -s) in Linux) - (pgrep -P0 -l | awk '/^1[ \t]/ {print $2;}') || true + if command -v pgrep >/dev/null + then + # BusyBox's version of ps does not support some options. + # On Linux systems, we prefer pgrep to get the name of PID1. + (pgrep -P0 -l | awk '/^1[ \t]/ {print $2;}') || true + else + ps -o comm= -p 1 2>/dev/null || cat /proc/1/comm + fi ;; FreeBSD|OpenBSD) - ps -o comm= -p 1 || true + ps -o comm= -p 1 2>/dev/null || true + ;; + Darwin) + basename "$(ps -o comm= -p 1 2>/dev/null)" ;; *) # return a empty string as unknown value From 4fe2dcba891ae52cccbe02553976be2bb7291fd1 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 30 Jan 2020 18:35:50 +0100 Subject: [PATCH 03/32] [explorer/init] Linux is a mess... --- cdist/conf/explorer/init | 44 +++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index 829d6ab8..ceae2e9f 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -25,14 +25,48 @@ case $(uname -s) in Linux) - if command -v pgrep >/dev/null + if test -d /proc/1/ then - # BusyBox's version of ps does not support some options. - # On Linux systems, we prefer pgrep to get the name of PID1. - (pgrep -P0 -l | awk '/^1[ \t]/ {print $2;}') || true + comm_name=$(cat /proc/1/comm) else - ps -o comm= -p 1 2>/dev/null || cat /proc/1/comm + # BusyBox's versions of ps and pgrep do not support some options + # depending on which compile-time options have been used. + # Both pgrep and ps are tried to get the command name + comm_name=$( + pgrep -P0 -l 2>/dev/null | awk '/^1[ \t]/ { print $2 }' + || ps -o comm= -p 1 2>/dev/null) fi + + case $comm_name + in + systemd) + echo systemd + ;; + init) + # It could be anything... + + if test -h /proc/1/exe + then + init_exe=/proc/1/exe + else + init_exe=$(command -v "$comm_name") + fi + + test -x "$comm_exe" || exit 1 + + case $("$comm_exe" --version | head -n 1) + in + *SysV*) + echo init + ;; + *upstart*) + echo upstart + ;; + *) + echo "" + ;; + esac + esac ;; FreeBSD|OpenBSD) ps -o comm= -p 1 2>/dev/null || true From 0640b02f90d92e11f6a4f8b7c0110d9b5a9bfb89 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Sat, 15 Feb 2020 14:59:12 +0100 Subject: [PATCH 04/32] Fix too short title underline --- cdist/conf/type/__systemd_service/man.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__systemd_service/man.rst b/cdist/conf/type/__systemd_service/man.rst index 678cee29..7eca398b 100644 --- a/cdist/conf/type/__systemd_service/man.rst +++ b/cdist/conf/type/__systemd_service/man.rst @@ -45,7 +45,7 @@ action Restarts the service BOOLEAN PARAMETERS ------------------ +------------------ if-required Only execute the action if minimum one required type outputs a message to From c09165d1228e887e2fb4dad456c6b1409211a499 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Sat, 15 Feb 2020 21:05:24 +0100 Subject: [PATCH 05/32] Fix spelling --- docs/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog b/docs/changelog index 9f1e6245..bd767b9d 100644 --- a/docs/changelog +++ b/docs/changelog @@ -9,7 +9,7 @@ Changelog * Type __package_apt: Update package index if it is older than one day (Ander Punnar) * Type __cron: Fix job removal if 'is' and 'should' don't match (Matthias Stecher) * New type: __systemd_service (Matthias Stecher) - * Type __postgres_role: Fix password command synthax (Timothée Floure) + * Type __postgres_role: Fix password command syntax (Timothée Floure) 6.5.0: 2020-01-23 * Type __acl: Add --entry parameter to replace --acl, deprecate --acl (Ander Punnar) From 70200cd28fe9b35670f574e77d49e747f23072f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Tue, 21 Jan 2020 10:06:09 +0100 Subject: [PATCH 06/32] Refactor __consul_agent type to support distribution packages --- cdist/conf/type/__consul_agent/man.rst | 3 + cdist/conf/type/__consul_agent/manifest | 373 +++++++++++------- .../type/__consul_agent/parameter/boolean | 1 + 3 files changed, 225 insertions(+), 152 deletions(-) diff --git a/cdist/conf/type/__consul_agent/man.rst b/cdist/conf/type/__consul_agent/man.rst index 966abc60..62ee70bb 100644 --- a/cdist/conf/type/__consul_agent/man.rst +++ b/cdist/conf/type/__consul_agent/man.rst @@ -116,6 +116,9 @@ verify-incoming verify-outgoing enforce the use of TLS and verify the peers authenticity on outgoing connections +use-distribution-package + uses distribution package instead of upstream binary + EXAMPLES -------- diff --git a/cdist/conf/type/__consul_agent/manifest b/cdist/conf/type/__consul_agent/manifest index e00f29ec..599f15b4 100755 --- a/cdist/conf/type/__consul_agent/manifest +++ b/cdist/conf/type/__consul_agent/manifest @@ -2,6 +2,7 @@ # # 2015 Steven Armstrong (steven-cdist at armstrong.cc) # 2015-2019 Nico Schottelius (nico-cdist at schottelius.org) +# 2019 Timothée Floure (timothee.floure at ungleich.ch) # # This file is part of cdist. # @@ -19,133 +20,64 @@ # along with cdist. If not, see . # - os=$(cat "$__global/explorer/os") -case "$os" in - alpine|scientific|centos|debian|devuan|redhat|ubuntu) - # whitelist safeguard - : - ;; - *) - echo "Your operating system ($os) is currently not supported by this type (${__type##*/})." >&2 - echo "Please contribute an implementation for it if you can." >&2 - exit 1 - ;; -esac +### +# Type parameters. state="$(cat "$__object/parameter/state")" user="$(cat "$__object/parameter/user")" group="$(cat "$__object/parameter/group")" +release=$(cat "$__global/explorer/lsb_release") +if [ -f "$__object/parameter/use-distribution-package" ]; then + use_distribution_package=1 +fi + +### +# Those are default that might be overriden by os-specific logic. + data_dir="/var/lib/consul" conf_dir="/etc/consul/conf.d" conf_file="config.json" +tls_dir="$conf_dir/tls" -# FIXME: there has got to be a better way to handle the dependencies in this case -case "$state" in - present) - __group "$group" --system --state "$state" - require="__group/$group" \ - __user "$user" --system --gid "$group" \ - --home "$data_dir" --state "$state" - export require="__user/consul" - ;; - absent) - echo "Sorry, state=absent currently not supported :-(" >&2 - exit 1 - require="$__object_name" \ - __user "$user" --system --gid "$group" --state "$state" - require="__user/$user" \ - __group "$group" --system --state "$state" - ;; -esac +### +# Sane deployment, based on distribution package when available. -__directory /etc/consul \ - --owner root --group "$group" --mode 750 --state "$state" -require="__directory/etc/consul" \ - __directory "$conf_dir" \ - --owner root --group "$group" --mode 750 --state "$state" +distribution_setup () { + case "$os" in + debian) + # consul is only available starting Debian 10 (buster). + # See https://packages.debian.org/buster/consul + if [ $release -lt 10 ]; then + echo "Consul is not available for your debian release." >&2 + echo "Please use the 'manual' (i.e. non-package) installation or \ + upgrade the target system." >&2 + exit 1 + fi -if [ -f "$__object/parameter/ca-file-source" ] || [ -f "$__object/parameter/cert-file-source" ] || [ -f "$__object/parameter/key-file-source" ]; then - # create directory for ssl certs - require="__directory/etc/consul" \ - __directory /etc/consul/ssl \ - --owner root --group "$group" --mode 750 --state "$state" -fi + # Override previously defined environment to match debian packaging. + conf_dir='/etc/consul.d' + user='consul' + grou='consul' + ;; + *) + echo "Your operating system ($os) is currently not supported with the \ + --use-distribution-package flag (${__type##*/})." >&2 + echo "Please use non-package installation or contribute an \ + implementation for if you can." >&2 + exit 1 + ;; + esac -__directory "$data_dir" \ - --owner "$user" --group "$group" --mode 770 --state "$state" + # Install consul package. + __package consul --state $state + export config_deployment_requires="__package/consul" +} -# Generate json config file -( -echo "{" - -# parameters we define ourself -printf ' "data_dir": "%s"\n' "$data_dir" - -cd "$__object/parameter/" -for param in *; do - case "$param" in - state|user|group|json-config) continue ;; - ca-file-source|cert-file-source|key-file-source) - source="$(cat "$__object/parameter/$param")" - destination="/etc/consul/ssl/${source##*/}" - require="__directory/etc/consul/ssl" \ - __file "$destination" \ - --owner root --group consul --mode 640 \ - --source "$source" \ - --state "$state" - key="$(echo "${param%-*}" | tr '-' '_')" - printf ' ,"%s": "%s"\n' "$key" "$destination" - ;; - disable-remote-exec|disable-update-check|leave-on-terminate|rejoin-after-leave|server|enable-syslog|verify-incoming|verify-outgoing) - # handle boolean parameters - key="$(echo "$param" | tr '-' '_')" - printf ' ,"%s": true\n' "$key" - ;; - retry-join) - # join multiple parameters into json array - retry_join="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join")" - # remove trailing , - printf ' ,"retry_join": [%s]\n' "${retry_join%*,}" - ;; - retry-join-wan) - # join multiple parameters into json array over wan - retry_join_wan="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join-wan")" - # remove trailing , - printf ' ,"retry_join_wan": [%s]\n' "${retry_join_wan%*,}" - ;; - bootstrap-expect) - # integer key=value parameters - key="$(echo "$param" | tr '-' '_')" - printf ' ,"%s": %s\n' "$key" "$(cat "$__object/parameter/$param")" - ;; - *) - # string key=value parameters - key="$(echo "$param" | tr '-' '_')" - printf ' ,"%s": "%s"\n' "$key" "$(cat "$__object/parameter/$param")" - ;; - esac -done -if [ -f "$__object/parameter/json-config" ]; then - json_config="$(cat "$__object/parameter/json-config")" - if [ "$json_config" = "-" ]; then - json_config="$__object/stdin" - fi - # remove leading and trailing whitespace and commas from first and last line - # indent each line with 3 spaces for consistency - json=$(sed -e 's/^[ \t]*/ /' -e '1s/^[ \t,]*//' -e '$s/[ \t,]*$//' "$json_config") - printf ' ,%s\n' "$json" -fi -echo "}" -) | \ -require="__directory${conf_dir}" \ - __config_file "${conf_dir}/${conf_file}" \ - --owner root --group "$group" --mode 640 \ - --state "$state" \ - --onchange 'service consul status >/dev/null && service consul reload || true' \ - --source - +### +# LEGACY manual deployment, kept for compatibility reasons. init_sysvinit() { @@ -179,47 +111,184 @@ init_upstart() require="__file/etc/init/consul.conf" __start_on_boot consul } -# Install init script to start on boot -case "$os" in - devuan) - init_sysvinit debian - ;; - centos|redhat) - os_version="$(sed 's/[^0-9.]//g' "$__global/explorer/os_version")" - major_version="${os_version%%.*}" - case "$major_version" in - [456]) - init_sysvinit redhat - ;; - 7) - init_systemd - ;; - *) - echo "Unsupported CentOS/Redhat version: $os_version" >&2 - exit 1 - ;; - esac - ;; +manual_setup () { + case "$os" in + alpine|scientific|centos|debian|devuan|redhat|ubuntu) + # whitelist safeguard + : + ;; + *) + echo "Your operating system ($os) is currently not supported by this \ + type (${__type##*/})." >&2 + echo "Please contribute an implementation for it if you can." >&2 + exit 1 + ;; + esac - debian) - os_version=$(cat "$__global/explorer/os_version") - major_version="${os_version%%.*}" + # FIXME: there has got to be a better way to handle the dependencies in this case + case "$state" in + present) + __group "$group" --system --state "$state" + require="__group/$group" __user "$user" \ + --system --gid "$group" --home "$data_dir" --state "$state" + ;; + *) + echo "The $state state is not (yet?) supported by this type." >&2 + exit 1 + ;; + esac - case "$major_version" in - [567]) - init_sysvinit debian - ;; - [89]|10) - init_systemd - ;; - *) - echo "Unsupported Debian version $os_version" >&2 - exit 1 - ;; - esac - ;; + # Create data directory. + require="__user/consul"__directory "$data_dir" \ + --owner "$user" --group "$group" --mode 770 --state "$state" - ubuntu) - init_upstart + # Create config directory. + require="__user/consul" __directory "$conf_dir" \ + --parents --owner root --group "$group" --mode 750 --state "$state" + + # Install init script to start on boot + case "$os" in + devuan) + init_sysvinit debian + ;; + centos|redhat) + os_version="$(sed 's/[^0-9.]//g' "$__global/explorer/os_version")" + major_version="${os_version%%.*}" + case "$major_version" in + [456]) + init_sysvinit redhat + ;; + 7) + init_systemd + ;; + *) + echo "Unsupported CentOS/Redhat version: $os_version" >&2 + exit 1 + ;; + esac + ;; + + debian) + os_version=$(cat "$__global/explorer/os_version") + major_version="${os_version%%.*}" + + case "$major_version" in + [567]) + init_sysvinit debian + ;; + [89]|10) + init_systemd + ;; + *) + echo "Unsupported Debian version $os_version" >&2 + exit 1 + ;; + esac + ;; + + ubuntu) + init_upstart + ;; + esac + + config_deployment_requires="__user/consul __directory/$conf_dir" +} + +### +# Trigger requested installation method. +if [ $use_distribution_package ]; then + distribution_setup +else + manual_setup +fi + +### +# Generate and deploy configuration. +json_configuration=$( + echo "{" + + # parameters we define ourself + printf ' "data_dir": "%s"\n' "$data_dir" + + cd "$__object/parameter/" + for param in *; do + case "$param" in + state|user|group|json-config|use-distribution-package) continue ;; + ca-file-source|cert-file-source|key-file-source) + source="$(cat "$__object/parameter/$param")" + destination="/etc/consul/ssl/${source##*/}" + require="__directory/etc/consul/ssl" \ + __file "$destination" \ + --owner root --group consul --mode 640 \ + --source "$source" \ + --state "$state" + key="$(echo "${param%-*}" | tr '-' '_')" + printf ' ,"%s": "%s"\n' "$key" "$destination" ;; -esac + disable-remote-exec|disable-update-check|leave-on-terminate\ + |rejoin-after-leave|server|enable-syslog|verify-incoming|verify-outgoing) + # handle boolean parameters + key="$(echo "$param" | tr '-' '_')" + printf ' ,"%s": true\n' "$key" + ;; + retry-join) + # join multiple parameters into json array + retry_join="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join")" + # remove trailing , + printf ' ,"retry_join": [%s]\n' "${retry_join%*,}" + ;; + retry-join-wan) + # join multiple parameters into json array over wan + retry_join_wan="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join-wan")" + # remove trailing , + printf ' ,"retry_join_wan": [%s]\n' "${retry_join_wan%*,}" + ;; + bootstrap-expect) + # integer key=value parameters + key="$(echo "$param" | tr '-' '_')" + printf ' ,"%s": %s\n' "$key" "$(cat "$__object/parameter/$param")" + ;; + *) + # string key=value parameters + key="$(echo "$param" | tr '-' '_')" + printf ' ,"%s": "%s"\n' "$key" "$(cat "$__object/parameter/$param")" + ;; + esac + done + if [ -f "$__object/parameter/json-config" ]; then + json_config="$(cat "$__object/parameter/json-config")" + if [ "$json_config" = "-" ]; then + json_config="$__object/stdin" + fi + # remove leading and trailing whitespace and commas from first and last line + # indent each line with 3 spaces for consistency + json=$(sed -e 's/^[ \t]*/ /' -e '1s/^[ \t,]*//' -e '$s/[ \t,]*$//' "$json_config") + printf ' ,%s\n' "$json" + fi + echo "}" +) +echo "$json_configuration" | require="$config_deployment_requires" \ + __file "$conf_dir/$conf_file" \ + --owner root --group "$group" --mode 640 \ + --state "$state" \ + --source - + +# Set configuration deployment as requirement for service restart. +restart_requires="__file/$conf_dir/$conf_file" + +### +# Install TLS certificates. +if [ -f "$__object/parameter/ca-file-source" ] || \ + [ -f "$__object/parameter/cert-file-source" ] || \ + [ -f "$__object/parameter/key-file-source" ]; then + + requires="__file/$conf_dir/$conf_file" __directory $conf_dir/tls \ + --owner root --group "$group" --mode 750 --state "$state" + + # Append to service restart requirements. + restart_requires="$restart_requires __directory/$conf_dir/tls" +fi + +### +# Restart consul agent after everything else. +require="$restart_requires" __service consul --action restart diff --git a/cdist/conf/type/__consul_agent/parameter/boolean b/cdist/conf/type/__consul_agent/parameter/boolean index 91f7f17e..c86853c3 100644 --- a/cdist/conf/type/__consul_agent/parameter/boolean +++ b/cdist/conf/type/__consul_agent/parameter/boolean @@ -6,3 +6,4 @@ server enable-syslog verify-incoming verify-outgoing +use-distribution-package From f595664924b3ae2ad190f9469fdf0be3b38d8a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Tue, 21 Jan 2020 10:07:21 +0100 Subject: [PATCH 07/32] Patch __consul_* to discover remote consul configuration dir --- cdist/conf/type/__consul_check/explorer/conf-dir | 1 + cdist/conf/type/__consul_check/manifest | 2 +- .../conf/type/__consul_service/explorer/conf-dir | 15 +++++++++++++++ cdist/conf/type/__consul_service/manifest | 5 ++--- .../type/__consul_watch_checks/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_checks/manifest | 2 +- .../type/__consul_watch_event/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_event/manifest | 2 +- .../type/__consul_watch_key/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_key/manifest | 2 +- .../__consul_watch_keyprefix/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_keyprefix/manifest | 2 +- .../type/__consul_watch_nodes/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_nodes/manifest | 2 +- .../type/__consul_watch_service/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_service/manifest | 2 +- .../__consul_watch_services/explorer/conf-dir | 1 + cdist/conf/type/__consul_watch_services/manifest | 2 +- 18 files changed, 33 insertions(+), 11 deletions(-) create mode 120000 cdist/conf/type/__consul_check/explorer/conf-dir create mode 100644 cdist/conf/type/__consul_service/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_checks/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_event/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_key/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_keyprefix/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_nodes/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_service/explorer/conf-dir create mode 120000 cdist/conf/type/__consul_watch_services/explorer/conf-dir diff --git a/cdist/conf/type/__consul_check/explorer/conf-dir b/cdist/conf/type/__consul_check/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_check/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_check/manifest b/cdist/conf/type/__consul_check/manifest index c9f7add9..522aa1a9 100755 --- a/cdist/conf/type/__consul_check/manifest +++ b/cdist/conf/type/__consul_check/manifest @@ -19,7 +19,7 @@ # name="$(cat "$__object/parameter/name" 2>/dev/null || echo "$__object_id")" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="check_${name}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_service/explorer/conf-dir b/cdist/conf/type/__consul_service/explorer/conf-dir new file mode 100644 index 00000000..6e94f781 --- /dev/null +++ b/cdist/conf/type/__consul_service/explorer/conf-dir @@ -0,0 +1,15 @@ +# Determine the configuration directory used by consul. + +check_dir () { + if [ -d "$1" ]; then + echo -n "$1" + exit + fi +} + +check_dir '/etc/consul/conf.d' +check_dir '/etc/consul.d' +check_dir '/etc/consul' + +echo 'Could not determine consul configuration dir. Exiting.' >&2 +exit 1 diff --git a/cdist/conf/type/__consul_service/manifest b/cdist/conf/type/__consul_service/manifest index 60397db7..d16f18e0 100755 --- a/cdist/conf/type/__consul_service/manifest +++ b/cdist/conf/type/__consul_service/manifest @@ -19,7 +19,7 @@ # name="$(cat "$__object/parameter/name" 2>/dev/null || echo "$__object_id")" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="service_${name}.json" state="$(cat "$__object/parameter/state")" @@ -45,7 +45,7 @@ printf ' "name": "%s"\n' "$name" cd "$__object/parameter/" for param in *; do case "$param" in - state|name|check-interval) continue ;; + state|name|check-interval|conf-dir) continue ;; check-script) printf ' ,"check": {\n' printf ' "script": "%s"\n' "$(cat "$__object/parameter/check-script")" @@ -86,7 +86,6 @@ echo " }" # end json file echo "}" ) | \ -require="__directory${conf_dir}" \ __config_file "${conf_dir}/${conf_file}" \ --owner root --group consul --mode 640 \ --state "$state" \ diff --git a/cdist/conf/type/__consul_watch_checks/explorer/conf-dir b/cdist/conf/type/__consul_watch_checks/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_checks/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_checks/manifest b/cdist/conf/type/__consul_watch_checks/manifest index 5fdd7a74..4976b25a 100755 --- a/cdist/conf/type/__consul_watch_checks/manifest +++ b/cdist/conf/type/__consul_watch_checks/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_event/explorer/conf-dir b/cdist/conf/type/__consul_watch_event/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_event/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_event/manifest b/cdist/conf/type/__consul_watch_event/manifest index 61934656..b17680c1 100755 --- a/cdist/conf/type/__consul_watch_event/manifest +++ b/cdist/conf/type/__consul_watch_event/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_key/explorer/conf-dir b/cdist/conf/type/__consul_watch_key/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_key/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_key/manifest b/cdist/conf/type/__consul_watch_key/manifest index 61934656..b17680c1 100755 --- a/cdist/conf/type/__consul_watch_key/manifest +++ b/cdist/conf/type/__consul_watch_key/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_keyprefix/explorer/conf-dir b/cdist/conf/type/__consul_watch_keyprefix/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_keyprefix/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_keyprefix/manifest b/cdist/conf/type/__consul_watch_keyprefix/manifest index 61934656..b17680c1 100755 --- a/cdist/conf/type/__consul_watch_keyprefix/manifest +++ b/cdist/conf/type/__consul_watch_keyprefix/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_nodes/explorer/conf-dir b/cdist/conf/type/__consul_watch_nodes/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_nodes/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_nodes/manifest b/cdist/conf/type/__consul_watch_nodes/manifest index 61934656..b17680c1 100755 --- a/cdist/conf/type/__consul_watch_nodes/manifest +++ b/cdist/conf/type/__consul_watch_nodes/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_service/explorer/conf-dir b/cdist/conf/type/__consul_watch_service/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_service/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_service/manifest b/cdist/conf/type/__consul_watch_service/manifest index db38eb18..e8d18328 100755 --- a/cdist/conf/type/__consul_watch_service/manifest +++ b/cdist/conf/type/__consul_watch_service/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" diff --git a/cdist/conf/type/__consul_watch_services/explorer/conf-dir b/cdist/conf/type/__consul_watch_services/explorer/conf-dir new file mode 120000 index 00000000..daa712c3 --- /dev/null +++ b/cdist/conf/type/__consul_watch_services/explorer/conf-dir @@ -0,0 +1 @@ +../../__consul_service/explorer/conf-dir \ No newline at end of file diff --git a/cdist/conf/type/__consul_watch_services/manifest b/cdist/conf/type/__consul_watch_services/manifest index 61934656..b17680c1 100755 --- a/cdist/conf/type/__consul_watch_services/manifest +++ b/cdist/conf/type/__consul_watch_services/manifest @@ -20,7 +20,7 @@ cdist_type="${__type##*/}" watch_type="${cdist_type##*_}" -conf_dir="/etc/consul/conf.d" +conf_dir=$(cat "$__object/explorer/conf-dir") conf_file="watch_${watch_type}_${__object_id}.json" state="$(cat "$__object/parameter/state")" From 31ad1bdaad701720303054d668cf9635987edf1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Sun, 26 Jan 2020 15:13:12 +0100 Subject: [PATCH 08/32] Fix various typos and styling errors in __consul_agent, conf-dir explorer --- cdist/conf/type/__consul_agent/manifest | 40 ++++++++++--------- .../type/__consul_service/explorer/conf-dir | 2 +- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/cdist/conf/type/__consul_agent/manifest b/cdist/conf/type/__consul_agent/manifest index 599f15b4..40667002 100755 --- a/cdist/conf/type/__consul_agent/manifest +++ b/cdist/conf/type/__consul_agent/manifest @@ -49,7 +49,7 @@ distribution_setup () { debian) # consul is only available starting Debian 10 (buster). # See https://packages.debian.org/buster/consul - if [ $release -lt 10 ]; then + if [ "$release" -lt 10 ]; then echo "Consul is not available for your debian release." >&2 echo "Please use the 'manual' (i.e. non-package) installation or \ upgrade the target system." >&2 @@ -59,7 +59,7 @@ distribution_setup () { # Override previously defined environment to match debian packaging. conf_dir='/etc/consul.d' user='consul' - grou='consul' + group='consul' ;; *) echo "Your operating system ($os) is currently not supported with the \ @@ -71,7 +71,7 @@ distribution_setup () { esac # Install consul package. - __package consul --state $state + __package consul --state "$state" export config_deployment_requires="__package/consul" } @@ -139,7 +139,7 @@ manual_setup () { esac # Create data directory. - require="__user/consul"__directory "$data_dir" \ + require="__user/consul" __directory "$data_dir" \ --owner "$user" --group "$group" --mode 770 --state "$state" # Create config directory. @@ -202,8 +202,23 @@ else manual_setup fi +### +# Install TLS certificates. + +if [ -f "$__object/parameter/ca-file-source" ] || \ + [ -f "$__object/parameter/cert-file-source" ] || \ + [ -f "$__object/parameter/key-file-source" ]; then + + requires="$config_deployment_requires" __directory $tls_dir \ + --owner root --group "$group" --mode 750 --state "$state" + + # Append to service restart requirements. + restart_requires="$restart_requires __directory/$conf_dir/tls" +fi + ### # Generate and deploy configuration. + json_configuration=$( echo "{" @@ -216,8 +231,8 @@ json_configuration=$( state|user|group|json-config|use-distribution-package) continue ;; ca-file-source|cert-file-source|key-file-source) source="$(cat "$__object/parameter/$param")" - destination="/etc/consul/ssl/${source##*/}" - require="__directory/etc/consul/ssl" \ + destination="$tls_dir/${source##*/}" + require="__directory/$tls_dir" \ __file "$destination" \ --owner root --group consul --mode 640 \ --source "$source" \ @@ -276,19 +291,6 @@ echo "$json_configuration" | require="$config_deployment_requires" \ # Set configuration deployment as requirement for service restart. restart_requires="__file/$conf_dir/$conf_file" -### -# Install TLS certificates. -if [ -f "$__object/parameter/ca-file-source" ] || \ - [ -f "$__object/parameter/cert-file-source" ] || \ - [ -f "$__object/parameter/key-file-source" ]; then - - requires="__file/$conf_dir/$conf_file" __directory $conf_dir/tls \ - --owner root --group "$group" --mode 750 --state "$state" - - # Append to service restart requirements. - restart_requires="$restart_requires __directory/$conf_dir/tls" -fi - ### # Restart consul agent after everything else. require="$restart_requires" __service consul --action restart diff --git a/cdist/conf/type/__consul_service/explorer/conf-dir b/cdist/conf/type/__consul_service/explorer/conf-dir index 6e94f781..0fc9ef84 100644 --- a/cdist/conf/type/__consul_service/explorer/conf-dir +++ b/cdist/conf/type/__consul_service/explorer/conf-dir @@ -2,7 +2,7 @@ check_dir () { if [ -d "$1" ]; then - echo -n "$1" + printf '%s' "$1" exit fi } From 09540dc6bd63cb338ed8dc27bf69e2cc3547f02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Mon, 17 Feb 2020 11:18:36 +0100 Subject: [PATCH 09/32] Add simple __service type --- .../type/__service/explorer/service-manager | 8 +++ cdist/conf/type/__service/gencode-remote | 9 ++++ cdist/conf/type/__service/man.rst | 51 +++++++++++++++++++ cdist/conf/type/__service/manifest | 15 ++++++ cdist/conf/type/__service/parameter/required | 1 + 5 files changed, 84 insertions(+) create mode 100755 cdist/conf/type/__service/explorer/service-manager create mode 100755 cdist/conf/type/__service/gencode-remote create mode 100644 cdist/conf/type/__service/man.rst create mode 100644 cdist/conf/type/__service/manifest create mode 100644 cdist/conf/type/__service/parameter/required diff --git a/cdist/conf/type/__service/explorer/service-manager b/cdist/conf/type/__service/explorer/service-manager new file mode 100755 index 00000000..55a873fa --- /dev/null +++ b/cdist/conf/type/__service/explorer/service-manager @@ -0,0 +1,8 @@ +#!/bin/sh + +# Assume systemd if systemctl is in PATH. +if [ "$(command -v systemctl)" ]; then + printf "systemd" +else + printf "unknown" +fi diff --git a/cdist/conf/type/__service/gencode-remote b/cdist/conf/type/__service/gencode-remote new file mode 100755 index 00000000..ac62e05f --- /dev/null +++ b/cdist/conf/type/__service/gencode-remote @@ -0,0 +1,9 @@ +#!/bin/sh + +manager="$(cat "$__object/explorer/service-manager")" +name=$__object_id +action="$(cat "$__object/parameter/action")" + +if [ "$manager" = "unknown" ]; then + echo "service '$name' '$action'" +fi diff --git a/cdist/conf/type/__service/man.rst b/cdist/conf/type/__service/man.rst new file mode 100644 index 00000000..f9b23d5b --- /dev/null +++ b/cdist/conf/type/__service/man.rst @@ -0,0 +1,51 @@ +cdist-type__service(7) +====================== + +NAME +---- +cdist-type__service - Run action on a system service + + +DESCRIPTION +----------- +This type allows you to run an action against a system service. + + +REQUIRED PARAMETERS +------------------- +action + Arbitrary parameter passed as action. Usually 'start', 'stop', 'reload' or 'restart'. + +OPTIONAL PARAMETERS +------------------- +None. + + +BOOLEAN PARAMETERS +------------------ +None. + + +EXAMPLES +-------- + +.. code-block:: sh + + # Restart nginx service. + __service nginx --action restart + + # Stop postfix service. + __service postfix --action stop + + +AUTHORS +------- +Timothée Floure + + +COPYING +------- +Copyright \(C) 2019 Timothée Floure. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. diff --git a/cdist/conf/type/__service/manifest b/cdist/conf/type/__service/manifest new file mode 100644 index 00000000..cb5af234 --- /dev/null +++ b/cdist/conf/type/__service/manifest @@ -0,0 +1,15 @@ +#!/bin/sh + +manager="$(cat "$__object/explorer/service-manager")" + +name=$__object_id +action="$(cat "$__object/parameter/action")" + +case "$manager" in + systemd) + __systemd_service "$name" --action "$action" + ;; + *) + # Unknown: handled by `service $NAME $action` in gencode-remote. + ;; +esac diff --git a/cdist/conf/type/__service/parameter/required b/cdist/conf/type/__service/parameter/required new file mode 100644 index 00000000..a9f84d41 --- /dev/null +++ b/cdist/conf/type/__service/parameter/required @@ -0,0 +1 @@ +action From b891bb05d5751fe0f80829d7fe54cd56468d5e51 Mon Sep 17 00:00:00 2001 From: Ander Punnar Date: Wed, 19 Feb 2020 12:58:22 +0200 Subject: [PATCH 10/32] __update_alternatives: add state explorer --- cdist/conf/type/__update_alternatives/explorer/state | 8 ++++++++ cdist/conf/type/__update_alternatives/gencode-remote | 4 ++++ 2 files changed, 12 insertions(+) create mode 100755 cdist/conf/type/__update_alternatives/explorer/state diff --git a/cdist/conf/type/__update_alternatives/explorer/state b/cdist/conf/type/__update_alternatives/explorer/state new file mode 100755 index 00000000..04a78aaa --- /dev/null +++ b/cdist/conf/type/__update_alternatives/explorer/state @@ -0,0 +1,8 @@ +#!/bin/sh -e +path="$(cat "$__object/parameter/path")" +name="$__object_id" +link="$(readlink "/etc/alternatives/$name")" +if [ "$path" = "$link" ] +then echo present +else echo absent +fi diff --git a/cdist/conf/type/__update_alternatives/gencode-remote b/cdist/conf/type/__update_alternatives/gencode-remote index 0e7b0d89..b632deb2 100755 --- a/cdist/conf/type/__update_alternatives/gencode-remote +++ b/cdist/conf/type/__update_alternatives/gencode-remote @@ -21,6 +21,10 @@ # Setup alternative - no standard way to create, always set # +if [ "$(cat "$__object/explorer/state")" = 'present' ] +then exit 0 +fi + path="$(cat "$__object/parameter/path")" name="$__object_id" echo "update-alternatives --quiet --set '$name' '$path'" From a3bc8f94075e23d8c0032fc8322aba5eebebd41e Mon Sep 17 00:00:00 2001 From: Ander Punnar Date: Wed, 19 Feb 2020 12:59:14 +0200 Subject: [PATCH 11/32] __update_alternatives: remove expired comment --- cdist/conf/type/__update_alternatives/gencode-remote | 3 --- 1 file changed, 3 deletions(-) diff --git a/cdist/conf/type/__update_alternatives/gencode-remote b/cdist/conf/type/__update_alternatives/gencode-remote index b632deb2..c0b49814 100755 --- a/cdist/conf/type/__update_alternatives/gencode-remote +++ b/cdist/conf/type/__update_alternatives/gencode-remote @@ -17,9 +17,6 @@ # You should have received a copy of the GNU General Public License # along with cdist. If not, see . # -# -# Setup alternative - no standard way to create, always set -# if [ "$(cat "$__object/explorer/state")" = 'present' ] then exit 0 From 1b0caeda13ddfc3d941332ea912983aba01b4819 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Wed, 19 Feb 2020 14:49:35 +0100 Subject: [PATCH 12/32] ++changelog --- docs/changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog b/docs/changelog index bd767b9d..6410d36d 100644 --- a/docs/changelog +++ b/docs/changelog @@ -1,6 +1,9 @@ Changelog --------- +next: + * Type __update_alternatives: Add state explorer (Ander Punnar) + 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) * Explorer os_release: Add fallbacks (Dennis Camera) From 28d3760e29aaf8cdb30390f7e78c2334d7af8bc4 Mon Sep 17 00:00:00 2001 From: Jin-Guk Kwon Date: Thu, 20 Feb 2020 09:40:55 +0100 Subject: [PATCH 13/32] [cdist]Update os_version for alpine --- cdist/conf/explorer/os_version | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cdist/conf/explorer/os_version b/cdist/conf/explorer/os_version index 4c41695b..1d54ea60 100755 --- a/cdist/conf/explorer/os_version +++ b/cdist/conf/explorer/os_version @@ -70,4 +70,7 @@ case "$("$__explorer/os")" in ubuntu) lsb_release -sr ;; -esac + alpine) + cat /etc/alpine-release + ;; +esac \ No newline at end of file From ceddbd15a04327489916b61e58fdf2d7a7728427 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Thu, 20 Feb 2020 10:15:34 +0100 Subject: [PATCH 14/32] ++changes --- docs/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog b/docs/changelog index 6410d36d..b0ebf789 100644 --- a/docs/changelog +++ b/docs/changelog @@ -3,6 +3,7 @@ Changelog next: * Type __update_alternatives: Add state explorer (Ander Punnar) + * Explorer os_version: Add support for Alpine Linux (Jin-Guk Kwon) 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) From 21c9e3db1852eebb88be5454137ceb23159f7dc0 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Mon, 3 Feb 2020 22:12:21 +0100 Subject: [PATCH 15/32] [explorer/init] Support more init systems --- cdist/conf/explorer/init | 225 ++++++++++++++++++++++++++++++--------- 1 file changed, 174 insertions(+), 51 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index ceae2e9f..bf1736cd 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -1,7 +1,8 @@ -#!/bin/sh +#!/bin/sh -e # # 2016 Daniel Heule (hda at sfs.biz) # Copyright 2017, Philippe Gregoire +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) # # This file is part of cdist. # @@ -23,59 +24,181 @@ # for example at linux this value is "init" or "systemd" in most cases # +set -e + +# Expected values: +# Linux: +# Gentoo: +# sysvinit, openrc-init + +# GNU: +# Debian: +# hurd-init, sysvinit + +# [root@fedora-12 ~]# readlink /proc/1/exe +# /sbin/init (deleted) +# [root@fedora-12 ~]# ls -l /proc/1/exe +# lrwxrwxrwx. 1 root root 0 2020-01-30 23:00 /proc/1/exe -> /sbin/init (deleted) + +# inspired by https://stackoverflow.com/a/33266819 +shreadlink() ( + CDPATH= + target=$1 fname= targetDir= + + # Resolve potential symlinks until the ultimate target is found. + while : + do + if ! test -e "$target" + then + printf 'ERROR: %s does not exist.\n' "'$target'" >&2 + return 1 + fi + + # Change to target dir; necessary for correct resolution of target path. + cd "$(dirname -- "$target")" + + fname=$(basename -- "$target") # Extract filename. + [ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/' + + [ -L "$fname" ] || break + + # Extract [next] target path, which may be defined + # *relative* to the symlink's own directory. + # Note: We parse `ls -l` output to find the symlink target + # which is the only POSIX-compliant, albeit somewhat fragile, way. + # FIXME: Will break if one of the filenames contain ’ -> ’ + target=$(ls -l "$fname" | sed -e 's/^.* -> //') + done + + # Get canonical dir. path + targetDir=$(pwd -P) + + # Output the ultimate target's canonical path. + # Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path. + if test "$fname" = '.' + then + printf '%s\n' "${targetDir%/}" + elif test "$fname" = '..' + then + # Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied + # AFTER canonicalization. + printf '%s\n' "$(dirname -- "${targetDir}")" + else + printf '%s/%s\n' "${targetDir%/}" "$fname" + fi +) + + case $(uname -s) in - Linux) - if test -d /proc/1/ - then - comm_name=$(cat /proc/1/comm) - else - # BusyBox's versions of ps and pgrep do not support some options - # depending on which compile-time options have been used. - # Both pgrep and ps are tried to get the command name - comm_name=$( - pgrep -P0 -l 2>/dev/null | awk '/^1[ \t]/ { print $2 }' - || ps -o comm= -p 1 2>/dev/null) - fi + Linux|GNU) + # if test -f /proc/1/comm + # then + # comm_name=$(cat /proc/1/comm) + # else + # BusyBox's versions of ps and pgrep do not support some options + # depending on which compile-time options have been used. + # Both pgrep and ps are tried to get the command name + # comm_name=$( + # pgrep -P0 -l 2>/dev/null | awk '/^1[ \t]/ { print $2 }' + # || ps -o comm= -p 1 2>/dev/null) + # fi - case $comm_name - in - systemd) - echo systemd - ;; - init) - # It could be anything... + init_exe=$(shreadlink /proc/1/exe) - if test -h /proc/1/exe - then - init_exe=/proc/1/exe - else - init_exe=$(command -v "$comm_name") - fi + if ! test -x "$init_exe" + then + # On some rare occasions it can happen that the + # running init's binary has been replaced. In this + # case Linux adjusts the symlink to "X (deleted)" + case $init_exe + in + *' (deleted)') + init_exe=${init_exe% (deleted)} + test -x "$init_exe" || exit 1 + ;; + *) + exit 1 + ;; + esac + fi - test -x "$comm_exe" || exit 1 + if test "$init_exe" = '/hurd/init' + then + # XXX: Could maybe be removed + echo hurd-init + exit 0 + fi - case $("$comm_exe" --version | head -n 1) - in - *SysV*) - echo init - ;; - *upstart*) - echo upstart - ;; - *) - echo "" - ;; - esac - esac - ;; - FreeBSD|OpenBSD) - ps -o comm= -p 1 2>/dev/null || true - ;; - Darwin) - basename "$(ps -o comm= -p 1 2>/dev/null)" - ;; - *) - # return a empty string as unknown value - echo "" - ;; + comm_name=$(basename "$init_exe") + case $comm_name + in + init) + : # handled below + ;; + systemd) + # NOTE: sd_booted(3) + if test -d /run/systemd/system/ + then + echo systemd + exit 0 + fi + # otherwise: treat like "init" + ;; + *) + echo "$comm_name" + exit 0 + ;; + esac + + # init: it could be anything... + case $("$init_exe" --version 2>/dev/null | head -n 1) + in + SysV*) + # This is a little bit more specific than init + echo sysvinit + exit 0 + ;; + *'GNU Hurd'*) + echo hurd-init + ;; + *upstart*) + echo upstart + exit 0 + ;; + esac + case $("$init_exe" --help 2>/dev/null | head -n 1) + in + BusyBox*) + echo busybox + exit 0 + ;; + esac + + echo init + ;; + FreeBSD|OpenBSD) + ps -o comm= -p 1 2>/dev/null || true + ;; + Darwin) + basename "$(ps -o comm= -p 1 2>/dev/null)" + ;; + SunOS) + comm_name=$(ps -o comm= -p 1 2>/dev/null) + if test "$(basename "$comm_name")" != 'init' + then + echo "${comm_name}" + exit 0 + fi + + # XXX: Is this the correct way?? + if test -f /etc/svc/volatile/svc_nonpersist.db + then + echo smf + exit 0 + fi + ;; + *) + # return a empty string as unknown value + echo "" + ;; esac From d895bb0e87f524e8a64a802e6ff1922e52860ffa Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Tue, 18 Feb 2020 01:24:41 +0100 Subject: [PATCH 16/32] [explorer/init] Clean up --- cdist/conf/explorer/init | 399 ++++++++++++++++++++++++--------------- 1 file changed, 246 insertions(+), 153 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index bf1736cd..2d4f07c1 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -20,185 +20,278 @@ # along with cdist. If not, see . # # -# Returns the process name of pid 1 ( normaly the init system ) -# for example at linux this value is "init" or "systemd" in most cases +# Returns the name of the init system (PID 1) # - -set -e - # Expected values: # Linux: +# Adélie Linux: +# sysvinit+openrc +# Alpine Linux: +# busybox-init+openrc +# ArchLinux: +# systemd, sysvinit +# CRUX: +# sysvinit +# Debian: +# systemd, upstart, sysvinit, openrc, ??? +# Devuan: +# sysvinit, ??? # Gentoo: -# sysvinit, openrc-init - +# sysvinit+openrc, openrc-init, systemd +# OpenBMC: +# systemd +# OpenWrt: +# procd, init?? +# RedHat (RHEL, CentOS, Fedora, RedHat Linux, ...): +# systemd, upstart, sysvinit +# Slackware: +# sysvinit +# SuSE: +# systemd, sysvinit +# Ubuntu: +# systemd, upstart, sysvinit +# # GNU: -# Debian: -# hurd-init, sysvinit +# Debian: +# hurd-init, sysvinit +# +# BSD: +# {Free,Open,Net}BSD: +# init +# +# Mac OS X: +# launchd, init +# +# Solaris/Illumos: +# smf, init + # [root@fedora-12 ~]# readlink /proc/1/exe # /sbin/init (deleted) # [root@fedora-12 ~]# ls -l /proc/1/exe # lrwxrwxrwx. 1 root root 0 2020-01-30 23:00 /proc/1/exe -> /sbin/init (deleted) -# inspired by https://stackoverflow.com/a/33266819 -shreadlink() ( - CDPATH= - target=$1 fname= targetDir= +set -e +#set -x # DEBUG - # Resolve potential symlinks until the ultimate target is found. - while : - do - if ! test -e "$target" - then - printf 'ERROR: %s does not exist.\n' "'$target'" >&2 - return 1 - fi - - # Change to target dir; necessary for correct resolution of target path. - cd "$(dirname -- "$target")" - - fname=$(basename -- "$target") # Extract filename. - [ "$fname" = '/' ] && fname='' # !! curiously, `basename /` returns '/' - - [ -L "$fname" ] || break - - # Extract [next] target path, which may be defined - # *relative* to the symlink's own directory. - # Note: We parse `ls -l` output to find the symlink target - # which is the only POSIX-compliant, albeit somewhat fragile, way. - # FIXME: Will break if one of the filenames contain ’ -> ’ - target=$(ls -l "$fname" | sed -e 's/^.* -> //') - done - - # Get canonical dir. path - targetDir=$(pwd -P) - - # Output the ultimate target's canonical path. - # Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path. - if test "$fname" = '.' +validate_busybox_init() { + # It is quite common to use SysVinit to stack other init systemd + # (like OpenRC) on top of it. So we check for that, too. + if stacked=$(validate_openrc) then - printf '%s\n' "${targetDir%/}" - elif test "$fname" = '..' - then - # Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied - # AFTER canonicalization. - printf '%s\n' "$(dirname -- "${targetDir}")" + echo "busybox-init+${stacked}" else - printf '%s/%s\n' "${targetDir%/}" "$fname" + echo busybox-init fi -) +} +validate_hurd_init() { + # FIXME: Test me! + test -x /hurd/init || return 1 + grep -q 'GNU Hurd' /hurd/init || return 1 + echo hurd-init +} -case $(uname -s) in - Linux|GNU) - # if test -f /proc/1/comm - # then - # comm_name=$(cat /proc/1/comm) - # else - # BusyBox's versions of ps and pgrep do not support some options - # depending on which compile-time options have been used. - # Both pgrep and ps are tried to get the command name - # comm_name=$( - # pgrep -P0 -l 2>/dev/null | awk '/^1[ \t]/ { print $2 }' - # || ps -o comm= -p 1 2>/dev/null) - # fi +validate_openrc() { + test -f /run/openrc/softlevel || return 1 + echo openrc +} - init_exe=$(shreadlink /proc/1/exe) +validate_procd() { + grep -q 'procd' /sbin/procd || return 1 + echo procd +} - if ! test -x "$init_exe" - then - # On some rare occasions it can happen that the - # running init's binary has been replaced. In this - # case Linux adjusts the symlink to "X (deleted)" - case $init_exe - in - *' (deleted)') - init_exe=${init_exe% (deleted)} - test -x "$init_exe" || exit 1 - ;; - *) - exit 1 - ;; - esac - fi +validate_runit() { + test -d /run/runit || return 1 + echo runit +} - if test "$init_exe" = '/hurd/init' - then - # XXX: Could maybe be removed - echo hurd-init - exit 0 - fi +validate_smf() { + # XXX: Is this the correct way?? + test -f /etc/svc/volatile/svc_nonpersist.db || return 1 + echo smf +} - comm_name=$(basename "$init_exe") - case $comm_name +validate_systemd() { + # NOTE: sd_booted(3) + test -d /run/systemd/system/ || return 1 + # systemctl --version | sed -e '/^systemd/!d;s/^systemd //' + echo systemd +} + +validate_sysvinit() { + test -x /sbin/init \ + && grep -q 'INIT_VERSION=sysvinit-[0-9.]*' /sbin/init \ + || return 1 + + # It is quite common to use SysVinit to stack other init systemd + # (like OpenRC) on top of it. So we check for that, too. + if stacked=$(validate_openrc) + then + echo "sysvinit+${stacked}" + else + echo sysvinit + fi + unset stacked +} + +validate_upstart() { + test -x "$(command -v initctl)" || return 1 + case $(initctl version) + in + *'(upstart '*')') + # if type -d /etc/init + # then + # # modern (DBus-based?) upstart >= 0.5 + # : + # elif type -d /etc/events.d + # then + # # ancient upstart + # : + # fi + echo upstart + ;; + *) + return 1 + ;; + esac +} + +find_init_procfs() ( + # First, check if the required file in procfs exists... + test -h /proc/1/exe || return 1 + + # Find init executable + init_exe=$(ls -l /proc/1/exe 2>/dev/null) + init_exe=${init_exe#* -> } + + if ! test -x "$init_exe" + then + # On some rare occasions it can happen that the + # running init's binary has been replaced. In this + # case Linux adjusts the symlink to "X (deleted)" + case $init_exe in - init) - : # handled below - ;; - systemd) - # NOTE: sd_booted(3) - if test -d /run/systemd/system/ - then - echo systemd - exit 0 - fi - # otherwise: treat like "init" + *' (deleted)') + init_exe=${init_exe% (deleted)} + test -x "$init_exe" || exit 1 ;; *) - echo "$comm_name" - exit 0 + exit 1 ;; esac + fi - # init: it could be anything... - case $("$init_exe" --version 2>/dev/null | head -n 1) - in - SysV*) - # This is a little bit more specific than init - echo sysvinit - exit 0 - ;; - *'GNU Hurd'*) - echo hurd-init - ;; - *upstart*) - echo upstart - exit 0 - ;; - esac - case $("$init_exe" --help 2>/dev/null | head -n 1) - in - BusyBox*) - echo busybox - exit 0 - ;; - esac + echo "${init_exe}" +) - echo init - ;; - FreeBSD|OpenBSD) - ps -o comm= -p 1 2>/dev/null || true - ;; - Darwin) - basename "$(ps -o comm= -p 1 2>/dev/null)" - ;; - SunOS) - comm_name=$(ps -o comm= -p 1 2>/dev/null) - if test "$(basename "$comm_name")" != 'init' - then - echo "${comm_name}" - exit 0 - fi +# BusyBox's versions of ps and pgrep do not support some options +# depending on which compile-time options have been used. - # XXX: Is this the correct way?? - if test -f /etc/svc/volatile/svc_nonpersist.db - then - echo smf - exit 0 - fi - ;; - *) - # return a empty string as unknown value - echo "" - ;; -esac +find_init_pgrep() { + pgrep -P0 -fl 2>/dev/null | awk -F '[[:blank:]]' '$1 == 1 { print $2 }' +} + +find_init_ps() { + case $(uname -s) + in + Darwin|NetBSD) + ps -o ucomm= -p 1 2>/dev/null + ;; + FreeBSD) + ps -o command= -p 1 2>/dev/null | cut -d ' ' -f 1 + ;; + OpenBSD) + ps -o command -p 1 2>/dev/null | tail -n +2 | cut -d ' ' -f 1 + ;; + *) + ps -o comm= -p 1 2>/dev/null + ;; + esac +} + +find_init() { + case $(uname -s) + in + Linux|GNU|NetBSD) + find_init_procfs || find_init_pgrep || find_init_ps + ;; + FreeBSD) + find_init_procfs || find_init_ps + ;; + OpenBSD) + find_init_pgrep || find_init_ps + ;; + Darwin|FreeBSD|SunOS) + find_init_ps + ;; + *) + echo "Don't know how to determine init." >&2 + echo 'Please send a patch.' >&2 + exit 1 + esac +} + +validate_by_comm_name() { + case $1 + in + busybox) + validate_busybox_init + ;; + init) + # FIXME: Do some more magic here! + echo init + ;; + openrc-init) + validate_openrc >/dev/null && echo openrc-init + ;; + runit) + validate_runit + ;; + systemd) + validate_systemd + ;; + *) + # Run validate function by comm name if available. + # Fall back to comm name if either it does not exist or + # returns non-zero. + type "validate_$1" >/dev/null && "validate_$1" || echo $1 + esac +} + +try_all() { + # init: it could be anything... + # We try some approaches to gather more information about init without + # calling it! On some init systemd this triggers a reinitialisation of + # the system which we don't want (e.g. embedded systems). + + validate_sysvinit || \ + validate_openrc || \ + validate_runit || \ + validate_smf || \ + validate_upstart || \ + validate_hurd_init || \ + echo init # fallback +} + +init=$(find_init) + +if test -x "${init}" +then + case $init + in + /hurd/init) + # FIXME: Create validate function + echo hurd-init + ;; + */init) + try_all + ;; + *) + validate_by_comm_name "$(basename "${init}")" + ;; + esac +else + validate_by_comm_name "${init}" +fi From 364340c8d5a1bcb6492d6c8cdfbbd808b13b5024 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 20 Feb 2020 21:34:21 +0100 Subject: [PATCH 17/32] [explorer/init] Refactor and testing --- cdist/conf/explorer/init | 392 ++++++++++++++++++++++++++------------- 1 file changed, 267 insertions(+), 125 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index 2d4f07c1..db417a14 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -21,7 +21,7 @@ # # # Returns the name of the init system (PID 1) -# + # Expected values: # Linux: # Adélie Linux: @@ -35,122 +35,221 @@ # Debian: # systemd, upstart, sysvinit, openrc, ??? # Devuan: -# sysvinit, ??? +# sysvinit, sysvinit+openrc # Gentoo: # sysvinit+openrc, openrc-init, systemd # OpenBMC: # systemd # OpenWrt: -# procd, init?? +# procd, init??? # RedHat (RHEL, CentOS, Fedora, RedHat Linux, ...): -# systemd, upstart, sysvinit +# systemd, upstart, upstart-legacy, sysvinit # Slackware: # sysvinit # SuSE: # systemd, sysvinit # Ubuntu: -# systemd, upstart, sysvinit +# systemd, upstart, upstart-legacy, sysvinit +# VoidLinux: +# runit # # GNU: # Debian: -# hurd-init, sysvinit +# sysvinit, hurd-init # # BSD: # {Free,Open,Net}BSD: # init # # Mac OS X: -# launchd, init +# launchd, init+SystemStarter # # Solaris/Illumos: -# smf, init +# smf, init??? +# NOTE: init systems can be stacked. This is popular to run OpenRC on top of +# sysvinit (Gentoo) or busybox-init (Alpine), but can also be used to run runit +# as a systemd service. This makes init system detection very complicated +# (which result is expected?) This script tries to untangle some combinations, +# OpenRC on top of sysv or busybox (X+openrc), but will ignore others (runit as +# a systemd service) + +# NOTE: When we have no idea, nothing will be printed! + +# NOTE: +# When trying to gather information about the init system make sure to do so +# without calling the binary! On some systems this triggers a reinitialisation +# of the system which we don't want (e.g. embedded systems). -# [root@fedora-12 ~]# readlink /proc/1/exe -# /sbin/init (deleted) -# [root@fedora-12 ~]# ls -l /proc/1/exe -# lrwxrwxrwx. 1 root root 0 2020-01-30 23:00 /proc/1/exe -> /sbin/init (deleted) set -e -#set -x # DEBUG -validate_busybox_init() { - # It is quite common to use SysVinit to stack other init systemd +KERNEL_NAME=$(uname -s) + +KNOWN_INIT_SYSTEMS=$(cat </dev/null 2>&1 || return 1 + launchctl getenv PATH >/dev/null || return 1 + echo launchd +} + +check_openrc() { test -f /run/openrc/softlevel || return 1 echo openrc } -validate_procd() { - grep -q 'procd' /sbin/procd || return 1 +check_procd() ( + procd_path=${1:-/sbin/procd} + test -x "${procd_path}" || return 1 + grep -q 'procd' "${procd_path}" || return 1 echo procd -} +) -validate_runit() { +check_runit() { test -d /run/runit || return 1 echo runit } -validate_smf() { +check_smf() { # XXX: Is this the correct way?? test -f /etc/svc/volatile/svc_nonpersist.db || return 1 echo smf } -validate_systemd() { +check_systemd() { # NOTE: sd_booted(3) test -d /run/systemd/system/ || return 1 # systemctl --version | sed -e '/^systemd/!d;s/^systemd //' echo systemd } -validate_sysvinit() { - test -x /sbin/init \ - && grep -q 'INIT_VERSION=sysvinit-[0-9.]*' /sbin/init \ - || return 1 +check_systemstarter() { + test -d /System/Library/StartupItems/ || return 1 + test -f /System/Library/StartupItems/LoginWindow/StartupParameters.plist || return 1 + echo init+SystemStarter +} + +check_sysvinit() ( + init_path=${1:-/sbin/init} + grep -q 'INIT_VERSION=sysvinit-[0-9.]*' "${init_path}" || return 1 # It is quite common to use SysVinit to stack other init systemd # (like OpenRC) on top of it. So we check for that, too. - if stacked=$(validate_openrc) + if stacked=$(check_openrc) then echo "sysvinit+${stacked}" else echo sysvinit fi unset stacked -} +) -validate_upstart() { +check_upstart() { test -x "$(command -v initctl)" || return 1 case $(initctl version) in *'(upstart '*')') - # if type -d /etc/init - # then - # # modern (DBus-based?) upstart >= 0.5 - # : - # elif type -d /etc/events.d - # then - # # ancient upstart - # : - # fi - echo upstart + if test -d /etc/init + then + # modern (DBus-based?) upstart >= 0.5 + echo upstart + elif test -d /etc/event.d + then + # ancient upstart + echo upstart-legacy + else + # whatever... + echo upstart + fi ;; *) return 1 @@ -163,7 +262,7 @@ find_init_procfs() ( test -h /proc/1/exe || return 1 # Find init executable - init_exe=$(ls -l /proc/1/exe 2>/dev/null) + init_exe=$(ls -l /proc/1/exe 2>/dev/null) || return 1 init_exe=${init_exe#* -> } if ! test -x "$init_exe" @@ -171,21 +270,100 @@ find_init_procfs() ( # On some rare occasions it can happen that the # running init's binary has been replaced. In this # case Linux adjusts the symlink to "X (deleted)" - case $init_exe - in - *' (deleted)') - init_exe=${init_exe% (deleted)} - test -x "$init_exe" || exit 1 - ;; - *) - exit 1 - ;; - esac + + # [root@fedora-12 ~]# readlink /proc/1/exe + # /sbin/init (deleted) + # [root@fedora-12 ~]# ls -l /proc/1/exe + # lrwxrwxrwx. 1 root root 0 2020-01-30 23:00 /proc/1/exe -> /sbin/init (deleted) + + init_exe=${init_exe% (deleted)} + test -x "$init_exe" || return 1 fi echo "${init_exe}" ) +guess_by_path() { + case $1 + in + /bin/busybox) + check_busybox_init "$1" && return + ;; + /lib/systemd/systemd) + check_systemd "$1" && return + ;; + /hurd/init) + check_hurd_init "$1" && return + ;; + /sbin/launchd) + check_launchd "$1" && return + ;; + /usr/bin/runit|/sbin/runit) + check_runit "$1" && return + ;; + /sbin/openrc-init) + if check_openrc "$1" >/dev/null + then + echo openrc-init + return + fi + ;; + /sbin/procd) + check_procd && return + ;; + /sbin/init|*/init) + # init: it could be anything -> (explicit) no match + return 1 + ;; + esac + + # No match + return 1 +} + +guess_by_comm_name() { + case $1 + in + busybox) + check_busybox_init && return + ;; + openrc-init) + if check_openrc >/dev/null + then + echo openrc-init + return 0 + fi + ;; + init) + # init could be anything -> no match + return 1 + ;; + *) + # Run check function by comm name if available. + # Fall back to comm name if either it does not exist or + # returns non-zero. + if type "check_$1" >/dev/null + then + "check_$1" && return + else + echo "$1" ; return 0 + fi + esac + + return 1 +} + +check_list() ( + # List must be a multi-line input on stdin (one name per line) + while read init + do + "check_${init}" || continue + return 0 + done + return 1 +) + + # BusyBox's versions of ps and pgrep do not support some options # depending on which compile-time options have been used. @@ -194,25 +372,31 @@ find_init_pgrep() { } find_init_ps() { - case $(uname -s) + case $KERNEL_NAME in - Darwin|NetBSD) - ps -o ucomm= -p 1 2>/dev/null + Darwin) + ps -o command -p 1 2>/dev/null | tail -n +2 ;; FreeBSD) - ps -o command= -p 1 2>/dev/null | cut -d ' ' -f 1 + ps -o args= -p 1 2>/dev/null | cut -d ' ' -f 1 ;; - OpenBSD) - ps -o command -p 1 2>/dev/null | tail -n +2 | cut -d ' ' -f 1 - ;; - *) + Linux) ps -o comm= -p 1 2>/dev/null ;; - esac + NetBSD) + ps -o comm= -p 1 2>/dev/null + ;; + OpenBSD) + ps -o args -p 1 2>/dev/null | tail -n +2 | cut -d ' ' -f 1 + ;; + *) + ps -o args= -p 1 2>/dev/null + ;; + esac | trim # trim trailing whitespace (some ps like Darwin add it) } find_init() { - case $(uname -s) + case $KERNEL_NAME in Linux|GNU|NetBSD) find_init_procfs || find_init_pgrep || find_init_ps @@ -233,65 +417,23 @@ find_init() { esac } -validate_by_comm_name() { - case $1 - in - busybox) - validate_busybox_init - ;; - init) - # FIXME: Do some more magic here! - echo init - ;; - openrc-init) - validate_openrc >/dev/null && echo openrc-init - ;; - runit) - validate_runit - ;; - systemd) - validate_systemd - ;; - *) - # Run validate function by comm name if available. - # Fall back to comm name if either it does not exist or - # returns non-zero. - type "validate_$1" >/dev/null && "validate_$1" || echo $1 - esac -} - -try_all() { - # init: it could be anything... - # We try some approaches to gather more information about init without - # calling it! On some init systemd this triggers a reinitialisation of - # the system which we don't want (e.g. embedded systems). - - validate_sysvinit || \ - validate_openrc || \ - validate_runit || \ - validate_smf || \ - validate_upstart || \ - validate_hurd_init || \ - echo init # fallback -} +# ----- init=$(find_init) -if test -x "${init}" -then - case $init - in - /hurd/init) - # FIXME: Create validate function - echo hurd-init - ;; - */init) - try_all - ;; - *) - validate_by_comm_name "$(basename "${init}")" - ;; - esac -else - validate_by_comm_name "${init}" -fi +# If we got a path, guess by the path first (fall back to file name if no match) +# else guess by file name directly. +{ + test -x "${init}" \ + && guess_by_path "${init}" \ + || guess_by_comm_name "$(basename "${init}")" +} && exit 0 || true + + +# Guessing based on the file path and name didn’t lead to a definitive result. +# +# We go through all of the checks until we find a match. To speed up the +# process, common cases will be checked first based on the underlying kernel. + +{ common_candidates_by_kernel; echo "${KNOWN_INIT_SYSTEMS}"; } \ + | unique | check_list From 0d84c91b4047d3da0571d0262b4b5d9a8f9796b9 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 20 Feb 2020 22:55:46 +0100 Subject: [PATCH 18/32] [explorer/init] Fix unique() for Solaris --- cdist/conf/explorer/init | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index db417a14..0f04a0ee 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -135,7 +135,8 @@ trim() { unique() { # Delete duplicate lines (keeping input order) - awk '!x[$0]++' + # NOTE: Solaris AWK breaks without if/print construct. + awk '{ if (!x[$0]++) print }' } From 0d6bc8e8f8166a3f61dd4da4a0e499499d3702c4 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Thu, 20 Feb 2020 23:29:21 +0100 Subject: [PATCH 19/32] [explorer/init] Make shellcheck happy --- cdist/conf/explorer/init | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cdist/conf/explorer/init b/cdist/conf/explorer/init index 0f04a0ee..1b921c68 100755 --- a/cdist/conf/explorer/init +++ b/cdist/conf/explorer/init @@ -310,7 +310,7 @@ guess_by_path() { fi ;; /sbin/procd) - check_procd && return + check_procd "$1" && return ;; /sbin/init|*/init) # init: it could be anything -> (explicit) no match @@ -356,7 +356,7 @@ guess_by_comm_name() { check_list() ( # List must be a multi-line input on stdin (one name per line) - while read init + while read -r init do "check_${init}" || continue return 0 @@ -408,7 +408,7 @@ find_init() { OpenBSD) find_init_pgrep || find_init_ps ;; - Darwin|FreeBSD|SunOS) + Darwin|SunOS) find_init_ps ;; *) @@ -424,6 +424,7 @@ init=$(find_init) # If we got a path, guess by the path first (fall back to file name if no match) # else guess by file name directly. +# shellcheck disable=SC2015 { test -x "${init}" \ && guess_by_path "${init}" \ From 49fc21ec47d665155edac73bdbae4fed9258f382 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Sun, 23 Feb 2020 09:32:03 +0100 Subject: [PATCH 20/32] ++changelog --- docs/changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/changelog b/docs/changelog index b0ebf789..8463bb89 100644 --- a/docs/changelog +++ b/docs/changelog @@ -4,6 +4,9 @@ Changelog next: * Type __update_alternatives: Add state explorer (Ander Punnar) * Explorer os_version: Add support for Alpine Linux (Jin-Guk Kwon) + * Explorer init: Rewrite and support more init systems (Dennis Camera) + * New type: __service (Timothée Floure) + * Types __consul_*: Add optional parameter for using distribution packages (Timothée Floure) 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) From c6aba8d189c2efc7c88f9c595acba7ceae5a4e00 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 23 Feb 2020 22:59:41 +0100 Subject: [PATCH 21/32] [explorer/disks] Fix for NetBSD When connecting over SSH and running /bin/sh, the PATH is missing sbin locations. sysctl is located at /sbin/sysctl on NetBSD. --- cdist/conf/explorer/disks | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cdist/conf/explorer/disks b/cdist/conf/explorer/disks index 87a6b5c6..08290bc7 100755 --- a/cdist/conf/explorer/disks +++ b/cdist/conf/explorer/disks @@ -1,14 +1,20 @@ -#!/bin/sh +#!/bin/sh -e uname_s="$(uname -s)" -case "${uname_s}" in +case $uname_s in FreeBSD) sysctl -n kern.disks ;; - OpenBSD|NetBSD) + OpenBSD) sysctl -n hw.disknames | grep -Eo '[lsw]d[0-9]+' | xargs ;; + NetBSD) + PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin" + sysctl -n hw.disknames \ + | awk 'BEGIN { RS = " " } /^[lsw]d[0-9]+/' \ + | xargs + ;; Linux) if command -v lsblk > /dev/null then @@ -23,5 +29,3 @@ case "${uname_s}" in printf "Don't know how to list disks for %s operating system, if you can please submit a patch\n" "${uname_s}" >&2 ;; esac - -exit 0 From e6f683b88633fa0722b3787e3daa39db640ce0f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Floure?= Date: Mon, 24 Feb 2020 09:20:49 +0100 Subject: [PATCH 22/32] Add support for alpine (edge) package to __consul_agent --- cdist/conf/type/__consul_agent/manifest | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cdist/conf/type/__consul_agent/manifest b/cdist/conf/type/__consul_agent/manifest index 40667002..0d819d45 100755 --- a/cdist/conf/type/__consul_agent/manifest +++ b/cdist/conf/type/__consul_agent/manifest @@ -61,6 +61,17 @@ distribution_setup () { user='consul' group='consul' ;; + alpine) + # consul is only available starting Alpine 3.12 (= edge during the 3.11 cycle). + # See https://pkgs.alpinelinux.org/packages?name=consul&branch=edge + + # Override previously defined environment to match alpine packaging. + conf_dir='/etc/consul' + conf_file='server.json' + data_dir='/var/consul' + user='consul' + group='consul' + ;; *) echo "Your operating system ($os) is currently not supported with the \ --use-distribution-package flag (${__type##*/})." >&2 From d3bd2669ec49fb861016e614893dac280ed5fd35 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 23 Feb 2020 23:07:40 +0100 Subject: [PATCH 23/32] [explorer/disks] Support Linux without lsblk (fallback to sysfs) --- cdist/conf/explorer/disks | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/cdist/conf/explorer/disks b/cdist/conf/explorer/disks index 08290bc7..0fabc95f 100755 --- a/cdist/conf/explorer/disks +++ b/cdist/conf/explorer/disks @@ -16,16 +16,33 @@ case $uname_s in | xargs ;; Linux) - if command -v lsblk > /dev/null + # list of major device numbers toexclude: + # ram disks, floppies, cdroms + # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt + ign_majors='1 2 11' + + if command -v lsblk >/dev/null 2>&1 then - # exclude ram disks, floppies and cdroms - # https://www.kernel.org/doc/Documentation/admin-guide/devices.txt - lsblk -e 1,2,11 -dno name | xargs + lsblk -e "$(echo "$ign_majors" | tr ' ' ',')" -dno name | xargs + elif test -d /sys/block/ + then + # shellcheck disable=SC2012 + ls -1 /sys/block/ \ + | awk -v ign_majors="$(echo "$ign_majors" | tr ' ' '|')" ' + { + devfile = "/sys/block/" $0 "/dev" + getline devno < devfile + close(devfile) + if (devno !~ "^(" ign_majors "):") print + }' \ + | xargs else - printf "Don't know how to list disks for %s operating system without lsblk, if you can please submit a patch\n" "${uname_s}" >&2 + echo "Don't know how to list disks on Linux without lsblk and sysfs." >&2 + echo 'If you can, please submit a patch.'>&2 fi ;; *) - printf "Don't know how to list disks for %s operating system, if you can please submit a patch\n" "${uname_s}" >&2 + printf "Don't know how to list disks for %s operating system.\n" "${uname_s}" >&2 + printf 'If you can please submit a patch\n' >&2 ;; esac From 1ef126e16f95e822562978abd895a3c036f7d5c4 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 23 Feb 2020 23:08:40 +0100 Subject: [PATCH 24/32] [explorer/disks] Move xargs call to the bottom --- cdist/conf/explorer/disks | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cdist/conf/explorer/disks b/cdist/conf/explorer/disks index 0fabc95f..ed1afce4 100755 --- a/cdist/conf/explorer/disks +++ b/cdist/conf/explorer/disks @@ -7,13 +7,12 @@ case $uname_s in sysctl -n kern.disks ;; OpenBSD) - sysctl -n hw.disknames | grep -Eo '[lsw]d[0-9]+' | xargs + sysctl -n hw.disknames | grep -Eo '[lsw]d[0-9]+' ;; NetBSD) PATH="${PATH}:/usr/local/sbin:/usr/sbin:/sbin" sysctl -n hw.disknames \ - | awk 'BEGIN { RS = " " } /^[lsw]d[0-9]+/' \ - | xargs + | awk 'BEGIN { RS = " " } /^[lsw]d[0-9]+/' ;; Linux) # list of major device numbers toexclude: @@ -23,7 +22,7 @@ case $uname_s in if command -v lsblk >/dev/null 2>&1 then - lsblk -e "$(echo "$ign_majors" | tr ' ' ',')" -dno name | xargs + lsblk -e "$(echo "$ign_majors" | tr ' ' ',')" -dno name elif test -d /sys/block/ then # shellcheck disable=SC2012 @@ -34,8 +33,7 @@ case $uname_s in getline devno < devfile close(devfile) if (devno !~ "^(" ign_majors "):") print - }' \ - | xargs + }' else echo "Don't know how to list disks on Linux without lsblk and sysfs." >&2 echo 'If you can, please submit a patch.'>&2 @@ -45,4 +43,5 @@ case $uname_s in printf "Don't know how to list disks for %s operating system.\n" "${uname_s}" >&2 printf 'If you can please submit a patch\n' >&2 ;; -esac +esac \ +| xargs From 6db6dc4ac0950579ce13252dcca6d0f61f5533c6 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 23 Feb 2020 23:14:14 +0100 Subject: [PATCH 25/32] [explorer/disks] Add license header --- cdist/conf/explorer/disks | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cdist/conf/explorer/disks b/cdist/conf/explorer/disks index ed1afce4..24540601 100755 --- a/cdist/conf/explorer/disks +++ b/cdist/conf/explorer/disks @@ -1,4 +1,24 @@ #!/bin/sh -e +# +# based on previous work by other people, modified by: +# 2020 Dennis Camera +# +# This file is part of cdist. +# +# cdist is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# cdist is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with cdist. If not, see . +# +# Finds disks of the system (excl. ram disks, floppy, cdrom) uname_s="$(uname -s)" From b2db864eaf95a50e7e0d31be52f86ab1d0bea480 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Wed, 26 Feb 2020 13:01:29 +0100 Subject: [PATCH 26/32] ++changelog --- docs/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog b/docs/changelog index 8463bb89..35590655 100644 --- a/docs/changelog +++ b/docs/changelog @@ -7,6 +7,7 @@ next: * Explorer init: Rewrite and support more init systems (Dennis Camera) * New type: __service (Timothée Floure) * Types __consul_*: Add optional parameter for using distribution packages (Timothée Floure) + * Explorer disks: Fix NetBSD, support Linux w/o lsblk (Dennis Camera) 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) From 6b4b6534a1187e2533f627ff485873aeac7c4a32 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 26 Feb 2020 16:12:21 +0100 Subject: [PATCH 27/32] [__directory] Give more precise error message when --state pre-exists --- cdist/conf/type/__directory/gencode-remote | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/cdist/conf/type/__directory/gencode-remote b/cdist/conf/type/__directory/gencode-remote index e1ab69d7..a1a32ea2 100755 --- a/cdist/conf/type/__directory/gencode-remote +++ b/cdist/conf/type/__directory/gencode-remote @@ -109,10 +109,24 @@ case "$state_should" in done ;; pre-exists) - if [ "$type" != "directory" ]; then - echo "Directory \"$destination\" does not exist" >&2 - exit 1 - fi + case $type in + directory) + # all good + exit 0 + ;; + none) + printf 'Directory "%s" does not exist\n' "$destination" >&2 + exit 1 + ;; + file|symlink) + printf 'File "%s" exists and is a %s, but should be a directory\n' "$destination" "$type" >&2 + exit 1 + ;; + *) + printf 'File or directory "%s" is in an unknown state\n' "$destination" >&2 + exit 1 + ;; + esac ;; absent) if [ "$type" = "directory" ]; then From 046f7d0663fb6e117f76747bf71c7976abc90962 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Wed, 26 Feb 2020 16:32:03 +0100 Subject: [PATCH 28/32] ++changelog --- docs/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog b/docs/changelog index 35590655..4fdfcd68 100644 --- a/docs/changelog +++ b/docs/changelog @@ -8,6 +8,7 @@ next: * New type: __service (Timothée Floure) * Types __consul_*: Add optional parameter for using distribution packages (Timothée Floure) * Explorer disks: Fix NetBSD, support Linux w/o lsblk (Dennis Camera) + * Type __directory: Add 'exists' and 'pre-exists' states (Dennis Camera) 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) From 46d2487f08e04d3f6f3cbd434404dda006e83276 Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 26 Feb 2020 16:40:53 +0100 Subject: [PATCH 29/32] [__file] Give more precise error message when --state pre-exists --- cdist/conf/type/__file/gencode-local | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/cdist/conf/type/__file/gencode-local b/cdist/conf/type/__file/gencode-local index fb9f9a92..231b6927 100755 --- a/cdist/conf/type/__file/gencode-local +++ b/cdist/conf/type/__file/gencode-local @@ -31,12 +31,24 @@ if [ "$state_should" = "pre-exists" ]; then exit 1 fi - if [ "$type" = "file" ]; then - exit 0 # nothing to do - else - echo "File \"$destination\" does not exist" - exit 1 - fi + case $type in + file) + # nothing to do + exit 0 + ;; + none) + printf 'File "%s" does not exist\n' "$destination" >&2 + exit 1 + ;; + directory|symlink) + printf 'File "%s" exists and is a %s, but should be a regular file\n' "$destination" "$type" >&2 + exit 1 + ;; + *) + printf 'File or directory "%s" is in an unknown state\n' "$destination" >&2 + exit 1 + ;; + esac fi upload_file= From 9eacba06bb218bd0627ef633b363495331ac6c5b Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Wed, 26 Feb 2020 16:48:14 +0100 Subject: [PATCH 30/32] [__file] Treat pre-exists as a special case in gencode-remote as it should never get there --- cdist/conf/type/__file/gencode-remote | 56 ++++++++++++++------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/cdist/conf/type/__file/gencode-remote b/cdist/conf/type/__file/gencode-remote index b04c471e..815593bd 100755 --- a/cdist/conf/type/__file/gencode-remote +++ b/cdist/conf/type/__file/gencode-remote @@ -55,37 +55,41 @@ set_owner() { } set_mode() { - echo "chmod '$1' '$destination'" - echo "chmod '$1'" >> "$__messages_out" - fire_onchange=1 + echo "chmod '$1' '$destination'" + echo "chmod '$1'" >> "$__messages_out" + fire_onchange=1 } case "$state_should" in - present|exists|pre-exists) - # Note: Mode - needs to happen last as a chown/chgrp can alter mode by - # clearing S_ISUID and S_ISGID bits (see chown(2)) - for attribute in group owner mode; do - if [ -f "$__object/parameter/$attribute" ]; then - value_should="$(cat "$__object/parameter/$attribute")" + present|exists) + # Note: Mode - needs to happen last as a chown/chgrp can alter mode by + # clearing S_ISUID and S_ISGID bits (see chown(2)) + for attribute in group owner mode; do + if [ -f "$__object/parameter/$attribute" ]; then + value_should="$(cat "$__object/parameter/$attribute")" - # change 0xxx format to xxx format => same as stat returns - if [ "$attribute" = mode ]; then - value_should="$(echo "$value_should" | sed 's/^0\(...\)/\1/')" - fi - - value_is="$(get_current_value "$attribute" "$value_should")" - if [ -f "$__object/files/set-attributes" ] || [ "$value_should" != "$value_is" ]; then - "set_$attribute" "$value_should" + # change 0xxx format to xxx format => same as stat returns + if [ "$attribute" = mode ]; then + value_should="$(echo "$value_should" | sed 's/^0\(...\)/\1/')" + fi + + value_is="$(get_current_value "$attribute" "$value_should")" + if [ -f "$__object/files/set-attributes" ] || [ "$value_should" != "$value_is" ]; then + "set_$attribute" "$value_should" + fi fi + done + if [ -f "$__object/files/set-attributes" ]; then + # set-attributes is created if file is created or uploaded in gencode-local + fire_onchange=1 fi - done - if [ -f "$__object/files/set-attributes" ]; then - # set-attributes is created if file is created or uploaded in gencode-local - fire_onchange=1 - fi - ;; + pre-exists) + # pre-exists should never reach gencode-remote… + exit 1 + ;; + absent) if [ "$type" = "file" ]; then echo "rm -f '$destination'" @@ -101,7 +105,7 @@ case "$state_should" in esac if [ -f "$__object/parameter/onchange" ]; then - if [ -n "$fire_onchange" ]; then - cat "$__object/parameter/onchange" - fi + if [ -n "$fire_onchange" ]; then + cat "$__object/parameter/onchange" + fi fi From da6ccf808ef4417b90e0882abd042f0a40f28a8e Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Wed, 26 Feb 2020 21:48:08 +0100 Subject: [PATCH 31/32] ++changelog --- docs/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog b/docs/changelog index 4fdfcd68..9075cf3f 100644 --- a/docs/changelog +++ b/docs/changelog @@ -9,6 +9,7 @@ next: * Types __consul_*: Add optional parameter for using distribution packages (Timothée Floure) * Explorer disks: Fix NetBSD, support Linux w/o lsblk (Dennis Camera) * Type __directory: Add 'exists' and 'pre-exists' states (Dennis Camera) + * Type __file: Improve error messages for pre-exists state (Dennis Camera) 6.5.1: 2020-02-15 * Type __consul_agent: Add Debian 10 support (Nico Schottelius) From 213f1b049c55205ffe233de22e68c4a4738c8b82 Mon Sep 17 00:00:00 2001 From: Darko Poljak Date: Thu, 27 Feb 2020 20:23:04 +0100 Subject: [PATCH 32/32] Release 6.5.2 --- docs/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog b/docs/changelog index 9075cf3f..64b124e8 100644 --- a/docs/changelog +++ b/docs/changelog @@ -1,7 +1,7 @@ Changelog --------- -next: +6.5.2: 2020-02-27 * Type __update_alternatives: Add state explorer (Ander Punnar) * Explorer os_version: Add support for Alpine Linux (Jin-Guk Kwon) * Explorer init: Rewrite and support more init systems (Dennis Camera)