Add kubens tool for namespace switching

Fixes #1. Now kubectx also ships with kubens.

Extracted utility functions to a utils.bash file, loaded
from ../include/utils.bash.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
This commit is contained in:
Ahmet Alp Balkan 2017-05-09 16:23:22 -07:00
parent c49f975e45
commit d441505348
No known key found for this signature in database
GPG Key ID: 5C02521D7B216AD6
7 changed files with 218 additions and 11 deletions

View File

@ -3,16 +3,23 @@ class Kubectx < Formula
homepage "https://github.com/ahmetb/kubectx" homepage "https://github.com/ahmetb/kubectx"
url "https://github.com/ahmetb/kubectx/archive/v0.2.0.tar.gz" url "https://github.com/ahmetb/kubectx/archive/v0.2.0.tar.gz"
sha256 "28069aff84aaba1aa38f42d3b27e64e460a5c0651fb56b1748f44fd832d912e3" sha256 "28069aff84aaba1aa38f42d3b27e64e460a5c0651fb56b1748f44fd832d912e3"
head "https://github.com/ahmetb/kubectx.git", :branch => "master"
bottle :unneeded bottle :unneeded
def install def install
bin.install "kubectx" bin.install "kubectx"
bin.install "kubens"
include.install "utils.bash"
bash_completion.install "completion/kubectx.bash" => "kubectx" bash_completion.install "completion/kubectx.bash" => "kubectx"
bash_completion.install "completion/kubens.bash" => "kubens"
zsh_completion.install "completion/kubectx.zsh" => "_kubectx" zsh_completion.install "completion/kubectx.zsh" => "_kubectx"
zsh_completion.install "completion/kubens.zsh" => "_kubens"
end end
test do test do
system "which", "kubectx" system "which", "kubectx"
system "which", "kubens"
end end
end end

View File

@ -1,3 +1,7 @@
This repository provides both `kubectx` and `kubens` tools. Purpose of this
project is to provide an utility and facilitate discussion about how `kubectl`
can manage contexts better.
# kubectx(1) # kubectx(1)
kubectx is an utility to manage and switch between kubectl(1) contexts. kubectx is an utility to manage and switch between kubectl(1) contexts.
@ -14,7 +18,7 @@ USAGE:
Purpose of this project is to provide an utility and facilitate discussion Purpose of this project is to provide an utility and facilitate discussion
about how `kubectl` can manage contexts better. about how `kubectl` can manage contexts better.
## Usage ### Usage
```sh ```sh
$ kubectx minikube $ kubectx minikube
@ -34,6 +38,38 @@ Aliased "gke_ahmetb_europe-west1-b_dublin" as "dublin".
`kubectx` also supports <kbd>Tab</kbd> completion, which helps with long context `kubectx` also supports <kbd>Tab</kbd> completion, which helps with long context
names. names.
-----
# kubens(1)
kubens is an utility to switch between Kubernetes namespaces.
```
USAGE:
kubens : list the namespaces
kubens <NAME> : change the active namespace
kubens - : switch to the previous namespace
kubens -h,--help : show this message
```
### Usage
```sh
$ kubens kube-system
Context "test" set.
Active namespace is "kube-system".
$ kubens -
Context "test" set.
Active namespace is "default".
```
`kubectx` also supports <kbd>Tab</kbd> completion, which helps with long context
names.
-----
## Installation ## Installation
For macOS: For macOS:

8
completion/kubens.bash Normal file
View File

@ -0,0 +1,8 @@
_kube_namespaces()
{
local curr_arg;
curr_arg=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "- $(kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}')" -- $curr_arg ) );
}
complete -F _kube_namespaces kubens

2
completion/kubens.zsh Normal file
View File

@ -0,0 +1,2 @@
#compdef kubens
_arguments "1: :(- $(kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}'))"

19
kubectx
View File

@ -21,6 +21,13 @@
set -eou pipefail set -eou pipefail
IFS=$'\n\t' IFS=$'\n\t'
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
if [[ -f "${SCRIPT_DIR}/utils.bash" ]]; then
source "${SCRIPT_DIR}/utils.bash"
else
source "${SCRIPT_DIR}/../include/utils.bash"
fi
KUBECTX="${HOME}/.kube/kubectx" KUBECTX="${HOME}/.kube/kubectx"
usage() { usage() {
@ -35,14 +42,6 @@ EOF
exit 1 exit 1
} }
current_context() {
kubectl config view -o=jsonpath='{.current-context}'
}
get_contexts() {
kubectl config get-contexts --output=name
}
list_contexts() { list_contexts() {
set -u pipefail set -u pipefail
local cur="$(current_context)" local cur="$(current_context)"
@ -88,7 +87,6 @@ set_context() {
} }
swap_context() { swap_context() {
set -e
local ctx="$(read_context)" local ctx="$(read_context)"
if [[ -z "${ctx}" ]]; then if [[ -z "${ctx}" ]]; then
echo "error: No previous context found." >&2 echo "error: No previous context found." >&2
@ -138,7 +136,8 @@ main() {
elif [[ "${1}" == '-h' || "${1}" == '--help' ]]; then elif [[ "${1}" == '-h' || "${1}" == '--help' ]]; then
usage usage
elif [[ "${1}" =~ ^-(.*) ]]; then elif [[ "${1}" =~ ^-(.*) ]]; then
echo "error: unrecognized flag" >&2; usage echo "error: unrecognized flag \"${1}\"" >&2
usage
elif [[ "${1}" =~ (.+)=(.+) ]]; then elif [[ "${1}" =~ (.+)=(.+) ]]; then
alias_context "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}" alias_context "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}"
else else

144
kubens Executable file
View File

@ -0,0 +1,144 @@
#!/bin/bash
#
# kubenx(1) is a utility to switch between Kubernetes namespaces.
# Copyright 2017 Google Inc.
#
# 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.
[[ -n $DEBUG ]] && set -x
set -eou pipefail
IFS=$'\n\t'
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
if [[ -f "${SCRIPT_DIR}/utils.bash" ]]; then
source "${SCRIPT_DIR}/utils.bash"
else
source "${SCRIPT_DIR}/../include/utils.bash"
fi
KUBENS_DIR="${HOME}/.kube/kubens"
usage() {
cat <<"EOF"
USAGE:
kubens : list the namespaces in the current context
kubens <NAME> : change the active namespace of current context
kubens - : switch to the previous namespace in this context
kubens -h,--help : show this message
EOF
exit 1
}
current_namespace() {
local cur_ctx=$(current_context)
ns="$(kubectl config view -o=jsonpath="{.contexts[?(@.name==\"${cur_ctx}\")].context.namespace}")"
if [[ -z "${ns}" ]]; then
echo "default"
else
echo "${ns}"
fi
}
namespace_file() {
local ctx="${1}"
echo "${KUBENS_DIR}/${ctx}"
}
read_namespace() {
local f="$(namespace_file "${1}")"
[[ -f "${f}" ]] && cat "${f}"
}
save_namespace() {
mkdir -p "${KUBENS_DIR}"
local f="$(namespace_file "${1}")"
local saved="$(read_namespace "${1}")"
if [[ "${saved}" != "${2}" ]]; then
printf %s "${2}" > "${f}"
fi
}
switch_namespace() {
local ctx="${1}"
kubectl config set-context "${ctx}" --namespace="${2}"
echo "Active namespace is \"${2}\".">&2
}
set_namespace() {
local ctx="$(current_context)"
local prev="$(current_namespace)"
if grep -q ^"${1}"\$ <(get_namespaces); then
switch_namespace "${ctx}" "${1}"
if [[ "${prev}" != "${1}" ]]; then
save_namespace "${ctx}" "${prev}"
fi
else
echo "error: no namespace exists with name \"${1}\".">&2
exit 1
fi
}
list_namespaces() {
local cur="$(current_namespace)"
local yellow=$(tput setaf 3)
local darkbg=$(tput setab 0)
local normal=$(tput sgr0)
for c in $(get_namespaces); do
if [[ "${c}" = "${cur}" ]]; then
echo "${darkbg}${yellow}${c}${normal}"
else
echo "${c}"
fi
done
}
swap_namespace() {
local ctx="$(current_context)"
local ns="$(read_namespace "${ctx}")"
if [[ -z "${ns}" ]]; then
echo "error: No previous namespace found for current context." >&2
exit 1
fi
set_namespace "${ns}"
}
main() {
if [[ "$#" -eq 0 ]]; then
list_namespaces
elif [[ "$#" -eq 1 ]]; then
if [[ "${1}" == '-h' || "${1}" == '--help' ]]; then
usage
elif [[ "${1}" == "-" ]]; then
swap_namespace
elif [[ "${1}" =~ ^-(.*) ]]; then
echo "error: unrecognized flag \"${1}\"" >&2
usage
elif [[ "${1}" =~ (.+)=(.+) ]]; then
alias_context "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}"
else
set_namespace "${1}"
fi
else
echo "error: too many flags" >&2
usage
fi
}
main "$@"

11
utils.bash Normal file
View File

@ -0,0 +1,11 @@
current_context() {
kubectl config view -o=jsonpath='{.current-context}'
}
get_contexts() {
kubectl config get-contexts -o=name | sort -n
}
get_namespaces() {
kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}'
}