(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
This commit is contained in:
Arda Güçlü 2022-08-24 09:52:10 +03:00 committed by Kubernetes Publisher
parent 74b38cf5e3
commit daf2914981
4 changed files with 35 additions and 25 deletions

View File

@ -30,6 +30,7 @@ import (
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers" "k8s.io/cli-runtime/pkg/printers"
"k8s.io/client-go/discovery"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates" "k8s.io/kubectl/pkg/util/templates"
@ -68,6 +69,11 @@ type APIResourceOptions struct {
Cached bool Cached bool
Categories []string Categories []string
groupChanged bool
nsChanged bool
discoveryClient discovery.CachedDiscoveryInterface
genericclioptions.IOStreams genericclioptions.IOStreams
} }
@ -87,7 +93,7 @@ func NewAPIResourceOptions(ioStreams genericclioptions.IOStreams) *APIResourceOp
} }
// NewCmdAPIResources creates the `api-resources` command // 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) o := NewAPIResourceOptions(ioStreams)
cmd := &cobra.Command{ 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."), Long: i18n.T("Print the supported API resources on the server."),
Example: apiresourcesExample, Example: apiresourcesExample,
Run: func(cmd *cobra.Command, args []string) { 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.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 // 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 { if len(args) != 0 {
return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) 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 return nil
} }
// RunAPIResources does the work // 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) w := printers.GetNewTabWriter(o.Out)
defer w.Flush() defer w.Flush()
discoveryclient, err := f.ToDiscoveryClient()
if err != nil {
return err
}
if !o.Cached { if !o.Cached {
// Always request fresh data from the server // Always request fresh data from the server
discoveryclient.Invalidate() o.discoveryClient.Invalidate()
} }
errs := []error{} errs := []error{}
lists, err := discoveryclient.ServerPreferredResources() lists, err := o.discoveryClient.ServerPreferredResources()
if err != nil { if err != nil {
errs = append(errs, err) errs = append(errs, err)
} }
resources := []groupResource{} resources := []groupResource{}
groupChanged := cmd.Flags().Changed("api-group")
nsChanged := cmd.Flags().Changed("namespaced")
for _, list := range lists { for _, list := range lists {
if len(list.APIResources) == 0 { if len(list.APIResources) == 0 {
continue continue
@ -176,11 +184,11 @@ func (o *APIResourceOptions) RunAPIResources(cmd *cobra.Command, f cmdutil.Facto
continue continue
} }
// filter apiGroup // filter apiGroup
if groupChanged && o.APIGroup != gv.Group { if o.groupChanged && o.APIGroup != gv.Group {
continue continue
} }
// filter namespaced // filter namespaced
if nsChanged && o.Namespaced != resource.Namespaced { if o.nsChanged && o.Namespaced != resource.Namespaced {
continue continue
} }
// filter to resources that support the specified verbs // filter to resources that support the specified verbs

View File

@ -34,12 +34,12 @@ func TestAPIResourcesComplete(t *testing.T) {
parentCmd.AddCommand(cmd) parentCmd.AddCommand(cmd)
o := NewAPIResourceOptions(genericclioptions.NewTestIOStreamsDiscard()) o := NewAPIResourceOptions(genericclioptions.NewTestIOStreamsDiscard())
err := o.Complete(cmd, []string{}) err := o.Complete(tf, cmd, []string{})
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
err = o.Complete(cmd, []string{"foo"}) err = o.Complete(tf, cmd, []string{"foo"})
if err == nil { if err == nil {
t.Fatalf("An error was expected but not returned") t.Fatalf("An error was expected but not returned")
} }

View File

@ -51,7 +51,7 @@ func NewAPIVersionsOptions(ioStreams genericclioptions.IOStreams) *APIVersionsOp
} }
// NewCmdAPIVersions creates the `api-versions` command // 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) o := NewAPIVersionsOptions(ioStreams)
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "api-versions", Use: "api-versions",
@ -60,7 +60,7 @@ func NewCmdAPIVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
Example: apiversionsExample, Example: apiversionsExample,
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) { 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()) 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 // 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 { if len(args) != 0 {
return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args) return cmdutil.UsageErrorf(cmd, "unexpected arguments: %v", args)
} }
var err error var err error
o.discoveryClient, err = f.ToDiscoveryClient() o.discoveryClient, err = restClientGetter.ToDiscoveryClient()
return err return err
} }

View File

@ -257,11 +257,13 @@ func ListUsersInConfig(toComplete string) []string {
} }
// compGetResourceList returns the list of api resources which begin with `toComplete`. // 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) buf := new(bytes.Buffer)
streams := genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: ioutil.Discard} streams := genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: ioutil.Discard}
o := apiresources.NewAPIResourceOptions(streams) o := apiresources.NewAPIResourceOptions(streams)
o.Complete(restClientGetter, cmd, nil)
// Get the list of resources // Get the list of resources
o.Output = "name" o.Output = "name"
o.Cached = true o.Cached = true
@ -269,7 +271,7 @@ func compGetResourceList(f cmdutil.Factory, cmd *cobra.Command, toComplete strin
// TODO:Should set --request-timeout=5s // TODO:Should set --request-timeout=5s
// Ignore errors as the output may still be valid // 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 // Resources can be a comma-separated list. The last element is then
// the one we should complete. For example if toComplete=="pods,secre" // the one we should complete. For example if toComplete=="pods,secre"