Last active
January 15, 2024 14:20
-
-
Save nicolas-goudry/7385f00bb50cc46cbf0763110bc0ffa0 to your computer and use it in GitHub Desktop.
Bash script to retrieve kcadm.sh from Keycloak server running on Kubernetes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Exit on error | |
set -e | |
# Variables | |
SCRIPT_NAME="$(basename "$0")" | |
OUTDIR="$PWD/kcadm" | |
# Color codes | |
NC="\e[0m" | |
BOLD="\e[1m" | |
DIM="\e[2m" | |
Y="\e[33m" | |
R="\e[31m" | |
G="\e[32m" | |
# Utility function to output error message | |
error() { | |
>&2 echo -e "${R}ERROR: $*${NC}" | |
} | |
# Utility function to output warning message | |
warn() { | |
>&2 echo -e "${Y}WARN: $*${NC}" | |
} | |
# Utility function to exit script with optional error message | |
die() { | |
if test "$#" -gt 0; then | |
error "$*" | |
fi | |
exit 1 | |
} | |
# Output help usage | |
usage() { | |
echo | |
echo "Retrieve necessary files to get a working local copy of the Keycloak" | |
echo "admin CLI (ie. kcadm.sh)." | |
echo | |
echo -e "${BOLD}Usage:${NC}" | |
echo | |
echo -e " ${DIM}\$${NC} $SCRIPT_NAME [OPTIONS]" | |
echo | |
echo -e "${BOLD}Options:${NC}" | |
echo | |
echo " -v, --version Set Keycloak server version" | |
echo " -h, --help Show this help message" | |
echo | |
} | |
_kubectl() { | |
kubectl -n "$NAMESPACE" "$@" | |
} | |
# Utility function to get an item list returned by a provided command | |
# and ask user to choose one item | |
list_select() { | |
local question="$1" | |
local destination="${2:-SELECTED_ITEM}" | |
local data_cmd="$3" | |
local ifs="$4" | |
if test -z "$question"; then | |
die "no question specified" | |
fi | |
if test -z "$data_cmd"; then | |
die "no command to get data was provided" | |
fi | |
local data=() | |
while IFS=$ifs read -r line; do | |
data+=("$line") | |
done < <($data_cmd) | |
local len=${#data[@]} | |
if test "$len" -eq 0; then | |
die "no data found" | |
elif test "$len" -eq 1; then | |
export "$destination"="${data[0]}" | |
else | |
local choice="" | |
while test -z "$choice"; do | |
echo "$question" | |
for i in "${!data[@]}"; do | |
echo -e "\t[$i] ${data[i]}" | |
done | |
read -rep "Select an item: " "choice" | |
if test -z "${data[choice]}"; then | |
error "invalid choice" | |
choice="" | |
fi | |
done | |
export "$destination"="${data[choice]}" | |
fi | |
} | |
# Check that kubectl command is available | |
check_kubectl() { | |
if test -z "$(command -v kubectl)"; then | |
die "missing kubectl binary" | |
fi | |
} | |
# Check output directory does not already contain kcadm.sh | |
check_outdir() { | |
if test -f "$OUTDIR/kcadm.sh"; then | |
warn "kcadm.sh is already installed." | |
read -rep "Continue anyway? [Y/n] " "choice" | |
case $choice in | |
[nN] ) exit;; | |
esac | |
fi | |
} | |
# Get version used in container by looking at the container image tag | |
get_version() { | |
if test -n "$VERSION"; then | |
echo "${DIM}Assuming Keycloak version $VERSION as requested by user.${NC}" | |
else | |
local version | |
version=$(_kubectl get po "$POD" -ojsonpath='{.spec.containers[0].image}' | grep -oP '.+:\K(\d+.\d+.\d+)$') | |
if test -z "$version"; then | |
error "failed to detect keycloak version" | |
echo "Use ${DIM}--version${NC} option to manually set the Keycloak server version" | |
die | |
fi | |
VERSION="$version" | |
fi | |
} | |
get_files() { | |
mkdir -p "$OUTDIR"/client/lib | |
_kubectl exec -i -c keycloak "$POD" -- cat /opt/keycloak/bin/kcadm.sh > "$OUTDIR"/kcadm.sh | |
chmod +x "$OUTDIR"/kcadm.sh | |
_kubectl exec -i -c keycloak "$POD" -- cat /opt/keycloak/bin/client/keycloak-admin-cli-"$VERSION".jar > "$OUTDIR"/client/keycloak-admin-cli-"$VERSION".jar | |
local libfiles | |
libfiles=$(_kubectl exec -i -c keycloak "$POD" -- ls /opt/keycloak/bin/client/lib) | |
for libfile in $libfiles; do | |
_kubectl exec -i -c keycloak "$POD" -- cat /opt/keycloak/bin/client/lib/"$libfile" > "$OUTDIR"/client/lib/"$libfile" | |
done | |
} | |
# Read script flags | |
while getopts 'hv:-:' OPT; do | |
# support long options: https://stackoverflow.com/a/28466267/519360 | |
if test "$OPT" = "-"; then # long option: reformulate OPT and OPTARG | |
OPT="${OPTARG%%=*}" # extract long option name | |
# shellcheck disable=SC2295 | |
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty) | |
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=` | |
fi | |
# Handle flags | |
case "$OPT" in | |
v | version ) VERSION="$OPTARG" ;; | |
h | help ) usage; exit 0 ;; | |
??* ) die "illegal option --${OPT}" ;; # bad long option | |
? ) exit 1 ;; # bad short option (error reported via getopts) | |
esac | |
done | |
main() { | |
echo -e "${DIM}Performing initial checks...${NC}" | |
check_kubectl | |
check_outdir | |
list_select "Select Keycloak Namespace:" "NAMESPACE" "kubectl get ns -ocustom-columns=NAME:.metadata.name --no-headers" | |
list_select "Select Pod:" "POD" "kubectl get pods -n $NAMESPACE --field-selector=status.phase=Running -ocustom-columns=NAME:.metadata.name --no-headers" | |
echo -e "${DIM}Detecting Keycloak version...${NC}" | |
get_version | |
echo -e "${DIM}Retrieving files...${NC}" | |
get_files | |
echo -e "${G}Keycloak admin CLI is available in $OUTDIR.${NC}" | |
echo -e "${DIM}Run \"PATH=$OUTDIR:\$PATH\" to make it available system wide.${NC}" | |
} | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment