(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/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

View File

@ -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")
}

View File

@ -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
}

View File

@ -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"