Skip to content

Instantly share code, notes, and snippets.

@joestringer
Last active July 2, 2020 03:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joestringer/cbd7ff46787614a7f4ab5a8f2c7c513f to your computer and use it in GitHub Desktop.
Save joestringer/cbd7ff46787614a7f4ab5a8f2c7c513f to your computer and use it in GitHub Desktop.
Process etcd kvstore dumps for relevant keys/values by lease
#!/bin/bash
set -eo pipefail
KV_DUMP="${1:-""}"
LEASES="${1:-""}"
LEASE_MODE=false
DEBUG_MODE=false
LOCK_FILTER=false
usage()
{
echo -e "usage: $0 [-i] [-l] [-d] <KV-DUMP> [VALID-LEASES]"
echo
echo -e "KV-DUMP\t\tJSON-formatted file dumped from etcdv3 via:"
echo -e " \t\tETCDCTL_API=\"3\" etcdctl get \"\" --prefix -w=json"
echo -e "VALID_LEASES:\tLine-delimited file with a list of valid leases"
echo
echo -e "-i\t\tList keys by lease-ID"
echo -e "-l\t\tOnly list lock paths"
echo -e "-d\t\tEnable debug output"
}
error()
{
>&2 echo -e "$@"
exit 1
}
debug()
{
if $DEBUG_MODE; then
>&2 echo "$@"
fi
}
parse_args()
{
for arg in "$@"; do
case "$arg" in
-i) LEASE_MODE=true;;
-l) LOCK_FILTER=true;;
-d) DEBUG_MODE=true;;
*) break;;
esac
shift
done
if [ $# -lt 1 ]; then
>&2 usage
exit 1
fi
if [ ! -e "$1" ]; then
error "$1: No such file or directory"
else
KV_DUMP="$1"
fi
if $LEASE_MODE && [ "$2" != "" ] && [ ! -e "$2" ]; then
error "$2: No such file or directory"
else
LEASES="$2"
fi
if ! jq --version >/dev/null; then
error "jq is required to run this script."
fi
}
main()
{
parse_args "$@"
if $LEASE_MODE; then
local invalid_leases=()
local valid_leases=""
if [ -e "$LEASES" ]; then
valid_leases="$(cat $LEASES | wc -l)"
debug "valid_leases = $valid_leases"
fi
cat "$KV_DUMP" \
| jq -r '.kvs[]|[.lease, .key] | @csv' \
| while IFS=$',' read -r lease key; do
#debug "$lease,$key"
local k="$(echo $key | sed 's/"//g' | base64 -d)"
if $LOCK_FILTER && ! echo "$k" | grep -q "lock"; then
debug "Skipping non-lock key $k"
continue
fi
local l="$(printf '%x\n' $lease)"
if [ -e "$LEASES" ]; then
local total_leases="$(echo $l | cat $LEASES - | sort -u | wc -l)"
if [ "$total_leases" -ne "$valid_leases" ]; then
invalid_leases+=("$l")
echo "[!!] $l | $k"
else
echo "$l | $k"
fi
else
echo "$l | $k"
fi
done
echo
for lease in ${array[@]}; do
>&2 echo "Unknown lease $lease"
done
else
cat "$KV_DUMP" \
| jq -r '.kvs[]|[.key, .value, .lease] | @csv' \
| while IFS=$',' read -r key value lease; do
local k="$(echo $key | sed 's/"//g' | base64 -d)"
if $LOCK_FILTER && ! echo "$k" | grep -q "lock"; then
debug "Skipping non-lock key $k"
continue
fi
local v="<empty>"
if [ "$value" != "" ]; then
v="$(echo $value | sed 's/"//g' | base64 -d)"
fi
local l="$(printf '%x\n' $lease)"
echo "$k => $v | $l"
done
fi
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment