diff --git a/kubectl-http b/kubectl-http new file mode 100755 index 0000000..8495307 --- /dev/null +++ b/kubectl-http @@ -0,0 +1,196 @@ +#!/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 . +# + +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() { + echo -e "$(basename "$0") is a wrapper for \`kubectl proxy' command which shows links to resources.\n" + echo -e "USAGE: $(basename "$0" | tr '-' ' ') [all|pods|services] [standard kubectl selectors]\n" + + echo -e "Command line arguments:" + echo -e " -h --help show this help" + echo -e " -hl --hyperlinks use terminal emulator's hyperlinks feature" + + echo + echo -e "Basic selectors:" + echo -e " all pods and services" + echo -e " po pod pods pods" + echo -e " svc service services services" + + echo + 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 +