SimonTheLeg / konf-go

konf is a lightweight kubeconfig manager. With konf you can use different kubeconfigs at the same time. And because it does not need subshells, konf is blazing fast!
Apache License 2.0
168 stars 12 forks source link
kubeconfig kubernetes

Konf - Lightweight kubeconfig Manager

Go Report Card test

Why konf?

demo.gif

Installation

1. Install the konf-go binary

1.1 Pre-compiled binary

The GH Releases provide pre-compiled binaries for common platforms.

1.2 Nix Package

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
    # ...
  ];
}

1.3 Building from source

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!

2. Install the konf shellwrapper

Depending on whether you are using zsh/bash or fish, please use the following:

A) zsh/bash

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)

B) fish

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.

Customizations to Have a Good Time

A collection of optional settings to improve quality of life with konf.

A) zsh/bash

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"

B) fish

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'

Usage

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

How does it work?

kubeconfig management across shells

Essentially konf maintains its state via two directories:

We need these two extra directories because:

zsh/bash-func-magic

One 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.

Contributing

Usage of stdout and 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.

Tests

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 ./...

Upgrading spf13/cobra

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.