diff options
-rw-r--r-- | CHANGELOG.md | 61 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | lib/main.bash | 17 | ||||
-rw-r--r-- | lib/subcommands/backup.bash | 4 | ||||
-rw-r--r-- | lib/subcommands/del.bash | 6 | ||||
-rw-r--r-- | lib/subcommands/pull.bash | 2 | ||||
-rw-r--r-- | lib/subcommands/sysinfo.bash | 69 | ||||
-rw-r--r-- | lib/subcommands/top.bash | 113 | ||||
-rw-r--r-- | lib/subcommands/zap.bash | 37 | ||||
-rw-r--r-- | lib/util.bash | 48 | ||||
-rw-r--r-- | lib/util/config.bash | 34 | ||||
-rw-r--r-- | lib/util/pkg.bash | 18 | ||||
-rw-r--r-- | lib/util/svc.bash | 107 | ||||
-rw-r--r-- | share/doc/bashtard.1.scd | 10 |
14 files changed, 486 insertions, 58 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 78cf85f..1680fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ <!-- -SPDX-FileCopyrightText: 2023 Patrick Spek <p.spek@tyil.nl> +SPDX-FileCopyrightText: 2024 Patrick Spek <p.spek@tyil.nl> SPDX-License-Identifier: AGPL-3.0-or-later --> @@ -11,7 +11,57 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [UNRELEASED] + +### Fixed + +- `config_subkeys` and `config_subkeys_for` should now leave off the `&` at the + end of a variable names which are references. + +## [2.1.0] - 2024-04-02 + +### Added + +- Configuration variables can be assigned values of other variables with the + `&=` assignment. This allows a single value to be re-used dynamically, rather + than having to explicitly set the same value several times. +- A `zap` command has been added to remove a playbook from the registry without + running the playbook's `playbook_del()` function. This is intended to easily + remove registry entries when a playbook itself has been deleted or is + otherwise broken in a way that the regular `del` subcommand cannot fix. + +### Changed + +- The `description.txt` is now allowed to be used without the `.txt` suffix. + Usage with the `.txt` suffix continues to be supported as well. + +### Fixed + +- Passing an empty string as default value to `config` should now properly + return an empty string without a warning about the configuration key not + existing. + +## [2.0.2] - 2024-02-28 + +### Fixed + +- Configuration values with `=` in their value part should now work properly + with `file_template`. Keys with `=` in them are still *not supported*. + +## [2.0.1] - 2023-09-25 + +### Added + +- A new `make` target has been added to build a .tar.gz distributable. + +### Changed + +- The `svc_` utils should now check which init service you're using when using a + linux system. The supported options are still only openrc and systemd. +- The `pull` subcommand should now properly return with exit-code 0 if no + problem were encountered. + +## [2.0.0] - 2023-05-22 ### Added @@ -28,6 +78,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 GNU+Linux distributions. - The `$BASHTARD_PLATFORM` variable now contains an additional entry, `init`, to allow for handling different init systems on GNU+Linux in a cleaner fashion. +- A `file_hash` utility function has been added. It currently uses `md5`, but is + written in such a fashion that this can easily be updated for the future. Its + intent is to encapsulate differences between naming and usage of hashing + utilities found on different systems. - A `dir_hash` utility function has been added, which will give you a hash based on the file contents of a directory. This function will find files recursively, calculate a hash for each of them, and then calculate a hash @@ -49,6 +103,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 which in turn should make re-using playbooks easier. - A convenience function has been introduced, `playbook_path()`, which can give you the absolute path to the playbook's base or data directory. +- A `top` subcommand has been added to give some generic information of all + nodes known to Bashtard. It uses information from the `sysinfo` subcommand, + which it will pull in through an `ssh` invocation. ### Changed @@ -9,9 +9,10 @@ ETCDIR=/etc # Variables for building (binary) packages PREFIX= -PKG_VERSION=0.0.0 +PKG_VERSION=2.1.0 PKG_WORKDIR:=$(or $(PKG_WORKDIR),$(shell mktemp -d)) PKG_ROOT:=$(PKG_WORKDIR)/bashtard-$(PKG_VERSION) +SOURCE_DATE_EPOCH:=$(shell git show -s --format=%ct) rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d)) @@ -76,6 +77,21 @@ pkg-debian: mkdir -pv -- "dist" dpkg-deb -b "$(PKG_ROOT)" "dist/bashtard-$(PKG_VERSION).deb" +pkg-targz: + mkdir -pv -- "dist" + tar \ + --exclude dist \ + --group=0 \ + --mtime="@$(SOURCE_DATE_EPOCH)" \ + --numeric-owner \ + --owner=0 \ + --pax-option="exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" \ + --sort=name \ + --transform "s@^./@bashtard-$(PKG_VERSION)/@" \ + --exclude-vcs \ + --exclude-vcs-ignores \ + -cvzf "dist/bashtard-$(PKG_VERSION).tar.gz" . + qa: # Check licenses reuse lint diff --git a/lib/main.bash b/lib/main.bash index db5832e..821c2d2 100644 --- a/lib/main.bash +++ b/lib/main.bash @@ -86,8 +86,10 @@ Usage: $BASHTARD_NAME ssh <command> $BASHTARD_NAME sync [playbook] $BASHTARD_NAME sysinfo + $BASHTARD_NAME top $BASHTARD_NAME var [-p <playbook>] <key> $BASHTARD_NAME var [-s] <key> <value> + $BASHTARD_NAME zap <playbook> Perform maintenance on your infra. @@ -102,7 +104,10 @@ Commands: sync Pull latest changes through git, and synchronize all added playbooks. sysinfo Show gathered information about this system. + top Show resource information about all known hosts. var Show or set the value of a given configuration key. + zap Remove a playbook from the registry without attempting to run + the delete step from the playbook. EOF if [[ ! -d "$BASHTARD_ETCDIR/playbooks.d" ]] @@ -133,9 +138,19 @@ EOF # Render playbook descriptions for playbook in "${playbooks[@]}" do + local description="" + + if [[ -f "$playbook/description.txt" ]] + then + description="$(cat "$playbook/description.txt")" + elif [[ -f "$playbook/description" ]] + then + description="$(cat "$playbook/description")" + fi + printf "\t%-${playbook_longest}s %s\n" \ "$(basename "$playbook")" \ - "$(cat "$playbook/description.txt")" + "$description" done } diff --git a/lib/subcommands/backup.bash b/lib/subcommands/backup.bash index 8048053..3d56539 100644 --- a/lib/subcommands/backup.bash +++ b/lib/subcommands/backup.bash @@ -72,7 +72,7 @@ backup_filesystem() { "--keep-weekly" "$(config "bashtard.backup.keep.weekly")" "--keep-monthly" "$(config "bashtard.backup.keep.monthly")" "--keep-yearly" "$(config "bashtard.backup.keep.yearly")" - "--prefix" "{fqdn}-" + "--glob-archives" "${BASHTARD_PLATFORM[fqdn]}-" "--remote-path" "$remote" "$repo/hostfs" ) @@ -144,7 +144,7 @@ backup_database_postgresql() { "--keep-weekly" "$(config "bashtard.backup.keep.weekly")" "--keep-monthly" "$(config "bashtard.backup.keep.monthly")" "--keep-yearly" "$(config "bashtard.backup.keep.yearly")" - "--prefix" "$database-" + "--glob-archives" "$database-" "--remote-path" "$remote" "$repo/postgresql-$database" ) diff --git a/lib/subcommands/del.bash b/lib/subcommands/del.bash index 3649e69..293e401 100644 --- a/lib/subcommands/del.bash +++ b/lib/subcommands/del.bash @@ -24,7 +24,7 @@ subcommand() # Make sure we only run add if the playbook is not in the registry yet if ! grep -Fqx "$BASHTARD_PLAYBOOK" "$playbook_registry" then - crit "bashtard/add" "'$BASHTARD_PLAYBOOK' is not registered for ${BASHTARD_PLATFORM[fqdn]}" + crit "bashtard/del" "'$BASHTARD_PLAYBOOK' is not registered for ${BASHTARD_PLATFORM[fqdn]}" return 3 fi @@ -32,13 +32,13 @@ subcommand() if [[ ! -d "$playbook_base" ]] then - emerg "bashtard/sync" "No such directory: $playbook_base" + emerg "bashtard/del" "No such directory: $playbook_base" return 1 fi if [[ ! -f "$playbook_base/playbook.bash" ]] then - emerg "bashtard/sync" "No such file: $playbook_base/playbook.bash" + emerg "bashtard/del" "No such file: $playbook_base/playbook.bash" return 1 fi diff --git a/lib/subcommands/pull.bash b/lib/subcommands/pull.bash index 4f2ae99..8dfb48b 100644 --- a/lib/subcommands/pull.bash +++ b/lib/subcommands/pull.bash @@ -19,4 +19,6 @@ subcommand() git -C "$BASHTARD_ETCDIR" pull origin master || return 4 git -C "$BASHTARD_ETCDIR" submodule update --init --recursive || return 4 [[ -n $dirty ]] && git -C "$BASHTARD_ETCDIR" stash pop + + return 0 } diff --git a/lib/subcommands/sysinfo.bash b/lib/subcommands/sysinfo.bash index 8aa237e..4bceb42 100644 --- a/lib/subcommands/sysinfo.bash +++ b/lib/subcommands/sysinfo.bash @@ -5,12 +5,81 @@ # SPDX-License-Identifier: AGPL-3.0-or-later subcommand() { + local load_1 + local load_5 + local load_15 + local memory_free + local memory_total + local memory_used + local storage_free + local storage_total + local storage_used + local uptime + + # Set the variables which are compatible on every POSIX-compliant system + storage_used="$(df | awk '/[0-9]+/ { sum += $3 } END { print sum }')" + storage_free="$(df | awk '/[0-9]+/ { sum += $4 } END { print sum }')" + storage_total=$(( storage_used + storage_free )) + + # And do platform-specific magic + case "${BASHTARD_PLATFORM[os]}" in + freebsd) + load_1="$(uptime | awk -F' *,? *' '{ print $(NF-2) }')" + load_5="$(uptime | awk -F' *,? *' '{ print $(NF-1) }')" + load_15="$(uptime | awk -F' *,? *' '{ print $NF }')" + memory_total=$(( $(sysctl -n hw.physmem) / 1024 )) + memory_used=$(( ( $(sysctl -n vm.stats.vm.v_active_count) * $(sysctl -n hw.pagesize) ) / 1024 )) + memory_free=$(( memory_total - memory_used)) + uptime=$(( "$(date +%s)" - "$(sysctl -a | awk '/^kern.boottime/ { print substr($5, 0, length($5)-1) }')" )) + ;; + *) + load_1="$(awk '{ print $1 }' < /proc/loadavg)" + load_5="$(awk '{ print $2 }' < /proc/loadavg)" + load_15="$(awk '{ print $3 }' < /proc/loadavg)" + memory_total="$(awk '/MemTotal/ { print $2 }' < /proc/meminfo)" + memory_free="$(awk '/MemAvailable/ { print $2 }' < /proc/meminfo)" + memory_used=$(( memory_total - memory_free )) + uptime="$(awk -F. '{ print $1 }' < /proc/uptime)" + ;; + esac + + # For any value that isn't set, just default to 0 to avoid all sorts of errors + [[ -z "$load_1" ]] && load_1=0 + [[ -z "$load_5" ]] && load_5=0 + [[ -z "$load_15" ]] && load_15=0 + [[ -z "$memory_free" ]] && memory_free=0 + [[ -z "$memory_total" ]] && memory_total=0 + [[ -z "$memory_used" ]] && memory_used=0 + [[ -z "$storage_free" ]] && storage_free=0 + [[ -z "$storage_total" ]] && storage_total=0 + [[ -z "$storage_used" ]] && storage_used=0 + [[ -z "$uptime" ]] && uptime=0 + + # Print the values that can be set by package maintainers printf "%-15s %s\n" "etcdir" "$BASHTARD_ETCDIR" printf "%-15s %s\n" "libdir" "$BASHTARD_LIBDIR" printf "%-15s %s\n" "sharedir" "$BASHTARD_SHAREDIR" + # Print all the discovered platform information for key in "${!BASHTARD_PLATFORM[@]}" do printf "%-15s %s\n" "$key" "${BASHTARD_PLATFORM[$key]}" done + + # Print fun little extras + printf "%-15s %0.1fGi / %0.1fGi\n" "memory" \ + "$(awk '{ print($1 / 1024 / 1024) }' <<< "$memory_used")" \ + "$(awk '{ print($1 / 1024 / 1024) }' <<< "$memory_total")" + printf "%-15s %0.1fGb / %0.1fGb\n" "storage" \ + "$(awk '{ print($1 / 1024 / 1024) }' <<< "$storage_used")" \ + "$(awk '{ print($1 / 1024 / 1024) }' <<< "$storage_total")" + printf "%-15s %0.2f %0.2f %0.2f\n" "load" \ + "$load_1" \ + "$load_5" \ + "$load_15" + printf "%-15s %dd %02dh %02dm %02ds\n" "uptime" \ + "$(( uptime / 60 / 60 / 24 ))" \ + "$(( uptime / 60 / 60 % 24 ))" \ + "$(( uptime / 60 % 60 ))" \ + "$(( uptime % 60 ))" } diff --git a/lib/subcommands/top.bash b/lib/subcommands/top.bash new file mode 100644 index 0000000..d4a9b3f --- /dev/null +++ b/lib/subcommands/top.bash @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2023 Patrick Spek <p.spek@tyil.nl> +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +subcommand() +{ + local results + local widths + + declare -A results + declare -A widths=( + [load]=0 + [memory]=0 + [node]=0 + [storage]=0 + [uptime]=0 + ) + + if [[ ! -d "$BASHTARD_ETCDIR/hosts.d" ]] + then + crit "$BASHTARD_NAME/ssh" "Could not find hosts file at $BASHTARD_ETCDIR/hosts.d" + return 3 + fi + + chgdir "$BASHTARD_ETCDIR/hosts.d" + + for node in * + do + local user + local host + + user="$(config_for "$node" "bashtard.ssh.user" "$USER")" + host="$(config_for "$node" "bashtard.ssh.host")" + + if [[ -z "$host" ]] + then + crit "$BASHTARD_NAME/ssh" "bashtard.ssh.host is not configured for $node" + continue + fi + + if [[ "$node" == "${BASHTARD_PLATFORM[fqdn]}" ]] + then + results+=(["$node"]="$("$BASHTARD_BIN" sysinfo)") + else + debug "$BASHTARD_NAME/ssh" "$user@$node ($host) > bashtard sysinfo" + # shellcheck disable=SC2029 + results+=(["$node"]="$(ssh "$user@$host" "bashtard sysinfo" 2>/dev/null)") + fi + + unset user + unset host + done + + # Check widths + for node in "${!results[@]}" + do + node_load="$(grep '^load' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" + node_memory="$(grep '^memory' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" + node_storage="$(grep '^storage' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" + node_uptime="$(grep '^uptime' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" + + width_load="$(wc -c <<< "$node_load")" + width_memory="$(wc -c <<< "$node_memory")" + width_node="$(wc -c <<< "$node")" + width_storage="$(wc -c <<< "$node_storage")" + width_uptime="$(wc -c <<< "$node_uptime")" + + if (( widths[load] < width_load )) + then + widths[load]=$width_load + fi + + if (( widths[memory] < width_memory )) + then + widths[memory]=$width_memory + fi + + if (( widths[node] < width_node )) + then + widths[node]=$width_node + fi + + if (( widths[storage] < width_storage )) + then + widths[storage]=$width_storage + fi + + if (( widths[uptime] < width_uptime )) + then + widths[uptime]=$width_uptime + fi + done + + # Print results + printf "$(tput bold)%-${widths[node]}s %-${widths[load]}s %-${widths[memory]}s %-${widths[storage]}s %-${widths[uptime]}s$(tput sgr0)\n" \ + "Node" \ + "Load" \ + "Memory" \ + "Storage" \ + "Uptime" + + for node in "${!results[@]}" + do + printf "%-${widths[node]}s %${widths[load]}s %${widths[memory]}s %${widths[storage]}s %${widths[uptime]}s\n" \ + "$node" \ + "$(grep '^load' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" \ + "$(grep '^memory' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" \ + "$(grep '^storage' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" \ + "$(grep '^uptime' <<< "${results["$node"]}" | sed 's/[^ ]* *//')" + done | sort +} diff --git a/lib/subcommands/zap.bash b/lib/subcommands/zap.bash new file mode 100644 index 0000000..dcefffd --- /dev/null +++ b/lib/subcommands/zap.bash @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2023 Patrick Spek <p.spek@tyil.nl> +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +subcommand() +{ + local buffer + local playbook_registry + + export BASHTARD_PLAYBOOK="$1" ; shift + + if [[ -z "$BASHTARD_PLAYBOOK" ]] + then + crit "bashtard/zap" "No playbook name specified" + return + fi + + playbook_registry="$BASHTARD_ETCDIR/registry.d/${BASHTARD_PLATFORM[fqdn]}" + + # Make sure we only run add if the playbook is not in the registry yet + if ! grep -Fqx "$BASHTARD_PLAYBOOK" "$playbook_registry" + then + crit "bashtard/zap" "'$BASHTARD_PLAYBOOK' is not registered for ${BASHTARD_PLATFORM[fqdn]}" + return 3 + fi + + notice "bashtard/zap" "Removing playbook '$BASHTARD_PLAYBOOK' from '${BASHTARD_PLATFORM[fqdn]}'" + + buffer="$(tmpfile)" + + # Remove the playbook from the registry + cp -- "$playbook_registry" "$buffer" + grep -Fvx "$BASHTARD_PLAYBOOK" "$buffer" \ + | sort > "$playbook_registry" +} diff --git a/lib/util.bash b/lib/util.bash index 54ec562..ad84247 100644 --- a/lib/util.bash +++ b/lib/util.bash @@ -18,6 +18,11 @@ chgdir() { cd -- "$1" || die "Failed to change directory to $1" } +# Removes whitespace surrounding a given text. +chomp() { + awk '{$1=$1};1' <<< "$@" +} + # Create a datetime stamp. This is a wrapper around the date utility, ensuring # that the date being formatted is always in UTC and respect SOURCE_DATE_EPOCH, # if it is set. @@ -61,9 +66,19 @@ die() { # in a directory. It can be used to check whether contents changed after # templating files in a given directory. dir_hash() { - find "$1" -type f -exec sha1sum {} \; \ - | sha1sum \ - | awk '{ print $1 }' + local path + + path="$1" ; shift + + for entry in "$path"/* + do + if [[ -d "$entry" ]] + then + dir_hash "$entry" + fi + + file_hash "$entry" + done | file_hash - } # Fetch a file from an URL. Using this function introduces a dependency on curl. @@ -106,6 +121,25 @@ fetch_http_wget() { wget --quiet --output-document "$2" "$1" } +# Hash a given file. This is a convenience function to work around different +# systems calling their file hashing programs differently, and generating +# different output. This function only expects 1 file as argument, and only +# outputs the hash of this particular file. +file_hash() { + file_hash_md5 "$@" +} + +file_hash_md5() { + local file + + file="$1" ; shift + + case "${BASHTARD_PLATFORM[key]}" in + freebsd) md5 "$file" | awk '{ print $NF }' ;; + linux-*) md5sum "$file" | awk '{ print $1 }' ;; + esac +} + # A very simple means of templating a file, using sed and awk. The template # file is assumed to exist within the share directory of the current playbook. # Variables are passed as key=value pairs to this function. Inside the @@ -128,18 +162,18 @@ file_template() do debug "bashtard/template" "Adding $kv to sedfile at $sedfile" - key="$(awk -F= '{ print $1 }' <<< "$kv")" + key="$(cut -d'=' -f -1 <<< "$kv")" if [[ -z "$key" ]] then - crit "bashtard/template" "Empty key in '$kv' while rendering $file?" + crit "bashtard/template" "Empty key in '$kv' while rendering $file" fi - value="$(awk -F= '{ print $NF }' <<< "$kv")" + value="$(cut -d'=' -f 2- <<< "$kv")" if [[ -z "$value" ]] then - crit "bashtard/template" "Empty key in '$kv' while rendering $file?" + crit "bashtard/template" "Empty key in '$kv' while rendering $file" fi # shellcheck disable=SC2016 diff --git a/lib/util/config.bash b/lib/util/config.bash index 4727706..ff20bd0 100644 --- a/lib/util/config.bash +++ b/lib/util/config.bash @@ -17,7 +17,11 @@ config_subkeys() { config_for() { local host=$1 ; shift local key=$1 ; shift - local default=$1 ; shift + + # Use a variable definition test to define default, in order to ensure + # it is _not_ defined if no argument for it was passed, but _is_ + # defined even if an empty string was passed. + test -v 1 && { local default=$1 ; shift ; } local default local file @@ -51,7 +55,26 @@ config_for() { [[ ! -f $file ]] && continue - value="$(awk -F= '$1 == "'"$key"'" { print $NF }' "$file")" + # Check if the lookup is a reference variable, defined by using + # &= instead of just a single = as seperator. If this exists, + # do a new config_for lookup, this time using the value as the + # key for the new lookup. + value="$(awk -F= '$1 == "'"$key"'&" { print $0 }' "$file" | cut -d'=' -f 2-)" + + if [[ -n $value ]] + then + debug "bashtard/config_for" "Found reference for $key to $value in $file" + + printf "%s" "$(config_for "$host" "$value")" + return + fi + + # Use awk to find the right line, then use cut to get the + # actual value. Cutting it out with awk _is_ possible, but + # comes with whitespace issues or having to deal with values + # containing the seperator (=), so using cut is much simpler + # and easier to understand. + value="$(awk -F= '$1 == "'"$key"'" { print $0 }' "$file" | cut -d'=' -f 2-)" if [[ -n $value ]] then @@ -62,8 +85,8 @@ config_for() { fi done - # Return default value - if [[ -n $default ]] + # Return default value, if one has been defined + if test -v default then printf "%s" "$default" return @@ -115,6 +138,9 @@ config_subkeys_for() { subkey="$(awk -F. '{ print $1 }' <<< "${result#"$key."}")" + # Remove trailing ampersand if it exists + [[ "${subkey: -1}" == "&" ]] && subkey="${subkey:0:-1}" + debug "bashtard/config_subkeys" "Found '$subkey' as subkey of '$key' through '$result'" results+=("$subkey") done < <(grep "^$key\." "$file" | awk -F= '{ print $1 }') diff --git a/lib/util/pkg.bash b/lib/util/pkg.bash index 1538c3e..1433815 100644 --- a/lib/util/pkg.bash +++ b/lib/util/pkg.bash @@ -33,10 +33,11 @@ pkg_install() { local app=$1 ; shift case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- /usr/sbin/pkg install -y "$app" ;; - linux-debian*) set -- apt install -y "$app" ;; - linux-gentoo) set -- emerge --ask=n --update "$app" ;; - linux-ubuntu) set -- apt install -y "$app" ;; + freebsd) set -- /usr/sbin/pkg install -y "$app" ;; + linux-alpine_linux) set -- apk add --no-cache "$app" ;; + linux-debian*) set -- apt install -y "$app" ;; + linux-gentoo) set -- emerge --ask=n --update "$app" ;; + linux-ubuntu) set -- apt install -y "$app" ;; *) crit "$system" "No package manager configured for ${BASHTARD_PLATFORM[key]}" return 1 @@ -54,10 +55,11 @@ pkg_uninstall() { local app=$1 ; shift case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- /usr/sbin/pkg uninstall -y "$app" ;; - linux-debian*) set -- apt remove -y "$app" ;; - linux-gentoo) set -- emerge --ask=n --unmerge "$app" ;; - linux-ubuntu) set -- apt remove -y "$app" ;; + freebsd) set -- /usr/sbin/pkg uninstall -y "$app" ;; + linux-alpine_linux) set -- apk del "$app" ;; + linux-debian*) set -- apt remove -y "$app" ;; + linux-gentoo) set -- emerge --ask=n --unmerge "$app" ;; + linux-ubuntu) set -- apt remove -y "$app" ;; *) crit "$system" "No package manager configured for ${BASHTARD_PLATFORM[key]}" return 1 diff --git a/lib/util/svc.bash b/lib/util/svc.bash index fd65e4c..1b1ecbc 100644 --- a/lib/util/svc.bash +++ b/lib/util/svc.bash @@ -34,11 +34,18 @@ svc_disable() { local service=$1 - case "${BASHTARD_PLATFORM[key]}" in - linux-gentoo) set -- /sbin/rc-update del "$service" ;; - linux-*) set -- systemctl disable "$service" ;; + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-update del "$service" ;; + systemd) set -- systemctl disable "$service" ;; + *) + crit "$system" "No service manager support to disable with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to enable for ${BASHTARD_PLATFORM[key]}" return 1 esac @@ -53,7 +60,16 @@ svc_enable() { local service=$1 local rc - case "${BASHTARD_PLATFORM[key]}" in + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-update add "$service" ;; + systemd) set -- systemctl enable "$service" ;; + *) + crit "$system" "No service manager support to enable with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; freebsd) rc="$(printf '%s_enable="YES"' "$service")" @@ -63,12 +79,9 @@ svc_enable() { fi return 0 - ;; - linux-gentoo) set -- /sbin/rc-update add "$service" ;; - linux-*) set -- systemctl enable "$service" ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to enable for ${BASHTARD_PLATFORM[key]}" return 1 esac @@ -82,12 +95,21 @@ svc_reload() { local service=$1 - case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- service "$service" reload ;; - linux-gentoo) set -- /sbin/rc-service "$service" reload ;; - linux-*) set -- systemctl reload "$service" ;; + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-service "$service" reload ;; + systemd) set -- systemctl reload "$service" ;; + *) + crit "$system" "No service manager support to reload with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; + freebsd) + set -- service "$service" reload + ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to reload for ${BASHTARD_PLATFORM[key]}" return 1 esac @@ -101,12 +123,21 @@ svc_restart() { local service=$1 - case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- service "$service" restart ;; - linux-gentoo) set -- /sbin/rc-service "$service" restart ;; - linux-*) set -- systemctl restart "$service" ;; + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-service "$service" restart ;; + systemd) set -- systemctl restart "$service" ;; + *) + crit "$system" "No service manager support to restart with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; + freebsd) + set -- service "$service" restart + ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to restart for ${BASHTARD_PLATFORM[key]}" return 1 esac @@ -120,12 +151,21 @@ svc_start() { local service=$1 - case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- service "$service" start ;; - linux-gentoo) set -- /sbin/rc-service "$service" start ;; - linux-*) set -- systemctl start "$service" ;; + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-service "$service" start ;; + systemd) set -- systemctl start "$service" ;; + *) + crit "$system" "No service manager support to start with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; + freebsd) + set -- service "$service" start + ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to start for ${BASHTARD_PLATFORM[key]}" return 1 esac @@ -139,12 +179,21 @@ svc_stop() { local service=$1 - case "${BASHTARD_PLATFORM[key]}" in - freebsd) set -- service "$service" stop ;; - linux-gentoo) set -- /sbin/rc-service "$service" stop ;; - linux-*) set -- systemctl stop "$service" ;; + case "${BASHTARD_PLATFORM[os]}" in + linux) + case "${BASHTARD_PLATFORM[init]}" in + openrc) set -- /sbin/rc-service "$service" stop ;; + systemd) set -- systemctl stop "$service" ;; + *) + crit "$system" "No service manager support to stop with ${BASHTARD_PLATFORM[init]}" + return 1 + esac + ;; + freebsd) + set -- service "$service" stop + ;; *) - crit "$system" "No service manager configured for ${BASHTARD_PLATFORM[key]}" + crit "$system" "No service manager support to stop for ${BASHTARD_PLATFORM[key]}" return 1 esac diff --git a/share/doc/bashtard.1.scd b/share/doc/bashtard.1.scd index 8f6e4b4..1a681e0 100644 --- a/share/doc/bashtard.1.scd +++ b/share/doc/bashtard.1.scd @@ -1,6 +1,6 @@ bashtard(1) -; SPDX-FileCopyrightText: 2023 Patrick Spek <p.spek@tyil.nl> +; SPDX-FileCopyrightText: 2024 Patrick Spek <p.spek@tyil.nl> ; SPDX-License-Identifier: AGPL-3.0-or-later # NAME @@ -21,6 +21,7 @@ bashtard - A Bash-based configuration management utility *bashtard* var [-p _playbook_] <_key_>++ *bashtard* var [-s] <_key_> <_value_>++ *bashtard* sysinfo +*bashtard* zap <playbook> # DESCRIPTION @@ -91,6 +92,13 @@ configuration file. This variant accepts the *-s* option, to instead save it to the *secrets* file, which should only be readable by the user maintaining the system through *bashtard*. +## zap + +Removes a playbook from the registry. Unlike *del*, this will not attempt to run +the *del* function defined within the playbook. This functionality can be used +to remove the entry of a misbehaving playbook, or to be able to re-run the *add* +function on it. + # SEE ALSO - _bashtard(3)_ -- Functions and variables exposed by *bashtard* for use in |