Search code examples
kubernetesautocompletekubectl

Any way to autocomplete multiple objects in a kubectl command?


k8s kubectl autocomplete is great, until you want to run a command for multiple things.

For example, I want to delete 2 pods, I can run:

k delete pod foo-12345 bar-67890

But I can only autocomplete with foo. What about bar<tab>?


Solution

  • It is in the best case a partial workaround. After a few test, I can say that your goal can be achieved, but it have some cons. There might be a 3rd party solution but I am not aware of any.

    bash-completion

    'bash-completion' package is required for making kubectl shell completion work as expected. You can install it using apt-get install bash-completionmo. More information can be found in Kubernetes Documentation Optional kubectl configurations.

    Debugging

    Bash-completion has it's own syntax and functions. For debugging purpose you can run export BASH_COMP_DEBUG_FILE=$HOME/compdebug.txt. It will create compdebug text file and send all debug output from kubectl shell completion functions to it. Example output below:

    __kubectl_parse_get: get completion by kubectl get  -o template --template="{{ range .items  }}{{ .metadata.name }} {{ end }}" "first-deployment-85b75bf4f9-mn8zh"
    __kubectl_handle_word: c is 0 words[c] is kubectl
    __kubectl_handle_command: c is 0 words[c] is kubectl
    __kubectl_handle_command: looking for _kubectl_root_command
    __kubectl_handle_word: c is 1 words[c] is get
    __kubectl_handle_command: c is 1 words[c] is get
    __kubectl_handle_command: looking for _kubectl_get
    __kubectl_handle_word: c is 2 words[c] is pod
    __kubectl_handle_noun: c is 2 words[c] is pod
    __kubectl_handle_reply
    __kubectl_parse_get: get completion by kubectl get  -o template --template="{{ range .items  }}{{ .metadata.name }} {{ end }}" "pod"
    

    How it works

    kubectl doesn't complete more than one object, because it's autocomplete function runs sub-request kubectl get argN to get list of objects, and argN is the previous arguments of the existing command line. When you use it first time, it takes arguments from kubectl command pod->argN and run kubectl get pod. The second time it takes arguments from kubectl command pod podname1->argN, so the sub-request looks like kubectl get podname1 instead of kubectl get pod which cause en error and empty output instead of list of the objects.

    Test Scenario

    To achieve this script you can use command kubectl completion bash > k8scompletion.sh.

    It's good to create second completion script that you can rollback to default settings - kubectl completion bash > k8scompletion-copy.sh.

    $ vi k8scompletion.sh
    

    In function __kubectl_get_resource() I've edited __kubectl_parse_get "${nouns[${#nouns[@]} -1]}" to __kubectl_parse_get "${nouns[0]}"

    __kubectl_get_resource()
    {
        if [[ ${#nouns[@]} -eq 0 ]]; then
          local kubectl_out
          if kubectl_out=$(__kubectl_debug_out "kubectl api-resources $(__kubectl_override_flags) -o name --cached --request-timeout=5s --verbs=get"); then
              COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
              return 0
          fi
          return 1
        fi
        __kubectl_parse_get "${nouns[0]}"
    }
    

    Script adjustment overview

    Adjusted script allows you to complete kubernetes resources and all objects from this resource. The following workaround is enough for demonstration and solving the mentioned in the question problem, but can cause some side effects, so please pay attention to the results you get.

    Side Note

    Shell completion script varies from one kubectl version to another, thus it is hard to create universal patch.

    Test Output

    $ kubectl delete <TAB>
    apiservices.apiregistration.k8s.io                            nodes.metrics.k8s.io
    backendconfigs.cloud.google.com                               persistentvolumeclaims
    certificatesigningrequests.certificates.k8s.io                persistentvolumes
    clusterrolebindings.rbac.authorization.k8s.io                 poddisruptionbudgets.policy
    clusterroles.rbac.authorization.k8s.io                        pods
    componentstatuses                                             podsecuritypolicies.policy
    configmaps                                                    pods.metrics.k8s.io
    controllerrevisions.apps                                      podtemplates
    cronjobs.batch                                                priorityclasses.scheduling.k8s.io
    csidrivers.storage.k8s.io                                     replicasets.apps
    ... and few others
    
    $ kubectl delete pod<TAB>
    poddisruptionbudgets.policy  pods                         podsecuritypolicies.policy   pods.metrics.k8s.io          podtemplates
    
    $ kubectl delete pod <TAB><TAB>
    httpd-deploy-1-6c4b998b99-jk876  httpd-deploy-6867dfd79c-tr648    nginx2                           nginx-deploy-2-94985d7bd-bdb4d
    httpd-deploy-2-64dc95c468-s7vt2  nginx                            nginx-deploy-1-5494687955-sm5lh  nginx-deploy-85df977897-44lcn
    
    $ kubectl get pod nginx<TAB>
    nginx                            nginx2                           nginx-deploy-1-5494687955-sm5lh  nginx-deploy-2-94985d7bd-bdb4d   nginx-deploy-85df977897-44lcn
    
    $ kubectl get pod nginx-deploy-<TAB>
    nginx-deploy-1-5494687955-sm5lh  nginx-deploy-2-94985d7bd-bdb4d   nginx-deploy-85df977897-44lcn
    
    $ kubectl get pod nginx-deploy-1<TAB>
    ###It autocomplete below after clicking on tab to nginx-deploy-1-5494687955-sm5lh
    
    $ kubectl get pod nginx-deploy-1-5494687955-sm5lh <TAB>
    httpd-deploy-1-6c4b998b99-jk876  httpd-deploy-6867dfd79c-tr648    nginx2                           nginx-deploy-2-94985d7bd-bdb4d
    httpd-deploy-2-64dc95c468-s7vt2  nginx                            nginx-deploy-1-5494687955-sm5lh  nginx-deploy-85df977897-44lcn
    
    $ kubectl delete pod nginx-deploy-1-5494687955-sm5lh nginx<TAB>
    nginx                            nginx2                           nginx-deploy-1-5494687955-29vqs  nginx-deploy-2-94985d7bd-bdb4d   nginx-deploy-85df977897-44lcn
    $ kubectl delete pod nginx-deploy-1-5494687955-sm5lh nginx2 <TAB>
    httpd-deploy-1-6c4b998b99-jk876  httpd-deploy-6867dfd79c-tr648    nginx2                           nginx-deploy-2-94985d7bd-bdb4d
    httpd-deploy-2-64dc95c468-s7vt2  nginx                            nginx-deploy-1-5494687955-29vqs  nginx-deploy-85df977897-44lcn
    $ kubectl delete pod nginx-deploy-1-5494687955-sm5lh nginx2
    

    Rollback changes

    To apply this specific completion script, you have to use source command - source k8scompletion.sh or source k8scompletion-copy.sh.