1 changed files with 196 additions and 0 deletions
@ -0,0 +1,196 @@
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env bash |
||||
|
||||
# |
||||
# Copyright (C) 2020, Maxim Lihachev, <envrm@yandex.ru> |
||||
# |
||||
# 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 <http://www.gnu.org/licenses/>. |
||||
# |
||||
|
||||
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 '<none>' | 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 '<li><a href="%s">%s</a></li>\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 |
||||
|
Loading…
Reference in new issue