garage-cluster/tools
2025-04-10 20:53:23 -05:00

161 lines
4.3 KiB
Bash
Executable File

#!/bin/bash
set -e -o pipefail
shq() {(
while [ $# -gt 0 ];do
echo -n "'$(echo -n "$1" | sed -e "s/'/'\"'\"'/g")'"
shift
done
)}
json() {( # json encode the argument
jq -n --arg v "$@" '$v'
)}
GARAGE_NAMESPACE="${GARAGE_NAMESPACE-garage}"
ARGS="$(shq "$@")"
ZERO="$0"
ONE="$1"
ONE_UNDER="$(echo -n "$ONE" | tr - _)"
NL="$(echo)"
enumerate_pods() { # enumerate kubernetes-based garage pods
kubectl get pod -n "$GARAGE_NAMESPACE" -l app=garage -o json | yq -ot '.items[] | [
.metadata.name,
.status.podIP,
.spec.containers[].ports[]|select(.name == "rpc")|.hostPort,
.spec.nodeName
]' | while read -r pod ip port node;do
gnid="$(grun "$pod" node id -q)"
printf "%${#pod}s %25s %s\n" $pod $node "$gnid@$ip:$port"
done
}
get_ids() { # get the public id of all discoverable servers
enumerate_pods | while read -r pod node gnid;do
echo "$gnid"
done
}
iterstats() { # get stats from running garage nodes via iteration over discovered ids
get_ids | while read -r id;do
garage -h "$id" stats
done
}
grun() {
TARGET="$1"
shift
kubectl exec -n "$GARAGE_NAMESPACE" -c garage "$TARGET" -- garage "$@"
}
garage() { # run an arbitrary garage command via a random garage pod
grun ds/garage "$@"
}
generate_secrets() { # generates secrets required to run garage
kubectl create secret -n "$GARAGE_NAMESPACE" generic garage-secrets \
--from-literal=admin-token="$( openssl rand -base64 32 )" \
--from-literal=metrics-token="$( openssl rand -base64 32 )" \
--from-literal=rpc-secret="$( openssl rand -hex 32 )"
}
generate_layout() {( # generates a sample layout, (args are included verbatim, e.g. -t k8s)
enumerate_pods | while read -r pod node gnid;do
kubectl get node/$node -o json | jq -r --arg zero "$ZERO" '
[
$zero,
"garage", "layout", "assign",
"-t", .metadata.name,
"-c", "\(.metadata.labels["strudelline.net/garage-meta-free-bytes"]|tonumber/1024/1024/1024|floor)G"
]+$ARGS.positional
| @sh' --args -- "$@" "${gnid%%@*}" | while read -r cmd;do
eval "set $cmd"
printf " %q" "$@" | cut -c 2-
done
done
)}
make_bucket() { # make a bucket along with metadata in a namespace
TARGETBUCKET="$1"
TARGETKEYNAME="${2-$TARGETBUCKET}-app-key"
TARGETNS="${3-$TARGETBUCKET}"
TARGETSECRET="${3-$TARGETKEYNAME}"
kubectl get namespace "$TARGETNS" > /dev/null
garage bucket create "$TARGETBUCKET"
eval "$(
(garage key info "$TARGETKEYNAME" 2> /dev/null || garage key create "$TARGETKEYNAME") | awk '
/^key id: /i {printf("KID=%s\n", $3);}
/^secret key: /i {printf("SK=%s\n", $3);}
')"
garage bucket allow --read --write --owner "$TARGETBUCKET" --key "$TARGETKEYNAME"
kubectl create secret generic \
-n "$TARGETNS" "$TARGETSECRET" \
--type kubernetes.io/basic-auth \
--from-literal=username="$KID" \
--from-literal=password="$SK" \
--from-literal=AWS_ACCESS_KEY_ID="$KID" \
--from-literal=AWS_SECRET_ACCESS_KEY="$SK" \
--from-literal=bucket="$TARGETBUCKET"
kubectl label -n "$TARGETNS" secret/$TARGETSECRET bucket="$TARGETBUCKET" key="$TARGETKEYNAME"
}
connect() { # attempt to connect all nodes
allids="$(get_ids)"
primary="$(echo "$allids" | head -1)"
echo "$allids" | sed 1d | while read -r id;do
garage -h $primary node connect "$id"
done
}
env() { # connect your local garage cli to a random node
jq -n -r \
--argjson secret "$(kubectl get secret -n "$GARAGE_NAMESPACE" garage-secrets -o json)" \
--arg gnid "$(get_ids | head -1)" \
'
rpc_secret=\($secret.data."rpc-secret")",
RPC_HOST=\($gnid)"
'
}
help() {( # this help
exec 1>&2
echo "usage: $0 <subcmd> [options]"
echo
echo GARAGE SUBCOMMANDS:
( 2>&1 garage --help || true ) | awk 'p==1&&/^ / {print lc,$0;next} p==1 {lc=$1;print;} /^SUBCOMMANDS:$/ {p=1}' | while read -r cmd help;do
printf " %-25s %s\n" "garage $cmd" "$help"
done
echo
echo "GARAGE CLUSTER TOOLS:"
grep -E "^[a-z_]+[(][)] {[(]? # .*" "$ZERO" | sed -Ee 's@[(][)] [{][(]? # @: @' |
while read cmd help;do
printf " %-25s %s\n" "$(echo -n $cmd | tr _ -)" "$help"
done
echo
)}
if [ "x$1" = x ];then
help
exit 1
fi
# we translate - to _ to allow enumerate-pods or enumerate_pods.
# it also changes -h to _h.
if [ "x$ONE" = "x-h" ];then
help
exit 0
fi
shift 1
"$ONE_UNDER" "$@"