From 09bbe37ce6043b0eabe72ef96c339c1417a69738 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Mon, 5 Sep 2022 19:13:49 -0400 Subject: [PATCH] Add shell completion support to plugin example The use of `kubectl_complete-ns` enables shell completion when calling the plugin through `kubectl ns`. The script only completes flag names and namespace arguments. Signed-off-by: Marc Khouzam --- .../src/k8s.io/sample-cli-plugin/README.md | 23 ++++++++++++++++++ .../sample-cli-plugin/kubectl_complete-ns | 24 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100755 staging/src/k8s.io/sample-cli-plugin/kubectl_complete-ns diff --git a/staging/src/k8s.io/sample-cli-plugin/README.md b/staging/src/k8s.io/sample-cli-plugin/README.md index f13664946bb..0aa94e58d6e 100644 --- a/staging/src/k8s.io/sample-cli-plugin/README.md +++ b/staging/src/k8s.io/sample-cli-plugin/README.md @@ -58,6 +58,29 @@ that kubectl points to. It can also be used as a means of showcasing usage of the cli-runtime set of utilities to aid in third-party plugin development. +## Shell completion + +This plugin supports shell completion when used through kubectl. To enable shell completion for the plugin +you must copy the file `./kubectl_complete-ns` somewhere on `$PATH` and give it executable permissions. + +The `./kubectl_complete-ns` script shows a hybrid approach to providing completions: +1. it uses the builtin `__complete` command provided by [Cobra](https://github.com/spf13/cobra) for flags +1. it calls `kubectl` to obtain the list of namespaces to complete arguments (note that a more elegant approach would be to have the `kubectl-ns` program itself provide completion of arguments by implementing Cobra's `ValidArgsFunction` to fetch the list of namespaces, but it would then be a less varied example) + +One can then do things like: +``` +$ kubectl ns +default kube-node-lease kube-public kube-system + +$ kubectl ns -- +--as -- Username to impersonate for the operation. User could be a regular user or a service account in a namespace. +--as-group -- Group to impersonate for the operation, this flag can be repeated to specify multiple groups. +--as-uid -- UID to impersonate for the operation. +--cache-dir -- Default cache directory +[...] +``` + +Note: kubectl v1.26 or higher is required for shell completion to work for plugins. ## Cleanup You can "uninstall" this plugin from kubectl by simply removing it from your PATH: diff --git a/staging/src/k8s.io/sample-cli-plugin/kubectl_complete-ns b/staging/src/k8s.io/sample-cli-plugin/kubectl_complete-ns new file mode 100755 index 00000000000..1a3e054514a --- /dev/null +++ b/staging/src/k8s.io/sample-cli-plugin/kubectl_complete-ns @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# If we are completing a flag, use Cobra's builtin completion system. +# To know if we are completing a flag we need the last argument starts with a `-` and does not contain an `=` +args=("$@") +lastArg=${args[((${#args[@]}-1))]} +if [[ "$lastArg" == -* ]]; then + if [[ "$lastArg" != *=* ]]; then + kubectl ns __complete "$@" + fi +else + # TODO Make sure we are not completing the value of a flag. + # TODO Only complete a single argument. + # Both are pretty hard to do in a shell script. The better way to do this would be to let + # Cobra do all the completions by using `cobra.ValidArgsFunction` in the program. + # But the below, although imperfect, is a nice example for plugins that don't use Cobra. + + # We are probably completing an argument. This plugin only accepts namespaces, let's fetch them. + kubectl get namespaces --output go-template='{{ range .items }}{{ .metadata.name }}{{"\n"}}{{ end }}' + + # Turn off file completion. See the ShellCompDirective documentation within + # https://github.com/spf13/cobra/blob/main/shell_completions.md#completion-of-nouns + echo :4 +fi