mirror of
https://github.com/ahmetb/kubectx.git
synced 2026-03-18 11:52:24 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a7358ce67 | ||
|
|
8e413fc8ac | ||
|
|
7e10232fdd | ||
|
|
572b3e83d9 | ||
|
|
03f24f2625 | ||
|
|
8dec9cf004 | ||
|
|
a376b02e88 | ||
|
|
da3f814280 | ||
|
|
d441505348 | ||
|
|
c49f975e45 | ||
|
|
8c6cf84801 | ||
|
|
d04543ffef | ||
|
|
d1c04555f4 | ||
|
|
6e2f181518 |
@@ -1,18 +1,26 @@
|
|||||||
class Kubectx < Formula
|
class Kubectx < Formula
|
||||||
desc "Tool that can switch between kubectl contexts easily and create aliases"
|
desc "Tool that can switch between kubectl contexts easily and create aliases"
|
||||||
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.3.0.tar.gz"
|
||||||
sha256 "9fb6557416e4be3ef7e9701527f89fa73a1a0545a3cafbe6bed7527061c6cfb7"
|
sha256 "720b6d9a960a7583983ac84c90d2ff89f4494584cf82a3abb5d4e66e72444621"
|
||||||
|
head "https://github.com/ahmetb/kubectx.git", :branch => "short-names"
|
||||||
bottle :unneeded
|
bottle :unneeded
|
||||||
|
|
||||||
|
option "with-short-names", "link as \"kctx\" and \"kns\" instead"
|
||||||
|
|
||||||
def install
|
def install
|
||||||
bin.install "kubectx"
|
bin.install "kubectx" => build.with?("short-names") ? "kctx" : "kubectx"
|
||||||
|
bin.install "kubens" => build.with?("short-names") ? "kns" : "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", build.with?("short-names") ? "kctx" : "kubectx"
|
||||||
|
system "which", build.with?("short-names") ? "kns" : "kubens"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
58
README.md
58
README.md
@@ -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.
|
||||||
|
|
||||||
## Example
|
### Usage
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ kubectx minikube
|
$ kubectx minikube
|
||||||
@@ -31,11 +35,57 @@ Context "dublin" set.
|
|||||||
Aliased "gke_ahmetb_europe-west1-b_dublin" as "dublin".
|
Aliased "gke_ahmetb_europe-west1-b_dublin" as "dublin".
|
||||||
```
|
```
|
||||||
|
|
||||||
[Set up `bash` and `zsh` completion →](completion/README.md)
|
`kubectx` supports <kbd>Tab</kbd> completion on bash/zsh shells to help with
|
||||||
|
long context names. You don't have to remember full context names anymore.
|
||||||
|
|
||||||
### Help wanted
|
-----
|
||||||
|
|
||||||
- [ ] homebrew formula/tap that installs the script and completions
|
# 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".
|
||||||
|
```
|
||||||
|
|
||||||
|
`kubens` also supports <kbd>Tab</kbd> completion on bash/zsh shells.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
**For macOS:**
|
||||||
|
|
||||||
|
> Use [Homebrew](https://brew.sh/) package manager:
|
||||||
|
>
|
||||||
|
> brew tap ahmetb/kubectx https://github.com/ahmetb/kubectx.git
|
||||||
|
> brew install kubectx
|
||||||
|
> this will also set up bash/zsh completion scripts automatically.
|
||||||
|
|
||||||
|
Running `brew install` with `--with-short-names` will install tools with names
|
||||||
|
`kctx` and `kns` to prevent prefix collision with `kubectl` name.
|
||||||
|
|
||||||
|
**Other platforms:**
|
||||||
|
|
||||||
|
> Download the `kubectx` script, make it executable and add it to your PATH. You
|
||||||
|
> can also install bash/zsh [completion scripts](completion/) manually.
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
kubectx provides shell completion scripts to complete context names, making it
|
|
||||||
even faster to switch between contexts easily.
|
|
||||||
|
|
||||||
## Bash setup
|
|
||||||
|
|
||||||
Copy the `kubectx.bash` file to your HOME directory:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cp kubectx.bash ~/.kubectx.bash
|
|
||||||
```
|
|
||||||
|
|
||||||
And source it in your `~/.bashrc` file by adding the line:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
[ -f ~/.kubectx.bash ] && source ~/.kubectx.bash
|
|
||||||
```
|
|
||||||
|
|
||||||
Start a new shell, type `kubectx`, then hit <kbd>Tab</kbd> to see the existing
|
|
||||||
contexts.
|
|
||||||
|
|
||||||
You can Add `TAB: menu-complete` to your `~/.inputrc` to cycle through the
|
|
||||||
options with <kbd>Tab</kbd>.
|
|
||||||
|
|
||||||
## Zsh setup
|
|
||||||
|
|
||||||
`zsh` can leverage the `bash` completion scripts. Copy the `kubectx.bash` file
|
|
||||||
to your HOME directory:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
cp kubectx.bash ~/.kubectx.bash
|
|
||||||
```
|
|
||||||
|
|
||||||
And add the following to your `.zshrc`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
[ -f ~/.kubectx.bash ] && source ~/.kubectx.bash
|
|
||||||
```
|
|
||||||
|
|
||||||
Start a new shell, type `kubectx`, then hit <kbd>Tab</kbd> to see the existing
|
|
||||||
contexts. If it does not work, modify the line above to:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
[ -f ~/.kubectx.bash ] && autoload bashcompinit && bashcompinit && \
|
|
||||||
source ~/.kubectx.bash
|
|
||||||
```
|
|
||||||
@@ -2,7 +2,7 @@ _kube_contexts()
|
|||||||
{
|
{
|
||||||
local curr_arg;
|
local curr_arg;
|
||||||
curr_arg=${COMP_WORDS[COMP_CWORD]}
|
curr_arg=${COMP_WORDS[COMP_CWORD]}
|
||||||
COMPREPLY=( $(compgen -W "- $(kubectl config get-contexts | awk '{print $2}' | tail -n +2)" -- $curr_arg ) );
|
COMPREPLY=( $(compgen -W "- $(kubectl config get-contexts --output='name')" -- $curr_arg ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
complete -F _kube_contexts kubectx
|
complete -F _kube_contexts kubectx kctx
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#compdef kubectx
|
#compdef kubectx kctx=kubectx
|
||||||
|
|
||||||
KUBECTX="${HOME}/.kube/kubectx"
|
local KUBECTX="${HOME}/.kube/kubectx"
|
||||||
PREV=""
|
PREV=""
|
||||||
if [ -f "$KUBECTX" ]; then
|
if [ -f "$KUBECTX" ]; then
|
||||||
# show '-' only if there's a saved previous context
|
# show '-' only if there's a saved previous context
|
||||||
PREV=$(cat "${KUBECTX}")
|
local PREV=$(cat "${KUBECTX}")
|
||||||
_arguments "1: :((-\:Back\ to\ ${PREV} \
|
_arguments "1: :((-\:Back\ to\ ${PREV} \
|
||||||
$(kubectl config get-contexts | awk '{print $2}' | tail -n +2)))"
|
$(kubectl config get-contexts --output='name')))"
|
||||||
else
|
else
|
||||||
_arguments "1: :($(kubectl config get-contexts | awk '{print $2}' | tail -n +2))"
|
_arguments "1: :($(kubectl config get-contexts --output='name'))"
|
||||||
fi
|
fi
|
||||||
|
|||||||
8
completion/kubens.bash
Normal file
8
completion/kubens.bash
Normal 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 kns
|
||||||
2
completion/kubens.zsh
Normal file
2
completion/kubens.zsh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#compdef kubens kns=kubens
|
||||||
|
_arguments "1: :(- $(kubectl get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}'))"
|
||||||
22
kubectx
22
kubectx
@@ -21,6 +21,15 @@
|
|||||||
set -eou pipefail
|
set -eou pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "$( readlink -f "${0}" 2>/dev/null || \
|
||||||
|
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" "${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,15 +44,6 @@ EOF
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
current_context() {
|
|
||||||
kubectl config view -o=jsonpath='{.current-context}'
|
|
||||||
}
|
|
||||||
|
|
||||||
get_contexts() {
|
|
||||||
kubectl config view \
|
|
||||||
-o=jsonpath='{range .contexts[*].name}{@}{"\n"}{end}'
|
|
||||||
}
|
|
||||||
|
|
||||||
list_contexts() {
|
list_contexts() {
|
||||||
set -u pipefail
|
set -u pipefail
|
||||||
local cur="$(current_context)"
|
local cur="$(current_context)"
|
||||||
@@ -89,7 +89,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
|
||||||
@@ -139,7 +138,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
|
||||||
|
|||||||
146
kubens
Executable file
146
kubens
Executable file
@@ -0,0 +1,146 @@
|
|||||||
|
#!/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}" 2>/dev/null || \
|
||||||
|
python -c "import os,sys; print(os.path.realpath(sys.argv[1]))" "${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
11
utils.bash
Normal 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}'
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user