From 7ab3f96100d7b1a0ca6131b4fdacc86a4f3e5c7c Mon Sep 17 00:00:00 2001 From: Phillip Wittrock Date: Thu, 12 Oct 2017 19:32:41 -0700 Subject: [PATCH] Move kubectl type conversion libs out of the resource & util package and into the conversion command. Kubectl shouldn't have code that does type conversion. This should be in the server. --- pkg/kubectl/cmd/convert.go | 101 +++++++++++++++++++++++++++++++- pkg/kubectl/cmd/util/helpers.go | 12 ---- pkg/kubectl/resource/BUILD | 1 - pkg/kubectl/resource/result.go | 88 ---------------------------- 4 files changed, 99 insertions(+), 103 deletions(-) diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index 58e3268ef53..3f369d0cc38 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/printers" + "github.com/golang/glog" "github.com/spf13/cobra" ) @@ -182,7 +183,7 @@ func (o *ConvertOptions) RunConvert() error { return fmt.Errorf("no objects passed to convert") } - objects, err := resource.AsVersionedObject(infos, !singleItemImplied, o.outputVersion, o.encoder) + objects, err := asVersionedObject(infos, !singleItemImplied, o.outputVersion, o.encoder) if err != nil { return err } @@ -192,7 +193,7 @@ func (o *ConvertOptions) RunConvert() error { if err != nil { return err } - filteredObj, err := cmdutil.ObjectListToVersionedObject(items, o.outputVersion) + filteredObj, err := objectListToVersionedObject(items, o.outputVersion) if err != nil { return err } @@ -201,3 +202,99 @@ func (o *ConvertOptions) RunConvert() error { return o.printer.PrintObj(objects, o.out) } + +// ObjectListToVersionedObject receives a list of api objects and a group version +// and squashes the list's items into a single versioned runtime.Object. +func objectListToVersionedObject(objects []runtime.Object, version schema.GroupVersion) (runtime.Object, error) { + objectList := &api.List{Items: objects} + converted, err := tryConvert(api.Scheme, objectList, version, api.Registry.GroupOrDie(api.GroupName).GroupVersion) + if err != nil { + return nil, err + } + return converted, nil +} + +// AsVersionedObject converts a list of infos into a single object - either a List containing +// the objects as children, or if only a single Object is present, as that object. The provided +// version will be preferred as the conversion target, but the Object's mapping version will be +// used if that version is not present. +func asVersionedObject(infos []*resource.Info, forceList bool, version schema.GroupVersion, encoder runtime.Encoder) (runtime.Object, error) { + objects, err := asVersionedObjects(infos, version, encoder) + if err != nil { + return nil, err + } + + var object runtime.Object + if len(objects) == 1 && !forceList { + object = objects[0] + } else { + object = &api.List{Items: objects} + converted, err := tryConvert(api.Scheme, object, version, api.Registry.GroupOrDie(api.GroupName).GroupVersion) + if err != nil { + return nil, err + } + object = converted + } + + actualVersion := object.GetObjectKind().GroupVersionKind() + if actualVersion.Version != version.Version { + defaultVersionInfo := "" + if len(actualVersion.Version) > 0 { + defaultVersionInfo = fmt.Sprintf("Defaulting to %q", actualVersion.Version) + } + glog.V(1).Infof("info: the output version specified is invalid. %s\n", defaultVersionInfo) + } + return object, nil +} + +// AsVersionedObjects converts a list of infos into versioned objects. The provided +// version will be preferred as the conversion target, but the Object's mapping version will be +// used if that version is not present. +func asVersionedObjects(infos []*resource.Info, version schema.GroupVersion, encoder runtime.Encoder) ([]runtime.Object, error) { + objects := []runtime.Object{} + for _, info := range infos { + if info.Object == nil { + continue + } + + // objects that are not part of api.Scheme must be converted to JSON + // TODO: convert to map[string]interface{}, attach to runtime.Unknown? + if !version.Empty() { + if _, _, err := api.Scheme.ObjectKinds(info.Object); runtime.IsNotRegisteredError(err) { + // TODO: ideally this would encode to version, but we don't expose multiple codecs here. + data, err := runtime.Encode(encoder, info.Object) + if err != nil { + return nil, err + } + // TODO: Set ContentEncoding and ContentType. + objects = append(objects, &runtime.Unknown{Raw: data}) + continue + } + } + + converted, err := tryConvert(info.Mapping.ObjectConvertor, info.Object, version, info.Mapping.GroupVersionKind.GroupVersion()) + if err != nil { + return nil, err + } + objects = append(objects, converted) + } + return objects, nil +} + +// tryConvert attempts to convert the given object to the provided versions in order. This function assumes +// the object is in internal version. +func tryConvert(converter runtime.ObjectConvertor, object runtime.Object, versions ...schema.GroupVersion) (runtime.Object, error) { + var last error + for _, version := range versions { + if version.Empty() { + return object, nil + } + obj, err := converter.ConvertToVersion(object, version) + if err != nil { + last = err + continue + } + return obj, nil + } + return nil, last +} diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index 58014f861a2..16ba707cd92 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -36,7 +36,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/json" @@ -731,17 +730,6 @@ func PrintFilterCount(out io.Writer, found, hidden, errors int, options *printer } } -// ObjectListToVersionedObject receives a list of api objects and a group version -// and squashes the list's items into a single versioned runtime.Object. -func ObjectListToVersionedObject(objects []runtime.Object, version schema.GroupVersion) (runtime.Object, error) { - objectList := &api.List{Items: objects} - converted, err := resource.TryConvert(api.Scheme, objectList, version, api.Registry.GroupOrDie(api.GroupName).GroupVersion) - if err != nil { - return nil, err - } - return converted, nil -} - // IsSiblingCommandExists receives a pointer to a cobra command and a target string. // Returns true if the target string is found in the list of sibling commands. func IsSiblingCommandExists(cmd *cobra.Command, targetCmdName string) bool { diff --git a/pkg/kubectl/resource/BUILD b/pkg/kubectl/resource/BUILD index 856b866ba86..5fb2b4fb07c 100644 --- a/pkg/kubectl/resource/BUILD +++ b/pkg/kubectl/resource/BUILD @@ -23,7 +23,6 @@ go_library( deps = [ "//pkg/api:go_default_library", "//pkg/kubectl/validation:go_default_library", - "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/text/encoding/unicode:go_default_library", "//vendor/golang.org/x/text/transform:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/pkg/kubectl/resource/result.go b/pkg/kubectl/resource/result.go index bb185754c5c..46578a5730b 100644 --- a/pkg/kubectl/resource/result.go +++ b/pkg/kubectl/resource/result.go @@ -20,12 +20,9 @@ import ( "fmt" "reflect" - "github.com/golang/glog" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" @@ -221,88 +218,3 @@ func (r *Result) Watch(resourceVersion string) (watch.Interface, error) { } return w.Watch(resourceVersion) } - -// AsVersionedObject converts a list of infos into a single object - either a List containing -// the objects as children, or if only a single Object is present, as that object. The provided -// version will be preferred as the conversion target, but the Object's mapping version will be -// used if that version is not present. -func AsVersionedObject(infos []*Info, forceList bool, version schema.GroupVersion, encoder runtime.Encoder) (runtime.Object, error) { - objects, err := AsVersionedObjects(infos, version, encoder) - if err != nil { - return nil, err - } - - var object runtime.Object - if len(objects) == 1 && !forceList { - object = objects[0] - } else { - object = &api.List{Items: objects} - converted, err := TryConvert(api.Scheme, object, version, api.Registry.GroupOrDie(api.GroupName).GroupVersion) - if err != nil { - return nil, err - } - object = converted - } - - actualVersion := object.GetObjectKind().GroupVersionKind() - if actualVersion.Version != version.Version { - defaultVersionInfo := "" - if len(actualVersion.Version) > 0 { - defaultVersionInfo = fmt.Sprintf("Defaulting to %q", actualVersion.Version) - } - glog.V(1).Infof("info: the output version specified is invalid. %s\n", defaultVersionInfo) - } - return object, nil -} - -// AsVersionedObjects converts a list of infos into versioned objects. The provided -// version will be preferred as the conversion target, but the Object's mapping version will be -// used if that version is not present. -func AsVersionedObjects(infos []*Info, version schema.GroupVersion, encoder runtime.Encoder) ([]runtime.Object, error) { - objects := []runtime.Object{} - for _, info := range infos { - if info.Object == nil { - continue - } - - // objects that are not part of api.Scheme must be converted to JSON - // TODO: convert to map[string]interface{}, attach to runtime.Unknown? - if !version.Empty() { - if _, _, err := api.Scheme.ObjectKinds(info.Object); runtime.IsNotRegisteredError(err) { - // TODO: ideally this would encode to version, but we don't expose multiple codecs here. - data, err := runtime.Encode(encoder, info.Object) - if err != nil { - return nil, err - } - // TODO: Set ContentEncoding and ContentType. - objects = append(objects, &runtime.Unknown{Raw: data}) - continue - } - } - - converted, err := TryConvert(info.Mapping.ObjectConvertor, info.Object, version, info.Mapping.GroupVersionKind.GroupVersion()) - if err != nil { - return nil, err - } - objects = append(objects, converted) - } - return objects, nil -} - -// TryConvert attempts to convert the given object to the provided versions in order. This function assumes -// the object is in internal version. -func TryConvert(converter runtime.ObjectConvertor, object runtime.Object, versions ...schema.GroupVersion) (runtime.Object, error) { - var last error - for _, version := range versions { - if version.Empty() { - return object, nil - } - obj, err := converter.ConvertToVersion(object, version) - if err != nil { - last = err - continue - } - return obj, nil - } - return nil, last -}