sbstp / kubie

A more powerful alternative to kubectx and kubens
https://blog.sbstp.ca/introducing-kubie/
zlib License
1.93k stars 100 forks source link

Eval instead of new shell? #85

Open JohnPolansky opened 3 years ago

JohnPolansky commented 3 years ago

So first off may I just say wow your tool is awesome and you've put a lot of attention into it. I've already switched over to using it and trying to get my colleagues on it too being able to work multiple clusters is a must for my daily work so this has been amazing.

I was curious as to why you are creating a new shell whenever you switch to the new K8 cluster. I admit I haven't had time to fully dig through your code, but it seems like you are using a combination of new kubeconfig files stored in temp directories and environment variables to allow multiple clusters in different terminal windows, which is really cool idea.

However I was wondering why open a new shell, for me the additional shell adds a significant "switch" time to the process and I'm not clear why as just starting a new zsh doesn't take as long. I was curious what if creating a new shell you use kubie to copy and create the new kube-config files like you do, but instead of opening a new shell with environment variables, when if you output those environment variables when you exit your app. Then use an eval call to execute the commands.

For example something like this:

function kubie() {
   25    eval $(cd /opt/tools/kubie ; kubie $@)
   26  }

When your app exits it outputs export KUBE_CONFIG=/tmp/path/file and the eval would trigger and set the values within the current shell, then any new execution of a new cluster switch would delete the previous files/create new ones.

I realize using the function eval call is a bit weird, but I've used it for some small tools I've used with great success, but I was curious if there were specific reasons why you wanted to spawn a new shell.

Thanks again great tool, just curious to understand better. :)

valorl commented 2 years ago

There could also just be a special flag on the commands that normally spawn a shell, that you can set in order to not spawn a shell and instead output the shell command. That way both modes are supported. The flag could be --mode=(shell|eval) maybe. I haven't dived into the code either, but there's probably some additional work needed (e.g. ns seems to expect nesting).

Also, maybe a benefit of the shell is that the lifetime of the new shell defines a scope for the temp file, which you can delete once the shell exits. With just eval in the root shell, it sounds harder to figure out when the kubeconfig isn't used anymore.

reegnz commented 1 year ago

I would also welcome it if you could just have kubie generate a temp. kubeconfig, and expose it's location and allow the handling of the shell integration by other tools. It would enable seamless integration with other shell tools like https://github.com/direnv/direnv. Only thing needed for that would be for kubie to print the export KUBECONFIG=/tmp/path/file so one can source it (as described above), or just printing the tmp file location.

TBQH I wouldn't care for kubie to know how long I use the kubeconfig, as I'd just use it to generate one given my direnv context. I would want my context to activate on directory switches, not necessarily explicit kubie calls.

valorl commented 1 year ago

I've also started seeing value in avoiding nested sessions and I personally moved to https://github.com/danielfoehrKn/kubeswitch for this reason.

M3t0r commented 1 month ago

I have managed to achieve this by putting this snippet in my ~/.zshrc

KUBIE_CONF_DIR=${XDG_RUNTIME_DIR:-/tmp}/kubie
mkdir -p "${KUBIE_CONF_DIR}"
export KUBIE_SESSION=$(mktemp "${KUBIE_CONF_DIR}/session.XXXXXXXXXX.json")
echo '{"history":[]}' > "${KUBIE_SESSION}"
export KUBECONFIG="${KUBIE_SESSION%.json}.kubeconf.yaml"
export KUBIE_KUBECONFIG="${KUBECONFIG}"
export KUBIE_ACTIVE=1
export KUBIE_DEPTH=1
export KUBIE_ZSH_USE_RPS1=0
export KUBIE_SHELL=zsh
trap -- "rm --force --preserve-root=all ${KUBIE_SESSION} ${KUBIE_KUBECONFIG}" EXIT

2 problems:

I think to achieve this we might do 3 things:

  1. Add a kubie session init command that creates an "empty" session and prints out a bunch of these envvar exports (like they are injected in src/shell/*.rs). This can be called and evaled from the shell without needing to spawn a new one.
  2. Add a kubie session gc command that should be called when the shell exits (via trap), that removes all unused sessions files. To make that easier we could store the parent PID in the session next to the history. So when cleaning up we can open all session files, read the pid, check if there is a process with that pid still running, and if not know that the session is dead and remove the files. This might not always remove all dead sessions, but it will never accidentally remove a running session, and it's also more exhaustive than just removing the current session for cases when the trap gets disabled.
  3. Make kubie ns not error with an "empty" session.

@sbstp what do you think? I'm open to implementing this.