#!/usr/bin/env bash # vim:ts=4:sts=4:sw=4:et # # Author: Hari Sekhon # Date: 2019-07-28 14:56:41 +0100 (Sun, 28 Jul 2019) # # https://github.com/harisekhon/bash-tools # # License: see accompanying Hari Sekhon LICENSE file # # If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish # # https://www.linkedin.com/in/harisekhon # # ============================================================================ # # K u b e r n e t e s / O p e n S h i f t # ============================================================================ # for x in kubectl oc; do if type -P "$x" &>/dev/null; then # shellcheck disable=SC1090 source <("$x" completion bash) fi done # minishift oc-env > ~/.minishift.env if [ -f ~/.minishift.env ]; then # remove .minishift.env if it causes errors, which can happen if it was generated when there was no MiniShift VM running # shellcheck disable=SC1090 . ~/.minishift.env || rm -f ~/.minishift.env fi #if [ -f "/usr/local/opt/kube-ps1/share/kube-ps1.sh" ]; then # . "/usr/local/opt/kube-ps1/share/kube-ps1.sh" # # overriden in prompt.sh which is evaluated later so this is sourced there # #PS1='$(kube_ps1)'" $PS1" #fi # ============================================================================ # # 'k8s-app' label is set by dashboard creation but who uses that k8s_get_pod_opts="-o wide -L app,env" alias po='k get po $k8s_get_pod_opts' alias kapply='k apply -f' alias kapp=kapply alias wp=watchpods alias ke=kubeexec alias kg='k get' alias ka='k apply' alias kl='k logs' alias kshell='kube-shell' alias kubesh='kube-shell' alias use="k config use-context" alias contexts="k config get-contexts" #alias context="k config current-context" context(){ k config current-context; } # contexts has this info and is more useful #alias clusters="k config get-clusters" alias kcd='k config set-context $(kubectl config current-context) --namespace' alias menv='eval $(minikube docker-env)' # ============================================================================ # kubectl_opts="${KUBECTL_OPTS:-}" # set K8S_NAMESPACE in local .bashrc or similar files for environments where your ~/.kube/config # gets regenerated daily with certification authentication from a kerberos login script, which # resets the 'kcd bigdata' namespace change. This way you automatically send the right namespace every time if [ "${K8S_NAMESPACE:-}" ]; then kubectl_opts="-n $K8S_NAMESPACE" fi # TODO: might split this later oc_opts="$kubectl_opts" # ============================================================================ # # oc() and kubectl() fix future invocations of k() to the each command if you want to explicitly switch between them oc(){ export KUBERNETES_CLI=oc # shellcheck disable=SC2086 command oc $oc_opts "$@" } kubectl(){ export KUBERNETES_CLI=kubectl # shellcheck disable=SC2086 command kubectl $kubectl_opts "$@" } k(){ local opts # more efficient than forking to check history every time if [ -n "$KUBERNETES_CLI" ]; then case "$KUBERNETES_CLI" in kubectl) opts="$kubectl_opts" ;; oc) opts="$oc_opts" ;; *) echo "invalid command '$KUBERNETES_CLI' listed in \$KUBERNETES_CLI (must be either 'kubectl' or 'oc' depending on whether you are using straight Kubernetes or OpenShift). Fix the variable or unset it to auto-detect when calling the k() function" return ;; esac # shellcheck disable=SC2086 command "$KUBERNETES_CLI" $opts "$@" else # shellcheck disable=SC2086 case "$(k8s_or_openshift)" in openshift) command oc $oc_opts "$@" export KUBERNETES_CLI=oc ;; k8s|*) command kubectl $kubectl_opts "$@" export KUBERNETES_CLI=kubectl ;; esac fi } krun(){ local image="$1" local name="${image//\//-}" shift # sleep infinity only works on some distros k run --generator=run-pod/v1 "$name" --image "$image" -ti -- /bin/sh } kexec(){ local line local name="${1//\//-}" if [ -z "$name" ]; then echo "usage: kexec " return 1 fi for ((i=0;i<100;i++)); do line="$(k get po | grep -F "$name")" if [ -z "$line" ]; then echo "No pod matching name $name found!" return 1 fi name="$(awk '/Running/{print $1}' <<< "$line")" if [ -n "$name" ]; then break fi echo "waiting for pod to start running..." sleep 1 done k exec -ti "$name" -- /bin/sh } # looks like both of these work on OpenShift context # # 'kubectl get pods' # # 'oc get pods' # figure out if we're using k8s or openshift via most recent commands - return either 'k8s' or 'openshift' k8s_or_openshift(){ local last_k8s_cmd last_k8s_cmd="$( history | grep -v history | grep -Eo -e '\' \ -e '\' \ -e '\' \ -e '\' | tail -n 1 )" case "$last_k8s_cmd" in oc|minishift) echo openshift # these end up in a subshell so aren't really useful, set in k() instead #export KUBERNETES_CLI=oc ;; kubectl|minikube) echo k8s #export KUBERNETES_CLI=kubectl ;; *) echo unknown ;; esac } oc_get_pods(){ # shellcheck disable=SC2086 oc get pods $k8s_get_pod_opts } k8s_get_pods(){ # shellcheck disable=SC2086 k get pods $k8s_get_pod_opts } get_pods(){ #case "$(k8s_or_openshift)" in # openshift) oc_get_pods # ;; # k8s) k8s_get_pods # ;; # *) k8s_get_pods # ;; #esac # # k8s functions now include k8s vs oc detection, no need for above or would end up double calling k8s_or_openshift k8s_get_pods } export -f get_pods get_pod(){ local filter="${1:-.*}" get_pods | grep -v '^NAME[[:space:]]' | grep Running | awk "/$filter/{print \$1; exit}" } watchpods(){ # watch on Mac (brew installed) doesn't have -x switch and doesn't work on even 'export -f function' # leave using kubectl call for now as that works on openshift too watch " echo 'Context: ' echo kubectl config current-context echo echo echo 'Pods:' echo kubectl $kubectl_opts get pods $k8s_get_pod_opts 2>&1 echo " } kdesc(){ k describe "$@" } kdp(){ kdesc pods "$@" } kdelp(){ k delete pod "$@" } kubeexec(){ local pod pod="$(get_pod "$1")" shift k exec -ti "$pod" "$@" /bin/sh } # Getting token works on stock Kubernetes but not OpenShift due to stricter defaults # # Error from server (Forbidden): secrets is forbidden: User "developer" cannot list secrets in the namespace "kube-system": no RBAC policy matched # error: resource name may not be empty # ## even after 'oc login' as system/admin # # Error from server (Forbidden): secrets is forbidden: User "system" cannot list secrets in the namespace "kube-system": no RBAC policy matched # error: resource name may not be empty # k8s_get_token(){ kubectl describe secret -n kube-system \ "$(kubectl get secrets -n kube-system | grep default | cut -f1 -d ' ')" | grep '^token' | awk '{print $2}' } k8s_get_api(){ local context local cluster context="$(context)" cluster="$(k config view -o jsonpath="{.contexts[?(@.name == \"$context\")].context.cluster}")" k config view -o jsonpath="{.clusters[?(@.name == \"$cluster\")].cluster.server}" # or if you have jq installed: # k get --raw=/api | jq -r '.serverAddressByClientCIDRs[0].serverAddress' echo } # run kubectl commands against multiple clusters kclusters(){ for context in $(kubectl config get-contexts -o=name --kubeconfig clusters.yaml); do kubectl "$@" --kubeconfig clusters.yaml --context="$context" done } # to kubectl apply manifests to both clusters for multi-cluster deployments kclustersapply(){ kclusters apply -f "$@" # eg. manifests }