rancher-sandbox / rancher-desktop

Container Management and Kubernetes on the Desktop
https://rancherdesktop.io
Apache License 2.0
5.92k stars 281 forks source link

Support shell completion #1260

Open fungiboletus opened 2 years ago

fungiboletus commented 2 years ago

Preflight Checklist

Problem Description

I would like to have completion in my shell (ZSH or Bash) for Docker or Kubectl.

Proposed Solution

I know some Docker installations have local files to load in my ~/.zshrc but I can't find them with Rancher Desktop. It would be nice if such files could be packaged with Rancher Desktop, or even loaded automatically.

Additional Information

No response

clegault commented 2 years ago

Proposed Solution

I happened upon this feature request while looking for an open issue regarding completions.

kubectl has built in completions for zsh and bash:

kubectl completion bash kubectl completion zsh

You can add them to your .zshrc like this:

# ZSH auto-completion for kubernetes.
if [ $commands[kubectl] ]; then
     source <(kubectl completion zsh)
fi

For docker completions, you can just pick it up from the official docker repo for inclusion, but you guys probably already know that: docker zsh completion

Additional Information

The issue I am tracking down is that once you execute the above in your .zshrc for kubectl, if rancher desktop is not already running you get an error:

exec zsh
I0204 23:58:37.498554   14688 versioner.go:58] Get https://127.0.0.1:6443/version?timeout=5s: dial tcp 127.0.0.1:6443: connect: connection refused

This is because ~/.kube/config contains connection information to the local k3s, but it is not running. I do not understand is why when executing the kubectl command to get a zsh or bash completion kubectl attempts to connect to server. I haven't been able to find this issue raised anywhere yet. I suppose it would only be apparent in a situation like the one Rancher Desktop created. A few more tests...

jandubois commented 2 years ago

I'm pretty sure this happens because the kubectl bundled with Rancher Desktop is actually kuberlr, a wrapper that checks the kube version of the server and then makes sure that the local kubectl version is compatible.

kubectl is only guaranteed to be compatible with the immediate prior and next versions, so e.g. kubectl 1.21.x will work with k8s 1.20.x, 1.21.x, and 1.22.x, but not earlier or later version (in practice it most of the time works, but not always).

Since Rancher Desktop supports a wide range of k8s versions, it can't just include a single static version of kubectl. The disadvantage is that it needs to contact the server to determine the correct client version, so throws an error when the server is unreachable.

clegault commented 2 years ago

I went to the kubectl repo and looked through the code for completions. I found that it connects to the server in order to put additional completions in place regarding the existing pods and resources available in what ever k8s its pointing at. I tested this out by re-sourcing the completions after I brought rancher desktop up. Anyway, thanks for the reply. I will ping the kubectl folks and see if maybe an option can be added to disable that level of completions. I spent a couple of hours today trying to figure out what was throwing that error in my .zshrc since I hadn't made any changes to it.

jandubois commented 2 years ago

Isn't this just a warning though, that you could just get rid off by redirecting stderr to /dev/null? It doesn't seem to slow the command significantly:

$ time ./kubectl completion zsh >/dev/null
I0205 00:38:45.547629   28348 versioner.go:58] Get https://127.0.0.1:6443/version?timeout=5s: dial tcp 127.0.0.1:6443: connect: connection refused

real    0m0.085s
user    0m0.054s
sys 0m0.035s

So maybe use source <(kubectl completion zsh 2>/dev/null). Or am I misunderstanding the issue?

clegault commented 2 years ago

That is the workaround I put in place. I am mainly looking to get it documented since none of this information is available anywhere. All of the docs on the kubernetes website state to source it like I showed, they made no mention of the fact that it makes a connection to get resource information for completions, which they don't do in the event that you don't have a config file. And the warning that comes out doesn’t state that it's coming from kubectl. It seems to me that it should be documented somewhere. Thanks again for the reply.

jandubois commented 2 years ago

And the warning that comes out doesn’t state that it's coming from kubectl.

It doesn't come from kubectl, it comes from the kuberlr wrapper:

https://github.com/flavio/kuberlr/blob/77846a03df781baef610ed7f24783e17f34eaef4/internal/finder/versioner.go#L58

clegault commented 2 years ago

Oh good, you found it. I stand corrected. Where do you think would be the best place to have it documented? I can bring it up with Dylan at the technical review next week. Thanks for the reply.

jtravee commented 2 years ago

I'm pretty sure this happens because the kubectl bundled with Rancher Desktop is actually kuberlr, a wrapper that checks the kube version of the server and then makes sure that the local kubectl version is compatible.

kubectl is only guaranteed to be compatible with the immediate prior and next versions, so e.g. kubectl 1.21.x will work with k8s 1.20.x, 1.21.x, and 1.22.x, but not earlier or later version (in practice it most of the time works, but not always).

Since Rancher Desktop supports a wide range of k8s versions, it can't just include a single static version of kubectl. The disadvantage is that it needs to contact the server to determine the correct client version, so throws an error when the server is unreachable.

Please confirm that this is the data that should be documented.

clegault commented 2 years ago

This is accurate. It's just missing the problem statement.

stefanlasiewski commented 1 year ago

Thanks for your work on this. I just wanted to state to that the shell completion feature also leads to a 5 second delay when bash is invoked, such as when I log in or run exec bash. It's not a huge problem, but I wanted to mention it for posterity.

$ echo $SHELL
/usr/local/bin/bash
$ which kubectl
/Users/stefanl/.rd/bin/kubectl

$ time kubectl completion bash > /dev/null
I0109 15:56:41.153400    1794 versioner.go:56] Remote kubernetes server unreachable

real    0m5.093s
user    0m0.064s
sys 0m0.039s
jawadqur commented 1 year ago

tbh this is very annoying. I do love rancher desktop, but can I accept the "risk" of version mismatch and just use regular kubectl? I tried deleting ~/.rd/bin/kubectl as well, but Rancher Desktop puts it back automatically. I close and open shells all day, having a 3-5 second delay every time I launch a new shell, and rancher isn't running.

jandubois commented 1 year ago

but can I accept the "risk" of version mismatch and just use regular kubectl

Yes, you probably can. Change the PATH setting to "Manual" and then add ~/.rd/bin at the end of the PATH instead of the beginning, and then have your own version of kubectl in a directory in front of it.

segevfiner commented 1 year ago

It would be helpful if Rancher Desktop linked shell completion scripts to $HOME/.rd as a start.

spangaer commented 1 week ago

Happy I found this ticket before filing a new one ✔️

I observe same or a similar problem with docker cli in WSL2. I can get it to work from the Windows path by adding following line my .bashrc

source <(docker completion bash)

It works from the Windows path, but it's slow (2 seconds). Version 1.16.0 has exacerbated the problem by switching to Windows FS extensions. Which means that it pulls a whopping 155 MB over that virtual wire for each touch. https://github.com/rancher-sandbox/rancher-desktop/commit/227eec9aa9f2bf6852da374f0c3fed196b3b7524

I have found that all my troubles disappear by making WSL FS copies of the key binaries (and make sure they are used). Script below. Any chance that this change can be reverted/enhanced to pushing those big core binaries to WSL.

If you want us to attempt to make a PR, we can give it a shot, but we have no Go pro's available, while it seems a trivial task for someone skilled in the art.

Anyhow, to help out others and GPT here's my current fix:

#!/bin/bash

# this script fixes docker auto completion for Rancher by
# 1) moving performance critical binaries to the WSL FS
#    (plugins were moved to Windows in version 1.16.0)
# 2) installing the autocomplete

# requires rsync jq bash-completion

# install by adding this file with
# `source ~/.docker/bashrc`
# to ~/.bashrc

rancher_linux="/mnt/c/Program Files/Rancher Desktop/resources/resources/linux"
# will be added to path on Ubuntu if it exists
local_bin=~/.local/bin

dot_docker=~/.docker
dot_docker_config="$dot_docker/config.json"
dot_docker_cp="$dot_docker/cli-plugins"

# ensure dirs exist
mkdir -p "$local_bin"
mkdir -p "$dot_docker_cp"

# sync performance critical binaries (only if changed)
# these are big and touched by autocomplete
rsync -a "$rancher_linux/bin/docker" "$local_bin/docker"
rsync -a -r --delete "$rancher_linux/docker-cli-plugins/" "$dot_docker_cp/"

# check if cliPluginsExtraDirs is present in the file
if jq -e '.cliPluginsExtraDirs' "$dot_docker_config" > /dev/null; then
  # remove the entry from the file, otherwise local plugins get ignored
  file_content=$(<"$dot_docker_config")
  jq 'del(.cliPluginsExtraDirs)' <<< "$file_content" > "$dot_docker_config"
fi

# install autocomplete
source <(~/.local/bin/docker completion bash)