diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index a66d86d7923..e9d1b88e5b6 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -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 diff --git a/pkg/kubectl/cmd/apiresources.go b/pkg/kubectl/cmd/apiresources.go index a719b3f6fbb..b2ad4f0df9d 100644 --- a/pkg/kubectl/cmd/apiresources.go +++ b/pkg/kubectl/cmd/apiresources.go @@ -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 { diff --git a/pkg/kubectl/cmd/apply_edit_last_applied.go b/pkg/kubectl/cmd/apply_edit_last_applied.go index c3008861f7b..e4700989ce9 100644 --- a/pkg/kubectl/cmd/apply_edit_last_applied.go +++ b/pkg/kubectl/cmd/apply_edit_last_applied.go @@ -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 diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index 6ed2a86a163..1b1cb9c244c 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -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") diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 099749442be..4cbf38eb367 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -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]}" } diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index b27072c1819..1b67b08eb1e 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -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) diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index acb3c733004..4789082b0ee 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -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 diff --git a/pkg/kubectl/cmd/get/get.go b/pkg/kubectl/cmd/get/get.go index b38054753ee..b51ee148342 100644 --- a/pkg/kubectl/cmd/get/get.go +++ b/pkg/kubectl/cmd/get/get.go @@ -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) diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 4b20f1e6bc8..7e35218581b 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -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) diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 91ba90d0fb0..19a06a747e9 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -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) diff --git a/pkg/kubectl/cmd/util/cached_discovery.go b/pkg/kubectl/cmd/util/cached_discovery.go index 0224ebbe9be..d053102bb61 100644 --- a/pkg/kubectl/cmd/util/cached_discovery.go +++ b/pkg/kubectl/cmd/util/cached_discovery.go @@ -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) { diff --git a/pkg/kubectl/cmd/util/printing.go b/pkg/kubectl/cmd/util/printing.go index cff8bb0ad60..ef3a0eda50e 100644 --- a/pkg/kubectl/cmd/util/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -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 -} diff --git a/staging/src/k8s.io/client-go/discovery/cached/memcache.go b/staging/src/k8s.io/client-go/discovery/cached/memcache.go index 585b4c80da8..d4313bcf3c0 100644 --- a/staging/src/k8s.io/client-go/discovery/cached/memcache.go +++ b/staging/src/k8s.io/client-go/discovery/cached/memcache.go @@ -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) { diff --git a/staging/src/k8s.io/client-go/discovery/discovery_client.go b/staging/src/k8s.io/client-go/discovery/discovery_client.go index 8beecb2f1ca..d59e8a02ac1 100644 --- a/staging/src/k8s.io/client-go/discovery/discovery_client.go +++ b/staging/src/k8s.io/client-go/discovery/discovery_client.go @@ -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