You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
5.2 KiB
216 lines
5.2 KiB
#!/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/>. |
|
# |
|
|
|
: <<'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<L<https://code.envrm.info/src/scripts-kubernetes>>. |
|
|
|
=head1 AUTHORS |
|
|
|
envrm B<L<https://code.envrm.info>>. |
|
|
|
=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 '<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 |
|
|
|
|