Small improvements - kubectl and autocompletion
Kubectl Small Improvements

Small improvements - kubectl and autocompletion

My two options to make life easier when working with kubectl, without any 3rd party tools installation (which I don’t like).

Switching context

AFAIK, lot of tutorials recommend kubectx for this purpose. Let’s be honest, this can be done using more native way (with some limitations ofc). I prefer simple alias here:

alias kct='kubectl config use-context'

Plus: autcompletion works out of the box here.

Minus: There is not option kct - to switch back to previous context. But honestly, I don’t remember a single time when I needed it.

Switching namespaces

Just as before, there is kubens present for this purpose. And more native way to do so is following shell function:

kns() {
    kubectl config set-context --current=true --namespace=$1
}

This time, the shell function instead of an alias is needed to handle the parameter $1 which accepts the namespace name.

Just use kns <namespace> and you are in that namespace.

Plus: native solution. Minuses:

  • No kns - to switch back to previous namespace.
  • No autocompletion this time.

Just as before first minus is a minor for me, but the second one is real pain. So let’s fix it.

Autocompletion

Little bit of theory: how does autcompletion works in shell?

By default - it’s a function or script that is meant to return the variable called COMPREPLY which is an array of values that you can choose from.

Simple, right?

So we need a function that returns the list of namespaces. Kubectl provides it:

kubectl get namespaces

But this func return a table, with more infos that we actually need. I could use awk for example, to prepare the list, but again, there is a more native way for it.

kubectl implements possibility to customize the output format. One important thing here, is that it uses the golang templating to do so.

The interesting value address is the same as within the Kubernetes object manifest, which looks like this for namespace:

apiVersion: v1
kind: Namespace
metadata:
  name: <nazwa>

According to this, the address we are interested in is: .metadata.name. Let’s combine it with disabling the headers and we have a ready command:

kubectl get namespaces --no-headers -o=custom-columns=NAME:.metadata.name

It returns the list of namespaces, just as the autocompletion requires. Let’s pack it into a function that generates COMPREPLY array. I’ve also added a timeout, so the shell won’t be blocked if the cluster is not responding:

_kns_autocomplete() {
    COMPREPLY=($(kubectl --request-timeout='3s' get namespaces --no-headers -o=custom-columns=NAME:.metadata.name))
}

Function name can be anything, but it’s a common practice to start the name of autocompletion functions with an underscore (which also prevents accidental calling of this function).

Last step: Shell must know that _kns_autocomplete generates completions for the kns function. For this purpose, I use the complete command:

complete -F _kns_autocomplete kns

Flag -F means autocompletion function, and the last parameter is the name of the function for which we assign autocompletion.

Final code:

_kns_autocomplete() {
    COMPREPLY=($(kubectl --request-timeout='3s' get namespaces --no-headers -o=custom-columns=NAME:.metadata.name))
}

kns() {
    kubectl config set-context --current=true --namespace=$1
}

complete -F _kns_autocomplete kns

Function are defined in the file that is executed at shell startup, e.g. .zshrc or any other file that is called by it.

To keep things tidy, I keep it in .aliases file.

Summary

I’d say this is a prefect example of small imprevements in workflow without doing bigger mess by installing 3rd party tools. And I’m aware that it’s not a 100% equal solution, but it works for me.

Try it out yourself. Doing improvements like this is really satisfying :) And you can always learn something new.