From f2f03d6ea4d6d181880a9f9c4f019d24065db4ec Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Sat, 16 Apr 2022 14:27:42 +0200 Subject: Initial draft for sync subcommand --- lib/main.bash | 34 +++++++++++++++++++++++++-- lib/subcommands/bootstrap.bash | 25 +++++++++++--------- lib/subcommands/sync.bash | 53 ++++++++++++++++++++++++++++++++++++++++++ lib/util.bash | 44 +++++++++++++++++------------------ 4 files changed, 121 insertions(+), 35 deletions(-) create mode 100644 lib/subcommands/sync.bash (limited to 'lib') diff --git a/lib/main.bash b/lib/main.bash index 8075b59..ce41b92 100644 --- a/lib/main.bash +++ b/lib/main.bash @@ -50,7 +50,7 @@ main() { debug "$BASHTARD_NAME/main" "\$TMPDIR set to $TMPDIR" # Actually perform the subcommand - debug "$BASHTARD_NAME/main" "Running subcommand" + debug "$BASHTARD_NAME/main" "Running subcommand '$subcommand'" subcommand "$@" local subcommand_exit=$? @@ -66,6 +66,10 @@ main() { } usage() { + local playbooks + local playbook_length + local playbook_longest=0 + cat < $BASHTARD_NAME ssh - $BASHTARD_NAME sync + $BASHTARD_NAME sync [playbook] $BASHTARD_NAME sysinfo Perform maintenance on your infra. @@ -89,6 +93,32 @@ Commands: Playbooks: EOF + + # Find all playbooks + mapfile -t playbooks < <(find \ + "$BASHTARD_ETCDIR/playbooks.d"/* \ + -maxdepth 0 \ + -type d \ + ) + + # Find longest playbook name + for playbook in "${playbooks[@]}" + do + playbook_length="$(printf "%s" "$(basename "$playbook")" | wc -c)" + + if (( playbook_longest < playbook_length )) + then + playbook_longest=$playbook_length + fi + done + + # Render playbook descriptions + for playbook in "${playbooks[@]}" + do + printf "\t%-${playbook_longest}s %s\n" \ + "$(basename "$playbook")" \ + "$(cat "$playbook/description.txt")" + done } # Discover information about the system. If any bugs are reported and you want diff --git a/lib/subcommands/bootstrap.bash b/lib/subcommands/bootstrap.bash index b2e540b..8750134 100644 --- a/lib/subcommands/bootstrap.bash +++ b/lib/subcommands/bootstrap.bash @@ -18,29 +18,30 @@ bootstrap_local() { local dirs=( "$BASHTARD_ETCDIR" + "$BASHTARD_ETCDIR/conf.d" "$BASHTARD_ETCDIR/hosts.d" "$BASHTARD_ETCDIR/os.d" "$BASHTARD_ETCDIR/playbooks.d" - "$BASHTARD_ETCDIR/playbook-registry.d/" + "$BASHTARD_ETCDIR/registry.d" + "$BASHTARD_ETCDIR/registry.d/${BASHTARD_PLATFORM[fqdn]}" ) local files=( "$BASHTARD_ETCDIR/defaults" - "$BASHTARD_ETCDIR/playbooks" - "$BASHTARD_ETCDIR/playbook-registry.d/${BASHTARD_PLATFORM[fqdn]}" "$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}" "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}" + "$BASHTARD_ETCDIR/playbooks.d/remotes" ) for dir in "${dirs[@]}" do - notice "bootstrap" "Creating $dir" + notice "bashtard/bootstrap" "Creating $dir" mkdir -p -- "$dir" done for file in "${files[@]}" do - notice "bootstrap" "Creating $file" + notice "bashtard/bootstrap" "Creating $file" touch -- "$file" done } @@ -53,20 +54,22 @@ bootstrap_remote() local files=( "$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}" "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}" - "$BASHTARD_ETCDIR/playbook-registry.d/${BASHTARD_PLATFORM[fqdn]}" + "$BASHTARD_ETCDIR/registry.d/${BASHTARD_PLATFORM[fqdn]}" ) for file in "${files[@]}" do [[ -f "$file" ]] && continue - notice "bootstrap" "Creating $file" + notice "bashtard/bootstrap" "Creating $file" touch -- "$file" done - while read -r playbook url + while read -r playbook url branch do - notice bootstrap "Cloning $playbook from $url" - git clone "$url" "$BASHTARD_ETCDIR/playbooks.d" - done < "$BASHTARD_ETCDIR/playbooks" + notice "bashtard/bootstrap" "Cloning $playbook from $url" + git clone "$url" "$BASHTARD_ETCDIR/playbooks.d/$playbook" + + # TODO: Clone appropriate branch + done < "$BASHTARD_ETCDIR/playbooks.d/remotes" } diff --git a/lib/subcommands/sync.bash b/lib/subcommands/sync.bash new file mode 100644 index 0000000..af5f282 --- /dev/null +++ b/lib/subcommands/sync.bash @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +subcommand() +{ + export BASHTARD_PLAYBOOK="$1" ; shift + + # If a specific playbook is given, sync that + if [[ ! -z "$BASHTARD_PLAYBOOK" ]] + then + sync_playbook "$BASHTARD_PLAYBOOK" + return + fi + + # Otherwise, do a full sync + notice "bashtard/sync" "Syncing remote playbooks" + + # Update all playbook sources + while read -r playbook url branch + do + pushd -- "$BASHTARD_ETCDIR/playbooks.d/$playbook" + git pull origin "$branch" + done < "$BASHTARD_ETCDIR/playbooks.d/remotes" + + # Run a sync for each registered playbook for this host + while read -r playbook + do + info "bashtard/sync" "Syncing $playbook" + "$BASHTARD_BASEDIR/bin/$BASHTARD_NAME" sync "$playbook" + done < "$BASHTARD_ETCDIR/registry.d/${BASHTARD_PLATFORM[fqdn]}" +} + +sync_playbook() +{ + local playbook_base="$BASHTARD_ETCDIR/playbooks.d/$BASHTARD_PLAYBOOK" + + notice "bashtard/sync" "Running sync for $BASHTARD_PLAYBOOK" + + if [[ ! -d "$playbook_base" ]] + then + emerg "bashtard/sync" "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" + return 1 + fi + + . "$playbook_base/playbook.bash" + + playbook_sync +} diff --git a/lib/util.bash b/lib/util.bash index 2c10ef4..c6ef534 100644 --- a/lib/util.bash +++ b/lib/util.bash @@ -3,7 +3,7 @@ # Change the working directory. In usage, this is the same as using cd, # however, it will make additional checks to ensure everything is going fine. chgdir() { - debug "tyilnet/chgdir" "Changing workdir to $1" + debug "bashtard/chgdir" "Changing workdir to $1" cd -- "$1" || die "Failed to change directory to $1" } @@ -42,7 +42,7 @@ config_for() { if [[ -n $value ]] then - debug "tyilnet/config_for" "Found $key=$value in $file" + debug "bashtard/config_for" "Found $key=$value in $file" printf "%s" "$value" return @@ -57,7 +57,7 @@ config_for() { fi # Error - alert "tyilnet/config_for" "No configuration value for $key" + alert "bashtard/config_for" "No configuration value for $key" } # Create a datetime stamp. This is a wrapper around the date utility, ensuring @@ -87,7 +87,7 @@ die() { do case "$opt" in i) code=$OPTARG ;; - *) alert "tyilnet/die" "Unused argument specified: $opt" ;; + *) alert "bashtard/die" "Unused argument specified: $opt" ;; esac done @@ -106,7 +106,7 @@ fetch_http() { do case "$opt" in o) buffer=$OPTARG ;; - *) alert "tyilnet/fetch_http" "Unused argument specified: $opt" ;; + *) alert "bashtard/fetch_http" "Unused argument specified: $opt" ;; esac done @@ -114,7 +114,7 @@ fetch_http() { [[ -z $buffer ]] && buffer="$(tmpfile)" - notice "tyilnet/fetch_http" "Downloading $1 to $buffer" + notice "bashtard/fetch_http" "Downloading $1 to $buffer" for util in curl wget do @@ -126,7 +126,7 @@ fetch_http() { return $exit_code done - die "tyilnet/fetch_http" "Unable to download file over HTTP!" + die "bashtard/fetch_http" "Unable to download file over HTTP!" } fetch_http_curl() { @@ -162,7 +162,7 @@ join_args() { do case "$opt" in c) IFS="$OPTARG" ;; - *) warn "tyilnet/join_args" "Unused opt specified: $opt" ;; + *) warn "bashtard/join_args" "Unused opt specified: $opt" ;; esac done @@ -173,7 +173,7 @@ join_args() { # OS independent package management pkg() { - local system="tyilnet/pkg" + local system="bashtard/pkg" local action=$1 ; shift local app="$(config "pkg.$1" "$(config "app.$1")")" ; shift @@ -196,7 +196,7 @@ pkg() { } pkg_install() { - local system="tyilnet/pkg/install" + local system="bashtard/pkg/install" local app=$1 ; shift @@ -216,7 +216,7 @@ pkg_install() { # OS independent service management. svc() { - local system="tyilnet/svc" + local system="bashtard/svc" local service local action @@ -240,7 +240,7 @@ svc() { } svc_enable() { - local system="tyilnet/svc/enable" + local system="bashtard/svc/enable" local service=$1 @@ -257,7 +257,7 @@ svc_enable() { } svc_restart() { - local system="tyilnet/svc/restart" + local system="bashtard/svc/restart" local service=$1 @@ -275,7 +275,7 @@ svc_restart() { } svc_start() { - local system="tyilnet/svc/start" + local system="bashtard/svc/start" local service=$1 @@ -299,26 +299,26 @@ template() if [[ ! -f $file ]] then - crit "tyilnet/template" "Tried to render template from $file, but it doesn't exist" + crit "bashtard/template" "Tried to render template from $file, but it doesn't exist" return fi for kv in "$@" do - debug "tyilnet/template" "Adding $kv to sedfile at $sedfile" + debug "bashtard/template" "Adding $kv to sedfile at $sedfile" key="$(awk -F= '{ print $1 }' <<< $kv)" if [[ -z "$key" ]] then - crit "tyilnet/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)" if [[ -z "$value" ]] then - crit "tyilnet/template" "Empty key in '$kv' while rendering $file?" + crit "bashtard/template" "Empty key in '$kv' while rendering $file?" fi printf 's@${%s}@%s@g\n' "$key" "$value" >> "$sedfile" @@ -337,10 +337,10 @@ tmpdir() { # Ensure the file was created succesfully if [[ ! -d "$dir" ]] then - die "tyilnet/tmpdir" "Failed to create a temporary directory at $dir" + die "bashtard/tmpdir" "Failed to create a temporary directory at $dir" fi - debug "tyilnet/tmpdir" "Temporary file created at $dir" + debug "bashtard/tmpdir" "Temporary file created at $dir" printf "%s" "$dir" } @@ -356,10 +356,10 @@ tmpfile() { # Ensure the file was created succesfully if [[ ! -f "$file" ]] then - die "tyilnet/tmpfile" "Failed to create a temporary file at $file" + die "bashtard/tmpfile" "Failed to create a temporary file at $file" fi - debug "tyilnet/tmpfile" "Temporary file created at $file" + debug "bashtard/tmpfile" "Temporary file created at $file" printf "%s" "$file" } -- cgit v1.1