diff --git a/contrib/completions/bash/oc b/contrib/completions/bash/oc index 4642a61423ae..300a7198ed4d 100644 --- a/contrib/completions/bash/oc +++ b/contrib/completions/bash/oc @@ -6609,6 +6609,107 @@ _oc_annotate() noun_aliases+=("users") } +_oc_api-resources() +{ + last_command="oc_api-resources" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--allow-missing-template-keys") + local_nonpersistent_flags+=("--allow-missing-template-keys") + flags+=("--api-group=") + local_nonpersistent_flags+=("--api-group=") + flags+=("--cached") + local_nonpersistent_flags+=("--cached") + flags+=("--namespaced") + local_nonpersistent_flags+=("--namespaced") + flags+=("--no-headers") + local_nonpersistent_flags+=("--no-headers") + flags+=("--output=") + two_word_flags+=("-o") + local_nonpersistent_flags+=("--output=") + flags+=("--verbs=") + local_nonpersistent_flags+=("--verbs=") + flags+=("--as=") + flags+=("--as-group=") + flags+=("--cache-dir=") + flags+=("--certificate-authority=") + flags+=("--client-certificate=") + flags+=("--client-key=") + flags+=("--cluster=") + flags+=("--config=") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + flags_with_completion+=("--namespace") + flags_completion+=("__oc_get_namespaces") + two_word_flags+=("-n") + flags_with_completion+=("-n") + flags_completion+=("__oc_get_namespaces") + flags+=("--password=") + flags+=("--request-timeout=") + flags+=("--server=") + two_word_flags+=("-s") + flags+=("--token=") + flags+=("--user=") + flags+=("--username=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_oc_api-versions() +{ + last_command="oc_api-versions" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--as=") + flags+=("--as-group=") + flags+=("--cache-dir=") + flags+=("--certificate-authority=") + flags+=("--client-certificate=") + flags+=("--client-key=") + flags+=("--cluster=") + flags+=("--config=") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + flags_with_completion+=("--namespace") + flags_completion+=("__oc_get_namespaces") + two_word_flags+=("-n") + flags_with_completion+=("-n") + flags_completion+=("__oc_get_namespaces") + flags+=("--password=") + flags+=("--request-timeout=") + flags+=("--server=") + two_word_flags+=("-s") + flags+=("--token=") + flags+=("--user=") + flags+=("--username=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oc_apply_edit-last-applied() { last_command="oc_apply_edit-last-applied" @@ -17982,6 +18083,8 @@ _oc_root_command() commands=() commands+=("adm") commands+=("annotate") + commands+=("api-resources") + commands+=("api-versions") commands+=("apply") commands+=("attach") commands+=("auth") diff --git a/contrib/completions/zsh/oc b/contrib/completions/zsh/oc index 38fc6ae1f5d0..8027f57bb9bc 100644 --- a/contrib/completions/zsh/oc +++ b/contrib/completions/zsh/oc @@ -6751,6 +6751,107 @@ _oc_annotate() noun_aliases+=("users") } +_oc_api-resources() +{ + last_command="oc_api-resources" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--allow-missing-template-keys") + local_nonpersistent_flags+=("--allow-missing-template-keys") + flags+=("--api-group=") + local_nonpersistent_flags+=("--api-group=") + flags+=("--cached") + local_nonpersistent_flags+=("--cached") + flags+=("--namespaced") + local_nonpersistent_flags+=("--namespaced") + flags+=("--no-headers") + local_nonpersistent_flags+=("--no-headers") + flags+=("--output=") + two_word_flags+=("-o") + local_nonpersistent_flags+=("--output=") + flags+=("--verbs=") + local_nonpersistent_flags+=("--verbs=") + flags+=("--as=") + flags+=("--as-group=") + flags+=("--cache-dir=") + flags+=("--certificate-authority=") + flags+=("--client-certificate=") + flags+=("--client-key=") + flags+=("--cluster=") + flags+=("--config=") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + flags_with_completion+=("--namespace") + flags_completion+=("__oc_get_namespaces") + two_word_flags+=("-n") + flags_with_completion+=("-n") + flags_completion+=("__oc_get_namespaces") + flags+=("--password=") + flags+=("--request-timeout=") + flags+=("--server=") + two_word_flags+=("-s") + flags+=("--token=") + flags+=("--user=") + flags+=("--username=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + +_oc_api-versions() +{ + last_command="oc_api-versions" + commands=() + + flags=() + two_word_flags=() + local_nonpersistent_flags=() + flags_with_completion=() + flags_completion=() + + flags+=("--as=") + flags+=("--as-group=") + flags+=("--cache-dir=") + flags+=("--certificate-authority=") + flags+=("--client-certificate=") + flags+=("--client-key=") + flags+=("--cluster=") + flags+=("--config=") + flags+=("--context=") + flags+=("--insecure-skip-tls-verify") + flags+=("--loglevel=") + flags+=("--logspec=") + flags+=("--match-server-version") + flags+=("--namespace=") + flags_with_completion+=("--namespace") + flags_completion+=("__oc_get_namespaces") + two_word_flags+=("-n") + flags_with_completion+=("-n") + flags_completion+=("__oc_get_namespaces") + flags+=("--password=") + flags+=("--request-timeout=") + flags+=("--server=") + two_word_flags+=("-s") + flags+=("--token=") + flags+=("--user=") + flags+=("--username=") + + must_have_one_flag=() + must_have_one_noun=() + noun_aliases=() +} + _oc_apply_edit-last-applied() { last_command="oc_apply_edit-last-applied" @@ -18124,6 +18225,8 @@ _oc_root_command() commands=() commands+=("adm") commands+=("annotate") + commands+=("api-resources") + commands+=("api-versions") commands+=("apply") commands+=("attach") commands+=("auth") diff --git a/docs/man/man1/.files_generated_oc b/docs/man/man1/.files_generated_oc index 13f73fcad18f..f0009f0561e8 100644 --- a/docs/man/man1/.files_generated_oc +++ b/docs/man/man1/.files_generated_oc @@ -118,6 +118,8 @@ oc-adm-uncordon.1 oc-adm-verify-image-signature.1 oc-adm.1 oc-annotate.1 +oc-api-resources.1 +oc-api-versions.1 oc-apply-edit-last-applied.1 oc-apply-set-last-applied.1 oc-apply-view-last-applied.1 diff --git a/docs/man/man1/oc-api-resources.1 b/docs/man/man1/oc-api-resources.1 new file mode 100644 index 000000000000..b6fd7a0f9896 --- /dev/null +++ b/docs/man/man1/oc-api-resources.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/docs/man/man1/oc-api-versions.1 b/docs/man/man1/oc-api-versions.1 new file mode 100644 index 000000000000..b6fd7a0f9896 --- /dev/null +++ b/docs/man/man1/oc-api-versions.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/pkg/oc/cli/cli.go b/pkg/oc/cli/cli.go index e9267c0be386..5e4f20811d8f 100644 --- a/pkg/oc/cli/cli.go +++ b/pkg/oc/cli/cli.go @@ -174,6 +174,8 @@ func NewCommandCLI(name, fullName string, in io.Reader, out, errout io.Writer) * importer.NewCmdImport(fullName, f, in, out, errout), image.NewCmdImage(fullName, f, in, out, errout), registry.NewCmd(fullName, f, in, out, errout), + cmd.NewCmdApiVersions(fullName, f, out), + cmd.NewCmdApiResources(fullName, f, out), }, }, { diff --git a/pkg/oc/cli/cmd/wrappers.go b/pkg/oc/cli/cmd/wrappers.go index 620551df3cb0..bf0869784d85 100644 --- a/pkg/oc/cli/cmd/wrappers.go +++ b/pkg/oc/cli/cmd/wrappers.go @@ -18,6 +18,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/cmd/config" "k8s.io/kubernetes/pkg/kubectl/cmd/resource" "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + "k8s.io/kubernetes/pkg/kubectl/util/i18n" cmdutil "github.com/openshift/origin/pkg/cmd/util" "github.com/openshift/origin/pkg/oc/cli/cmd/create" @@ -788,3 +789,39 @@ func NewCmdAuth(fullName string, f *clientcmd.Factory, out, errout io.Writer) *c func NewCmdPlugin(fullName string, f *clientcmd.Factory, in io.Reader, out, errout io.Writer) *cobra.Command { return kcmd.NewCmdPlugin(f, in, out, errout) } + +var ( + apiresourcesExample = templates.Examples(` + # Print the supported API Resources + %[1]s api-resources + + # Print the supported API Resources with more information + %[1]s api-resources -o wide + + # Print the supported namespaced resources + %[1]s api-resources --namespaced=true + + # Print the supported non-namespaced resources + %[1]s api-resources --namespaced=false + + # Print the supported API Resources with specific APIGroup + %[1]s api-resources --api-group=extensions`) +) + +func NewCmdApiResources(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { + cmd := kcmd.NewCmdApiResources(f, out) + cmd.Example = fmt.Sprintf(apiresourcesExample, fullName) + return cmd +} + +var ( + apiversionsExample = templates.Examples(i18n.T(` + # Print the supported API versions + %[1]s api-versions`)) +) + +func NewCmdApiVersions(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { + cmd := kcmd.NewCmdApiVersions(f, out) + cmd.Example = fmt.Sprintf(apiversionsExample, fullName) + return cmd +} diff --git a/pkg/oc/cli/kubectl_compat_test.go b/pkg/oc/cli/kubectl_compat_test.go index 9c771e254743..841cde6d72c6 100644 --- a/pkg/oc/cli/kubectl_compat_test.go +++ b/pkg/oc/cli/kubectl_compat_test.go @@ -17,9 +17,9 @@ import ( // NEVER ADD TO THIS LIST // TODO kill this list var MissingCommands = sets.NewString( - "namespace", "rolling-update", - "cluster-info", "api-versions", - "stop", + "namespace", + "rolling-update", + "cluster-info", // are on admin commands "cordon", @@ -30,12 +30,7 @@ var MissingCommands = sets.NewString( "certificate", // TODO commands to assess - "apiversions", - "clusterinfo", - "resize", - "rollingupdate", "run-container", - "update", "alpha", ) diff --git a/test/cmd/apiresources.sh b/test/cmd/apiresources.sh new file mode 100755 index 000000000000..471d81c9a06b --- /dev/null +++ b/test/cmd/apiresources.sh @@ -0,0 +1,15 @@ +#!/bin/bash +source "$(dirname "${BASH_SOURCE}")/../../hack/lib/init.sh" +trap os::test::junit::reconcile_output EXIT + +os::test::junit::declare_suite_start "cmd/apiresources" + +os::cmd::expect_success_and_text 'oc api-resources' 'imagestreamtags' +os::cmd::expect_success_and_text 'oc api-resources --api-group=build.openshift.io' 'BuildConfig' +os::cmd::expect_success_and_text 'oc api-resources --namespaced=false' 'Image' +os::cmd::expect_success_and_text 'oc api-resources --verbs=get' 'project.openshift.io' + +os::cmd::expect_success_and_text 'oc api-versions' 'route.openshift.io/v1' + +echo "apiresources: ok" +os::test::junit::declare_suite_end diff --git a/vendor/k8s.io/kubernetes/docs/.generated_docs b/vendor/k8s.io/kubernetes/docs/.generated_docs index c0198d7757bf..2f0f59e9a30d 100644 --- a/vendor/k8s.io/kubernetes/docs/.generated_docs +++ b/vendor/k8s.io/kubernetes/docs/.generated_docs @@ -145,6 +145,7 @@ docs/man/man1/kubeadm.1 docs/man/man1/kubectl-alpha-diff.1 docs/man/man1/kubectl-alpha.1 docs/man/man1/kubectl-annotate.1 +docs/man/man1/kubectl-api-resources.1 docs/man/man1/kubectl-api-versions.1 docs/man/man1/kubectl-apply-edit-last-applied.1 docs/man/man1/kubectl-apply-set-last-applied.1 @@ -245,6 +246,7 @@ docs/user-guide/kubectl/kubectl.md docs/user-guide/kubectl/kubectl_alpha.md docs/user-guide/kubectl/kubectl_alpha_diff.md docs/user-guide/kubectl/kubectl_annotate.md +docs/user-guide/kubectl/kubectl_api-resources.md docs/user-guide/kubectl/kubectl_api-versions.md docs/user-guide/kubectl/kubectl_apply.md docs/user-guide/kubectl/kubectl_apply_edit-last-applied.md @@ -341,6 +343,7 @@ docs/user-guide/kubectl/kubectl_version.md docs/yaml/kubectl/kubectl.yaml docs/yaml/kubectl/kubectl_alpha.yaml docs/yaml/kubectl/kubectl_annotate.yaml +docs/yaml/kubectl/kubectl_api-resources.yaml docs/yaml/kubectl/kubectl_api-versions.yaml docs/yaml/kubectl/kubectl_apply.yaml docs/yaml/kubectl/kubectl_attach.yaml diff --git a/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 new file mode 100644 index 000000000000..b6fd7a0f9896 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/man/man1/kubectl-api-resources.1 @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md new file mode 100644 index 000000000000..b6fd7a0f9896 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/user-guide/kubectl/kubectl_api-resources.md @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml new file mode 100644 index 000000000000..b6fd7a0f9896 --- /dev/null +++ b/vendor/k8s.io/kubernetes/docs/yaml/kubectl/kubectl_api-resources.yaml @@ -0,0 +1,3 @@ +This file is autogenerated, but we've stopped checking such files into the +repository to reduce the need for rebases. Please run hack/generate-docs.sh to +populate this file. diff --git a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh index 4ecc5a6e6d42..fb3b251082f8 100755 --- a/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh +++ b/vendor/k8s.io/kubernetes/hack/make-rules/test-cmd-util.sh @@ -4837,6 +4837,11 @@ runTests() { record_command run_RESTMapper_evaluation_tests + # find all resources + kubectl "${kube_flags[@]}" api-resources + # find all namespaced resources that support list by name and get them + kubectl "${kube_flags[@]}" api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl "${kube_flags[@]}" get -o name + ################ # Cluster Role # ################ diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD index 41c8c72ac17f..c77ee0657096 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/BUILD @@ -9,6 +9,7 @@ go_library( srcs = [ "alpha.go", "annotate.go", + "apiresources.go", "apiversions.go", "apply.go", "apply_edit_last_applied.go", diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go new file mode 100644 index 000000000000..342529edb12b --- /dev/null +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/apiresources.go @@ -0,0 +1,233 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cmd + +import ( + "fmt" + "io" + "sort" + "strings" + + "github.com/spf13/cobra" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + "k8s.io/kubernetes/pkg/printers" +) + +var ( + apiresourcesExample = templates.Examples(` + # Print the supported API Resources + kubectl api-resources + + # Print the supported API Resources with more information + kubectl api-resources -o wide + + # Print the supported namespaced resources + kubectl api-resources --namespaced=true + + # Print the supported non-namespaced resources + kubectl api-resources --namespaced=false + + # Print the supported API Resources with specific APIGroup + kubectl api-resources --api-group=extensions`) +) + +// ApiResourcesOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of +// referencing the cmd.Flags() +type ApiResourcesOptions struct { + out io.Writer + + Output string + APIGroup string + Namespaced bool + Verbs []string + NoHeaders bool + Cached bool +} + +// groupResource contains the APIGroup and APIResource +type groupResource struct { + APIGroup string + APIResource metav1.APIResource +} + +func NewCmdApiResources(f cmdutil.Factory, out io.Writer) *cobra.Command { + options := &ApiResourcesOptions{ + out: out, + } + + cmd := &cobra.Command{ + Use: "api-resources", + Short: "Print the supported API resources on the server", + Long: "Print the supported API resources on the server", + Example: apiresourcesExample, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(options.Complete(cmd)) + cmdutil.CheckErr(options.Validate(cmd)) + cmdutil.CheckErr(options.RunApiResources(cmd, f)) + }, + } + cmdutil.AddOutputFlags(cmd) + cmdutil.AddNoHeadersFlags(cmd) + cmd.Flags().StringVar(&options.APIGroup, "api-group", "", "Limit to resources in the specified API group.") + cmd.Flags().BoolVar(&options.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.") + cmd.Flags().StringSliceVar(&options.Verbs, "verbs", options.Verbs, "Limit to resources that support the specified verbs.") + cmd.Flags().BoolVar(&options.Cached, "cached", options.Cached, "Use the cached list of resources if available.") + return cmd +} + +func (o *ApiResourcesOptions) Complete(cmd *cobra.Command) error { + o.Output = cmdutil.GetFlagString(cmd, "output") + o.NoHeaders = cmdutil.GetFlagBool(cmd, "no-headers") + return nil +} + +func (o *ApiResourcesOptions) Validate(cmd *cobra.Command) error { + validOutputTypes := sets.NewString("", "json", "yaml", "wide", "name", "custom-columns", "custom-columns-file", "go-template", "go-template-file", "jsonpath", "jsonpath-file") + supportedOutputTypes := sets.NewString("", "wide", "name") + outputFormat := cmdutil.GetFlagString(cmd, "output") + if !validOutputTypes.Has(outputFormat) { + return fmt.Errorf("output must be one of '' or 'wide': %v", outputFormat) + } + if !supportedOutputTypes.Has(outputFormat) { + return fmt.Errorf("--output %v is not available", outputFormat) + } + return nil +} + +func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Factory) error { + w := printers.GetNewTabWriter(o.out) + defer w.Flush() + + discoveryclient, err := f.DiscoveryClient() + if err != nil { + return err + } + + if !o.Cached { + // Always request fresh data from the server + discoveryclient.Invalidate() + } + + lists, err := discoveryclient.ServerPreferredResources() + if err != nil { + return err + } + + resources := []groupResource{} + + groupChanged := cmd.Flags().Changed("api-group") + nsChanged := cmd.Flags().Changed("namespaced") + + for _, list := range lists { + if len(list.APIResources) == 0 { + continue + } + gv, err := schema.ParseGroupVersion(list.GroupVersion) + if err != nil { + continue + } + for _, resource := range list.APIResources { + if len(resource.Verbs) == 0 { + continue + } + // filter apiGroup + if groupChanged && o.APIGroup != gv.Group { + continue + } + // filter namespaced + if nsChanged && o.Namespaced != resource.Namespaced { + continue + } + // filter to resources that support the specified verbs + if len(o.Verbs) > 0 && !sets.NewString(resource.Verbs...).HasAll(o.Verbs...) { + continue + } + resources = append(resources, groupResource{ + APIGroup: gv.Group, + APIResource: resource, + }) + } + } + + if o.NoHeaders == false && o.Output != "name" { + if err = printContextHeaders(w, o.Output); err != nil { + return err + } + } + + sort.Stable(sortableGroupResource(resources)) + for _, r := range resources { + switch o.Output { + case "name": + name := r.APIResource.Name + if len(r.APIGroup) > 0 { + name += "." + r.APIGroup + } + if _, err := fmt.Fprintf(w, "%s\n", name); err != nil { + return err + } + case "wide": + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\t%v\n", + r.APIResource.Name, + strings.Join(r.APIResource.ShortNames, ","), + r.APIGroup, + r.APIResource.Namespaced, + r.APIResource.Kind, + r.APIResource.Verbs); err != nil { + return err + } + case "": + if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%v\t%s\n", + r.APIResource.Name, + strings.Join(r.APIResource.ShortNames, ","), + r.APIGroup, + r.APIResource.Namespaced, + r.APIResource.Kind); err != nil { + return err + } + } + } + return nil +} + +func printContextHeaders(out io.Writer, output string) error { + columnNames := []string{"NAME", "SHORTNAMES", "APIGROUP", "NAMESPACED", "KIND"} + if output == "wide" { + columnNames = append(columnNames, "VERBS") + } + _, err := fmt.Fprintf(out, "%s\n", strings.Join(columnNames, "\t")) + return err +} + +type sortableGroupResource []groupResource + +func (s sortableGroupResource) Len() int { return len(s) } +func (s sortableGroupResource) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sortableGroupResource) Less(i, j int) bool { + ret := strings.Compare(s[i].APIGroup, s[j].APIGroup) + if ret > 0 { + return false + } else if ret == 0 { + return strings.Compare(s[i].APIResource.Name, s[j].APIResource.Name) < 0 + } + return true +} diff --git a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go index 3bdd843b975e..c2c79a7ace87 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go +++ b/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/cmd.go @@ -345,6 +345,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob cmds.AddCommand(NewCmdPlugin(f, in, out, err)) cmds.AddCommand(NewCmdVersion(f, out)) cmds.AddCommand(NewCmdApiVersions(f, out)) + cmds.AddCommand(NewCmdApiResources(f, out)) cmds.AddCommand(NewCmdOptions(out)) return cmds