diff --git a/plugins/kube-ps1/README.md b/plugins/kube-ps1/README.md new file mode 100644 index 000000000..a572773a3 --- /dev/null +++ b/plugins/kube-ps1/README.md @@ -0,0 +1,76 @@ +Kubernetes prompt for zsh +========================= + +A Kubernetes (k8s) zsh prompt that displays the current cluster cluster +and the namespace. + +Inspired by several tools used to simplify usage of kubectl + +NOTE: If you are not using zsh, check out [kube-ps1](https://github.com/jonmosco/kube-ps1) designed for bash +as well as zsh. + +## Requirements + +The default prompt assumes you have the kubectl command line utility installed. It +can be obtained here: + +[Install and Set up kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) + +If using this with OpenShift, the oc tool needs installed. It can be obtained from here: + +[OC Client Tools](https://www.openshift.org/download.html) + +## Helper utilities + +There are several great tools that make using kubectl very enjoyable. + +[kubectx and kubenx](https://github.com/ahmetb/kubectx) are great for +fast switching between clusters and namespaces. + +## Prompt Structure + +The prompt layout is: + +``` +(|:) +``` + +Supported platforms: +* k8s - Kubernetes +* ocp - OpenShift + +## Install + +1. Clone this repository +2. Source the kube-ps1.zsh in your ~./.zshrc + +ZSH: +``` +source path/kube-ps1.sh +PROMPT='$(kube_ps1) ' +``` + +## Colors + +The colors are of my opinion. Blue was used as the prefix to match the Kubernetes +color as closely as possible. Red was chosen as the cluster name to stand out, and cyan +for the namespace. These can of course be changed. + +## Customization + +The default settings can be overridden in ~/.zshrc + +| Variable | Default | Meaning | +| :------- | :-----: | ------- | +| `KUBE_PS1_DEFAULT` | `true` | Default settings for the prompt | +| `KUBE_PS1_PREFIX` | `(` | Prompt opening character | +| `KUBE_PS1_DEFAULT_LABEL` | `⎈ ` | Default prompt symbol | +| `KUBE_PS1_SEPERATOR` | `\|` | Separator between symbol and cluster name | +| `KUBE_PS1_PLATFORM` | `kubectl` | Cluster type and binary to use | +| `KUBE_PS1_DIVIDER` | `:` | Separator between cluster and namespace | +| `KUBE_PS1_SUFFIX` | `)` | Prompt closing character | +| `KUBE_PS1_DEFAULT_LABEL_IMG` | `false` | Use Kubernetes img as the label: ☸️ | + +## Contributors + +Jared Yanovich diff --git a/plugins/kube-ps1/kube-ps1.zsh b/plugins/kube-ps1/kube-ps1.zsh new file mode 100644 index 000000000..e1cb4339d --- /dev/null +++ b/plugins/kube-ps1/kube-ps1.zsh @@ -0,0 +1,123 @@ +#!/bin/zsh + +# Kubernetes prompt helper for bash/zsh +# Displays current context and namespace + +# Copyright 2017 Jon Mosco +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Debug +[[ -n $DEBUG ]] && set -x + +setopt PROMPT_SUBST +add-zsh-hook precmd _kube_ps1_load +zmodload zsh/stat + +# Default values for the prompt +# Override these values in ~/.zshrc or ~/.bashrc +KUBE_PS1_DEFAULT="${KUBE_PS1_DEFAULT:=true}" +KUBE_PS1_PREFIX="(" +KUBE_PS1_DEFAULT_LABEL="${KUBE_PS1_DEFAULT_LABEL:="⎈ "}" +KUBE_PS1_DEFAULT_LABEL_IMG="${KUBE_PS1_DEFAULT_LABEL_IMG:=false}" +KUBE_PS1_SEPERATOR="|" +KUBE_PS1_PLATFORM="${KUBE_PS1_PLATFORM:="kubectl"}" +KUBE_PS1_DIVIDER=":" +KUBE_PS1_SUFFIX=")" +KUBE_PS1_UNAME=$(uname) +KUBE_PS1_LAST_TIME=0 + +kube_ps1_label () { + + [[ "${KUBE_PS1_DEFAULT_LABEL_IMG}" == false ]] && return + + if [[ "${KUBE_PS1_DEFAULT_LABEL_IMG}" == true ]]; then + local KUBE_LABEL="☸️ " + fi + + KUBE_PS1_DEFAULT_LABEL="${KUBE_LABEL}" + +} + +_kube_ps1_split() { + type setopt >/dev/null 2>&1 && setopt SH_WORD_SPLIT + local IFS=$1 + echo $2 +} + +_kube_ps1_file_newer_than() { + + local mtime + local file=$1 + local check_time=$2 + mtime=$(stat +mtime "${file}") + + [ "${mtime}" -gt "${check_time}" ] + +} + +_kube_ps1_load() { + # kubectl will read the environment variable $KUBECONFIG + # otherwise set it to ~/.kube/config + KUBECONFIG="${KUBECONFIG:=$HOME/.kube/config}" + + for conf in $(_kube_ps1_split : "${KUBECONFIG}"); do + # TODO: check existence of $conf + if _kube_ps1_file_newer_than "${conf}" "${KUBE_PS1_LAST_TIME}"; then + _kube_ps1_get_context_ns + return + fi + done +} + +_kube_ps1_get_context_ns() { + + # Set the command time + KUBE_PS1_LAST_TIME=$(date +%s) + + if [[ "${KUBE_PS1_DEFAULT}" == true ]]; then + local KUBE_BINARY="${KUBE_PS1_PLATFORM}" + elif [[ "${KUBE_PS1_DEFAULT}" == false ]] && [[ "${KUBE_PS1_PLATFORM}" == "kubectl" ]];then + local KUBE_BINARY="kubectl" + elif [[ "${KUBE_PS1_PLATFORM}" == "oc" ]]; then + local KUBE_BINARY="oc" + fi + + KUBE_PS1_CONTEXT="$(${KUBE_BINARY} config current-context)" + KUBE_PS1_NAMESPACE="$(${KUBE_BINARY} config view --minify --output 'jsonpath={..namespace}')" + # Set namespace to default if it is not defined + KUBE_PS1_NAMESPACE="${KUBE_PS1_NAMESPACE:-default}" + +} + +# source our symbol +kube_ps1_label + +# Build our prompt +kube_ps1 () { + local reset_color="%f" + local blue="%F{blue}" + local red="%F{red}" + local cyan="%F{cyan}" + + KUBE_PS1="${reset_color}$KUBE_PS1_PREFIX" + KUBE_PS1+="${blue}$KUBE_PS1_DEFAULT_LABEL" + KUBE_PS1+="${reset_color}$KUBE_PS1_SEPERATOR" + KUBE_PS1+="${red}$KUBE_PS1_CONTEXT${reset_color}" + KUBE_PS1+="$KUBE_PS1_DIVIDER" + KUBE_PS1+="${cyan}$KUBE_PS1_NAMESPACE${reset_color}" + KUBE_PS1+="$KUBE_PS1_SUFFIX" + + echo "${KUBE_PS1}" + +}