diff --git a/pkg/api/latest/latest.go b/pkg/api/latest/latest.go index 7ba42fb8465..da643154dca 100644 --- a/pkg/api/latest/latest.go +++ b/pkg/api/latest/latest.go @@ -42,6 +42,12 @@ var ( IsRegistered = allGroups.IsRegistered ) +// ExternalVersions is a list of all external versions for this API group in order of +// most preferred to least preferred +var ExternalVersions = []unversioned.GroupVersion{ + {Group: "", Version: "v1"}, +} + // GroupMetaMap is a map between group names and their metadata. type GroupMetaMap map[string]*GroupMeta diff --git a/pkg/client/unversioned/client.go b/pkg/client/unversioned/client.go index 31026e59ce2..b761fdcd64c 100644 --- a/pkg/client/unversioned/client.go +++ b/pkg/client/unversioned/client.go @@ -27,6 +27,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/version" ) @@ -183,12 +184,12 @@ func (c *Client) ValidateComponents() (*api.ComponentStatusList, error) { // SwaggerSchemaInterface has a method to retrieve the swagger schema. Used in // client.Interface type SwaggerSchemaInterface interface { - SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) + SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) } // SwaggerSchema retrieves and parses the swagger API schema the server supports. -func (c *Client) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, error) { - if groupVersion == "" { +func (c *Client) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { + if version.IsEmpty() { return nil, fmt.Errorf("groupVersion cannot be empty") } @@ -198,14 +199,14 @@ func (c *Client) SwaggerSchema(groupVersion string) (*swagger.ApiDeclaration, er } groupVersions := ExtractGroupVersions(groupList) // This check also takes care the case that kubectl is newer than the running endpoint - if stringDoesntExistIn(groupVersion, groupVersions) { - return nil, fmt.Errorf("API version: %s is not supported by the server. Use one of: %v", groupVersion, groupVersions) + if stringDoesntExistIn(version.String(), groupVersions) { + return nil, fmt.Errorf("API version: %v is not supported by the server. Use one of: %v", version, groupVersions) } var path string - if groupVersion == "v1" { - path = "/swaggerapi/api/" + groupVersion + if version == v1.SchemeGroupVersion { + path = "/swaggerapi/api/" + version.Version } else { - path = "/swaggerapi/apis/" + groupVersion + path = "/swaggerapi/apis/" + version.Group + "/" + version.Version } body, err := c.Get().AbsPath(path).Do().Raw() diff --git a/pkg/client/unversioned/client_test.go b/pkg/client/unversioned/client_test.go index 95ac1a6e3da..faff677da43 100644 --- a/pkg/client/unversioned/client_test.go +++ b/pkg/client/unversioned/client_test.go @@ -31,6 +31,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/api/v1" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" @@ -496,7 +497,7 @@ func TestGetSwaggerSchema(t *testing.T) { } client := NewOrDie(&Config{Host: server.URL}) - got, err := client.SwaggerSchema("v1") + got, err := client.SwaggerSchema(v1.SchemeGroupVersion) if err != nil { t.Fatalf("unexpected encoding error: %v", err) } @@ -506,7 +507,7 @@ func TestGetSwaggerSchema(t *testing.T) { } func TestGetSwaggerSchemaFail(t *testing.T) { - expErr := "API version: v4 is not supported by the server. Use one of: [v1 v2 v3]" + expErr := "API version: api.group/v4 is not supported by the server. Use one of: [v1 v2 v3]" server, err := swaggerSchemaFakeServer() if err != nil { @@ -514,7 +515,7 @@ func TestGetSwaggerSchemaFail(t *testing.T) { } client := NewOrDie(&Config{Host: server.URL}) - got, err := client.SwaggerSchema("v4") + got, err := client.SwaggerSchema(unversioned.GroupVersion{Group: "api.group", Version: "v4"}) if got != nil { t.Fatalf("unexpected response: %v", got) } diff --git a/pkg/client/unversioned/clientcmd/api/latest/latest.go b/pkg/client/unversioned/clientcmd/api/latest/latest.go index d1272295676..ecce3cbdd51 100644 --- a/pkg/client/unversioned/clientcmd/api/latest/latest.go +++ b/pkg/client/unversioned/clientcmd/api/latest/latest.go @@ -17,6 +17,7 @@ limitations under the License. package latest import ( + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api/v1" "k8s.io/kubernetes/pkg/runtime" ) @@ -24,6 +25,8 @@ import ( // Version is the string that represents the current external default version. const Version = "v1" +var ExternalVersion = unversioned.GroupVersion{Group: "", Version: "v1"} + // OldestVersion is the string that represents the oldest server version supported, // for client code that wants to hardcode the lowest common denominator. const OldestVersion = "v1" diff --git a/pkg/client/unversioned/testclient/testclient.go b/pkg/client/unversioned/testclient/testclient.go index b7aaa08afcc..b6bd6e2150e 100644 --- a/pkg/client/unversioned/testclient/testclient.go +++ b/pkg/client/unversioned/testclient/testclient.go @@ -25,6 +25,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/registered" "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/api/v1" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/version" @@ -306,10 +307,14 @@ func (c *Fake) ComponentStatuses() client.ComponentStatusInterface { } // SwaggerSchema returns an empty swagger.ApiDeclaration for testing -func (c *Fake) SwaggerSchema(version string) (*swagger.ApiDeclaration, error) { +func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { action := ActionImpl{} action.Verb = "get" - action.Resource = "/swaggerapi/api/" + version + if version == v1.SchemeGroupVersion { + action.Resource = "/swaggerapi/api/" + version.Version + } else { + action.Resource = "/swaggerapi/apis/" + version.Group + "/" + version.Version + } c.Invokes(action, nil) return &swagger.ApiDeclaration{}, nil diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 1338de60091..d311dc8e350 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -95,7 +95,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args [] } info := infos[0] mapping := info.ResourceMapping() - if err := f.CanBeAutoscaled(mapping.GroupVersionKind.Kind); err != nil { + if err := f.CanBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil { return err } diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index 205795ea2ab..040919177fc 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -21,7 +21,6 @@ import ( "fmt" "io" - "github.com/golang/glog" "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" @@ -70,16 +69,12 @@ func NewCmdConfigView(out io.Writer, ConfigAccess ConfigAccess) *cobra.Command { } printer, _, err := cmdutil.PrinterForCommand(cmd) - if err != nil { - glog.FatalDepth(1, err) - } - version := cmdutil.OutputVersion(cmd, latest.Version) + cmdutil.CheckErr(err) + version, err := cmdutil.OutputVersion(cmd, &latest.ExternalVersion) + cmdutil.CheckErr(err) printer = kubectl.NewVersionedPrinter(printer, clientcmdapi.Scheme, version) - if err := options.Run(out, printer); err != nil { - glog.FatalDepth(1, err) - } - + cmdutil.CheckErr(options.Run(out, printer)) }, } diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index 311d166c137..3f8bd962bc9 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -90,17 +90,16 @@ type ConvertOptions struct { out io.Writer printer kubectl.ResourcePrinter - outputVersion string + outputVersion unversioned.GroupVersion } // Complete collects information required to run Convert command from command line. func (o *ConvertOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) (err error) { - o.outputVersion = cmdutil.OutputVersion(cmd, latest.GroupOrDie("").GroupVersion.Version) - outputGV, err := unversioned.ParseGroupVersion(o.outputVersion) + o.outputVersion, err = cmdutil.OutputVersion(cmd, &latest.ExternalVersions[0]) if err != nil { - return fmt.Errorf("unable to parse group/version from %q: %v", o.outputVersion, err) + return err } - if !registered.IsRegisteredAPIGroupVersion(outputGV) { + if !registered.IsRegisteredAPIGroupVersion(o.outputVersion) { cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion) } @@ -152,7 +151,7 @@ func (o *ConvertOptions) RunConvert() error { return err } - objects, err := resource.AsVersionedObject(infos, false, o.outputVersion) + objects, err := resource.AsVersionedObject(infos, false, o.outputVersion.String()) if err != nil { return err } diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index 4a9782e539d..4c496576e51 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/api/unversioned" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" @@ -149,10 +150,13 @@ func RunEdit(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin windowsLineEndings := cmdutil.GetFlagBool(cmd, "windows-line-endings") edit := editor.NewDefaultEditor(f.EditorEnvs()) - defaultVersion := cmdutil.OutputVersionFromGroupVersion(cmd, clientConfig.GroupVersion) + defaultVersion, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return err + } results := editResults{} for { - objs, err := resource.AsVersionedObjects(infos, defaultVersion) + objs, err := resource.AsVersionedObjects(infos, defaultVersion.String()) if err != nil { return preservedFile(err, results.file, out) } @@ -356,7 +360,7 @@ type editResults struct { edit []*resource.Info file string - version string + version unversioned.GroupVersion } func (r *editResults) addError(err error, info *resource.Info) string { diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index 7059d1f554c..170275a9ff1 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "k8s.io/kubernetes/pkg/api/latest" + "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" ) @@ -70,7 +71,8 @@ func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st } recursive := cmdutil.GetFlagBool(cmd, "recursive") - apiV := cmdutil.GetFlagString(cmd, "api-version") + apiVersionString := cmdutil.GetFlagString(cmd, "api-version") + apiVersion := unversioned.GroupVersion{} mapper, _ := f.Object() // TODO: After we figured out the new syntax to separate group and resource, allow @@ -87,14 +89,21 @@ func RunExplain(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st return err } - if len(apiV) == 0 { + if len(apiVersionString) == 0 { groupMeta, err := latest.Group(gvk.Group) if err != nil { return err } - apiV = groupMeta.GroupVersion.String() + apiVersion = groupMeta.GroupVersion + + } else { + apiVersion, err = unversioned.ParseGroupVersion(apiVersionString) + if err != nil { + return nil + } } - swagSchema, err := kubectl.GetSwaggerSchema(apiV, client) + + swagSchema, err := kubectl.GetSwaggerSchema(apiVersion, client) if err != nil { return err } diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 606b20707e7..d0341eca662 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -120,7 +120,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str } info := infos[0] mapping := info.ResourceMapping() - if err := f.CanBeExposed(mapping.GroupVersionKind.Kind); err != nil { + if err := f.CanBeExposed(mapping.GroupVersionKind.GroupKind()); err != nil { return err } // Get the input object diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 0bd4a95b367..7755e6fe37f 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -209,8 +209,11 @@ func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string // the outermost object will be converted to the output-version, but inner // objects can use their mappings - version := cmdutil.OutputVersionFromGroupVersion(cmd, clientConfig.GroupVersion) - obj, err := resource.AsVersionedObject(infos, !singular, version) + version, err := cmdutil.OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return err + } + obj, err := resource.AsVersionedObject(infos, !singular, version.String()) if err != nil { return err } diff --git a/pkg/kubectl/cmd/get_test.go b/pkg/kubectl/cmd/get_test.go index 9aad99dd902..340506f8157 100644 --- a/pkg/kubectl/cmd/get_test.go +++ b/pkg/kubectl/cmd/get_test.go @@ -164,7 +164,7 @@ func TestGetUnknownSchemaObjectListGeneric(t *testing.T) { rcVersion: testapi.Default.Version(), }, "handles second specific version": { - outputVersion: "unlikelyversion", + outputVersion: "unlikely.group/unlikelyversion", listVersion: testapi.Default.Version(), testtypeVersion: unlikelyGV.String(), rcVersion: testapi.Default.Version(), // see expected behavior 3b diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 5b8376cd382..8f1735060f1 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -95,9 +95,9 @@ type Factory struct { // Returns the generator for the provided generator name Generator func(name string) (kubectl.Generator, bool) // Check whether the kind of resources could be exposed - CanBeExposed func(kind string) error + CanBeExposed func(kind unversioned.GroupKind) error // Check whether the kind of resources could be autoscaled - CanBeAutoscaled func(kind string) error + CanBeAutoscaled func(kind unversioned.GroupKind) error // AttachablePodForObject returns the pod to which to attach given an object. AttachablePodForObject func(object runtime.Object) (*api.Pod, error) // EditorEnvs returns a group of environment variables that the edit command @@ -140,12 +140,12 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { Object: func() (meta.RESTMapper, runtime.ObjectTyper) { cfg, err := clientConfig.ClientConfig() CheckErr(err) - cmdApiVersion := "" + cmdApiVersion := unversioned.GroupVersion{} if cfg.GroupVersion != nil { - cmdApiVersion = cfg.GroupVersion.String() + cmdApiVersion = *cfg.GroupVersion } - return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersion: cmdApiVersion}, api.Scheme + return kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}, api.Scheme }, Client: func() (*client.Client, error) { return clients.ClientForVersion("") @@ -163,9 +163,9 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return nil, err } switch gvk.Group { - case "": + case api.SchemeGroupVersion.Group: return client.RESTClient, nil - case "extensions": + case extensions.SchemeGroupVersion.Group: return client.ExtensionsClient.RESTClient, nil } return nil, fmt.Errorf("unable to get RESTClient for resource '%s'", mapping.Resource) @@ -290,21 +290,21 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { generator, ok := generators[name] return generator, ok }, - CanBeExposed: func(kind string) error { + CanBeExposed: func(kind unversioned.GroupKind) error { switch kind { - case "ReplicationController", "Service", "Pod": + case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"): // nothing to do here default: return fmt.Errorf("cannot expose a %s", kind) } return nil }, - CanBeAutoscaled: func(kind string) error { + CanBeAutoscaled: func(kind unversioned.GroupKind) error { switch kind { - case "ReplicationController", "Deployment": + case api.Kind("ReplicationController"), extensions.Kind("Deployment"): // nothing to do here default: - return fmt.Errorf("cannot autoscale a %s", kind) + return fmt.Errorf("cannot autoscale a %v", kind) } return nil }, @@ -604,19 +604,20 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin if err != nil { return nil, err } - defaultVersion := "" - if clientConfig.GroupVersion != nil { - defaultVersion = clientConfig.GroupVersion.String() - } - version := OutputVersion(cmd, defaultVersion) - if len(version) == 0 { - version = mapping.GroupVersionKind.GroupVersion().String() + version, err := OutputVersion(cmd, clientConfig.GroupVersion) + if err != nil { + return nil, err } - if len(version) == 0 { + if version.IsEmpty() { + version = mapping.GroupVersionKind.GroupVersion() + } + if version.IsEmpty() { return nil, fmt.Errorf("you must specify an output-version when using this output format") } - printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.GroupVersionKind.GroupVersion().String()) + + printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.GroupVersionKind.GroupVersion()) + } else { // Some callers do not have "label-columns" so we can't use the GetFlagStringSlice() helper columnLabel, err := cmd.Flags().GetStringSlice("label-columns") @@ -629,6 +630,7 @@ func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMappin } printer = maybeWrapSortingPrinter(cmd, printer) } + return printer, nil } diff --git a/pkg/kubectl/cmd/util/factory_test.go b/pkg/kubectl/cmd/util/factory_test.go index 3d4c8d20757..ee905276613 100644 --- a/pkg/kubectl/cmd/util/factory_test.go +++ b/pkg/kubectl/cmd/util/factory_test.go @@ -170,15 +170,15 @@ func TestLabelsForObject(t *testing.T) { func TestCanBeExposed(t *testing.T) { factory := NewFactory(nil) tests := []struct { - kind string + kind unversioned.GroupKind expectErr bool }{ { - kind: "ReplicationController", + kind: api.Kind("ReplicationController"), expectErr: false, }, { - kind: "Node", + kind: api.Kind("Node"), expectErr: true, }, } diff --git a/pkg/kubectl/cmd/util/printing.go b/pkg/kubectl/cmd/util/printing.go index 78081d37ff4..1422c02f02e 100644 --- a/pkg/kubectl/cmd/util/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -76,22 +76,18 @@ func ValidateOutputArgs(cmd *cobra.Command) error { } // OutputVersion returns the preferred output version for generic content (JSON, YAML, or templates) -// TODO, when this has no callers, replace it with OutputVersionFromGroupVersion. Also this shoudl return a GroupVersion -func OutputVersion(cmd *cobra.Command, defaultVersion string) string { - outputVersion := GetFlagString(cmd, "output-version") - if len(outputVersion) == 0 { - outputVersion = defaultVersion - } - return outputVersion -} +// defaultVersion is never mutated. Nil simply allows clean passing in common usage from client.Config +func OutputVersion(cmd *cobra.Command, defaultVersion *unversioned.GroupVersion) (unversioned.GroupVersion, error) { + outputVersionString := GetFlagString(cmd, "output-version") + if len(outputVersionString) == 0 { + if defaultVersion == nil { + return unversioned.GroupVersion{}, nil + } -// OutputVersionFromGroupVersion returns the preferred output version for generic content (JSON, YAML, or templates) -func OutputVersionFromGroupVersion(cmd *cobra.Command, defaultGV *unversioned.GroupVersion) string { - outputVersion := GetFlagString(cmd, "output-version") - if len(outputVersion) == 0 && defaultGV != nil { - outputVersion = defaultGV.String() + return *defaultVersion, nil } - return outputVersion + + return unversioned.ParseGroupVersion(outputVersionString) } // PrinterForCommand returns the default printer for this command. diff --git a/pkg/kubectl/explain.go b/pkg/kubectl/explain.go index ef7cd8ddb0b..57b072c9889 100644 --- a/pkg/kubectl/explain.go +++ b/pkg/kubectl/explain.go @@ -24,6 +24,7 @@ import ( "github.com/emicklei/go-restful/swagger" "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" apiutil "k8s.io/kubernetes/pkg/api/util" client "k8s.io/kubernetes/pkg/client/unversioned" ) @@ -32,8 +33,8 @@ var allModels = make(map[string]*swagger.NamedModel) var recursive = false // this is global for convenience, can become int for multiple levels // GetSwaggerSchema returns the swagger spec from master -func GetSwaggerSchema(apiVer string, kubeClient client.Interface) (*swagger.ApiDeclaration, error) { - swaggerSchema, err := kubeClient.SwaggerSchema(apiVer) +func GetSwaggerSchema(version unversioned.GroupVersion, kubeClient client.Interface) (*swagger.ApiDeclaration, error) { + swaggerSchema, err := kubeClient.SwaggerSchema(version) if err != nil { return nil, fmt.Errorf("couldn't read swagger schema from server: %v", err) } diff --git a/pkg/kubectl/kubectl.go b/pkg/kubectl/kubectl.go index 2efbf024b9b..98bfeef3f6c 100644 --- a/pkg/kubectl/kubectl.go +++ b/pkg/kubectl/kubectl.go @@ -47,14 +47,24 @@ func makeImageList(spec *api.PodSpec) string { // correspond to a preferred output version (if feasible) type OutputVersionMapper struct { meta.RESTMapper - OutputVersion string + + // output versions takes a list of preferred GroupVersions. Only the first + // hit for a given group will have effect. This allows different output versions + // depending upon the group of the kind being requested + OutputVersions []unversioned.GroupVersion } // RESTMapping implements meta.RESTMapper by prepending the output version to the preferred version list. func (m OutputVersionMapper) RESTMapping(gk unversioned.GroupKind, versions ...string) (*meta.RESTMapping, error) { - mapping, err := m.RESTMapper.RESTMapping(gk, m.OutputVersion) - if err == nil { - return mapping, nil + for _, preferredVersion := range m.OutputVersions { + if gk.Group == preferredVersion.Group { + mapping, err := m.RESTMapper.RESTMapping(gk, preferredVersion.Version) + if err == nil { + return mapping, nil + } + + break + } } return m.RESTMapper.RESTMapping(gk, versions...) diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index 6b042a8eb9b..9af4760ea97 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -157,28 +157,28 @@ func (fn ResourcePrinterFunc) HandledResources() []string { type VersionedPrinter struct { printer ResourcePrinter convertor runtime.ObjectConvertor - version []string + versions []unversioned.GroupVersion } // NewVersionedPrinter wraps a printer to convert objects to a known API version prior to printing. -func NewVersionedPrinter(printer ResourcePrinter, convertor runtime.ObjectConvertor, version ...string) ResourcePrinter { +func NewVersionedPrinter(printer ResourcePrinter, convertor runtime.ObjectConvertor, versions ...unversioned.GroupVersion) ResourcePrinter { return &VersionedPrinter{ printer: printer, convertor: convertor, - version: version, + versions: versions, } } // PrintObj implements ResourcePrinter func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error { - if len(p.version) == 0 { + if len(p.versions) == 0 { return fmt.Errorf("no version specified, object cannot be converted") } - for _, version := range p.version { - if len(version) == 0 { + for _, version := range p.versions { + if version.IsEmpty() { continue } - converted, err := p.convertor.ConvertToVersion(obj, version) + converted, err := p.convertor.ConvertToVersion(obj, version.String()) if conversion.IsNotRegisteredError(err) { continue } @@ -187,7 +187,7 @@ func (p *VersionedPrinter) PrintObj(obj runtime.Object, w io.Writer) error { } return p.printer.PrintObj(converted, w) } - return fmt.Errorf("the object cannot be converted to any of the versions: %v", p.version) + return fmt.Errorf("the object cannot be converted to any of the versions: %v", p.versions) } // TODO: implement HandledResources() diff --git a/pkg/kubectl/resource_printer_test.go b/pkg/kubectl/resource_printer_test.go index 592d9761be8..324813d708c 100644 --- a/pkg/kubectl/resource_printer_test.go +++ b/pkg/kubectl/resource_printer_test.go @@ -64,7 +64,7 @@ func TestVersionedPrinter(t *testing.T) { return nil }), api.Scheme, - testapi.Default.Version(), + *testapi.Default.GroupVersion(), ) if err := p.PrintObj(original, nil); err != nil { t.Errorf("unexpected error: %v", err) @@ -422,7 +422,7 @@ func TestTemplateStrings(t *testing.T) { t.Fatalf("tmpl fail: %v", err) } - printer := NewVersionedPrinter(p, api.Scheme, testapi.Default.Version()) + printer := NewVersionedPrinter(p, api.Scheme, *testapi.Default.GroupVersion()) for name, item := range table { buffer := &bytes.Buffer{}