diff --git a/tcdbinfo.sh b/tcdbinfo.sh index ecf54f6..eaa4e9d 100755 --- a/tcdbinfo.sh +++ b/tcdbinfo.sh @@ -1,28 +1,149 @@ -#!/bin/bash +#! /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 -# get namespaces -namespaces=$(k3s kubectl get secrets -A | grep -E "dbcreds|cnpg-main-urls" | awk '{print $1, $2}') +set -e -# iterate over namespaces -( printf "Application | Username | Password | Address | Port\n" -echo "$namespaces" | while read ns secret; do - # extract application name - app_name=$(echo "$ns" | sed 's/^ix-//') - if [ "$secret" = "dbcreds" ]; then - creds=$(k3s kubectl get secret/$secret --namespace "$ns" -o jsonpath='{.data.url}' | base64 -d) - else - creds=$(k3s kubectl get secret/$secret --namespace "$ns" -o jsonpath='{.data.std}' | base64 -d) +JSON=0 +if [[ $# -gt 0 && "$1" =~ ^-- ]]; then + if [[ "$1" == "--help" ]]; then + cat <] [app1] [app...] + +Description: + When running the script (as root) without any arguments, it will list + all TrueChart apps with database credential secrets. + + The scope can be narrowed by passing app name arguments. + + The FIRST argument, however, will affect the output: + --help - Display this usage text. + --json - Output all fields in JSON format + --cols= - Where can be empty, a preset name or + a comma delimited list of columns. + + An empty string will show the default preset. + + Presets: + default - The default preset + safe - Similar to the default, but without + the password column + debug - Full connection URL with password + masked with asterisks ('******') + + Columns: + name - App name, preceding with ix- + raw_url - DB connection URL as it is stored + in kubernetes secrets. + This can only be used within the + same pod + url - Fully formed URL. + safeurl - Same as url, with password masked. + protocol - Connection protocol. + username - DB Username + password - Password + pwd_len - Password length + host - Hostname + port - Conection Port + dbname - DB name + + When '--cols' is not specified, default behavious can be overridden + by exporting the TCDBCOLS envrionment variable. + + --cols takes presedence, and overrides any behavior dictated by the + environment variable + +USAGE + exit 0 + elif [[ "$1" == "--json" ]]; then + JSON=1 + elif [[ "$1" =~ ^--cols ]]; then + [[ "$1" =~ ^--cols= ]] || shift + TCDBCOLS="${1#--cols=}" fi - - # get username, password, addresspart, and port - username=$(echo "$creds" | awk -F '//' '{print $2}' | awk -F ':' '{print $1}') - password=$(echo "$creds" | awk -F ':' '{print $3}' | awk -F '@' '{print $1}') - addresspart=$(echo "$creds" | awk -F '@' '{print $2}' | awk -F ':' '{print $1}') - port=$(echo "$creds" | awk -F ':' '{print $4}' | awk -F '/' '{print $1}') + shift +fi +TCDBCOLS="${TCDBCOLS:-default}" +case "$TCDBCOLS" in + 'default' ) + TCDBCOLS='name,protocol,username,password,pwd_len,host,port,dbname' + ;; + 'safe' ) + TCDBCOLS='name,protocol,username,pwd_len,host,port,dbname' + ;; + 'debug' ) + TCDBCOLS='name,safeurl' + ;; +esac - # construct full address - full_address="${addresspart}.${ns}.svc.cluster.local" +require_root + +QUERY_NAMESPACE=' -A' +[[ $# -eq 0 ]] || QUERY_NAMESPACE=$( printf -- ' --namespace=ix-%s' "${@}" ) + +jqcode=' +.items[] | select(.metadata.name|test("(dbcreds|cnpg-main-urls)$$")) +| { + "name": .metadata.namespace, + "app": .metadata.labels."app.kubernetes.io/instance", + "url": (if .data.url != null then .data.url else .data.std end) | @base64d, + "data": ( + (if .data.url != null then .data.url else .data.std end) | + @base64d | + match("(.*)://(.+):(.+)@([^:]+)(:(\\d+))?/(.*)$") | .captures | { + "protocol": .[0].string, + "username": .[1].string, + "password": .[2].string, + "passwordlen": .[2].string | length, + "host": .[3].string, + "safeport": .[4].string, + "port": .[5].string, + "dbname": .[6].string, + } + ) +} | { + "name": .name, + "raw_url": .url, + "url": "\(.data.protocol)://\(.data.username)@\(.data.password):\(.data.host).\(.name).svc.cluster.local\(.data.safeport)/\(.data.dbname)", + "safeurl": "\(.data.protocol)://\(.data.username)@*******:\(.data.host).\(.name).svc.cluster.local\(.data.safeport)/\(.data.dbname)", + "protocol": .data.protocol, + "username": .data.username, + "password": .data.password, + "pwd_len": .data.passwordlen, + "host": "\(.data.host).\(.name).svc.cluster.local", + "port": .data.port, + "dbname": .data.dbname +} +' + +json_results=$( + <<<"${QUERY_NAMESPACE}" \ + xargs -n1 k3s kubectl \ + get secrets \ + --output json \ + | jq "$jqcode" +) + +[[ "$JSON" -eq 1 ]] && echo "$json_results" && exit 0 + +JQ_COLS="[$( <<<"\"$TCDBCOLS\"" \ + jq -r '. | split(",") | map( "\"\(.)\"" ) | join(",")' +)]" +JQ_COLS_REGEX="$( <<<"$JQ_COLS" \ + jq -r '. | map ( ".\(.)" ) | join(",")' +)" + +jqcode=' + ['"${JQ_COLS^^}"'] + [.[] | + ['"$JQ_COLS_REGEX"'] + ] | .[] | join("|") +' + +<<<"$json_results" jq -s '.' | jq -r "$jqcode" | column -t -s "|" + +exit 0 - # print results with aligned columns - printf "%s | %s | %s | %s | %s\n" "$app_name" "$username" "$password" "$full_address" "$port" -done ) | column -t -s "|"