Added real pretty print of disk changes

This commit is contained in:
oddlama 2020-04-21 00:40:54 +02:00
parent 7effe7f76b
commit 7136079ad3
No known key found for this signature in database
GPG Key ID: 88EA325D51D53908
6 changed files with 352 additions and 100 deletions

View File

@ -9,20 +9,21 @@ source "$GENTOO_INSTALL_REPO_DIR/scripts/internal_config.sh" || exit 1
create_default_disk_layout() {
local device="$1"
create_partition new_id=part_efi device="$device" size=128MiB type=efi
create_partition new_id=part_swap device="$device" size=8GiB type=raid
create_partition new_id=part_root device="$device" size=auto type=raid
create_gpt new_id=gpt device="$device"
create_partition new_id=part_efi id=gpt size=128MiB type=efi
create_partition new_id=part_swap id=gpt size=8GiB type=raid
create_partition new_id=part_root id=gpt size=auto type=raid
format id=part_efi type=efi label=efi
format id=part_swap type=swap label=swap
format id=part_root type=ext4 label=ext4
set_efi id=part_efi
set_swap id=part_swap
set_root id=part_root
DISK_ID_EFI=part_efi
DISK_ID_SWAP=part_raid
DISK_ID_ROOT=part_luks
}
create_default_disk_layout
create_default_disk_layout /dev/sdX
# Example 2: Multiple disks, with raid 0 and luks
@ -31,23 +32,23 @@ create_default_disk_layout
# - root: raid 0 → luks → fs
devices=(/dev/sd{X,Y})
for i in "${!devices[@]}"; do
device="${devices[$i]}"
create_partition new_id="part_efi_dev${i}" device="$device" size=128MiB type=efi
create_partition new_id="part_swap_dev${i}" device="$device" size=8GiB type=raid
create_partition new_id="part_root_dev${i}" device="$device" size=auto type=raid
create_gpt new_id="gpt_dev${i}" device="${devices[$i]}"
create_partition new_id="part_efi_dev${i}" id="gpt_dev${i}" size=128MiB type=efi
create_partition new_id="part_swap_dev${i}" id="gpt_dev${i}" size=8GiB type=raid
create_partition new_id="part_root_dev${i}" id="gpt_dev${i}" size=auto type=raid
done
create_raid new_id=part_raid_swap level=0 ids="${part_swap_dev*}"
create_raid new_id=part_raid_root level=0 ids="${part_root_dev*}"
create_raid new_id=part_raid_swap level=0 ids="$(expand_ids '^part_swap_dev\d$')"
create_raid new_id=part_raid_root level=0 ids="$(expand_ids '^part_root_dev\d$')"
create_luks new_id=part_luks_root id=part_raid_root
format id=part_efi_dev0 type=efi label=efi
format id=part_raid_swap type=swap label=swap
format id=part_luks_root type=ext4 label=ext4
set_efi id=part_efi_dev0
set_swap id=part_raid_swap
set_root id=part_luks_root
DISK_ID_EFI=part_efi_dev0
DISK_ID_SWAP=part_raid_swap
DISK_ID_ROOT=part_luks_root
################################################

View File

@ -21,18 +21,23 @@ sync_time() {
}
check_config() {
[[ "$KEYMAP" =~ ^[0-9A-Za-z-]*$ ]] \
[[ $KEYMAP =~ ^[0-9A-Za-z-]*$ ]] \
|| die "KEYMAP contains invalid characters"
# Check hostname per RFC1123
local hostname_regex='^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
[[ "$HOSTNAME" =~ $hostname_regex ]] \
[[ $HOSTNAME =~ $hostname_regex ]] \
|| die "'$HOSTNAME' is not a valid hostname"
if [[ "$INSTALL_ANSIBLE" == true ]]; then
[[ "$INSTALL_SSHD" == true ]] \
[[ -n $DISK_ID_ROOT ]] \
|| die "You must assign DISK_ID_ROOT"
[[ -n $DISK_ID_EFI ]] || [[ -n $DISK_ID_BOOT ]] \
|| die "You must assign DISK_ID_EFI or DISK_ID_BOOT"
if [[ $INSTALL_ANSIBLE == true ]]; then
[[ $INSTALL_SSHD == true ]] \
|| die "You must enable INSTALL_SSHD for ansible"
[[ -n "$ANSIBLE_SSH_AUTHORIZED_KEYS" ]] \
[[ -n $ANSIBLE_SSH_AUTHORIZED_KEYS ]] \
|| die "Missing pubkey for ansible user"
fi
}
@ -53,9 +58,224 @@ prepare_installation_environment() {
check_has_program uuidgen
check_has_program wget
[[ $USED_RAID == true ]] \
&& check_has_program mdadm
[[ $USED_LUKS == true ]] \
&& check_has_program cryptsetup
sync_time
}
add_summary_entry() {
local parent="$1"
local id="$2"
local name="$3"
local hint="$4"
local desc="$5"
local ptr
case "$id" in
"$DISK_ID_BOOT") ptr="← boot" ;;
"$DISK_ID_EFI") ptr="← efi" ;;
"$DISK_ID_SWAP") ptr="← swap" ;;
"$DISK_ID_ROOT") ptr="← root" ;;
# \x1f characters compensate for printf byte count and unicode character count mismatch due to '←'
*) ptr="$(echo -e "\x1f\x1f")" ;;
esac
summary_tree[$parent]+=";$id"
summary_name[$id]="$name"
summary_hint[$id]="$hint"
summary_ptr[$id]="$ptr"
summary_desc[$id]="$desc"
}
summary_color_args() {
for arg in "$@"; do
if [[ -v "arguments[$arg]" ]]; then
printf '%-28s ' "$arg=${arguments[$arg]}"
fi
done
}
disk_create_gpt() {
if [[ $disk_action_summarize_only == true ]]; then
if [[ -v arguments[id] ]]; then
add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "gpt" "" ""
else
add_summary_entry __root__ "${arguments[new_id]}" "${arguments[device]}" "(gpt)" ""
fi
return 0
fi
}
disk_create_partition() {
if [[ $disk_action_summarize_only == true ]]; then
add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "part" "(${arguments[type]})" "$(summary_color_args size)"
return 0
fi
}
disk_create_raid() {
if [[ $disk_action_summarize_only == true ]]; then
local id
# Splitting is intentional here
# shellcheck disable=SC2086
for id in ${arguments[ids]//';'/ }; do
add_summary_entry "$id" "_${arguments[new_id]}" "raid${arguments[level]}" "" ""
done
add_summary_entry __root__ "${arguments[new_id]}" "raid${arguments[level]}" "" ""
return 0
fi
}
disk_create_luks() {
if [[ $disk_action_summarize_only == true ]]; then
add_summary_entry "${arguments[id]}" "${arguments[new_id]}" "luks" "" ""
return 0
fi
}
disk_format() {
if [[ $disk_action_summarize_only == true ]]; then
add_summary_entry "${arguments[id]}" "__fs__${arguments[id]}" "${arguments[type]}" "(fs)" "$(summary_color_args label)"
return 0
fi
}
apply_disk_action() {
unset known_arguments
unset arguments; declare -A arguments; parse_arguments "$@"
case "${arguments[action]}" in
'create_gpt') disk_create_gpt ;;
'create_partition') disk_create_partition ;;
'create_raid') disk_create_raid ;;
'create_luks') disk_create_luks ;;
'format') disk_format ;;
*) echo "Ignoring invalid action: ${arguments[action]}" ;;
esac
}
print_summary_tree_entry() {
local indent_chars=""
local indent="0"
local d="1"
local maxd="$((depth - 1))"
while [[ $d -lt $maxd ]]; do
if [[ ${summary_depth_continues[$d]} == true ]]; then
indent_chars+='│ '
else
indent_chars+=' '
fi
indent=$((indent + 2))
d="$((d + 1))"
done
if [[ $maxd -gt 0 ]]; then
if [[ ${summary_depth_continues[$maxd]} == true ]]; then
indent_chars+='├─'
else
indent_chars+='└─'
fi
indent=$((indent + 2))
fi
local name="${summary_name[$root]}"
local hint="${summary_hint[$root]}"
local desc="${summary_desc[$root]}"
local ptr="${summary_ptr[$root]}"
local id_name=""
if [[ $root != __* ]]; then
if [[ $root == _* ]]; then
id_name="${root:1}"
else
id_name="${root}"
fi
fi
local align=0
if [[ $indent -lt 33 ]]; then
align="$((33 - indent))"
fi
elog "$indent_chars$(printf "%-${align}s %-47s %s" \
"$name $hint" \
"$id_name $ptr" \
"$desc")"
}
print_summary_tree() {
local root="$1"
local depth="$((depth + 1))"
local has_children=false
if [[ -v "summary_tree[$root]" ]]; then
local children="${summary_tree[$root]}"
has_children=true
summary_depth_continues[$depth]=true
else
summary_depth_continues[$depth]=false
fi
if [[ $root != __root__ ]]; then
print_summary_tree_entry "$root"
fi
if [[ $has_children == true ]]; then
local count="$(tr ';' '\n' <<< "$children" | grep -c '\S')"
local idx=0
# Splitting is intentional here
# shellcheck disable=SC2086
for id in ${children//';'/ }; do
idx="$((idx + 1))"
[[ $idx == "$count" ]] \
&& summary_depth_continues[$depth]=false
print_summary_tree "$id"
# separate blocks by newline
[[ ${summary_depth_continues[0]} == true ]] && [[ $depth == 1 ]] && [[ $idx == "$count" ]] \
&& elog
done
fi
}
summarize_disk_actions() {
elog "Current lsblk output"
for_line_in <(lsblk \
|| die "Error in lsblk") elog
disk_action_summarize_only=true
declare -A summary_tree
declare -A summary_name
declare -A summary_hint
declare -A summary_ptr
declare -A summary_desc
declare -A summary_depth_continues
apply_disk_actions
unset disk_action_summarize_only
local depth=-1
elog
elog "Configured disk layout"
elog ────────────────────────────────────────────────────────────────────────────────
elog "$(printf '%-26s %-28s %s' NODE ID OPTIONS)"
elog ────────────────────────────────────────────────────────────────────────────────
print_summary_tree __root__
elog ────────────────────────────────────────────────────────────────────────────────
}
apply_disk_actions() {
local param
local current_params=()
for param in "${DISK_ACTIONS[@]}"; do
if [[ $param == ';' ]]; then
apply_disk_action "${current_params[@]}"
current_params=()
else
current_params+=("$param")
fi
done
}
partition_device_print_config_summary() {
elog "-------- Partition configuration --------"
elog "Device: $PARTITION_DEVICE"
@ -65,22 +285,22 @@ partition_device_print_config_summary() {
elog "New partition table:"
elog "$PARTITION_DEVICE"
elog "├─efi size=$PARTITION_EFI_SIZE"
if [[ "$ENABLE_SWAP" == true ]]; then
if [[ $ENABLE_SWAP == true ]]; then
elog "├─swap size=$PARTITION_SWAP_SIZE"
fi
elog "└─linux size=[remaining]"
if [[ "$ENABLE_SWAP" != true ]]; then
if [[ $ENABLE_SWAP != true ]]; then
elog "swap: disabled"
fi
}
partition_device() {
[[ "$ENABLE_PARTITIONING" == true ]] \
[[ $ENABLE_PARTITIONING == true ]] \
|| return 0
einfo "Preparing partitioning of device '$PARTITION_DEVICE'"
[[ -b "$PARTITION_DEVICE" ]] \
[[ -b $PARTITION_DEVICE ]] \
|| die "Selected device '$PARTITION_DEVICE' is not a block device"
partition_device_print_config_summary
@ -99,7 +319,7 @@ partition_device() {
|| die "Could not create efi partition"
# Create swap partition
if [[ "$ENABLE_SWAP" == true ]]; then
if [[ $ENABLE_SWAP == true ]]; then
sgdisk -n "0:0:+$PARTITION_SWAP_SIZE" -t 0:8200 -c 0:"swap" -u 0:"$PARTITION_UUID_SWAP" "$PARTITION_DEVICE" >/dev/null \
|| die "Could not create swap partition"
fi
@ -119,15 +339,15 @@ partition_device() {
}
format_partitions() {
[[ "$ENABLE_FORMATTING" == true ]] \
[[ $ENABLE_FORMATTING == true ]] \
|| return 0
if [[ "$ENABLE_PARTITIONING" != true ]]; then
if [[ $ENABLE_PARTITIONING != true ]]; then
einfo "Preparing to format the following partitions:"
blkid -t PARTUUID="$PARTITION_UUID_EFI" \
|| die "Error while listing efi partition"
if [[ "$ENABLE_SWAP" == true ]]; then
if [[ $ENABLE_SWAP == true ]]; then
blkid -t PARTUUID="$PARTITION_UUID_SWAP" \
|| die "Error while listing swap partition"
fi
@ -148,7 +368,7 @@ format_partitions() {
mkfs.fat -F 32 -n "efi" "$dev" \
|| die "Could not format EFI partition"
if [[ "$ENABLE_SWAP" == true ]]; then
if [[ $ENABLE_SWAP == true ]]; then
dev="$(get_device_by_partuuid "$PARTITION_UUID_SWAP")" \
|| die "Could not resolve partition UUID '$PARTITION_UUID_SWAP'"
einfo " $dev (swap)"
@ -235,7 +455,7 @@ download_stage3() {
CURRENT_STAGE3_VERIFIED="${CURRENT_STAGE3}.verified"
# Download file if not already downloaded
if [[ -e "$CURRENT_STAGE3_VERIFIED" ]]; then
if [[ -e $CURRENT_STAGE3_VERIFIED ]]; then
einfo "$STAGE3_BASENAME tarball already downloaded and verified"
else
einfo "Downloading $STAGE3_BASENAME tarball"
@ -312,6 +532,7 @@ env_update() {
}
mkdir_or_die() {
# shellcheck disable=SC2174
mkdir -m "$1" -p "$2" \
|| die "Could not create directory '$2'"
}

View File

@ -17,6 +17,11 @@ UUID_STORAGE_DIR="$TMP_DIR/uuids"
# The desired efi partition mountpoint for the actual system
EFI_MOUNTPOINT="/boot/efi"
# Flag to track usage of raid (needed to check for mdadm existence)
USED_RAID=false
# Flag to track usage of luks (needed to check for cryptsetup existence)
USED_LUKS=false
# An array of disk related actions to perform
DISK_ACTIONS=()
# An associative set to check for existing ids
@ -26,8 +31,8 @@ only_one_of() {
local previous=""
local a
for a in "$@"; do
if [[ -v "arguments[$a]" ]]; then
if [[ -z "$previous" ]]; then
if [[ -v arguments[$a] ]]; then
if [[ -z $previous ]]; then
previous="$a"
else
die_trace 2 "Only one of the arguments ($*) can be given"
@ -38,30 +43,36 @@ only_one_of() {
create_new_id() {
local id="${arguments[$1]}"
[[ ! -v "DISK_KNOWN_IDS[$id]" ]] \
[[ $id == *';'* ]] \
&& die_trace 2 "Identifier contains invalid character ';'"
[[ ! -v DISK_KNOWN_IDS[$id] ]] \
|| die_trace 2 "Identifier '$id' already exists"
DISK_KNOWN_IDS[$id]=true
}
verify_existing_id() {
local id="${arguments[$1]}"
[[ -v "DISK_KNOWN_IDS[$id]" ]] \
[[ -v DISK_KNOWN_IDS[$id] ]] \
|| die_trace 2 "Identifier $1='$id' not found"
}
verify_existing_unique_ids() {
local ids="${arguments[$1]}"
local arg="$1"
local ids="${arguments[$arg]}"
count_orig="$(tr ' ' '\n' <<< "$ids" | wc -l)"
count_uniq="$(tr ' ' '\n' <<< "$ids" | sort -u | wc -l)"
[[ "$count_orig" -eq "$count_uniq" ]] \
|| die_trace 2 "$1=... contains duplicate identifiers"
count_orig="$(tr ';' '\n' <<< "$ids" | grep -c '\S')"
count_uniq="$(tr ';' '\n' <<< "$ids" | grep '\S' | sort -u | wc -l)"
[[ $count_orig -gt 0 ]] \
|| die_trace 2 "$arg=... must contain at least one entry"
[[ $count_orig -eq $count_uniq ]] \
|| die_trace 2 "$arg=... contains duplicate identifiers"
local i
local id
# Splitting is intentional here
for i in $ids; do # shellcheck disable=SC2068
[[ -v "DISK_KNOWN_IDS[$i]" ]] \
|| die_trace 2 "$1=... contains unknown identifier '$i'"
# shellcheck disable=SC2086
for id in ${ids//';'/ }; do
[[ -v DISK_KNOWN_IDS[$id] ]] \
|| die_trace 2 "$arg=... contains unknown identifier '$id'"
done
}
@ -72,7 +83,7 @@ verify_option() {
local arg="${arguments[$opt]}"
local i
for i in "$@"; do
[[ "$i" == "$arg" ]] \
[[ $i == "$arg" ]] \
&& return 0
done
@ -92,31 +103,43 @@ verify_option() {
#}
# Named arguments:
# new_id: Id for the new partition
# size: Size for the new partition, or auto to allocate the rest
# type: The parition type, either (efi, swap, raid, luks, linux) (or a 4 digit hex-code for gdisk).
# [one of]
# device: The operand block device
# id: The operand device id
create_partition() {
local known_arguments=('+new_id' '+device|id' '+size' '+type')
# new_id: Id for the new gpt table
# device: The operand block device
create_gpt() {
local known_arguments=('+new_id' '+device|id')
unset arguments; declare -A arguments; parse_arguments "$@"
only_one_of device id
create_new_id new_id
verify_option type efi swap raid luks linux
[[ -v "arguments[id]" ]] \
[[ -v arguments[id] ]] \
&& verify_existing_id id
DISK_ACTIONS+=("action=create_partition" "$@")
DISK_ACTIONS+=("action=create_gpt" "$@" ";")
}
# Named arguments:
# new_id: Id for the new partition
# size: Size for the new partition, or auto to allocate the rest
# type: The parition type, either (boot, efi, swap, raid, luks, linux) (or a 4 digit hex-code for gdisk).
# id: The operand device id
create_partition() {
local known_arguments=('+new_id' '+id' '+size' '+type')
unset arguments; declare -A arguments; parse_arguments "$@"
create_new_id new_id
verify_existing_id id
verify_option type boot efi swap raid luks linux
DISK_ACTIONS+=("action=create_partition" "$@" ";")
}
# Named arguments:
# new_id: Id for the new raid
# level: Raid level
# ids: Ids of all member devices
# ids: Comma separated list of all member ids
create_raid() {
USED_RAID=true
local known_arguments=('+new_id' '+level' '+ids')
unset arguments; declare -A arguments; parse_arguments "$@"
@ -124,36 +147,43 @@ create_raid() {
verify_option level 0 1 5 6
verify_existing_unique_ids ids
DISK_ACTIONS+=("action=create_raid" "$@")
DISK_ACTIONS+=("action=create_raid" "$@" ";")
}
# Named arguments:
# new_id: Id for the new luks
# [one of]
# device: The operand block device
# id: The operand device id
# id: The operand device id
create_luks() {
local known_arguments=('+new_id' '+device|id')
USED_LUKS=true
local known_arguments=('+new_id' '+id')
unset arguments; declare -A arguments; parse_arguments "$@"
create_new_id new_id
only_one_of device id
[[ -v "arguments[id]" ]] \
&& verify_existing_id id
verify_existing_id id
DISK_ACTIONS+=("action=create_luks" "$@")
DISK_ACTIONS+=("action=create_luks" "$@" ";")
}
# Named arguments:
# id: Id of the device / partition created earlier
# type: One of (efi, swap, ext4)
# type: One of (boot, efi, swap, ext4)
# label: The label for the formatted disk
format() {
local known_arguments=('+id' '+type')
local known_arguments=('+id' '+type' '?label')
unset arguments; declare -A arguments; parse_arguments "$@"
verify_existing_id id
verify_option type efi swap ext4
verify_option type boot efi swap ext4
DISK_ACTIONS+=("action=format" "$@")
DISK_ACTIONS+=("action=format" "$@" ";")
}
# Returns a comma separated list of all registered ids matching the given regex.
expand_ids() {
local regex="$1"
for id in "${!DISK_KNOWN_IDS[@]}"; do
[[ $id =~ $regex ]] \
&& echo -n "$id;"
done
}

View File

@ -7,11 +7,11 @@ set -uo pipefail
# Find the directory this script is stored in. (from: http://stackoverflow.com/questions/59895)
get_source_dir() {
local source="${BASH_SOURCE[0]}"
while [[ -h "${source}" ]]
while [[ -h $source ]]
do
local tmp="$(cd -P "$(dirname "${source}")" && pwd)"
source="$(readlink "${source}")"
[[ "${source}" != /* ]] && source="${tmp}/${source}"
[[ $source != /* ]] && source="${tmp}/${source}"
done
echo -n "$(realpath "$(dirname "${source}")")"
@ -128,7 +128,7 @@ install_ansible() {
mkdir_or_die 0700 "$ANSIBLE_HOME"
mkdir_or_die 0700 "$ANSIBLE_HOME/.ssh"
if [[ -n "$ANSIBLE_SSH_AUTHORIZED_KEYS" ]]; then
if [[ -n $ANSIBLE_SSH_AUTHORIZED_KEYS ]]; then
einfo "Adding authorized keys for ansible"
touch_or_die 0600 "$ANSIBLE_HOME/.ssh/authorized_keys"
echo "$ANSIBLE_SSH_AUTHORIZED_KEYS" >> "$ANSIBLE_HOME/.ssh/authorized_keys" \
@ -194,7 +194,7 @@ main_install_gentoo_in_chroot() {
|| die "Could not append entry to fstab"
echo "PARTUUID=$PARTITION_UUID_EFI /boot/efi vfat defaults,noatime,fmask=0022,dmask=0022,noexec,nodev,nosuid,discard 0 2" >> /etc/fstab \
|| die "Could not append entry to fstab"
if [[ "$ENABLE_SWAP" == true ]]; then
if [[ $ENABLE_SWAP == true ]]; then
echo "PARTUUID=$PARTITION_UUID_SWAP none swap defaults,discard 0 0" >> /etc/fstab \
|| die "Could not append entry to fstab"
fi
@ -204,7 +204,7 @@ main_install_gentoo_in_chroot() {
try emerge --verbose app-portage/gentoolkit
# Install and enable sshd
if [[ "$INSTALL_SSHD" == true ]]; then
if [[ $INSTALL_SSHD == true ]]; then
install_sshd
fi
@ -215,13 +215,14 @@ main_install_gentoo_in_chroot() {
|| die "Could not add dhcpcd to default services"
# Install ansible
if [[ "$INSTALL_ANSIBLE" == true ]]; then
if [[ $INSTALL_ANSIBLE == true ]]; then
install_ansible
fi
# Install additional packages, if any.
if [[ -n "$ADDITIONAL_PACKAGES" ]]; then
if [[ -n $ADDITIONAL_PACKAGES ]]; then
einfo "Installing additional packages"
# shellcheck disable=SC2086
try emerge --verbose --autounmask-continue=y -- $ADDITIONAL_PACKAGES
fi
@ -264,7 +265,7 @@ main_umount() {
trap 'kill "$GENTOO_INSTALL_REPO_SCRIPT_PID"' INT
SCRIPT_ALIAS="$(basename "$0")"
if [[ "$SCRIPT_ALIAS" == "main.sh" ]]; then
if [[ $SCRIPT_ALIAS == main.sh ]]; then
SCRIPT_ALIAS="$1"
shift
fi

View File

@ -1,7 +1,7 @@
#!/bin/bash
set -uo pipefail
[[ "${EXECUTED_IN_CHROOT}" != true ]] \
[[ ${EXECUTED_IN_CHROOT} != true ]] \
&& { echo "This script must not be executed directly!" >&2; exit 1; }
# Source the systems profile
@ -12,7 +12,7 @@ umask 0077
# Export nproc variables
export NPROC="$(nproc || echo 2)"
export NPROC_ONE="$(($NPROC + 1))"
export NPROC_ONE="$((NPROC + 1))"
# Set default makeflags and emerge flags for parallel emerges
export MAKEFLAGS="-j$NPROC"

View File

@ -32,7 +32,7 @@ die_trace() {
}
for_line_in() {
while IFS="" read -r line || [[ -n "$line" ]]; do
while IFS="" read -r line || [[ -n $line ]]; do
"$2" "$line"
done <"$1"
}
@ -68,7 +68,7 @@ try() {
"$@"
cmd_status="$?"
if [[ "$cmd_status" != 0 ]]; then
if [[ $cmd_status != 0 ]]; then
echo " * Command failed: \$ $*"
echo "Last command failed with exit code $cmd_status"
@ -132,7 +132,7 @@ load_or_generate_uuid() {
local uuid
local uuid_file="$UUID_STORAGE_DIR/$1"
if [[ -e "$uuid_file" ]]; then
if [[ -e $uuid_file ]]; then
uuid="$(cat "$uuid_file")"
else
uuid="$(uuidgen -r)"
@ -144,10 +144,8 @@ load_or_generate_uuid() {
}
# Parses named arguments and stores them in the associative array `arguments`.
# The associative array `known_arguments` must contain a list of arguments
# prefixed with + (mandatory) or ? (optional).
# "at least one of" can be expressed by +a|b|c.
# all mandatory arguments are given.
# If given, the associative array `known_arguments` must contain a list of arguments
# prefixed with + (mandatory) or ? (optional). "at least one of" can be expressed by +a|b|c.
parse_arguments() {
local key
local value
@ -155,11 +153,11 @@ parse_arguments() {
for a in "$@"; do
key="${a%%=*}"
value="${a#*=}"
arguments["$key"]="$value"
arguments[$key]="$value"
done
declare -A allowed_keys
if [[ -v "known_arguments" ]]; then
if [[ -v known_arguments ]]; then
local m
for m in "${known_arguments[@]}"; do
case "${m:0:1}" in
@ -168,28 +166,29 @@ parse_arguments() {
local has_opt=false
local m_opt
# Splitting is intentional here
for m_opt in ${m//|/ }; do # shellcheck disable=SC2068
allowed_keys["$m_opt"]=true
if [[ -v "arguments[$m_opt]" ]]; then
# shellcheck disable=SC2086
for m_opt in ${m//|/ }; do
allowed_keys[$m_opt]=true
if [[ -v arguments[$m_opt] ]]; then
has_opt=true
fi
done
[[ "$has_opt" == true ]] \
[[ $has_opt == true ]] \
|| die_trace 2 "Missing mandatory argument $m=..."
;;
'?')
allowed_keys["${m:1}"]=true
allowed_keys[${m:1}]=true
;;
*) die_trace 2 "Invalid start character in known_arguments, in argument '$m'" ;;
esac
done
fi
for a in "${!arguments[@]}"; do
[[ -v "allowed_keys[$a]" ]] \
|| die_trace 2 "Unkown argument '$a'"
done
for a in "${!arguments[@]}"; do
[[ -v allowed_keys[$a] ]] \
|| die_trace 2 "Unkown argument '$a'"
done
fi
}