#!/usr/bin/env bash # # Copyright (C) 2020, Maxim Lihachev, # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation, version 3. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # : <<'MAN' =head1 NAME kubectl-http is a wrapper for I<`kubectl proxy'> command which shows links to resources. =head1 USAGE kubectl http [all|pods|services] [standard kubectl selectors] =head1 OPTIONS -h --help = show this help -hl --hyperlinks = use terminal emulator's hyperlinks feature Basic selectors: all pods and services po pod pods pods svc service services services =head1 BUGS If you find a bug, please report it at B>. =head1 AUTHORS envrm B>. =cut MAN rstc="\033[00m" blue="\033[1;36m" green="\033[1;32m" magenta="\033[1;35m" red="\033[1;31m" yellow="\033[1;33m" USE_HYPERLINKS=false # Default resource's type to query TYPE=svc # Default kubectl's proxy endpoint PROXY_URL="http://127.0.0.1:8001" shortname() { local name_length=${2:-30} host=${1/:*} port=${1/*:} if [ "${#1}" -gt "$name_length" ]; then echo "$(head -c "$name_length" <<<"$host")~:$port" else echo "$1" fi } # Print horizontal rule hr() { echo -e -n "$magenta" printf "%${COLS}s" | sed 's/ /─/g' echo -e "$rstc" } usage() { sed -E -n '/^.*MAN/,/^MAN$/{//!p;}; /^MAN$/q' "$0" | sed -E 's/=head. |[LIBC]<|\b>*//g; /=cut/d' exit "${1:-0}" } footer() { >&2 echo >&2 hr >&2 echo -e " ${magenta}The index page with the links to resources: ${blue}${PROXY_URL}/index" >&2 hr >&2 echo } # Remove temporary directory cleanup() { rm -rf "$WWW_DIRECTORY" } kubectl_get() { local resource=${1:-svc} shift [ $# -eq 0 ] && local filter="-A" case "$resource" in all) { kubectl_get pods "$@"; kubectl_get svc "$@"; };; svc) eval kubectl get svc "$@" "$filter" --no-headers=true \ -o=custom-columns=NAME:.metadata.selfLink,PORTS:.spec.ports[*].port;; pods) eval kubectl get pod "$@" "$filter" --no-headers=true \ -o=custom-columns=NAME:.metadata.selfLink,PORTS:.spec.containers[*].ports[*].containerPort;; esac | grep -v '' | sed -E 's/[[:space:]]+/,/g' } die() { >&2 echo -e "${red}ERROR: ${*}${rstc}" exit 1 } # Clean up temporary files on exit trap cleanup EXIT SIGINT SIGHUP SIGQUIT KUBECTL_ARGS=() while [[ $# -gt 0 ]]; do key="$1" case $key in -h|--help) usage 0;; -hl|--hyperlinks) USE_HYPERLINKS=true; shift;; all) TYPE=all; shift;; po|pod|pods) TYPE=pods; shift;; svc|service|services) TYPE=svc; shift;; *) KUBECTL_ARGS+=("$1"); shift;; esac done set -- "${KUBECTL_ARGS[@]}" # Temporary directory for index.html file WWW_DIRECTORY=$(mktemp -d --tmpdir=/tmp KUBE_PROXY.XXXXXXXX) COLS=$(tput cols) declare -a SERVICES declare -A URLS mapfile -t SERVICES <<<"$(kubectl_get "$TYPE" "$@")" [ "${#SERVICES}" -eq 0 ] && die "No resource found" for service in "${SERVICES[@]}"; do svc_url=${service//,*/} ports=${service#*,} IFS=',' for port in $ports; do id="$(cut -d '/' -f 5,6,7 <<<"$svc_url"):${port}" URLS["$id"]="${PROXY_URL}${svc_url}:${port}/proxy" done done mapfile -d '' SORTED_URLS < <(printf '%s\0' "${!URLS[@]}" | sort -z) echo MAX_VAL_LENGTH=$(printf '%s\n' "${URLS[@]}" \ | awk '{ print length }' \ | sort -n -r \ | head -n 1) MAX_KEY_LENGTH=$(printf '%s\n' "${!URLS[@]}" \ | sed -E 's/\/[^\/]+$//' \ | awk '{ print length }' \ | sort -n -r \ | head -n 1) # ~ ' - ' + ':' + 5-digit of port + spaces MAX_NAME_LENGTH=$(( COLS - MAX_KEY_LENGTH - MAX_VAL_LENGTH - 15 )) for key in "${SORTED_URLS[@]}"; do printf '
  • %s
  • \n' "${URLS[$key]}" "$key" >> "${WWW_DIRECTORY}/index.html" IFS='/' read -r ns rs name <<<"$key" if [ "$USE_HYPERLINKS" == "true" ]; then # Address under hyperlink echo -e -n "- \e]8;;${URLS[$key]}\e\\\\" echo -e -n "${magenta}${ns}${rstc}/" # namespace echo -e -n "${yellow}${rs}${rstc}/" # resource's type echo -e "${green}${name}${rstc}\e]8;;\e\\" # resource's name else # - namespace/service http://127.0.0.1:8001/api/.../service:port/proxy echo -e -n " - ${magenta}${ns}${rstc}/" # namespace echo -e -n "${yellow}${rs}${rstc}/" # resource's type if [ "$MAX_NAME_LENGTH" -gt 10 ]; then echo -e -n "${green}$(shortname "$name" "$MAX_NAME_LENGTH") " # short resource's name else echo -e -n "${green}${name}\n - " # resource's name on the its own line fi echo -e "${blue}${URLS[$key]}${rstc}" # API URL fi done | column -t footer >&2 kubectl proxy --www="$WWW_DIRECTORY" --www-prefix=/index