98 Commits

Author SHA1 Message Date
Ahmet Alp Balkan
dcb43fdf1b Release v0.7.1 2019-11-09 16:46:53 -08:00
Ahmet Alp Balkan
e2f7dc0de2 Print plugin-friendly usage string
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2019-11-09 16:46:27 -08:00
Pedro Rodrigues
9645e5c62c Add zsh completion for kubectx subcommand (-d) (#178)
- Add basic completion for subcommand -d.
  Note: Kubectx will suggest all available contexts.

- References:
  - http://zsh.sourceforge.net/Doc/Release/Completion-System.html#Completion-System
  - https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
2019-10-24 15:25:31 -07:00
Oliver Ford
00a1e12bfb Disable preview when fuzzy-finding (#163)
The user may have global settings that enable the preview pane in fzf.

Whatever the preview command is set as, it probably doesn't render
anything meaningful for kubens - I can't think what would be.

For kubectx, the context yaml itself would _maybe_ be helpful, but it
likely contains secrets, so I don't personally think I'd find it useful
enough to get into.

This commit thus disables the preview, so that if the user did have it
enabled, there's now no pane where there would previously have probably
been an error, such as:

    [bat error]: '<namespace>': No such file or directory (os error 2)
2019-10-11 12:14:32 -04:00
Eugene Aseev
c3dd1e5deb Add missing instruction for zsh on Linux (#173)
* Add missing instruction for zsh on Linux

* Add completion reloading to .zshrc
2019-09-09 08:13:33 -07:00
Ahmet Alp Balkan
a21638226f Release v0.7.0 2019-08-30 11:50:15 -07:00
Ahmet Alp Balkan
28e7c12f51 Introduce -c/--current options for kubectx/kubens (#171)
Per #127 the user community wants to have this feature, primarily as
-c and --current flags.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2019-08-30 11:49:49 -07:00
ferhat elmas
1652420a15 Enable shellcheck and fix issues (#170) 2019-08-25 12:05:01 -07:00
Ed Vinyard
543e035090 fix typo in "Customizing colors" example (#166) 2019-08-10 11:28:51 -07:00
Nils Breunese
a5e810b837 Add install instructions for MacPorts users (#159) 2019-07-15 10:29:52 -07:00
Christian Rebischke
62f3f27889 changed instructions for arch linux (#152)
I have pushed kubectx to the official repositories.
Users can install it via `pacman` now :)

Signed-off-by: Christian Rebischke <chris@nullday.de>
2019-05-22 17:01:08 +02:00
Ahmet Alp Balkan
4258f03446 Add shields.io badges 2019-05-08 19:39:34 -07:00
Ahmet Alp Balkan
b9614bd2e0 kubectx rename check if old_name is a valid ctx (#139)
Without this safeguard, when user runs `kubectx NEW_NAME=OLD_NAME` where
NEW_NAME is an existing context but OLD_NAME isn't, we end up deleting NEW_NAME
and not doing any renames (because OLD_NAME is not found).

Fixes #136.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2019-04-04 08:59:51 -07:00
Ahmet Alp Balkan
b3732b309e Update README.md 2019-02-06 10:20:55 -08:00
Tariq Ibrahim
a1bce92cc8 Fix alignment of kubectx help in USAGE text. (#129) 2019-02-04 14:21:45 -08:00
Tariq Ibrahim
1356c37cc0 Fix typos in readme doc. (#126)
* Fix typos in readme doc.

* fix typos
2019-01-30 12:20:37 -08:00
Ahmet Alp Balkan
10c9bd58ca v0.6.3
- FIX: Show current context/ns color in interactive (fzf) mode. (#109)
- TEST: Add integration tests for kubectx (#111, #113) and kubens (#105, #117)

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2019-01-28 10:11:52 -08:00
Jonathan Liuti
b6e918b084 Remove --with-short-names from doc (#120)
First measure to avoid confusing people.
see #112
2019-01-13 14:56:24 -08:00
Kumbirai Tanekha
402cc2c4b9 add cli tests for kubens (#117)
* split bats test invocation by executable

* add more cli tests for kubens

* clean up kubens tests

* small cleanup to kubens tests
2019-01-03 10:06:13 -08:00
Philippe MARTIN
df557e4fa7 Add more cli tests for kubectx (#113) 2019-01-02 09:47:01 -08:00
Ahmet Alp Balkan
b584d14f90 Show color in interactive mode (#109)
This patch introduces an internal _KUBECTX_FORCE_COLOR environment variable
that overrides color output decision.

With this, fzf output shows the color indicators for ctx/ns and choosing the
option with the color works without any extra handling.

Fixes #89.
Fixes #98.
2018-12-29 11:05:00 -08:00
Philippe MARTIN
acbf324464 test: Add more kubectx tests (#111) 2018-12-25 11:38:45 -08:00
Ahmet Alp Balkan
845f3b690b test: enable travis-ci with bats (#108)
- add .travis.yml.
- move bats fixtures to .bats extension, since it allows detection of test
files automatically by file extension.
- use BATS_TEST_DIRNAME variable to compute location of COMMAND.
- IMPORTANT: use `echo "$output">&2` before final check so that we can debug
  the test cases by their output

Ref #2.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-12-22 13:22:08 -08:00
Philippe MARTIN
2b5bf4e429 Add simple tests for kubectx/kubens -h/--help (#105) 2018-12-22 13:02:20 -08:00
Eric Bailey
4a7d7cf025 README.md: add fish completion installation hint (#106)
This should work for most users anyway.
2018-12-21 20:30:46 -08:00
Ahmet Alp Balkan
dfeb7df363 Release v0.6.2 2018-11-26 12:23:47 -08:00
Rafael Bodill
407a84ce9e Support XDG_CACHE_HOME environment variable (#93) 2018-11-26 12:21:43 -08:00
Chad Metcalf
ec994aff89 Check for kubectl.exe on Windows (#96)
On the various flavors of bash for Windows kubectl won't resolve as the binary is kubectl.exe.
Simple aliasing doesn't seem to work. So test for both otherwise fail with a not found error.
2018-11-26 12:21:21 -08:00
Robert James Hernandez
3aeb4e76d2 fix subshell error handling (#95)
fixes #5
2018-11-07 09:27:34 -08:00
Ahmet Alp Balkan
517dae9fc8 Adding dependency checker for kubectx and kubens (#92)
Ensure kubectl in PATH for kubectx and kubens.
2018-10-22 10:10:08 -07:00
Robert James Hernandez
083e56f221 Ensure kubectl in PATH for kubens 2018-10-19 22:20:16 -07:00
Robert James Hernandez
6c94248e98 Ensure kubectl in PATH for kubectx 2018-10-19 22:20:03 -07:00
Gianpaolo Macario
244dd5b8a5 kubens: Fix typo in comment (#90) 2018-10-17 09:04:46 -07:00
Ahmet Alp Balkan
121f15d1d3 Update README.md 2018-10-16 20:15:36 -07:00
Ahmet Alp Balkan
21a1e1e963 Add ga-beacon 2018-10-16 20:15:01 -07:00
Mitchell Turner
6811a5f03c Added example of using bash completion (#86)
Added example using bash completion.

Example clones into `~/.kubectx` for people who don't want to make modifications outside of `$HOME`.
2018-09-16 23:31:35 -07:00
Ahmet Alp Balkan
41296a5fcf README: fix typo in ln cmd for zsh comp
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-09-05 15:26:17 -07:00
schnatterer
34a9e100c8 README: Install completion for zsh & Linux (#80) 2018-09-04 15:59:34 -07:00
Ahmet Alp Balkan
365fa23d87 zsh: fix kubectx completion for 2+ contexts (#81)
fixes #68

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-08-31 15:40:26 -07:00
Oliver
ccc077b6c5 allow disabling interactive mode with fzf (#82)
Introduce KUBECTX_IGNORE_FZF for both kubectx/kubens to force-disable
attempt to enable interactive mode and lookup for fzf(1).
2018-08-31 15:39:43 -07:00
Ahmet Alp Balkan
d931779c0c Release v0.6.1
- FIX: fix crash when kubectx/kubens is installed --with-short-names and fzf(1)
  is in PATH, but calling the binaries with the wrong name. (#78)
2018-08-24 09:28:10 -07:00
Ahmet Alp Balkan
f01719a5a6 fix: --with-short-names not compatible with fzf (#79)
When kubectx is installed as kctx, FZF_DEFAULT_COMMAND=kubectx won't work.

Fixes #78.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-08-24 09:28:00 -07:00
Ahmet Alp Balkan
46d593305a Release v0.6.0
- FEATURE: interactive search mode when kubectx and kubens are ran without any
  arguments and fzf(1) is detected in PATH. (#71, #74)
- FIX: kubectx -d now doesn't ignore arguments after the first argument. (#75)
- FIX: empty output bug when TERM=vt100 even though NO_COLOR is set. (#57, #73)
- FIX: --help exits with code 0 now. (#69, #72)
2018-08-23 10:19:12 -07:00
Ahmet Alp Balkan
595c27ada7 fix: ignored args while deleting multiple clusters (#76)
Fixes #75.
2018-08-23 10:17:42 -07:00
Ahmet Alp Balkan
8df92316d6 add support for interactive selection with fzf (#74)
Present a fuzzy search choice in "kubectx" and "kubens" commands without
arguments.

![demo2](https://user-images.githubusercontent.com/159209/44478683-40f16d00-a5f3-11e8-99e2-f32f2a3539c1.gif)

Fixes #71.
2018-08-22 10:08:13 -07:00
Ahmet Alp Balkan
7b23263fc2 ignore errors from tput (to fix TERM=vt100) (#73)
Currently TERM=vt100 is causing kubectx failure since tput is returning
exitcode=1. vt100 does not have colors. Ignoring tput exit code.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-08-22 09:50:34 -07:00
Vít Listík
e368d13eea help exit status 0 (#72) 2018-08-19 16:40:47 -07:00
Ahmet Alp Balkan
7bc9a1277c Release v0.5.1 2018-08-06 12:21:18 -07:00
Ahmet Alp Balkan
bc46739ab5 add note about NO_COLOR 2018-08-06 12:20:51 -07:00
Ahmet Alp Balkan
5a1366b7c9 Merge pull request #64 from idvoretskyi/patch-1
Debian package installation information added
2018-07-19 20:04:13 -07:00
Ihor Dvoretskyi
5144c0f958 Debian releases information added
Signed-off-by: Ihor Dvoretskyi <ihor@linux.com>
2018-07-19 23:03:25 +00:00
Ihor Dvoretskyi
11336883cb Debian releases information added
Signed-off-by: Ihor Dvoretskyi <ihor@linux.com>
2018-07-19 23:00:17 +00:00
Ihor Dvoretskyi
b1324570ad Debian releases information added
Signed-off-by: Ihor Dvoretskyi <ihor@linux.com>
2018-07-19 22:58:08 +00:00
Ihor Dvoretskyi
5f4160766d Debian package installation information added
As the package is currently available for Debian Buster and Sid, the brief installation information added.
2018-07-18 22:53:09 +03:00
Ahmet Alp Balkan
c606382a62 Respect $NO_COLOR
Fixes #54.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-06-10 14:16:05 -07:00
Ahmet Alp Balkan
428fb0045c Merge pull request #53 from prabhu43/master
Configure highlight color for current context & namespace
2018-06-07 12:27:45 -07:00
Prabhu Jayakumar
a97ab8367d Update Readme 2018-06-08 00:35:45 +05:30
Prabhu Jayakumar
9beb1a1587 Configure highlight color for current context & namespace using environment variable 2018-06-05 23:29:08 +05:30
Prabhu Jayakumar
c23c2a9e29 Revert "Use * to indicate current context & current namespace"
This reverts commit dad48e5397.
2018-05-30 00:32:23 +05:30
Prabhu Jayakumar
dad48e5397 Use * to indicate current context & current namespace 2018-05-28 23:03:03 +05:30
Ahmet Alp Balkan
e9fbafc923 Merge pull request #46 from uesteibar/delete-multiple-contexts
Allow deleting multiple contexts at once
2018-05-25 11:06:09 -07:00
Ahmet Alp Balkan
b7af607a91 Merge pull request #48 from xnaveira/portable
Make the scripts portable
2018-05-23 09:26:23 -07:00
Xavier Naveira
bcb89389c6 Make the scripts portable 2018-05-23 17:09:54 +02:00
uesteibar
4a1d73d5fe Allow deleting multiple contexts at once
fixes #39

Example: `kubectx -d ctx1 ctx2`
2018-05-18 23:20:49 +02:00
Ahmet Alp Balkan
f986c148b2 Merge pull request #44 from fiws/patch-1
add Arch AUR note to the readme
2018-04-28 16:35:13 -07:00
Ahmet Alp Balkan
2799a9e331 Fix indentation to 80 chars, make title Arch Linux 2018-04-28 16:34:57 -07:00
Filip Weiss
d61654cb39 add Arch AUR note to the readme 2018-04-28 00:34:00 +02:00
Ahmet Alp Balkan
d1b69a995a Merge pull request #41 from ahmetb/tty_check
Do not print colors if stdout isn't tty
2018-04-17 13:17:10 -07:00
Ahmet Alp Balkan
4520d3f54b Do not print colors if stdout isn't tty
This is previously offered in #18, #22, and #27 and I previously rejected
these PRs. My rationale was to prevent scripting around kubectx as it is
meant to be used as an interactive tool.

But clearly that will be a problem, when you're doing operations like:

    kubectx -d $(kubectx)

which I proposed in #39. Plus this change is harmless. I think this
implementation does a better check than the previous ones.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-10 21:53:14 -07:00
Ahmet Alp Balkan
d906013970 Fix readme.md
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-10 09:45:57 -07:00
Ahmet Alp Balkan
c4867bc1f2 Merge pull request #38 from ahmetb/delete-context
Prototype context deletion (kubectx -d)
2018-04-09 16:06:51 -07:00
Ahmet Alp Balkan
7b6528a4ae Prototype context deletion (kubectx -d)
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-04 12:40:23 -07:00
Ahmet Alp Balkan
07583efe3d Update -h message in README.md
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-04 12:32:37 -07:00
Ahmet Alp Balkan
cce04a3279 Merge pull request #37 from jvassev/fix-kubens
Allow for '/' in context name
2018-04-04 12:12:43 -07:00
Julian Vassev
d6f706a28e Allow for '/' in context name
Also, fix `kubens -` which fails to save previous namespace
after 6610d70
2018-04-04 11:42:04 -07:00
Ahmet Alp Balkan
0141d66224 Support "kubectx NAME=." to rename current-context
Fixes #24.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-02 23:52:18 -07:00
Ahmet Alp Balkan
fbce3de6b9 Add overwriting to rename
rename now deletes the context (soft-delete, as in does not delete user or
cluster of the context) if the specified name exists.

Fixes #25.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-02 23:27:51 -07:00
Ahmet Alp Balkan
6610d70ca8 separate local declarations and function calls
Suggested by SC2155 (https://github.com/koalaman/shellcheck/wiki/SC2155).

It captures some of the errors from kubectl that were previously described
in #5. However, this doesn't completely address that.

Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2018-04-02 22:20:35 -07:00
Ahmet Alp Balkan
80336137bd Merge pull request #32 from shiroyasha/installation-steps-linux
Example installation steps on Linux
2018-03-30 10:26:18 -07:00
Ahmet Alp Balkan
1c9b5c54e8 Merge pull request #33 from jonmosco/utils_bash
Incorporate utils.bash into each executable to help simplify packaging for Linux and other platforms.  This adds to PR #32
2018-03-15 10:17:48 -07:00
Jon Mosco
b188f4da88 Incorporate utils.bash into each executable to help simplify packaging
for Linux and other platforms.  This adds to PR #32

remove unused functions
2018-03-15 12:34:18 -04:00
Igor Šarčević
57893cb668 Example installation steps on Linux 2018-03-10 13:17:09 +01:00
Ahmet Alp Balkan
8da629d98e Update README.md 2018-03-01 10:27:55 -08:00
Ahmet Alp Balkan
b2992aa0df Update readme to add fish completion support 2018-01-18 10:18:50 -08:00
Ahmet Alp Balkan
2f33693466 Merge pull request #26 from ichekrygin/master
Add Fish Shell Completions
2018-01-18 10:18:04 -08:00
Illya Chekrygin
c813642dc3 Add fish completions for kubectx and kubens 2018-01-17 23:23:53 -08:00
Ahmet Alp Balkan
12575f8ce4 Update README.md 2018-01-12 15:30:38 -08:00
Ahmet Alp Balkan
46d4236f1a Update README.md 2018-01-12 15:29:57 -08:00
Ahmet Alp Balkan
7ae68ada83 Update README.md 2018-01-02 14:58:33 -08:00
Ahmet Alp Balkan
146b67d2b0 Merge pull request #20 from knil-sama/knil-sama-readme-typo
Update README.md
2017-12-20 09:04:05 -08:00
Clement Demonchy
e3ceb14db5 Update README.md
Correct typo soemwhere -> somewhere
2017-12-20 14:16:28 +01:00
Ahmet Alp Balkan
6e250aecb6 Remove Formula/*, it's now in homebrew-core
Signed-off-by: Ahmet Alp Balkan <ahmetb@google.com>
2017-12-14 15:21:10 -08:00
Ahmet Alp Balkan
d613c37c16 Update README.md 2017-12-12 10:34:58 -08:00
Ahmet Alp Balkan
61f1aa8fd7 Update README.md 2017-12-12 10:34:44 -08:00
Ahmet Alp Balkan
8390860474 Update README.md 2017-11-17 10:15:31 -08:00
Ahmet Alp Balkan
394288edc0 Update README.md 2017-11-15 12:49:33 -08:00
Ahmet Alp Balkan
dc6d2e57b3 README.md: Add user testimonials 2017-11-15 12:48:05 -08:00
Ahmet Alp Balkan
aa215b9eeb Update installation instructions for non-macOS 2017-11-15 12:41:03 -08:00
16 changed files with 883 additions and 142 deletions

11
.travis.yml Normal file
View File

@@ -0,0 +1,11 @@
before_install:
- sudo add-apt-repository ppa:duggan/bats --yes
- sudo apt-get update -qq
- sudo apt-get install -qq bats
- sudo curl -fsSL -o /usr/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.13.1/bin/linux/amd64/kubectl
- sudo chmod +x /usr/bin/kubectl
script:
- bats test/kubectx.bats
- bats test/kubens.bats
- shellcheck kubectx
- shellcheck kubens

View File

@@ -1,26 +0,0 @@
class Kubectx < Formula
desc "Tool that can switch between kubectl contexts easily and create aliases"
homepage "https://github.com/ahmetb/kubectx"
url "https://github.com/ahmetb/kubectx/archive/v0.3.1.tar.gz"
sha256 "4e995f5bec6f41c8d5b6e77f413a58ead077816348e72de26dde3655ec2b7d0b"
head "https://github.com/ahmetb/kubectx.git", :branch => "short-names"
bottle :unneeded
option "with-short-names", "link as \"kctx\" and \"kns\" instead"
def install
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/kubens.bash" => "kubens"
zsh_completion.install "completion/kubectx.zsh" => "_kubectx"
zsh_completion.install "completion/kubens.zsh" => "_kubens"
end
test do
system "which", build.with?("short-names") ? "kctx" : "kubectx"
system "which", build.with?("short-names") ? "kns" : "kubens"
end
end

171
README.md
View File

@@ -1,23 +1,35 @@
# `kubectx` + `kubens`: Power tools for kubectl
![Latest GitHub release](https://img.shields.io/github/release/ahmetb/kubectx.svg)
![GitHub stars](https://img.shields.io/github/stars/ahmetb/kubectx.svg?label=github%20stars)
![Travis (.org) branch](https://img.shields.io/travis/ahmetb/kubectx/master.svg)
![Proudly written in Bash](https://img.shields.io/badge/written%20in-bash-ff69b4.svg)
This repository provides both `kubectx` and `kubens` tools.
**`kubectx`** help you switch between clusters back and forth:
**`kubectx`** helps you switch between clusters back and forth:
![kubectx demo GIF](img/kubectx-demo.gif)
**`kubens`** help you switch between Kubernetes namespaces smoothly:
**`kubens`** helps you switch between Kubernetes namespaces smoothly:
![kubens demo GIF](img/kubens-demo.gif)
# kubectx(1)
kubectx is an utility to manage and switch between kubectl(1) contexts.
kubectx is a utility to manage and switch between kubectl(1) contexts.
```
USAGE:
kubectx : list the contexts
kubectx <NAME> : switch to context <NAME>
kubectx - : switch to the previous context
kubectx -c, --current : show the current context name
kubectx <NEW_NAME>=<NAME> : rename context <NAME> to <NEW_NAME>
kubectx -h,--help : show this message
kubectx <NEW_NAME>=. : rename current-context to <NEW_NAME>
kubectx -d <NAME> : delete context <NAME> ('.' for current-context)
(this command won't delete the user/cluster entry
that is used by the context)
```
### Usage
@@ -37,21 +49,21 @@ Context "dublin" set.
Aliased "gke_ahmetb_europe-west1-b_dublin" as "dublin".
```
`kubectx` supports <kbd>Tab</kbd> completion on bash/zsh shells to help with
`kubectx` supports <kbd>Tab</kbd> completion on bash/zsh/fish shells to help with
long context names. You don't have to remember full context names anymore.
-----
# kubens(1)
kubens is an utility to switch between Kubernetes namespaces.
kubens is a 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
kubens -c, --current : show the current namespace
```
@@ -67,35 +79,142 @@ Context "test" set.
Active namespace is "default".
```
`kubens` also supports <kbd>Tab</kbd> completion on bash/zsh shells.
`kubens` also supports <kbd>Tab</kbd> completion on bash/zsh/fish shells.
-----
## Installation
**For macOS:**
### macOS
:tada: kubectx is now in Homebrew! :confetti_ball:
#### Homebrew
> Use the [Homebrew](https://brew.sh/) package manager:
>
> brew install kubectx
>
> this will also set up bash/zsh completion scripts automatically.
:confetti_ball: If you use [Homebrew](https://brew.sh/) you can install like this:
Running `brew install` with `--with-short-names` will install tools with names
`kctx` and `kns` to prevent prefix collision with `kubectl` name.
brew install kubectx
> Note: If you installed kubectx before it was accepted to Homebrew core
> repository, reinstall with:
> `brew untap ahmetb/kubectx && brew uninstall --force kubectx && brew update && brew install kubectx`
This command will set up bash/zsh/fish completion scripts automatically.
**Other platforms:**
- If you like to add context/namespace info to your shell prompt (`$PS1`),
I recommend trying out [kube-ps1](https://github.com/jonmosco/kube-ps1).
- Download the `kubectx` script
- Add it somewhere in your PATH
- Make it executable (`chmod +x`)
- You can also install bash/zsh [completion scripts](completion/) manually.
#### MacPorts
If you use [MacPorts](https://www.macports.org) you can install like this:
sudo port install kubectx
### Linux
Since `kubectx`/`kubens` are written in Bash, you should be able to install
them to any POSIX environment that has Bash installed.
- Download the `kubectx`, and `kubens` scripts.
- Either:
- save them all to somewhere in your `PATH`,
- or save them to a directory, then create symlinks to `kubectx`/`kubens` from
somewhere in your `PATH`, like `/usr/local/bin`
- Make `kubectx` and `kubens` executable (`chmod +x ...`)
- Install bash/zsh/fish [completion scripts](completion/).
- For zsh:
The completion scripts have to be in a path that belongs to `$fpath`. Either link or copy them to an existing folder.
If using oh-my-zsh you can do as follows:
```bash
mkdir -p ~/.oh-my-zsh/completions
chmod -R 755 ~/.oh-my-zsh/completions
ln -s /opt/kubectx/completion/kubectx.zsh ~/.oh-my-zsh/completions/_kubectx.zsh
ln -s /opt/kubectx/completion/kubens.zsh ~/.oh-my-zsh/completions/_kubens.zsh
```
Note that the leading underscore seems to be a convention. If completion doesn't work, add `autoload -U compinit && compinit` to your `.zshrc` (similar to [`zsh-completions`](https://github.com/zsh-users/zsh-completions/blob/master/README.md#oh-my-zsh)).
If not using oh-my-zsh, you could link to `/usr/share/zsh/functions/Completion` (might require sudo), depending on the `$fpath` of your zsh installation.
In case of error, calling `compaudit` might help.
- For bash:
```bash
git clone https://github.com/ahmetb/kubectx.git ~/.kubectx
COMPDIR=$(pkg-config --variable=completionsdir bash-completion)
ln -sf ~/.kubectx/completion/kubens.bash $COMPDIR/kubens
ln -sf ~/.kubectx/completion/kubectx.bash $COMPDIR/kubectx
cat << FOE >> ~/.bashrc
#kubectx and kubens
export PATH=~/.kubectx:\$PATH
FOE
```
- For fish:
```fish
mkdir -p ~/.config/fish/completions
ln -s /opt/kubectx/completion/kubectx.fish ~/.config/fish/completions/
ln -s /opt/kubectx/completion/kubens.fish ~/.config/fish/completions/
```
Example installation steps:
``` bash
sudo git clone https://github.com/ahmetb/kubectx /opt/kubectx
sudo ln -s /opt/kubectx/kubectx /usr/local/bin/kubectx
sudo ln -s /opt/kubectx/kubens /usr/local/bin/kubens
```
#### Arch Linux
Available as official Arch Linux package. Install it via:
```bash
sudo pacman -S kubectx
```
#### Debian/Ubuntu
Available as a Debian package for [Debian Buster (testing)](https://packages.debian.org/buster/kubectx), [Sid (unstable)](https://packages.debian.org/sid/kubectx) (_note: if you are unfamiliar with Debian release process and how to enable testing/unstable repos, check the [Debian Wiki](https://wiki.debian.org/DebianReleases)_):
``` bash
sudo apt install kubectx
```
-----
### Interactive mode
If you want `kubectx` and `kubens` commands to present you an interactive menu
with fuzzy searching, you just need to [install
`fzf`](https://github.com/junegunn/fzf) in your PATH.
![kubectx interactive search with fzf](img/kubectx-interactive.gif)
If you have `fzf` installed, but want to opt out of using this feature, set the environment variable `KUBECTX_IGNORE_FZF=1`.
-----
### Customizing colors
If you like to customize the colors indicating the current namespace or context, set the environment variables `KUBECTX_CURRENT_FGCOLOR` and `KUBECTX_CURRENT_BGCOLOR` (refer color codes [here](https://linux.101hacks.com/ps1-examples/prompt-color-using-tput/)):
```
export KUBECTX_CURRENT_FGCOLOR=$(tput setaf 6) # blue text
export KUBECTX_CURRENT_BGCOLOR=$(tput setab 7) # white background
```
Colors in the output can be disabled by setting the
[`NO_COLOR`](http://no-color.org/) environment variable.
-----
#### Users
| What are others saying about kubectx? |
| ---- |
| _“Thank you for kubectx & kubens - I use them all the time & have them in my k8s toolset to maintain happiness :) ”_ [@pbouwer](https://twitter.com/pbouwer/status/925896377929949184) |
| _“I can't imagine working without kubectx and especially kubens anymore. It's pure gold.”_ [@timoreimann](https://twitter.com/timoreimann/status/925801946757419008) |
| _“I'm liking kubectx from @ahmetb, makes it super-easy to switch #Kubernetes contexts [...]”_ &mdash; [@lizrice](https://twitter.com/lizrice/status/928556415517589505) |
| _“Also using it on a daily basis. This and my zsh config that shows me the current k8s context 😉”_ [@puja108](https://twitter.com/puja108/status/928742521139810305) |
| _“Lately I've found myself using the kubens command more than kubectx. Both very useful though :-)”_ [@stuartleeks](https://twitter.com/stuartleeks/status/928562850464907264) |
| _“yeah kubens rocks!”_ [@embano1](https://twitter.com/embano1/status/928698440732815360) |
| _“Special thanks to Ahmet Alp Balkan for creating kubectx, kubens, and kubectl aliases, as these tools made my life better.”_ [@strebeld](https://medium.com/@strebeld/5-ways-to-enhance-kubectl-ux-97c8893227a) |
| _“❤ this shell script @ahmetb wrote to help make switching between kubectl config contexts a breeze.”_ [@briandanowski](https://twitter.com/briandanowski/status/1085409568165896193) |
> If you liked `kubectx`, you may like my [`kubectl-aliases`](https://github.com/ahmetb/kubectl-aliases) project, too.
-----
@@ -105,4 +224,4 @@ Disclaimer: This is not an official Google product.
#### Stargazers over time
[![Stargazers over time](https://starcharts.herokuapp.com/ahmetb/kubectx.svg)](https://starcharts.herokuapp.com/ahmetb/kubectx)
![Google Analytics](https://ga-beacon.appspot.com/UA-2609286-17/kubectx/README?pixel)

3
completion/kubectx.fish Normal file
View File

@@ -0,0 +1,3 @@
# kubectx
complete -f -c kubectx -a "- (kubectl config get-contexts --output='name')"

View File

@@ -2,11 +2,17 @@
local KUBECTX="${HOME}/.kube/kubectx"
PREV=""
local all_contexts="$(kubectl config get-contexts --output='name')"
if [ -f "$KUBECTX" ]; then
# show '-' only if there's a saved previous context
local PREV=$(cat "${KUBECTX}")
_arguments "1: :((- \
$(kubectl config get-contexts --output='name')))"
_arguments \
"-d:*: :(${all_contexts})" \
"(- *): :(- ${all_contexts})"
else
_arguments "1: :($(kubectl config get-contexts --output='name'))"
_arguments \
"-d:*: :(${all_contexts})" \
"(- *): :(${all_contexts})"
fi

3
completion/kubens.fish Normal file
View File

@@ -0,0 +1,3 @@
# kubens
complete -f -c kubens -a "(kubectl get ns -o=custom-columns=NAME:.metadata.name --no-headers)"

BIN
img/kubectx-interactive.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

173
kubectx
View File

@@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
#
# kubectx(1) is a utility to manage and switch between kubectl contexts.
@@ -21,39 +21,68 @@
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"
SELF_CMD="$0"
SELF="kubectx"
if [[ "$(basename "$0")" == kubectl-* ]]; then # invoked as plugin
SELF="kubectl ctx"
fi
KUBECTX="${HOME}/.kube/kubectx"
KUBECTX="${XDG_CACHE_HOME:-$HOME/.kube}/kubectx"
usage() {
cat <<"EOF"
cat <<EOF
USAGE:
kubectx : list the contexts
kubectx <NAME> : switch to context <NAME>
kubectx - : switch to the previous context
kubectx <NEW_NAME>=<NAME> : rename context <NAME> to <NEW_NAME>
kubectx -h,--help : show this message
$SELF : list the contexts
$SELF <NAME> : switch to context <NAME>
$SELF - : switch to the previous context
$SELF -c, --current : show the current context name
$SELF <NEW_NAME>=<NAME> : rename context <NAME> to <NEW_NAME>
$SELF <NEW_NAME>=. : rename current-context to <NEW_NAME>
$SELF -d <NAME> [<NAME...>] : delete context <NAME> ('.' for current-context)
(this command won't delete the user/cluster entry
that is used by the context)
$SELF -h,--help : show this message
EOF
exit 1
}
exit_err() {
echo >&2 "${1}"
exit 1
}
current_context() {
$KUBECTL config view -o=jsonpath='{.current-context}'
}
get_contexts() {
$KUBECTL config get-contexts -o=name | sort -n
}
list_contexts() {
set -u pipefail
local cur="$(current_context)"
local yellow=$(tput setaf 3)
local darkbg=$(tput setab 0)
local normal=$(tput sgr0)
local cur ctx_list
cur="$(current_context)" || exit_err "error getting current context"
ctx_list=$(get_contexts) || exit_err "error getting context list"
for c in $(get_contexts); do
if [[ "${c}" = "${cur}" ]]; then
echo "${darkbg}${yellow}${c}${normal}"
local yellow darkbg normal
yellow=$(tput setaf 3 || true)
darkbg=$(tput setab 0 || true)
normal=$(tput sgr0 || true)
local cur_ctx_fg cur_ctx_bg
cur_ctx_fg=${KUBECTX_CURRENT_FGCOLOR:-$yellow}
cur_ctx_bg=${KUBECTX_CURRENT_BGCOLOR:-$darkbg}
for c in $ctx_list; do
if [[ -n "${_KUBECTX_FORCE_COLOR:-}" || \
-t 1 && -z "${NO_COLOR:-}" ]]; then
# colored output mode
if [[ "${c}" = "${cur}" ]]; then
echo "${cur_ctx_bg}${cur_ctx_fg}${c}${normal}"
else
echo "${c}"
fi
else
echo "${c}"
fi
@@ -67,7 +96,8 @@ read_context() {
}
save_context() {
local saved="$(read_context)"
local saved
saved="$(read_context)"
if [[ "${saved}" != "${1}" ]]; then
printf %s "${1}" > "${KUBECTX}"
@@ -75,11 +105,25 @@ save_context() {
}
switch_context() {
kubectl config use-context "${1}"
$KUBECTL config use-context "${1}"
}
choose_context_interactive() {
local choice
choice="$(_KUBECTX_FORCE_COLOR=1 \
FZF_DEFAULT_COMMAND="${SELF_CMD}" \
fzf --ansi --no-preview || true)"
if [[ -z "${choice}" ]]; then
echo 2>&1 "error: you did not choose any of the options"
exit 1
else
set_context "${choice}"
fi
}
set_context() {
local prev="$(current_context)"
local prev
prev="$(current_context)" || exit_err "error getting current context"
switch_context "${1}"
@@ -89,7 +133,8 @@ set_context() {
}
swap_context() {
local ctx="$(read_context)"
local ctx
ctx="$(read_context)"
if [[ -z "${ctx}" ]]; then
echo "error: No previous context found." >&2
exit 1
@@ -97,45 +142,88 @@ swap_context() {
set_context "${ctx}"
}
user_of_context() {
kubectl config view \
-o=jsonpath="{.contexts[?(@.name==\"${1}\")].context.user}"
}
cluster_of_context() {
kubectl config view \
-o=jsonpath="{.contexts[?(@.name==\"${1}\")].context.cluster}"
context_exists() {
grep -q ^"${1}"\$ <($KUBECTL config get-contexts -o=name)
}
rename_context() {
local old_name="${1}"
local new_name="${2}"
local old_user="$(user_of_context "${old_name}")"
local old_cluster="$(cluster_of_context "${old_name}")"
if [[ "${old_name}" == "." ]]; then
old_name="$(current_context)"
fi
if [[ -z "$old_user" || -z "$old_cluster" ]]; then
echo "error: Cannot retrieve context ${old_name}." >&2
if ! context_exists "${old_name}"; then
echo "error: Context \"${old_name}\" not found, can't rename it." >&2
exit 1
fi
kubectl config rename-context "${old_name}" "${new_name}"
if context_exists "${new_name}"; then
echo "Context \"${new_name}\" exists, deleting..." >&2
$KUBECTL config delete-context "${new_name}" 1>/dev/null 2>&1
fi
$KUBECTL config rename-context "${old_name}" "${new_name}"
}
delete_contexts() {
for i in "${@}"; do
delete_context "${i}"
done
}
delete_context() {
local ctx
ctx="${1}"
if [[ "${ctx}" == "." ]]; then
ctx="$(current_context)" || exit_err "error getting current context"
fi
echo "Deleting context \"${ctx}\"..." >&2
$KUBECTL config delete-context "${ctx}"
}
main() {
if hash kubectl 2>/dev/null; then
KUBECTL=kubectl
elif hash kubectl.exe 2>/dev/null; then
KUBECTL=kubectl.exe
else
echo >&2 "kubectl is not installed"
exit 1
fi
if [[ "$#" -eq 0 ]]; then
list_contexts
if [[ -t 1 && -z "${KUBECTX_IGNORE_FZF:-}" && "$(type fzf &>/dev/null; echo $?)" -eq 0 ]]; then
choose_context_interactive
else
list_contexts
fi
elif [[ "${1}" == "-d" ]]; then
if [[ "$#" -lt 2 ]]; then
echo "error: missing context NAME" >&2
usage
exit 1
fi
delete_contexts "${@:2}"
elif [[ "$#" -gt 1 ]]; then
echo "error: too many flags" >&2
echo "error: too many arguments" >&2
usage
exit 1
elif [[ "$#" -eq 1 ]]; then
if [[ "${1}" == "-" ]]; then
swap_context
elif [[ "${1}" == '-c' || "${1}" == '--current' ]]; then
# we don't call current_context here for two reasons:
# - it does not fail when current-context property is not set
# - it does not return a trailing newline
kubectl config current-context
elif [[ "${1}" == '-h' || "${1}" == '--help' ]]; then
usage
elif [[ "${1}" =~ ^-(.*) ]]; then
echo "error: unrecognized flag \"${1}\"" >&2
usage
exit 1
elif [[ "${1}" =~ (.+)=(.+) ]]; then
rename_context "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}"
else
@@ -143,6 +231,7 @@ main() {
fi
else
usage
exit 1
fi
}

146
kubens
View File

@@ -1,6 +1,6 @@
#!/bin/bash
#!/usr/bin/env bash
#
# kubenx(1) is a utility to switch between Kubernetes namespaces.
# kubens(1) is a utility to switch between Kubernetes namespaces.
# Copyright 2017 Google Inc.
#
@@ -21,31 +21,37 @@
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"
SELF_CMD="$0"
SELF="kubens"
if [[ "$(basename "$0")" == kubectl-* ]]; then # invoked as plugin
SELF="kubectl ns"
fi
KUBENS_DIR="${HOME}/.kube/kubens"
KUBENS_DIR="${XDG_CACHE_HOME:-$HOME/.kube}/kubens"
usage() {
cat <<"EOF"
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
$SELF : list the namespaces in the current context
$SELF <NAME> : change the active namespace of current context
$SELF - : switch to the previous namespace in this context
$SELF -c, --current : show the current namespace
$SELF -h,--help : show this message
EOF
exit 1
}
exit_err() {
echo >&2 "${1}"
exit 1
}
current_namespace() {
local cur_ctx=$(current_context)
ns="$(kubectl config view -o=jsonpath="{.contexts[?(@.name==\"${cur_ctx}\")].context.namespace}")"
local cur_ctx
cur_ctx="$(current_context)" || exit_err "error getting current context"
ns="$($KUBECTL config view -o=jsonpath="{.contexts[?(@.name==\"${cur_ctx}\")].context.namespace}")" \
|| exit_err "error getting current namespace"
if [[ -z "${ns}" ]]; then
echo "default"
else
@@ -53,20 +59,37 @@ current_namespace() {
fi
}
current_context() {
$KUBECTL config current-context
}
get_namespaces() {
$KUBECTL get namespaces -o=jsonpath='{range .items[*].metadata.name}{@}{"\n"}{end}'
}
escape_context_name() {
echo "${1//\//-}"
}
namespace_file() {
local ctx="${1}"
local ctx
ctx="$(escape_context_name "${1}")"
echo "${KUBENS_DIR}/${ctx}"
}
read_namespace() {
local f="$(namespace_file "${1}")"
local f
f="$(namespace_file "${1}")"
[[ -f "${f}" ]] && cat "${f}"
return 0
}
save_namespace() {
mkdir -p "${KUBENS_DIR}"
local f="$(namespace_file "${1}")"
local saved="$(read_namespace "${1}")"
local f saved
f="$(namespace_file "${1}")"
saved="$(read_namespace "${1}")"
if [[ "${saved}" != "${2}" ]]; then
printf %s "${2}" > "${f}"
@@ -75,13 +98,35 @@ save_namespace() {
switch_namespace() {
local ctx="${1}"
kubectl config set-context "${ctx}" --namespace="${2}"
$KUBECTL config set-context "${ctx}" --namespace="${2}"
echo "Active namespace is \"${2}\".">&2
}
choose_namespace_interactive() {
# directly calling kubens via fzf might fail with a cryptic error like
# "$FZF_DEFAULT_COMMAND failed", so try to see if we can list namespaces
# locally first
if [[ -z "$(list_namespaces)" ]]; then
echo >&2 "error: could not list namespaces (is the cluster accessible?)"
exit 1
fi
local choice
choice="$(_KUBECTX_FORCE_COLOR=1 \
FZF_DEFAULT_COMMAND="${SELF_CMD}" \
fzf --ansi --no-preview || true)"
if [[ -z "${choice}" ]]; then
echo 2>&1 "error: you did not choose any of the options"
exit 1
else
set_namespace "${choice}"
fi
}
set_namespace() {
local ctx="$(current_context)"
local prev="$(current_namespace)"
local ctx prev
ctx="$(current_context)" || exit_err "error getting current context"
prev="$(current_namespace)" || exit_error "error getting current namespace"
if grep -q ^"${1}"\$ <(get_namespaces); then
switch_namespace "${ctx}" "${1}"
@@ -96,24 +141,38 @@ set_namespace() {
}
list_namespaces() {
local cur="$(current_namespace)"
local yellow darkbg normal
yellow=$(tput setaf 3 || true)
darkbg=$(tput setab 0 || true)
normal=$(tput sgr0 || true)
local yellow=$(tput setaf 3)
local darkbg=$(tput setab 0)
local normal=$(tput sgr0)
local cur_ctx_fg cur_ctx_bg
cur_ctx_fg=${KUBECTX_CURRENT_FGCOLOR:-$yellow}
cur_ctx_bg=${KUBECTX_CURRENT_BGCOLOR:-$darkbg}
for c in $(get_namespaces); do
local cur ns_list
cur="$(current_namespace)" || exit_err "error getting current namespace"
ns_list=$(get_namespaces) || exit_err "error getting namespace list"
for c in $ns_list; do
if [[ -n "${_KUBECTX_FORCE_COLOR:-}" || \
-t 1 && -z "${NO_COLOR:-}" ]]; then
# colored output mode
if [[ "${c}" = "${cur}" ]]; then
echo "${darkbg}${yellow}${c}${normal}"
echo "${cur_ctx_bg}${cur_ctx_fg}${c}${normal}"
else
echo "${c}"
fi
else
echo "${c}"
fi
done
}
swap_namespace() {
local ctx="$(current_context)"
local ns="$(read_namespace "${ctx}")"
local ctx ns
ctx="$(current_context)" || exit_err "error getting current context"
ns="$(read_namespace "${ctx}")"
if [[ -z "${ns}" ]]; then
echo "error: No previous namespace found for current context." >&2
exit 1
@@ -122,16 +181,34 @@ swap_namespace() {
}
main() {
if [[ -z "${KUBECTL:-}" ]]; then
if hash kubectl 2>/dev/null; then
KUBECTL=kubectl
elif hash kubectl.exe 2>/dev/null; then
KUBECTL=kubectl.exe
else
echo >&2 "kubectl is not installed"
exit 1
fi
fi
if [[ "$#" -eq 0 ]]; then
list_namespaces
if [[ -t 1 && -z ${KUBECTX_IGNORE_FZF:-} && "$(type fzf &>/dev/null; echo $?)" -eq 0 ]]; then
choose_namespace_interactive
else
list_namespaces
fi
elif [[ "$#" -eq 1 ]]; then
if [[ "${1}" == '-h' || "${1}" == '--help' ]]; then
usage
elif [[ "${1}" == "-" ]]; then
swap_namespace
elif [[ "${1}" == '-c' || "${1}" == '--current' ]]; then
current_namespace
elif [[ "${1}" =~ ^-(.*) ]]; then
echo "error: unrecognized flag \"${1}\"" >&2
usage
exit 1
elif [[ "${1}" =~ (.+)=(.+) ]]; then
alias_context "${BASH_REMATCH[2]}" "${BASH_REMATCH[1]}"
else
@@ -140,6 +217,7 @@ main() {
else
echo "error: too many flags" >&2
usage
exit 1
fi
}

30
test/common.bash Normal file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bats
# bats setup function
setup() {
export XDG_CACHE_HOME="$(mktemp -d)"
export KUBECONFIG="${XDG_CACHE_HOME}/config"
}
# bats teardown function
teardown() {
rm -rf "$XDG_CACHE_HOME"
}
use_config() {
cp "$BATS_TEST_DIRNAME/testdata/$1" $KUBECONFIG
}
# wrappers around "kubectl config" command
get_namespace() {
kubectl config view -o=jsonpath="{.contexts[?(@.name==\"$(get_context)\")].context.namespace}"
}
get_context() {
kubectl config current-context
}
switch_context() {
kubectl config use-context "${1}"
}

241
test/kubectx.bats Normal file
View File

@@ -0,0 +1,241 @@
#!/usr/bin/env bats
COMMAND="$BATS_TEST_DIRNAME/../kubectx"
load common
@test "no kubectl detected" {
OLDPATH="$PATH"
PATH=/bin
run ${COMMAND}
echo "$output"
[ "$status" -eq 1 ]
[[ "$output" = "kubectl is not installed" ]]
PATH="$OLDPATH"
}
@test "--help should not fail" {
run ${COMMAND} --help
echo "$output"
[ "$status" -eq 0 ]
}
@test "-h should not fail" {
run ${COMMAND} -h
echo "$output"
[ "$status" -eq 0 ]
}
@test "switch to previous context when no one exists" {
use_config config1
run ${COMMAND} -
echo "$output"
[ "$status" -eq 1 ]
[[ "$output" = "error: No previous context found." ]]
}
@test "list contexts when no kubeconfig exists" {
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" = "" ]]
}
@test "get one context and list contexts" {
use_config config1
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" = "user1@cluster1" ]]
}
@test "get two contexts and list contexts" {
use_config config2
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" = *"user1@cluster1"* ]]
[[ "$output" = *"user2@cluster1"* ]]
}
@test "get two contexts and select contexts" {
use_config config2
run ${COMMAND} user1@cluster1
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user1@cluster1" ]]
run ${COMMAND} user2@cluster1
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user2@cluster1" ]]
}
@test "get two contexts and switch between contexts" {
use_config config2
run ${COMMAND} user1@cluster1
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user1@cluster1" ]]
run ${COMMAND} user2@cluster1
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user2@cluster1" ]]
run ${COMMAND} -
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user1@cluster1" ]]
run ${COMMAND} -
echo "$output"
[ "$status" -eq 0 ]
echo "$(get_context)"
[[ "$(get_context)" = "user2@cluster1" ]]
}
@test "get one context and switch to non existent context" {
use_config config1
run ${COMMAND} "unknown-context"
echo "$output"
[ "$status" -eq 1 ]
}
@test "-c/--current fails when no context set" {
use_config config1
run "${COMMAND}" -c
echo "$output"
[ $status -eq 1 ]
run "${COMMAND}" --current
echo "$output"
[ $status -eq 1 ]
}
@test "-c/--current prints the current context" {
use_config config1
run "${COMMAND}" user1@cluster1
[ $status -eq 0 ]
run "${COMMAND}" -c
echo "$output"
[ $status -eq 0 ]
[[ "$output" = "user1@cluster1" ]]
run "${COMMAND}" --current
echo "$output"
[ $status -eq 0 ]
[[ "$output" = "user1@cluster1" ]]
}
@test "rename context" {
use_config config2
run ${COMMAND} "new-context=user1@cluster1"
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ ! "$output" = *"user1@cluster1"* ]]
[[ "$output" = *"new-context"* ]]
[[ "$output" = *"user2@cluster1"* ]]
}
@test "rename current context" {
use_config config2
run ${COMMAND} user2@cluster1
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND} new-context=.
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ ! "$output" = *"user2@cluster1"* ]]
[[ "$output" = *"user1@cluster1"* ]]
[[ "$output" = *"new-context"* ]]
}
@test "delete context" {
use_config config2
run ${COMMAND} -d "user1@cluster1"
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ ! "$output" = "user1@cluster1" ]]
[[ "$output" = "user2@cluster1" ]]
}
@test "delete current context" {
use_config config2
run ${COMMAND} user2@cluster1
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND} -d .
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ ! "$output" = "user2@cluster1" ]]
[[ "$output" = "user1@cluster1" ]]
}
@test "delete non existent context" {
use_config config1
run ${COMMAND} -d "unknown-context"
echo "$output"
[ "$status" -eq 1 ]
}
@test "delete several contexts" {
use_config config2
run ${COMMAND} -d "user1@cluster1" "user2@cluster1"
echo "$output"
[ "$status" -eq 0 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" = "" ]]
}
@test "delete several contexts including a non existent one" {
use_config config2
run ${COMMAND} -d "user1@cluster1" "non-existent" "user2@cluster1"
echo "$output"
[ "$status" -eq 1 ]
run ${COMMAND}
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" = "user2@cluster1" ]]
}

144
test/kubens.bats Normal file
View File

@@ -0,0 +1,144 @@
#!/usr/bin/env bats
COMMAND="${BATS_TEST_DIRNAME}/../kubens"
export KUBECTL="$BATS_TEST_DIRNAME/../test/mock-kubectl"
load common
@test "--help should not fail" {
run ${COMMAND} --help
echo "$output">&2
[[ "$status" -eq 0 ]]
}
@test "-h should not fail" {
run ${COMMAND} -h
echo "$output">&2
[[ "$status" -eq 0 ]]
}
@test "list namespaces when no kubeconfig exists" {
run ${COMMAND}
echo "$output"
[[ "$status" -eq 1 ]]
[[ "$output" = *"current-context is not set"* ]]
}
@test "list namespaces" {
use_config config1
switch_context user1@cluster1
run ${COMMAND}
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = *"ns1"* ]]
[[ "$output" = *"ns2"* ]]
}
@test "switch to existing namespace" {
use_config config1
switch_context user1@cluster1
run ${COMMAND} "ns1"
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = *'Active namespace is "ns1"'* ]]
}
@test "switch to non-existing namespace" {
use_config config1
switch_context user1@cluster1
run ${COMMAND} "unknown-namespace"
echo "$output"
[[ "$status" -eq 1 ]]
[[ "$output" = *'no namespace exists with name "unknown-namespace"'* ]]
}
@test "switch between namespaces" {
use_config config1
switch_context user1@cluster1
run ${COMMAND} ns1
echo "$output"
[[ "$status" -eq 0 ]]
echo "$(get_namespace)"
[[ "$(get_namespace)" = "ns1" ]]
run ${COMMAND} ns2
echo "$output"
[[ "$status" -eq 0 ]]
echo "$(get_namespace)"
[[ "$(get_namespace)" = "ns2" ]]
run ${COMMAND} -
echo "$output"
[[ "$status" -eq 0 ]]
echo "$(get_namespace)"
[[ "$(get_namespace)" = "ns1" ]]
run ${COMMAND} -
echo "$output"
[[ "$status" -eq 0 ]]
echo "$(get_namespace)"
[[ "$(get_namespace)" = "ns2" ]]
}
@test "switch to previous namespace when none exists" {
use_config config1
switch_context user1@cluster1
run ${COMMAND} -
echo "$output"
[[ "$status" -eq 1 ]]
[[ "$output" = *"No previous namespace found for current context"* ]]
}
@test "switch to namespace when current context is empty" {
use_config config1
run ${COMMAND} -
echo "$output"
[[ "$status" -eq 1 ]]
[[ "$output" = *"current-context is not set"* ]]
}
@test "-c/--current works when no namespace is set on context" {
use_config config1
switch_context user1@cluster1
run ${COMMAND} "-c"
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = "default" ]]
run ${COMMAND} "--current"
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = "default" ]]
}
@test "-c/--current prints the namespace after it is set" {
use_config config1
switch_context user1@cluster1
${COMMAND} ns1
run ${COMMAND} "-c"
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = "ns1" ]]
run ${COMMAND} "--current"
echo "$output"
[[ "$status" -eq 0 ]]
[[ "$output" = "ns1" ]]
}
@test "-c/--current fails when current context is not set" {
use_config config1
run ${COMMAND} -c
echo "$output"
[[ "$status" -eq 1 ]]
run ${COMMAND} --current
echo "$output"
[[ "$status" -eq 1 ]]
}

12
test/mock-kubectl Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
[[ -n $DEBUG ]] && set -x
set -eou pipefail
if [[ $@ == *'get namespaces'* ]]; then
echo "ns1"
echo "ns2"
else
kubectl $@
fi

18
test/testdata/config1 vendored Normal file
View File

@@ -0,0 +1,18 @@
# config with one context
apiVersion: v1
clusters:
- cluster:
server: ""
name: cluster1
contexts:
- context:
cluster: cluster1
user: user1
name: user1@cluster1
current-context: ""
kind: Config
preferences: {}
users:
- name: user1
user: {}

24
test/testdata/config2 vendored Normal file
View File

@@ -0,0 +1,24 @@
# config with two contexts
apiVersion: v1
clusters:
- cluster:
server: ""
name: cluster1
contexts:
- context:
cluster: cluster1
user: user1
name: user1@cluster1
- context:
cluster: cluster1
user: user2
name: user2@cluster1
current-context: ""
kind: Config
preferences: {}
users:
- name: user1
user: {}
- name: user2
user: {}

View File

@@ -1,11 +0,0 @@
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}'
}