mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #63421 from liggitt/discover-completions
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Cache preferred resources, use in kubectl resource name autocomplete Fixes #63145 Fixes https://github.com/kubernetes/kubectl/issues/357 Alternative to #61928 * starts to unify preferred resource logic on top of ServerGroups()/ServerResourcesForGroupVersion() methods * allows indicating a cached list of resources is acceptable when calling `kubectl api-resources` (default is still to rediscover) * uses `kubectl api-resources` in bash completion ```sh $ kubectl get [TAB][TAB] apiservices.apiregistration.k8s.io networkpolicies.extensions certificatesigningrequests.certificates.k8s.io networkpolicies.networking.k8s.io clusterrolebindings.rbac.authorization.k8s.io nodes clusterroles.rbac.authorization.k8s.io persistentvolumeclaims componentstatuses persistentvolumes configmaps poddisruptionbudgets.policy controllerrevisions.apps pods cronjobs.batch podsecuritypolicies.extensions customresourcedefinitions.apiextensions.k8s.io podsecuritypolicies.policy daemonsets.apps podtemplates daemonsets.extensions replicasets.apps deployments.apps replicasets.extensions deployments.extensions replicationcontrollers endpoints resourcequotas events rolebindings.rbac.authorization.k8s.io events.events.k8s.io roles.rbac.authorization.k8s.io horizontalpodautoscalers.autoscaling secrets ingresses.extensions serviceaccounts initializerconfigurations.admissionregistration.k8s.io services jobs.batch statefulsets.apps limitranges storageclasses.storage.k8s.io mutatingwebhookconfigurations.admissionregistration.k8s.io validatingwebhookconfigurations.admissionregistration.k8s.io namespaces volumeattachments.storage.k8s.io ``` ```release-note NONE ```
This commit is contained in:
commit
068b7befa9
@ -120,7 +120,6 @@ func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions
|
||||
|
||||
func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewAnnotateOptions(ioStreams)
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
|
||||
@ -133,8 +132,6 @@ func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioption
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunAnnotate())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
// bind flag structs
|
||||
|
@ -59,6 +59,7 @@ type ApiResourcesOptions struct {
|
||||
Namespaced bool
|
||||
Verbs []string
|
||||
NoHeaders bool
|
||||
Cached bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -94,6 +95,7 @@ func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams
|
||||
cmd.Flags().StringVar(&o.APIGroup, "api-group", "", "Limit to resources in the specified API group.")
|
||||
cmd.Flags().BoolVar(&o.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.")
|
||||
cmd.Flags().StringSliceVar(&o.Verbs, "verbs", o.Verbs, "Limit to resources that support the specified verbs.")
|
||||
cmd.Flags().BoolVar(&o.Cached, "cached", o.Cached, "Use the cached list of resources if available.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -125,8 +127,10 @@ func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Fact
|
||||
return err
|
||||
}
|
||||
|
||||
// Always request fresh data from the server
|
||||
discoveryclient.Invalidate()
|
||||
if !o.Cached {
|
||||
// Always request fresh data from the server
|
||||
discoveryclient.Invalidate()
|
||||
}
|
||||
|
||||
lists, err := discoveryclient.ServerPreferredResources()
|
||||
if err != nil {
|
||||
|
@ -19,7 +19,6 @@ package cmd
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor"
|
||||
@ -59,8 +58,6 @@ var (
|
||||
func NewCmdApplyEditLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := editor.NewEditOptions(editor.ApplyEditMode, ioStreams)
|
||||
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "edit-last-applied (RESOURCE/NAME | -f FILENAME)",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -75,8 +72,6 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, ioStreams genericclioptions.I
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
// bind flag structs
|
||||
|
@ -67,7 +67,6 @@ func NewViewLastAppliedOptions(ioStreams genericclioptions.IOStreams) *ViewLastA
|
||||
|
||||
func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
options := NewViewLastAppliedOptions(ioStreams)
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAME)",
|
||||
@ -80,8 +79,6 @@ func NewCmdApplyViewLastApplied(f cmdutil.Factory, ioStreams genericclioptions.I
|
||||
cmdutil.CheckErr(options.Validate(cmd))
|
||||
cmdutil.CheckErr(options.RunApplyViewLastApplied(cmd))
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&options.OutputFormat, "output", "o", options.OutputFormat, "Output format. Must be one of yaml|json")
|
||||
|
@ -60,9 +60,6 @@ __kubectl_override_flags()
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ "${w}" == "--all-namespaces" ]; then
|
||||
namespace="--all-namespaces"
|
||||
fi
|
||||
done
|
||||
for var in "${__kubectl_override_flag_list[@]##*-}"; do
|
||||
if eval "test -n \"\$${var}\""; then
|
||||
@ -109,7 +106,12 @@ __kubectl_parse_get()
|
||||
__kubectl_get_resource()
|
||||
{
|
||||
if [[ ${#nouns[@]} -eq 0 ]]; then
|
||||
return 1
|
||||
local kubectl_out
|
||||
if kubectl_out=$(kubectl api-resources $(__kubectl_override_flags) -o name --cached --request-timeout=5s --verbs=get 2>/dev/null); then
|
||||
COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
__kubectl_parse_get "${nouns[${#nouns[@]} -1]}"
|
||||
}
|
||||
|
@ -115,7 +115,6 @@ type DeleteOptions struct {
|
||||
|
||||
func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
deleteFlags := NewDeleteCommandFlags("containing the resource to delete.")
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])",
|
||||
@ -138,8 +137,6 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
}
|
||||
},
|
||||
SuggestFor: []string{"rm"},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
deleteFlags.AddFlags(cmd)
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor"
|
||||
@ -72,8 +71,6 @@ func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra
|
||||
o := editor.NewEditOptions(editor.NormalEditMode, ioStreams)
|
||||
o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true}
|
||||
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -88,8 +85,6 @@ func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
// bind flag structs
|
||||
|
@ -148,7 +148,6 @@ func NewGetOptions(parent string, streams genericclioptions.IOStreams) *GetOptio
|
||||
// retrieves one or more resources from a server.
|
||||
func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewGetOptions(parent, streams)
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "get [(-o|--output=)json|yaml|wide|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=...] (TYPE[.VERSION][.GROUP] [NAME | -l label] | TYPE[.VERSION][.GROUP]/NAME ...) [flags]",
|
||||
@ -162,8 +161,6 @@ func NewCmdGet(parent string, f cmdutil.Factory, streams genericclioptions.IOStr
|
||||
cmdutil.CheckErr(o.Run(f, cmd, args))
|
||||
},
|
||||
SuggestFor: []string{"list", "ps"},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
@ -34,7 +34,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
@ -124,8 +123,6 @@ func NewLabelOptions(ioStreams genericclioptions.IOStreams) *LabelOptions {
|
||||
func NewCmdLabel(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewLabelOptions(ioStreams)
|
||||
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -137,8 +134,6 @@ func NewCmdLabel(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunLabel())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
o.RecordFlags.AddFlags(cmd)
|
||||
|
@ -33,7 +33,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
@ -106,7 +105,6 @@ func NewPatchOptions(ioStreams genericclioptions.IOStreams) *PatchOptions {
|
||||
|
||||
func NewCmdPatch(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewPatchOptions(ioStreams)
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "patch (-f FILENAME | TYPE NAME) -p PATCH",
|
||||
@ -119,8 +117,6 @@ func NewCmdPatch(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunPatch())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
}
|
||||
|
||||
o.RecordFlags.AddFlags(cmd)
|
||||
|
@ -220,11 +220,11 @@ func (d *CachedDiscoveryClient) RESTClient() restclient.Interface {
|
||||
}
|
||||
|
||||
func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
|
||||
return d.delegate.ServerPreferredResources()
|
||||
return discovery.ServerPreferredResources(d)
|
||||
}
|
||||
|
||||
func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
||||
return d.delegate.ServerPreferredNamespacedResources()
|
||||
return discovery.ServerPreferredNamespacedResources(d)
|
||||
}
|
||||
|
||||
func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) {
|
||||
|
@ -239,15 +239,3 @@ func maybeWrapSortingPrinter(printer printers.ResourcePrinter, printOpts printer
|
||||
func SuggestApiResources(parent string) string {
|
||||
return templates.LongDesc(fmt.Sprintf("Use \"%s api-resources\" for a complete list of supported resources.", parent))
|
||||
}
|
||||
|
||||
// Retrieve a list of handled resources from printer as valid args
|
||||
// TODO: This function implementation should be replaced with a real implementation from the discovery service.
|
||||
func ValidArgList(f ClientAccessFactory) []string {
|
||||
validArgs := []string{}
|
||||
|
||||
humanReadablePrinter := printers.NewHumanReadablePrinter(nil, printers.PrintOptions{})
|
||||
printersinternal.AddHandlers(humanReadablePrinter)
|
||||
validArgs = humanReadablePrinter.HandledResources()
|
||||
|
||||
return validArgs
|
||||
}
|
||||
|
@ -96,18 +96,12 @@ func (d *memCacheClient) RESTClient() restclient.Interface {
|
||||
return d.delegate.RESTClient()
|
||||
}
|
||||
|
||||
// TODO: Should this also be cached? The results seem more likely to be
|
||||
// inconsistent with ServerGroups and ServerResources given the requirement to
|
||||
// actively Invalidate.
|
||||
func (d *memCacheClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
|
||||
return d.delegate.ServerPreferredResources()
|
||||
return discovery.ServerPreferredResources(d)
|
||||
}
|
||||
|
||||
// TODO: Should this also be cached? The results seem more likely to be
|
||||
// inconsistent with ServerGroups and ServerResources given the requirement to
|
||||
// actively Invalidate.
|
||||
func (d *memCacheClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
||||
return d.delegate.ServerPreferredNamespacedResources()
|
||||
return discovery.ServerPreferredNamespacedResources(d)
|
||||
}
|
||||
|
||||
func (d *memCacheClient) ServerVersion() (*version.Info, error) {
|
||||
|
@ -250,6 +250,11 @@ func IsGroupDiscoveryFailedError(err error) bool {
|
||||
|
||||
// serverPreferredResources returns the supported resources with the version preferred by the server.
|
||||
func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, error) {
|
||||
return ServerPreferredResources(d)
|
||||
}
|
||||
|
||||
// ServerPreferredResources uses the provided discovery interface to look up preferred resources
|
||||
func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) {
|
||||
serverGroupList, err := d.ServerGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -319,7 +324,12 @@ func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList,
|
||||
// ServerPreferredNamespacedResources returns the supported namespaced resources with the
|
||||
// version preferred by the server.
|
||||
func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
|
||||
all, err := d.ServerPreferredResources()
|
||||
return ServerPreferredNamespacedResources(d)
|
||||
}
|
||||
|
||||
// ServerPreferredNamespacedResources uses the provided discovery interface to look up preferred namespaced resources
|
||||
func ServerPreferredNamespacedResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) {
|
||||
all, err := ServerPreferredResources(d)
|
||||
return FilteredBy(ResourcePredicateFunc(func(groupVersion string, r *metav1.APIResource) bool {
|
||||
return r.Namespaced
|
||||
}), all), err
|
||||
|
Loading…
Reference in New Issue
Block a user