diff --git a/pkg/api/copy_test.go b/pkg/api/copy_test.go index efd055e40dc..1866c7cf0e0 100644 --- a/pkg/api/copy_test.go +++ b/pkg/api/copy_test.go @@ -32,24 +32,24 @@ import ( func TestDeepCopyApiObjects(t *testing.T) { for i := 0; i < *fuzzIters; i++ { - for _, gv := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { - f := apitesting.FuzzerFor(t, gv.String(), rand.NewSource(rand.Int63())) - for kind := range api.Scheme.KnownTypes(gv) { - doDeepCopyTest(t, gv.String(), kind, f) + for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { + f := apitesting.FuzzerFor(t, version.String(), rand.NewSource(rand.Int63())) + for kind := range api.Scheme.KnownTypes(version) { + doDeepCopyTest(t, version.WithKind(kind), f) } } } } -func doDeepCopyTest(t *testing.T, version, kind string, f *fuzz.Fuzzer) { - item, err := api.Scheme.New(version, kind) +func doDeepCopyTest(t *testing.T, kind unversioned.GroupVersionKind, f *fuzz.Fuzzer) { + item, err := api.Scheme.New(kind) if err != nil { - t.Fatalf("Could not create a %s: %s", kind, err) + t.Fatalf("Could not create a %v: %s", kind, err) } f.Fuzz(item) itemCopy, err := api.Scheme.DeepCopy(item) if err != nil { - t.Errorf("Could not deep copy a %s: %s", kind, err) + t.Errorf("Could not deep copy a %v: %s", kind, err) return } @@ -60,9 +60,9 @@ func doDeepCopyTest(t *testing.T, version, kind string, f *fuzz.Fuzzer) { func TestDeepCopySingleType(t *testing.T) { for i := 0; i < *fuzzIters; i++ { - for _, version := range []string{"", testapi.Default.GroupVersion().String()} { - f := apitesting.FuzzerFor(t, version, rand.NewSource(rand.Int63())) - doDeepCopyTest(t, version, "Pod", f) + for _, version := range []unversioned.GroupVersion{testapi.Default.InternalGroupVersion(), *testapi.Default.GroupVersion()} { + f := apitesting.FuzzerFor(t, version.String(), rand.NewSource(rand.Int63())) + doDeepCopyTest(t, version.WithKind("Pod"), f) } } } diff --git a/pkg/api/serialization_test.go b/pkg/api/serialization_test.go index 7bcf597ebef..9a77a6b19a5 100644 --- a/pkg/api/serialization_test.go +++ b/pkg/api/serialization_test.go @@ -139,7 +139,7 @@ func TestList(t *testing.T) { defer api.Scheme.Log(nil) kind := "List" - item, err := api.Scheme.New("", kind) + item, err := api.Scheme.New(api.SchemeGroupVersion.WithKind(kind)) if err != nil { t.Errorf("Couldn't make a %v? %v", kind, err) return @@ -172,7 +172,7 @@ func TestRoundTripTypes(t *testing.T) { } func doRoundTripTest(kind string, t *testing.T) { - item, err := api.Scheme.New(testapi.Default.InternalGroupVersion().String(), kind) + item, err := api.Scheme.New(testapi.Default.InternalGroupVersion().WithKind(kind)) if err != nil { t.Fatalf("Couldn't make a %v? %v", kind, err) } diff --git a/pkg/apiserver/api_installer.go b/pkg/apiserver/api_installer.go index fd31b9634b7..a9b6b37683c 100644 --- a/pkg/apiserver/api_installer.go +++ b/pkg/apiserver/api_installer.go @@ -104,9 +104,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag admit := a.group.Admit context := a.group.Context - serverGroupVersion := a.group.GroupVersion - if a.group.ServerGroupVersion != nil { - serverGroupVersion = *a.group.ServerGroupVersion + optionsExternalVersion := a.group.GroupVersion + if a.group.OptionsExternalVersion != nil { + optionsExternalVersion = *a.group.OptionsExternalVersion } var resource, subresource string @@ -148,7 +148,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag } kind := fqKindToRegister.Kind - versionedPtr, err := a.group.Creater.New(a.group.GroupVersion.String(), kind) + versionedPtr, err := a.group.Creater.New(a.group.GroupVersion.WithKind(kind)) if err != nil { return nil, err } @@ -218,14 +218,14 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag if isLister { list := lister.NewList() listGVK, err := a.group.Typer.ObjectKind(list) - versionedListPtr, err := a.group.Creater.New(a.group.GroupVersion.String(), listGVK.Kind) + versionedListPtr, err := a.group.Creater.New(a.group.GroupVersion.WithKind(listGVK.Kind)) if err != nil { return nil, err } versionedList = indirectArbitraryPointer(versionedListPtr) } - versionedListOptions, err := a.group.Creater.New(serverGroupVersion.String(), "ListOptions") + versionedListOptions, err := a.group.Creater.New(optionsExternalVersion.WithKind("ListOptions")) if err != nil { return nil, err } @@ -233,7 +233,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag var versionedDeleterObject interface{} switch { case isGracefulDeleter: - objectPtr, err := a.group.Creater.New(serverGroupVersion.String(), "DeleteOptions") + objectPtr, err := a.group.Creater.New(optionsExternalVersion.WithKind("DeleteOptions")) if err != nil { return nil, err } @@ -243,7 +243,7 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag gracefulDeleter = rest.GracefulDeleteAdapter{Deleter: deleter} } - versionedStatusPtr, err := a.group.Creater.New(serverGroupVersion.String(), "Status") + versionedStatusPtr, err := a.group.Creater.New(optionsExternalVersion.WithKind("Status")) if err != nil { return nil, err } @@ -263,9 +263,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag return nil, err } // TODO this should be a list of all the different external versions we can coerce into the internalKind - getOptionsExternalKind = serverGroupVersion.WithKind(getOptionsInternalKind.Kind) + getOptionsExternalKind = optionsExternalVersion.WithKind(getOptionsInternalKind.Kind) - versionedGetOptions, err = a.group.Creater.New(serverGroupVersion.String(), getOptionsInternalKind.Kind) + versionedGetOptions, err = a.group.Creater.New(optionsExternalVersion.WithKind(getOptionsInternalKind.Kind)) if err != nil { return nil, err } @@ -288,9 +288,9 @@ func (a *APIInstaller) registerResourceHandlers(path string, storage rest.Storag return nil, err } // TODO this should be a list of all the different external versions we can coerce into the internalKind - connectOptionsExternalKind = serverGroupVersion.WithKind(connectOptionsInternalKind.Kind) + connectOptionsExternalKind = optionsExternalVersion.WithKind(connectOptionsInternalKind.Kind) - versionedConnectOptions, err = a.group.Creater.New(serverGroupVersion.String(), connectOptionsInternalKind.Kind) + versionedConnectOptions, err = a.group.Creater.New(optionsExternalVersion.WithKind(connectOptionsInternalKind.Kind)) } } diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 9cf6de86f48..a7b876ac0f6 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -79,19 +79,20 @@ type Mux interface { type APIGroupVersion struct { Storage map[string]rest.Storage - Root string + Root string + + // GroupVersion is the external group version GroupVersion unversioned.GroupVersion // RequestInfoResolver is used to parse URLs for the legacy proxy handler. Don't use this for anything else // TODO: refactor proxy handler to use sub resources RequestInfoResolver *RequestInfoResolver - // ServerVersion controls the Kubernetes APIVersion used for common objects in the apiserver + // OptionsExternalVersion controls the Kubernetes APIVersion used for common objects in the apiserver // schema like api.Status, api.DeleteOptions, and unversioned.ListOptions. Other implementors may // define a version "v1beta1" but want to use the Kubernetes "v1" internal objects. If - // empty, defaults to Version. - // TODO this seems suspicious. Is this actually just "unversioned" now? - ServerGroupVersion *unversioned.GroupVersion + // empty, defaults to GroupVersion. + OptionsExternalVersion *unversioned.GroupVersion Mapper meta.RESTMapper diff --git a/pkg/apiserver/apiserver_test.go b/pkg/apiserver/apiserver_test.go index 15cc3f2679e..12d2307fd25 100644 --- a/pkg/apiserver/apiserver_test.go +++ b/pkg/apiserver/apiserver_test.go @@ -233,7 +233,7 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission. group := template group.Root = "/" + grouplessPrefix group.GroupVersion = grouplessGroupVersion - group.ServerGroupVersion = &grouplessGroupVersion + group.OptionsExternalVersion = &grouplessGroupVersion group.Codec = grouplessCodec if err := (&group).InstallREST(container); err != nil { panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err)) @@ -245,7 +245,7 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission. group := template group.Root = "/" + prefix group.GroupVersion = testGroupVersion - group.ServerGroupVersion = &testGroupVersion + group.OptionsExternalVersion = &testGroupVersion group.Codec = codec if err := (&group).InstallREST(container); err != nil { panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err)) @@ -257,7 +257,7 @@ func handleInternal(storage map[string]rest.Storage, admissionControl admission. group := template group.Root = "/" + prefix group.GroupVersion = newGroupVersion - group.ServerGroupVersion = &newGroupVersion + group.OptionsExternalVersion = &newGroupVersion group.Codec = newCodec if err := (&group).InstallREST(container); err != nil { panic(fmt.Sprintf("unable to install container %s: %v", group.GroupVersion, err)) @@ -2241,9 +2241,9 @@ func TestUpdateREST(t *testing.T) { Context: requestContextMapper, Mapper: namespaceMapper, - GroupVersion: newGroupVersion, - ServerGroupVersion: &newGroupVersion, - Codec: newCodec, + GroupVersion: newGroupVersion, + OptionsExternalVersion: &newGroupVersion, + Codec: newCodec, } } @@ -2323,9 +2323,9 @@ func TestParentResourceIsRequired(t *testing.T) { Context: requestContextMapper, Mapper: namespaceMapper, - GroupVersion: newGroupVersion, - ServerGroupVersion: &newGroupVersion, - Codec: newCodec, + GroupVersion: newGroupVersion, + OptionsExternalVersion: &newGroupVersion, + Codec: newCodec, } container := restful.NewContainer() if err := group.InstallREST(container); err == nil { @@ -2352,9 +2352,9 @@ func TestParentResourceIsRequired(t *testing.T) { Context: requestContextMapper, Mapper: namespaceMapper, - GroupVersion: newGroupVersion, - ServerGroupVersion: &newGroupVersion, - Codec: newCodec, + GroupVersion: newGroupVersion, + OptionsExternalVersion: &newGroupVersion, + Codec: newCodec, } container = restful.NewContainer() if err := group.InstallREST(container); err != nil { diff --git a/pkg/apiserver/resthandler.go b/pkg/apiserver/resthandler.go index 5f736f290e7..615c1fa54ae 100644 --- a/pkg/apiserver/resthandler.go +++ b/pkg/apiserver/resthandler.go @@ -149,7 +149,7 @@ func getRequestOptions(req *restful.Request, scope RequestScope, internalKind, e query = newQuery } - versioned, err := scope.Creater.New(externalKind.GroupVersion().String(), externalKind.Kind) + versioned, err := scope.Creater.New(externalKind) if err != nil { return nil, err } diff --git a/pkg/client/unversioned/testclient/fixture.go b/pkg/client/unversioned/testclient/fixture.go index 7d138ea87be..e6aa3434740 100644 --- a/pkg/client/unversioned/testclient/fixture.go +++ b/pkg/client/unversioned/testclient/fixture.go @@ -152,24 +152,24 @@ func NewObjects(scheme ObjectScheme, decoder runtime.ObjectDecoder) ObjectRetrie } } -func (o objects) Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) { +func (o objects) Kind(kind unversioned.GroupVersionKind, name string) (runtime.Object, error) { // TODO our test clients deal in internal versions. We need to plumb that knowledge down here // we might do this via an extra function to the scheme to allow getting internal group versions // I'm punting for now - gvk.Version = "" + kind.Version = "" - empty, _ := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) + empty, _ := o.scheme.New(kind) nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) - arr, ok := o.types[gvk.Kind] + arr, ok := o.types[kind.Kind] if !ok { - if strings.HasSuffix(gvk.Kind, "List") { - itemKind := gvk.Kind[:len(gvk.Kind)-4] + if strings.HasSuffix(kind.Kind, "List") { + itemKind := kind.Kind[:len(kind.Kind)-4] arr, ok := o.types[itemKind] if !ok { return empty, nil } - out, err := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) + out, err := o.scheme.New(kind) if err != nil { return nilValue, err } @@ -181,25 +181,25 @@ func (o objects) Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Ob } return out, nil } - return nilValue, errors.NewNotFound(gvk.Kind, name) + return nilValue, errors.NewNotFound(kind.Kind, name) } - index := o.last[gvk.Kind] + index := o.last[kind.Kind] if index >= len(arr) { index = len(arr) - 1 } if index < 0 { - return nilValue, errors.NewNotFound(gvk.Kind, name) + return nilValue, errors.NewNotFound(kind.Kind, name) } out, err := o.scheme.Copy(arr[index]) if err != nil { return nilValue, err } - o.last[gvk.Kind] = index + 1 + o.last[kind.Kind] = index + 1 if status, ok := out.(*unversioned.Status); ok { if status.Details != nil { - status.Details.Kind = gvk.Kind + status.Details.Kind = kind.Kind } if status.Status != unversioned.StatusSuccess { return nilValue, &errors.StatusError{ErrStatus: *status} diff --git a/pkg/conversion/decode.go b/pkg/conversion/decode.go index c2507034f13..0e5c7a76285 100644 --- a/pkg/conversion/decode.go +++ b/pkg/conversion/decode.go @@ -26,36 +26,36 @@ import ( "k8s.io/kubernetes/pkg/api/unversioned" ) -func (s *Scheme) DecodeToVersionedObject(data []byte) (interface{}, string, string, error) { - gvk, err := s.DataKind(data) +func (s *Scheme) DecodeToVersionedObject(data []byte) (interface{}, unversioned.GroupVersionKind, error) { + kind, err := s.DataKind(data) if err != nil { - return nil, "", "", err + return nil, unversioned.GroupVersionKind{}, err } - internalGV, exists := s.InternalVersions[gvk.Group] + internalGV, exists := s.InternalVersions[kind.Group] if !exists { - return nil, "", "", fmt.Errorf("no internalVersion specified for %v", gvk) + return nil, unversioned.GroupVersionKind{}, fmt.Errorf("no internalVersion specified for %v", kind) } - if len(gvk.Group) == 0 && len(internalGV.Group) != 0 { - return nil, "", "", fmt.Errorf("group not set in '%s'", string(data)) + if len(kind.Group) == 0 && len(internalGV.Group) != 0 { + return nil, unversioned.GroupVersionKind{}, fmt.Errorf("group not set in '%s'", string(data)) } - if len(gvk.Version) == 0 && len(internalGV.Version) != 0 { - return nil, "", "", fmt.Errorf("version not set in '%s'", string(data)) + if len(kind.Version) == 0 && len(internalGV.Version) != 0 { + return nil, unversioned.GroupVersionKind{}, fmt.Errorf("version not set in '%s'", string(data)) } - if gvk.Kind == "" { - return nil, "", "", fmt.Errorf("kind not set in '%s'", string(data)) + if kind.Kind == "" { + return nil, unversioned.GroupVersionKind{}, fmt.Errorf("kind not set in '%s'", string(data)) } - obj, err := s.NewObject(gvk.GroupVersion().String(), gvk.Kind) + obj, err := s.NewObject(kind) if err != nil { - return nil, "", "", err + return nil, unversioned.GroupVersionKind{}, err } if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(obj); err != nil { - return nil, "", "", err + return nil, unversioned.GroupVersionKind{}, err } - return obj, gvk.GroupVersion().String(), gvk.Kind, nil + return obj, kind, nil } // Decode converts a JSON string back into a pointer to an api object. @@ -74,8 +74,8 @@ func (s *Scheme) Decode(data []byte) (interface{}, error) { // set unless version is also "". // a GroupVersion with .IsEmpty() == true is means "use the internal version for // the object's group" -func (s *Scheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (interface{}, error) { - obj, sourceVersion, kind, err := s.DecodeToVersionedObject(data) +func (s *Scheme) DecodeToVersion(data []byte, targetVersion unversioned.GroupVersion) (interface{}, error) { + obj, sourceKind, err := s.DecodeToVersionedObject(data) if err != nil { return nil, err } @@ -84,28 +84,23 @@ func (s *Scheme) DecodeToVersion(data []byte, gv unversioned.GroupVersion) (inte return nil, err } - sourceGV, err := unversioned.ParseGroupVersion(sourceVersion) - if err != nil { - return nil, err - } - - // if the gv is empty, then we want the internal version, but the internal version varies by + // if the targetVersion is empty, then we want the internal version, but the internal version varies by // group. We can lookup the group now because we have knowledge of the group - if gv.IsEmpty() { + if targetVersion.IsEmpty() { exists := false - gv, exists = s.InternalVersions[sourceGV.Group] + targetVersion, exists = s.InternalVersions[sourceKind.Group] if !exists { - return nil, fmt.Errorf("no internalVersion specified for %v", gv) + return nil, fmt.Errorf("no internalVersion specified for %v", targetVersion) } } // Convert if needed. - if gv != sourceGV { - objOut, err := s.NewObject(gv.String(), kind) + if targetVersion != sourceKind.GroupVersion() { + objOut, err := s.NewObject(targetVersion.WithKind(sourceKind.Kind)) if err != nil { return nil, err } - flags, meta := s.generateConvertMeta(sourceGV, gv, obj) + flags, meta := s.generateConvertMeta(sourceKind.GroupVersion(), targetVersion, obj) if err := s.converter.Convert(obj, objOut, flags, meta); err != nil { return nil, err } @@ -134,28 +129,28 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{} if len(data) == 0 { return errors.New("empty input") } - dataGVK, err := s.DataKind(data) + dataKind, err := s.DataKind(data) if err != nil { return err } - if len(dataGVK.Group) == 0 { - dataGVK.Group = requestedGVK.Group + if len(dataKind.Group) == 0 { + dataKind.Group = requestedGVK.Group } - if len(dataGVK.Version) == 0 { - dataGVK.Version = requestedGVK.Version + if len(dataKind.Version) == 0 { + dataKind.Version = requestedGVK.Version } - if len(dataGVK.Kind) == 0 { - dataGVK.Kind = requestedGVK.Kind + if len(dataKind.Kind) == 0 { + dataKind.Kind = requestedGVK.Kind } - if len(requestedGVK.Group) > 0 && requestedGVK.Group != dataGVK.Group { - return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataGVK, requestedGVK)) + if len(requestedGVK.Group) > 0 && requestedGVK.Group != dataKind.Group { + return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataKind, requestedGVK)) } - if len(requestedGVK.Version) > 0 && requestedGVK.Version != dataGVK.Version { - return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataGVK, requestedGVK)) + if len(requestedGVK.Version) > 0 && requestedGVK.Version != dataKind.Version { + return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataKind, requestedGVK)) } - if len(requestedGVK.Kind) > 0 && requestedGVK.Kind != dataGVK.Kind { - return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataGVK, requestedGVK)) + if len(requestedGVK.Kind) > 0 && requestedGVK.Kind != dataKind.Kind { + return errors.New(fmt.Sprintf("The fully qualified kind in the data (%v) does not match the specified apiVersion(%v)", dataKind, requestedGVK)) } objGVK, err := s.ObjectKind(obj) @@ -164,24 +159,24 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{} } // Assume objects with unset fields are being unmarshalled into the // correct type. - if len(dataGVK.Group) == 0 { - dataGVK.Group = objGVK.Group + if len(dataKind.Group) == 0 { + dataKind.Group = objGVK.Group } - if len(dataGVK.Version) == 0 { - dataGVK.Version = objGVK.Version + if len(dataKind.Version) == 0 { + dataKind.Version = objGVK.Version } - if len(dataGVK.Kind) == 0 { - dataGVK.Kind = objGVK.Kind + if len(dataKind.Kind) == 0 { + dataKind.Kind = objGVK.Kind } - external, err := s.NewObject(dataGVK.GroupVersion().String(), dataGVK.Kind) + external, err := s.NewObject(dataKind) if err != nil { return err } if err := codec.NewDecoderBytes(data, new(codec.JsonHandle)).Decode(external); err != nil { return err } - flags, meta := s.generateConvertMeta(dataGVK.GroupVersion(), objGVK.GroupVersion(), external) + flags, meta := s.generateConvertMeta(dataKind.GroupVersion(), objGVK.GroupVersion(), external) if err := s.converter.Convert(external, obj, flags, meta); err != nil { return err } diff --git a/pkg/conversion/encode.go b/pkg/conversion/encode.go index 4896e20c8d4..3120583d454 100644 --- a/pkg/conversion/encode.go +++ b/pkg/conversion/encode.go @@ -62,14 +62,14 @@ func (s *Scheme) EncodeToVersion(obj interface{}, destVersion string) (data []by return buff.Bytes(), nil } -func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stream io.Writer) error { +func (s *Scheme) EncodeToVersionStream(obj interface{}, destGroupVersionString string, stream io.Writer) error { obj = maybeCopy(obj) v, _ := EnforcePtr(obj) // maybeCopy guarantees a pointer // Don't encode an object defined in the unversioned package, unless if the - // destVersion is v1, encode it to v1 for backward compatibility. + // destGroupVersionString is v1, encode it to v1 for backward compatibility. pkg := path.Base(v.Type().PkgPath()) - if pkg == "unversioned" && destVersion != "v1" { + if pkg == "unversioned" && destGroupVersionString != "v1" { // TODO: convert this to streaming too data, err := s.encodeUnversionedObject(obj) if err != nil { @@ -80,21 +80,26 @@ func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stre } if _, registered := s.typeToGVK[v.Type()]; !registered { - return fmt.Errorf("type %v is not registered for %q and it will be impossible to Decode it, therefore Encode will refuse to encode it.", v.Type(), destVersion) + return fmt.Errorf("type %v is not registered for %q and it will be impossible to Decode it, therefore Encode will refuse to encode it.", v.Type(), destGroupVersionString) } - objGVK, err := s.ObjectKind(obj) + objKind, err := s.ObjectKind(obj) + if err != nil { + return err + } + + destVersion, err := unversioned.ParseGroupVersion(destGroupVersionString) if err != nil { return err } // Perform a conversion if necessary. - if objGVK.GroupVersion().String() != destVersion { - objOut, err := s.NewObject(destVersion, objGVK.Kind) + if objKind.GroupVersion() != destVersion { + objOut, err := s.NewObject(destVersion.WithKind(objKind.Kind)) if err != nil { return err } - flags, meta := s.generateConvertMeta(objGVK.GroupVersion(), unversioned.ParseGroupVersionOrDie(destVersion), obj) + flags, meta := s.generateConvertMeta(objKind.GroupVersion(), destVersion, obj) err = s.converter.Convert(obj, objOut, flags, meta) if err != nil { return err @@ -106,11 +111,11 @@ func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stre if err != nil { return err } - objGVK.Kind = newGroupVersionKind.Kind + objKind.Kind = newGroupVersionKind.Kind } // Version and Kind should be set on the wire. - err = s.SetVersionAndKind(destVersion, objGVK.Kind, obj) + err = s.SetVersionAndKind(destVersion.String(), objKind.Kind, obj) if err != nil { return err } diff --git a/pkg/conversion/scheme.go b/pkg/conversion/scheme.go index c4ec96ca188..b38857ea3b2 100644 --- a/pkg/conversion/scheme.go +++ b/pkg/conversion/scheme.go @@ -163,18 +163,12 @@ func (s *Scheme) KnownTypes(gv unversioned.GroupVersion) map[string]reflect.Type // NewObject returns a new object of the given version and name, // or an error if it hasn't been registered. -func (s *Scheme) NewObject(gvString, kind string) (interface{}, error) { - gv, err := unversioned.ParseGroupVersion(gvString) - if err != nil { - return nil, err - } - gvk := gv.WithKind(kind) - - if t, exists := s.gvkToType[gvk]; exists { +func (s *Scheme) NewObject(kind unversioned.GroupVersionKind) (interface{}, error) { + if t, exists := s.gvkToType[kind]; exists { return reflect.New(t).Interface(), nil } - return nil, ¬RegisteredErr{gvk: gvk} + return nil, ¬RegisteredErr{gvk: kind} } // AddConversionFuncs adds functions to the list of conversion functions. The given @@ -326,7 +320,7 @@ func (s *Scheme) Convert(in, out interface{}) error { // ConvertToVersion attempts to convert an input object to its matching Kind in another // version within this scheme. Will return an error if the provided version does not // contain the inKind (or a mapping by name defined with AddKnownTypeWithName). -func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{}, error) { +func (s *Scheme) ConvertToVersion(in interface{}, outGroupVersionString string) (interface{}, error) { t := reflect.TypeOf(in) if t.Kind() != reflect.Ptr { return nil, fmt.Errorf("only pointer types may be converted: %v", t) @@ -338,25 +332,25 @@ func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{ gvks, ok := s.typeToGVK[t] if !ok { - return nil, fmt.Errorf("%v cannot be converted into version %q", t, outVersion) + return nil, fmt.Errorf("%v cannot be converted into version %q", t, outGroupVersionString) } - outGV, err := unversioned.ParseGroupVersion(outVersion) + outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return nil, err } - outGVK := outGV.WithKind(gvks[0].Kind) + outKind := outVersion.WithKind(gvks[0].Kind) - inGVK, err := s.ObjectKind(in) + inKind, err := s.ObjectKind(in) if err != nil { return nil, err } - out, err := s.NewObject(outGV.String(), outGVK.Kind) + out, err := s.NewObject(outKind) if err != nil { return nil, err } - flags, meta := s.generateConvertMeta(inGVK.GroupVersion(), outGV, in) + flags, meta := s.generateConvertMeta(inKind.GroupVersion(), outVersion, in) if err := s.converter.Convert(in, out, flags, meta); err != nil { return nil, err } @@ -367,7 +361,7 @@ func (s *Scheme) ConvertToVersion(in interface{}, outVersion string) (interface{ // return nil, err // } // ======= - if err := s.SetVersionAndKind(outGV.String(), outGVK.Kind, out); err != nil { + if err := s.SetVersionAndKind(outVersion.String(), outKind.Kind, out); err != nil { return nil, err // >>>>>>> Update ObjectTyper to GroupVersion } diff --git a/pkg/kubectl/resource/mapper.go b/pkg/kubectl/resource/mapper.go index edf54d10ed7..27607f72e33 100644 --- a/pkg/kubectl/resource/mapper.go +++ b/pkg/kubectl/resource/mapper.go @@ -73,7 +73,7 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) { var versionedObject interface{} - if vo, _, _, err := api.Scheme.Raw().DecodeToVersionedObject(data); err == nil { + if vo, _, err := api.Scheme.Raw().DecodeToVersionedObject(data); err == nil { versionedObject = vo } return &Info{ diff --git a/pkg/master/master.go b/pkg/master/master.go index 57c877c5534..b0173c34a79 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -1002,7 +1002,7 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV strings.ToLower(kind) + "s": resourceStorage, } - serverGroupVersion := latest.GroupOrDie("").GroupVersion + optionsExternalVersion := latest.GroupOrDie("").GroupVersion return &apiserver.APIGroupVersion{ Root: apiRoot, @@ -1013,11 +1013,11 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV Convertor: api.Scheme, Typer: api.Scheme, - Mapper: thirdpartyresourcedata.NewMapper(latest.GroupOrDie("extensions").RESTMapper, kind, version, group), - Codec: thirdpartyresourcedata.NewCodec(latest.GroupOrDie("extensions").Codec, kind), - Linker: latest.GroupOrDie("extensions").SelfLinker, - Storage: storage, - ServerGroupVersion: &serverGroupVersion, + Mapper: thirdpartyresourcedata.NewMapper(latest.GroupOrDie("extensions").RESTMapper, kind, version, group), + Codec: thirdpartyresourcedata.NewCodec(latest.GroupOrDie("extensions").Codec, kind), + Linker: latest.GroupOrDie("extensions").SelfLinker, + Storage: storage, + OptionsExternalVersion: &optionsExternalVersion, Context: m.requestContextMapper, @@ -1092,7 +1092,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion { } extensionsGroup := latest.GroupOrDie("extensions") - serverGroupVersion := latest.GroupOrDie("").GroupVersion + optionsExternalVersion := latest.GroupOrDie("").GroupVersion return &apiserver.APIGroupVersion{ Root: m.apiGroupPrefix, @@ -1102,12 +1102,12 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion { Convertor: api.Scheme, Typer: api.Scheme, - Mapper: extensionsGroup.RESTMapper, - Codec: extensionsGroup.Codec, - Linker: extensionsGroup.SelfLinker, - Storage: storage, - GroupVersion: extensionsGroup.GroupVersion, - ServerGroupVersion: &serverGroupVersion, + Mapper: extensionsGroup.RESTMapper, + Codec: extensionsGroup.Codec, + Linker: extensionsGroup.SelfLinker, + Storage: storage, + GroupVersion: extensionsGroup.GroupVersion, + OptionsExternalVersion: &optionsExternalVersion, Admit: m.admissionControl, Context: m.requestContextMapper, diff --git a/pkg/registry/thirdpartyresourcedata/codec.go b/pkg/registry/thirdpartyresourcedata/codec.go index 8fedc1027ad..6cec754e30b 100644 --- a/pkg/registry/thirdpartyresourcedata/codec.go +++ b/pkg/registry/thirdpartyresourcedata/codec.go @@ -290,19 +290,19 @@ type thirdPartyResourceDataCreator struct { delegate runtime.ObjectCreater } -func (t *thirdPartyResourceDataCreator) New(groupVersion, kind string) (out runtime.Object, err error) { - switch kind { +func (t *thirdPartyResourceDataCreator) New(kind unversioned.GroupVersionKind) (out runtime.Object, err error) { + switch kind.Kind { case "ThirdPartyResourceData": - if apiutil.GetGroupVersion(t.group, t.version) != groupVersion { - return nil, fmt.Errorf("unknown version %s for kind %s", groupVersion, kind) + if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { + return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceData{}, nil case "ThirdPartyResourceDataList": - if apiutil.GetGroupVersion(t.group, t.version) != groupVersion { - return nil, fmt.Errorf("unknown version %s for kind %s", groupVersion, kind) + if apiutil.GetGroupVersion(t.group, t.version) != kind.GroupVersion().String() { + return nil, fmt.Errorf("unknown kind %v", kind) } return &extensions.ThirdPartyResourceDataList{}, nil default: - return t.delegate.New(groupVersion, kind) + return t.delegate.New(kind) } } diff --git a/pkg/registry/thirdpartyresourcedata/codec_test.go b/pkg/registry/thirdpartyresourcedata/codec_test.go index 62125c1467d..42928bd2ebf 100644 --- a/pkg/registry/thirdpartyresourcedata/codec_test.go +++ b/pkg/registry/thirdpartyresourcedata/codec_test.go @@ -140,35 +140,31 @@ func TestCreater(t *testing.T) { creater := NewObjectCreator("creater group", "creater version", api.Scheme) tests := []struct { name string - version string - kind string + kind unversioned.GroupVersionKind expectedObj runtime.Object expectErr bool }{ { name: "valid ThirdPartyResourceData creation", - version: "creater group/creater version", - kind: "ThirdPartyResourceData", + kind: unversioned.GroupVersionKind{Group: "creater group", Version: "creater version", Kind: "ThirdPartyResourceData"}, expectedObj: &extensions.ThirdPartyResourceData{}, expectErr: false, }, { name: "invalid ThirdPartyResourceData creation", - version: "invalid version", - kind: "ThirdPartyResourceData", + kind: unversioned.GroupVersionKind{Version: "invalid version", Kind: "ThirdPartyResourceData"}, expectedObj: nil, expectErr: true, }, { name: "valid ListOptions creation", - version: "v1", - kind: "ListOptions", + kind: unversioned.GroupVersionKind{Version: "v1", Kind: "ListOptions"}, expectedObj: &v1.ListOptions{}, expectErr: false, }, } for _, test := range tests { - out, err := creater.New(test.version, test.kind) + out, err := creater.New(test.kind) if err != nil && !test.expectErr { t.Errorf("[%s] unexpected error: %v", test.name, err) } diff --git a/pkg/runtime/conversion_generator.go b/pkg/runtime/conversion_generator.go index 093c8c5b77b..12f274084c8 100644 --- a/pkg/runtime/conversion_generator.go +++ b/pkg/runtime/conversion_generator.go @@ -90,12 +90,12 @@ func (g *conversionGenerator) AddImport(pkg string) string { func (g *conversionGenerator) GenerateConversionsForType(gv unversioned.GroupVersion, reflection reflect.Type) error { kind := reflection.Name() // TODO this is equivalent to what it did before, but it needs to be fixed for the proper group - internalGV, exists := g.scheme.InternalVersions[gv.Group] + internalVersion, exists := g.scheme.InternalVersions[gv.Group] if !exists { return fmt.Errorf("no internal version for %v", gv) } - internalObj, err := g.scheme.NewObject(internalGV.String(), kind) + internalObj, err := g.scheme.NewObject(internalVersion.WithKind(kind)) if err != nil { return fmt.Errorf("cannot create an object of type %v in internal version", kind) } diff --git a/pkg/runtime/interfaces.go b/pkg/runtime/interfaces.go index 349c83bd5c9..fc968521810 100644 --- a/pkg/runtime/interfaces.go +++ b/pkg/runtime/interfaces.go @@ -109,7 +109,7 @@ type ObjectTyper interface { // ObjectCreater contains methods for instantiating an object by kind and version. type ObjectCreater interface { - New(version, kind string) (out Object, err error) + New(kind unversioned.GroupVersionKind) (out Object, err error) } // ObjectCopier duplicates an object. diff --git a/pkg/runtime/scheme.go b/pkg/runtime/scheme.go index 75846054fa4..b221d100eb7 100644 --- a/pkg/runtime/scheme.go +++ b/pkg/runtime/scheme.go @@ -70,14 +70,18 @@ func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExt } // Figure out the type and kind of the output object. - _, outVersion, scheme := self.fromScope(s) - gvk, err := scheme.raw.ObjectKind(in.Object) + _, outGroupVersionString, scheme := self.fromScope(s) + objKind, err := scheme.raw.ObjectKind(in.Object) + if err != nil { + return err + } + outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return err } // Manufacture an object of this type and kind. - outObj, err := scheme.New(outVersion, gvk.Kind) + outObj, err := scheme.New(outVersion.WithKind(objKind.Kind)) if err != nil { return err } @@ -90,7 +94,7 @@ func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExt // Copy the kind field into the output object. err = s.Convert( - &emptyPlugin{PluginBase: PluginBase{Kind: gvk.Kind}}, + &emptyPlugin{PluginBase: PluginBase{Kind: objKind.Kind}}, outObj, conversion.SourceToDest|conversion.IgnoreMissingFields|conversion.AllowDifferentFieldTypeNames, ) @@ -98,7 +102,7 @@ func (self *Scheme) embeddedObjectToRawExtension(in *EmbeddedObject, out *RawExt return err } // Because we provide the correct version, EncodeToVersion will not attempt a conversion. - raw, err := scheme.EncodeToVersion(outObj, outVersion) + raw, err := scheme.EncodeToVersion(outObj, outVersion.String()) if err != nil { // TODO: if this fails, create an Unknown-- maybe some other // component will understand it. @@ -117,15 +121,23 @@ func (self *Scheme) rawExtensionToEmbeddedObject(in *RawExtension, out *Embedded return nil } // Figure out the type and kind of the output object. - inVersion, outVersion, scheme := self.fromScope(s) - gvk, err := scheme.raw.DataKind(in.RawJSON) + inGroupVersionString, outGroupVersionString, scheme := self.fromScope(s) + dataKind, err := scheme.raw.DataKind(in.RawJSON) + if err != nil { + return err + } + inVersion, err := unversioned.ParseGroupVersion(inGroupVersionString) + if err != nil { + return err + } + outVersion, err := unversioned.ParseGroupVersion(outGroupVersionString) if err != nil { return err } // We have to make this object ourselves because we don't store the version field for // plugin objects. - inObj, err := scheme.New(inVersion, gvk.Kind) + inObj, err := scheme.New(inVersion.WithKind(dataKind.Kind)) if err != nil { return err } @@ -136,7 +148,7 @@ func (self *Scheme) rawExtensionToEmbeddedObject(in *RawExtension, out *Embedded } // Make the desired internal version, and do the conversion. - outObj, err := scheme.New(outVersion, gvk.Kind) + outObj, err := scheme.New(outVersion.WithKind(dataKind.Kind)) if err != nil { return err } @@ -209,14 +221,14 @@ func (self *Scheme) rawExtensionToRuntimeObjectArray(in *[]RawExtension, out *[] for i := range src { data := src[i].RawJSON - gvk, err := scheme.raw.DataKind(data) + dataKind, err := scheme.raw.DataKind(data) if err != nil { return err } dest[i] = &Unknown{ TypeMeta: TypeMeta{ - APIVersion: gvk.GroupVersion().String(), - Kind: gvk.Kind, + APIVersion: dataKind.GroupVersion().String(), + Kind: dataKind.Kind, }, RawJSON: data, } @@ -306,10 +318,9 @@ func (s *Scheme) Recognizes(gvk unversioned.GroupVersionKind) bool { return s.raw.Recognizes(gvk) } -// New returns a new API object of the given version ("" for internal -// representation) and name, or an error if it hasn't been registered. -func (s *Scheme) New(versionName, typeName string) (Object, error) { - obj, err := s.raw.NewObject(versionName, typeName) +// New returns a new API object of the given kind, or an error if it hasn't been registered. +func (s *Scheme) New(kind unversioned.GroupVersionKind) (Object, error) { + obj, err := s.raw.NewObject(kind) if err != nil { return nil, err }