Last active
November 18, 2022 19:40
-
-
Save emmeowzing/b9425e3cad33f871e278d135ea8bad1a to your computer and use it in GitHub Desktop.
Switch Rancher clusters from your terminal, updating / merging your kube config
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
# Connect to one of our clusters via Rancher's CLI. | |
set -e | |
_RANCHER_URL="${1:-$RANCHER_URL}" | |
_RANCHER_TOKEN="${2:-$RANCHER_TOKEN}" | |
DEFAULT_CLUSTER="${3:-development} | |
## | |
# Print an error message to stderr. | |
_error() | |
{ | |
if [ $# -ne 1 ] | |
then | |
printf "Expected 1 argument to \`_error\`, received %s.\\n" "$#" >&2 | |
exit 1 | |
fi | |
local message | |
message="$1" | |
printf "\e[2m\e[1mERROR\e[0m\e[2m: %s\e[0m\\n" "$message" >&2 | |
} | |
## | |
# Print a warning message to stderr. | |
_warning() | |
{ | |
if [ $# -ne 1 ] | |
then | |
_error "Expected 1 argument to \`_warning\`, received $#.\\n" | |
return 1 | |
fi | |
local message | |
message="$1" | |
printf "\e[2m\e[1mWARNING\e[0m\e[2m: %s\e[0m\\n" "$message" >&2 | |
} | |
## | |
# Get a user's response on a question to set environment variables. | |
# Call like `X="$(response "Enter your name: " "Emma")"` | |
# To set a default value on `X` if the user just hits enter. | |
response() | |
{ | |
if [ $# -eq 0 ] | |
then | |
_error "Must submit at least 2 arguments to \`response\` function for IO." | |
return 1 | |
elif [ $# -gt 2 ] | |
then | |
_warning "received >2 arguments at response function, ignoring extra arguments" | |
fi | |
question="$1" | |
default="$2" | |
read -r -p "$question" var | |
if [ "$var" ] | |
then | |
printf "%s" "$var" | |
else | |
if [ "$default" ] | |
then | |
_warning "Defaulting to $default" | |
else | |
_warning "Attempted to default, but no value given, returning \"\"" | |
fi | |
printf "%s" "$default" | |
fi | |
return 0 | |
} | |
if command -v pass >/dev/null && [ -z "$_RANCHER_TOKEN" ]; then | |
_RANCHER_TOKEN="$(pass show rancher-token)" | |
elif [ -z "$_RANCHER_TOKEN" ]; then | |
_error "must set RANCHER_TOKEN environment variable or set up pass" | |
exit 1 | |
fi | |
# Ensure we have some binaries this script requires. | |
if ! command -v kubectl >/dev/null; then | |
_error "must install the kubectl CLI: https://kubernetes.io/docs/tasks/tools/" | |
exit 1 | |
fi | |
if ! command -v rancher >/dev/null; then | |
_error "must install the Rancher CLI: https://github.com/rancher/cli" | |
exit 1 | |
fi | |
if ! command -v mapfile >/dev/null; then | |
_error "must upgrade bash (brew install bash)" | |
exit 1 | |
fi | |
if ! command -v column >/dev/null; then | |
_error "must upgrade util-linux (apt install util-linux)" | |
exit 1 | |
fi | |
# Ensure the expected directory structure is present. | |
if [ ! -d "$HOME"/.kube ]; then | |
_warning "setting up ~/.kube/config, directory doesn't exist" | |
mkdir "$HOME"/.kube | |
touch "$HOME"/.kube/config | |
elif [ -d "$HOME"/.kube ] && [ ! -f "$HOME"/.kube/config ]; then | |
_warning "setting up ~/.kube/config, directory doesn't exist" | |
touch "$HOME"/.kube/config | |
fi | |
## | |
# Switch rancher cluster contexts. | |
rancher_switch_cluster() | |
{ | |
local cluster="$1" | |
printf "Info: Attempting to create ~/.kube/config for cluster \"%s\"\\n" "$cluster" | |
if ! rancher clusters kf "$cluster" > config.new; then | |
if [ -f config.new ]; then rm config.new; fi | |
exit 1 | |
fi | |
# Flatten new kubeconfig into existing config and clean up. | |
cp "$HOME"/.kube/config "$HOME"/.kube/config.bak | |
KUBECONFIG=config.new:"$HOME"/.kube/config.bak kubectl config view --flatten > "$HOME"/.kube/config && \ | |
rm "$HOME"/.kube/config.bak config.new && \ | |
printf "Info: Successfully switched context to cluster \"%s\"\\n" "$cluster" | |
} | |
## | |
# Provide an interface to connect to a particular Rancher cluster. | |
rancher_select_cluster() | |
{ | |
local cluster _cluster i n clusters selected_cluster | |
mapfile -t clusters < <(rancher clusters ls --format "{{ .Cluster.Name }}") | |
clusters+=("all") | |
i=1 | |
n="${#clusters[@]}" | |
while true; do | |
printf "Select a cluster:\\n\\n" | |
for cluster in "${clusters[@]}"; do | |
printf "(%s) %s\\n" "$i" "$cluster" | |
(( i += 1 )) | |
done | column -t && printf "\\n" | |
selected_cluster="$(response "Select a cluster (by name or index): " "${DEFAULT_CLUSTER}")" | |
# Ensure this cluster is in the list (slow, linear search), either by index or name, and call a context switch. | |
i=1 | |
for cluster in "${clusters[@]}"; do | |
if [ "$selected_cluster" = "$cluster" ]; then | |
if [ "$selected_cluster" != "all" ]; then | |
rancher_switch_cluster "$selected_cluster" | |
else | |
# Loop over all clusters and merge their configs to a dev's local kubeconfig, defaulting to ${DEFAULT_CLUSTER}. | |
for _cluster in "${clusters[@]}"; do | |
if [ "$_cluster" != "all" ]; then | |
rancher_switch_cluster "$_cluster" | |
fi | |
done | |
kubectl config use-context "${DEFAULT_CLUSTER}" | |
fi | |
return 0 | |
elif [ "$selected_cluster" = "$i" ]; then | |
if [ "${clusters[$(( i - 1 ))]}" != "all" ]; then | |
rancher_switch_cluster "${clusters[$(( i - 1 ))]}" | |
else | |
for _cluster in "${clusters[@]}"; do | |
if [ "$_cluster" != "all" ]; then | |
rancher_switch_cluster "$_cluster" | |
fi | |
done | |
kubectl config use-context "${DEFAULT_CLUSTER}" | |
fi | |
return 0 | |
elif [ "$i" -eq "$n" ]; then | |
_error "Cluster \"$selected_cluster\" does not exist, try again" | |
i=1 | |
break | |
fi | |
(( i += 1 )) | |
done | |
done | |
} | |
## | |
# Log in to our Rancher server to connect to clusters. | |
rancher_login() | |
{ | |
local token="$1" | |
local url="$2" | |
echo 1 | rancher login -t "$token" "$url" >/dev/null | |
} | |
rancher_login "$_RANCHER_TOKEN" "$_RANCHER_URL" | |
rancher_select_cluster | |
unset -v _RANCHER_TOKEN _RANCHER_URL DEFAULT_CLUSTER | |
unset -f _error _warning response rancher_select_cluster rancher_login rancher_switch_cluster |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment