From daf29149810e250918bb08ffb45f6734e34b952f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arda=20G=C3=BC=C3=A7l=C3=BC?= Date: Wed, 24 Aug 2022 09:52:10 +0300 Subject: [PATCH] (kubectl apiresources): Use restclientgetter instead cmdutil.Factory This PR changes `kubectl apiresources` command by using restclientgetter instead of cmdutil.Factory for loose coupling and a couple of minor refactorings. This PR also unleashes migration of other commands depending on apiresources via completion. Kubernetes-commit: 50c93bfe04557eccb38b46cc4b99a6a3ec13f85b --- pkg/cmd/apiresources/apiresources.go | 42 ++++++++++++++--------- pkg/cmd/apiresources/apiresources_test.go | 4 +-- pkg/cmd/apiresources/apiversions.go | 8 ++--- pkg/util/completion/completion.go | 6 ++-- 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/pkg/cmd/apiresources/apiresources.go b/pkg/cmd/apiresources/apiresources.go index c7c0767a..6a02ac87 100644 --- a/pkg/cmd/apiresources/apiresources.go +++ b/pkg/cmd/apiresources/apiresources.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/printers" + "k8s.io/client-go/discovery" cmdutil "k8s.io/kubectl/pkg/cmd/util" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" @@ -68,6 +69,11 @@ type APIResourceOptions struct { Cached bool Categories []string + groupChanged bool + nsChanged bool + + discoveryClient discovery.CachedDiscoveryInterface + genericclioptions.IOStreams } @@ -87,7 +93,7 @@ func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *APIResourceOp } // NewCmdAPIResources creates the `api-resources` command -func NewCmdAPIResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { +func NewCmdAPIResources(restClientGetter genericclioptions.RESTClientGetter, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewAPIResourceOptions(ioStreams) cmd := &cobra.Command{ @@ -96,9 +102,9 @@ func NewCmdAPIResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams Long: i18n.T("Print the supported API resources on the server."), Example: apiresourcesExample, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(cmd, args)) + cmdutil.CheckErr(o.Complete(restClientGetter, cmd, args)) cmdutil.CheckErr(o.Validate()) - cmdutil.CheckErr(o.RunAPIResources(cmd, f)) + cmdutil.CheckErr(o.RunAPIResources()) }, } @@ -130,39 +136,41 @@ func (o *APIResourceOptions) Validate() error { } // Complete adapts from the command line args and validates them -func (o *APIResourceOptions) Complete(cmd *cobra.Command, args []string) error { +func (o *APIResourceOptions) Complete(restClientGetter genericclioptions.RESTClientGetter, cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) } + + discoveryClient, err := restClientGetter.ToDiscoveryClient() + if err != nil { + return err + } + o.discoveryClient = discoveryClient + + o.groupChanged = cmd.Flags().Changed("api-group") + o.nsChanged = cmd.Flags().Changed("namespaced") + return nil } // RunAPIResources does the work -func (o *APIResourceOptions) RunAPIResources(cmd *cobra.Command, f cmdutil.Factory) error { +func (o *APIResourceOptions) RunAPIResources() error { w := printers.GetNewTabWriter(o.Out) defer w.Flush() - discoveryclient, err := f.ToDiscoveryClient() - if err != nil { - return err - } - if !o.Cached { // Always request fresh data from the server - discoveryclient.Invalidate() + o.discoveryClient.Invalidate() } errs := []error{} - lists, err := discoveryclient.ServerPreferredResources() + lists, err := o.discoveryClient.ServerPreferredResources() if err != nil { errs = append(errs, err) } resources := []groupResource{} - groupChanged := cmd.Flags().Changed("api-group") - nsChanged := cmd.Flags().Changed("namespaced") - for _, list := range lists { if len(list.APIResources) == 0 { continue @@ -176,11 +184,11 @@ func (o *APIResourceOptions) RunAPIResources(cmd *cobra.Command, f cmdutil.Facto continue } // filter apiGroup - if groupChanged && o.APIGroup != gv.Group { + if o.groupChanged && o.APIGroup != gv.Group { continue } // filter namespaced - if nsChanged && o.Namespaced != resource.Namespaced { + if o.nsChanged && o.Namespaced != resource.Namespaced { continue } // filter to resources that support the specified verbs diff --git a/pkg/cmd/apiresources/apiresources_test.go b/pkg/cmd/apiresources/apiresources_test.go index bdb1b7b7..4112f951 100644 --- a/pkg/cmd/apiresources/apiresources_test.go +++ b/pkg/cmd/apiresources/apiresources_test.go @@ -34,12 +34,12 @@ func TestAPIResourcesComplete(t *testing.T) { parentCmd.AddCommand(cmd) o := NewAPIResourceOptions(genericclioptions.NewTestIOStreamsDiscard()) - err := o.Complete(cmd, []string{}) + err := o.Complete(tf, cmd, []string{}) if err != nil { t.Fatalf("Unexpected error: %v", err) } - err = o.Complete(cmd, []string{"foo"}) + err = o.Complete(tf, cmd, []string{"foo"}) if err == nil { t.Fatalf("An error was expected but not returned") } diff --git a/pkg/cmd/apiresources/apiversions.go b/pkg/cmd/apiresources/apiversions.go index a0970f83..5003a947 100644 --- a/pkg/cmd/apiresources/apiversions.go +++ b/pkg/cmd/apiresources/apiversions.go @@ -51,7 +51,7 @@ func NewAPIVersionsOptions(ioStreams genericclioptions.IOStreams) *APIVersionsOp } // NewCmdAPIVersions creates the `api-versions` command -func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command { +func NewCmdAPIVersions(restClientGetter genericclioptions.RESTClientGetter, ioStreams genericclioptions.IOStreams) *cobra.Command { o := NewAPIVersionsOptions(ioStreams) cmd := &cobra.Command{ Use: "api-versions", @@ -60,7 +60,7 @@ func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) Example: apiversionsExample, DisableFlagsInUseLine: true, Run: func(cmd *cobra.Command, args []string) { - cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Complete(restClientGetter, cmd, args)) cmdutil.CheckErr(o.RunAPIVersions()) }, } @@ -68,12 +68,12 @@ func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) } // Complete adapts from the command line args and factory to the data required -func (o *APIVersionsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { +func (o *APIVersionsOptions) Complete(restClientGetter genericclioptions.RESTClientGetter, cmd *cobra.Command, args []string) error { if len(args) != 0 { return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) } var err error - o.discoveryClient, err = f.ToDiscoveryClient() + o.discoveryClient, err = restClientGetter.ToDiscoveryClient() return err } diff --git a/pkg/util/completion/completion.go b/pkg/util/completion/completion.go index 6110b50a..154c5e68 100644 --- a/pkg/util/completion/completion.go +++ b/pkg/util/completion/completion.go @@ -257,11 +257,13 @@ func ListUsersInConfig(toComplete string) []string { } // compGetResourceList returns the list of api resources which begin with `toComplete`. -func compGetResourceList(f cmdutil.Factory, cmd *cobra.Command, toComplete string) []string { +func compGetResourceList(restClientGetter genericclioptions.RESTClientGetter, cmd *cobra.Command, toComplete string) []string { buf := new(bytes.Buffer) streams := genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: ioutil.Discard} o := apiresources.NewAPIResourceOptions(streams) + o.Complete(restClientGetter, cmd, nil) + // Get the list of resources o.Output = "name" o.Cached = true @@ -269,7 +271,7 @@ func compGetResourceList(f cmdutil.Factory, cmd *cobra.Command, toComplete strin // TODO:Should set --request-timeout=5s // Ignore errors as the output may still be valid - o.RunAPIResources(cmd, f) + o.RunAPIResources() // Resources can be a comma-separated list. The last element is then // the one we should complete. For example if toComplete=="pods,secre"