From c6022128ec4298c5d60869f67e1fd8f95c42eb14 Mon Sep 17 00:00:00 2001 From: Lockszmith Date: Wed, 8 Nov 2023 18:10:59 -0500 Subject: [PATCH] Adding some k8s related tools --- fix-kubectl | 70 ++++++++++++ kube-get-secrets.sh | 135 ++++++++++++++++++++++ watch-k3s-app | 268 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 473 insertions(+) create mode 100755 fix-kubectl create mode 100755 kube-get-secrets.sh create mode 100755 watch-k3s-app diff --git a/fix-kubectl b/fix-kubectl new file mode 100755 index 0000000..205d4be --- /dev/null +++ b/fix-kubectl @@ -0,0 +1,70 @@ +#! /usr/bin/env bash +if [[ "$0" == "$SHELL" ]]; then + + if [[ -z "FIX_KUBECTL_RECALL" ]]; then + unset kubectl 2>/dev/null || unalias kubectl 2>/dev/null || true + + export KUBECONFIG=/etc/rancher/k3s/k3s.yaml + fi + + [[ 'function' == $(type -t kubectl-fix) ]] && unset kubectl-fix + + [[ ! -r "$HOME/.kube/config" ]] \ + || export KUBECONFIG="${KUBECONFIG:-$HOME/.kube/config}" + + if [[ -n "$(type -t 'k3s')" && -z "$(type -t 'kubectl')" ]]; then + if [[ -r "${KUBECONFIG}" ]]; then + kubectl() { k3s kubectl "${@}"; } + elif [[ -n "${KUBECONFIG}" && -e "${KUBECONFIG}" ]]; then + eval " + kubectl-fix() { + mkdir \"$HOME/.kube\" -p + if [[ -e \"\${KUBECONFIG}\" && ! -r \"$HOME/.kube/config\" ]]; then + sudo install --mod 600 --owner \"$USER\" \"\${KUBECONFIG}\" \"$HOME/.kube/config\" + unset KUBECONFIG + fi + FIX_KUBECTL_RECALL=1 . \"$BASH_SOURCE\" + }" + fi + fi + + if [[ -n "$(type -t 'kubectl')" ]]; then + + . <( kubectl completion ${SHELL##*/} ) + + if [[ -n "$(type -t 'kubectl-cnpg')" ]]; then + . <( kubectl cnpg completion ${SHELL##*/} ) + else + CNPG_VER="${CNPG_VER:-1.20.2}" + GH_URL=https://github.com/cloudnative-pg/cloudnative-pg + DEB_FILE="kubectl-cnpg_${CNPG_VER}_linux_x86_64.deb" + URL=${GH_URL}/releases/download/v${CNPG_VER}/${DEB_FILE} + printf '%s\n' \ + 'To download adn install cnpg kubectl plugin, run:' \ + " wget ${URL}" \ + " sudo dpkg -i $DEB_FILE" + + fi + + if [[ -n "$(type -t 'k3s')" ]]; then + . <( k3s completion ${SHELL##*/} ) + fi + + if [[ -n "$(type -t 'helm')" ]]; then + . <( helm completion ${SHELL##*/} 2>/dev/null ) + fi + + kg() { + kubectl get ${NS:+--namespace=}${NS:---all-namespaces} "${@}" | { sed -u 1q; sort; } + } + fi +elif [[ "$1" == '-' ]]; then + cat $0 +else + SCRIPT_NAME="$(basename $0)" + printf '%s\n' \ + "It seems $SCRIPT_NAME was invoked as a script. It should be sourced instead." \ + 'The easiest way is to call it like this:' \ + " $ . <( $SCRIPT_NAME - ) # Note the '-' after the script's name" \ + '' +fi diff --git a/kube-get-secrets.sh b/kube-get-secrets.sh new file mode 100755 index 0000000..0569f2a --- /dev/null +++ b/kube-get-secrets.sh @@ -0,0 +1,135 @@ +#! /usr/bin/env bash +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +USER_HOME=$HOME +[[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")" +. ${SHRC_D:-$SCRIPT_DIR}/01_util.functions + +set -e + +JSON=0 +if [[ " $* " =~ " --help " ]]; then + cat <&2 + $ZELLIJ_PATH ${INTAB:+action new-tab} --layout <( + get_zellij_layout +# ZELLIJ_PATH="$ZELLIJ_PATH" APP="$APP" NS="$NS" TAIL="$TAIL" \ +# envsubst < ~/watch-k3s-app.kdl + ) + else + unset ZELLIJ_PATH + export NOZELLIJ=1 APP="$APP" + $0 -- "charts" + $0 -- "pvc" + $0 -- "apps" + $0 -- "services" + $0 -- "events" + $0 -- "pods" + $0 -- "cnpg" + $0 -- "logs" + fi +} + +get_zellij_layout() { + cat - </dev/null | tr '\0' "${1:?Repeat character missing}" +} +visual_sleep() { + local SLEEP=$(( 0 + ${1:-2} )) MSG="${MSG:-Restarting in %s %s}" + tput sc; + while (( SLEEP > 0 )); do + tput el; printf "$MSG" "${SLEEP}s" "$(repeat_out . ${SLEEP})" + sleep 1s + tput rc 1; tput el; + (( SLEEP-=1 )) || true + done +} + +[[ "$1" == "--" ]] || APP=${APP:-${1}} +NS=${APP:+--namespace=ix-}${APP:---all-namespaces} + +case $1 in + "--help") + cat - < [ []] + +Invokation modifiers (environment variable): + [NOREPEAT=1] [NOWATCH=1] [SLEEP=3] $(basename $0) ... + +Description: + This script will pull from k3s the follwing: + charts (helm charts) + pvc + apps (deployment.apps) + services + events + pods + cnpg status (applicable for APP only) + contianer-logs (applicable for APP only) + + By default, if zellij exists, it will WATCH all of these for + changes in parallel. + If zellij doesn't exist, it will list all, SLEEP for a few seconds, + then REPEAT. + + To produce output to share in bug reports, calling with + NOREPEAT=1 NOWATCH=1 ... + will output all the details and exit. + + If an APP is specified, output is confined to the specific + namespace and service. Otherwise, it will output information about + k3s all-namespaces. + + * For cnpg status, the cnpg plugin needs to be installed. + On TrueNAS SCALE, this install might be required after a reboot. + +Zellij specific support + When zellij exists and running, zellij will create a set of panes + with the above list of views watching for changes in parallel. + + It maps - as the exit key. + and it maps as a Full-Screen toggle, to use it you need to + select inside a pane with a mouse, and then click the key. + + +USAGE + ;; + "--") + eval "${*:3}" + export KUBECONFIG + K_WATCH="${ZELLIJ_PATH:+--watch-only --no-headers}" + C_WATCH="watch -tcn4" + [[ -z "$NOZELLIJ" && -z "$NOWATCH" ]] || { K_WATCH=''; C_WATCH='eval'; } + + + case "$2" in + "charts") + ${C_WATCH} "helm list ${NS} | sort" + ;; + "pvc") + k3s kubectl get pvc ${NS} --sort-by='.metadata.creationTimestamp' + [[ -z "${K_WATCH}" ]] || k3s kubectl get pvc ${NS} ${K_WATCH} + ;; + "apps") + k3s kubectl get deployment.apps ${NS} --sort-by='.metadata.creationTimestamp' + [[ -z "${K_WATCH}" ]] || k3s kubectl get deployment.apps ${NS} ${K_WATCH} + ;; + "services") + k3s kubectl get services ${NS} --sort-by='.metadata.creationTimestamp' + [[ -z "${K_WATCH}" ]] || k3s kubectl get services ${NS} ${K_WATCH} + ;; + "events") + k3s kubectl get events ${NS} --sort-by='.metadata.creationTimestamp' + [[ -z "${K_WATCH}" ]] || k3s kubectl get events ${NS} ${K_WATCH} \ + ;; + "pods") + k3s kubectl get pods ${NS} --sort-by='.metadata.creationTimestamp' + [[ -z "${K_WATCH}" ]] || k3s kubectl get pods ${NS} \ + ${K_WATCH}; + ;; + "cnpg") + sleep 0.4s; + [[ -n "${APP}" ]] \ + && ${C_WATCH} "k3s kubectl cnpg status ${NS} ${APP}-cnpg-main" \ + || k3s kubectl get clusters.postgresql.cnpg.io ${NS} ${K_WATCH} + ;; + "logs") + MSG='N/A with --all-namespaces' + if [[ -n "${APP}" ]]; then + MSG="no pods active for $APP" + APP=($(k3s kubectl get pods ${NS} --output name | grep -E "^pod/$APP(-[^-]+){2}$")) + + FOLLOW='--follow' + [[ -z "$NOWATCH" ]] || { FOLLOW=''; TAIL=${TAIL:-40}; } + + while ! k3s kubectl logs ${NS} ${FOLLOW} ${TAIL:+--tail=${TAIL}} \ + "${APP}"; do + printf 'could not load logs, checking for previous logs...\n' + k3s kubectl logs ${NS} -p ${TAIL:+--tail=${TAIL}} "${APP}" \ + || printf "${MSG}" + + [[ -z "$NOWATCH" ]] || break; + visual_sleep ${SLEEP:-3} + done + fi + ;; + *) + printf "Don't know how to handle $2\n" 1>&2; + false; + ;; + esac + ;; + *) + while main "$1" && [[ -z "$NOREPEAT" ]]; do + tput cuu1; + visual_sleep ${SLEEP:-3} + done +esac +