The GH Releases provide pre-compiled binaries for common platforms.
The package can be installed in the local nix-profile.
nix-env -iA nixpkgs.konf
For adhoc or testing purposes a shell with the package can be spawned.
nix-shell -p konf
For NixOS users it is highly recommended to install the package by adding it to the list of systemPackages
.
{ # ...
environment.systemPackages = with pkgs; [
konf
# ...
];
}
go install github.com/simontheleg/konf-go@latest
Please do not rename or alias this binary, it is not be called by the user directly. Instead alias the konf shellwrapper described in the next step!
Depending on whether you are using zsh/bash or fish, please use the following:
Add the following to your .zshrc
/ .bashrc
and restart your shell or re-source this file:
# Currently supported shells: zsh, bash
source <(konf-go shellwrapper zsh)
Add the following to your config.fish
and restart your shell or re-source this file:
konf-go shellwrapper fish | source
This will install a shellwrapper called konf
, which you can use like any command. The wrapper can also be aliased if need be.
A collection of optional settings to improve quality of life with konf.
These can be added to your .zshrc
/ .bashrc
:
# Autocompletion. Currently supported shells: zsh, bash
source <(konf completion zsh)
# Open last konf on new shell session
konf --silent set -
# Alias
alias kctx="konf set"
alias kns="konf ns"
These can be added to your config.fish
:
# Autocompletion
konf completion fish | source
# Open last konf on new shell session
set -x KUBECONFIG (konf --silent set -)
# Alias
abbr --add --global -- kctx 'konf set'
abbr --add --global -- kns 'konf ns'
Before any kubeconfig can be used with konf you have to import it:
konf import <path-to-your-kubeconf>
This is required, because konf maintains its own store of kubeconfigs to be able to work its "no-additional-shell-required"-magic.
Afterwards you can quickly switch between konfs using either:
konf set # will open a picker dialogue
konf set - # will open the last konf
konf set <id> # will set a specific konf. <id> is usually <context>_<cluster>
Additional commands and flags can be seen by calling konf --help
Essentially konf maintains its state via two directories:
<konfDir>/store
-> contains all of your imported kubeconfigs, where each context is split into its own file<konfDir>/active
-> contains all currently active konfs. The filename refers to the PID of the shell. Konf will automatically clean unused files after you close the sessionWe need these two extra directories because:
$KUBECONFIG
variable to point to one kubeconfig file. If there are multiple contexts in that file, kubernetes looks for a current-context
key and sets the config to that, thus introducing some ambiguity. To avoid this, konf import splits all the contexts into separate filesOne of the largest difficulties in this project lies in the core design of the shell.
Essentially a child process cannot make modifications to its parents.
This includes setting an environment variable, which affects us because we want to set $KUBECONFIG
.
The way we work around this "limitation" is by using a zsh/bash function that executes our binary and then sets $KUBECONFIG
to the output of konf-go
.
With this trick we are able to set $KUBECONFIG
and can make this project work. Since only the result of stdout will be captured by the zsh/bash-func, we can still communicate normally with the user by using stderr.
When developing for konf, it is important to understand the konf-shellwrapper. It is designed to solve the problem described in the zsh/bash-func-magic section.
It works by saving the stdOut of konf-go in a separate variable and then evaluating the result. Should the result contain the keyword KUBECONFIGCHANGE:
, the wrapper will set $KUBECONFIG
to the value after the colon.
Otherwise the wrapper ist just going to print the result to stdOut in the terminal. This setup allows for konf-go commands to print to stdOut (which is required for example for zsh/bash completion). Additionally it should be able to handle large stdOut outputs as well, as it only parses the first line of output.
Interactive prompts however (like promptUI) should always print their dialogue to stdErr, as the wrapper has troubles with user input. Nonetheless you can still easily submit the result of the selection to the wrapper later on using the aforementioned keyword. So it should not be a big issue.
By default go test ./...
will run both unit and integration tests. Integration tests are mainly used to check for filename validity and only write in the /tmp/konf
directory. They are mainly being used by the CI. If you only want to run unit-test, you can do so by using the -short
flag:
go test -short ./...
If you want to only run integration tests, simply run:
go test -run Integration ./...
Special care should be taken before upgrading the cobra package.
This is due to the fact that in completion.go
we use the standard completion from the library and then apply some string insertions at certain positions.
As a result, before any upgrade of the package, it should be checked whether the GenXYZCompletion funcs from cobra have changed.
Unfortunately I was not able to find a more elegant solution, so for now we just have to be vigilant when upgrading the dependency.