From e0b7f526332361dad4fe51e9bd92aa67e8a59806 Mon Sep 17 00:00:00 2001 From: deads2k Date: Wed, 18 Nov 2015 09:26:29 -0500 Subject: [PATCH] hack up queryToObject to continue to work as it used to --- pkg/apiserver/resthandler.go | 24 ++++++++-- pkg/client/unversioned/testclient/fixture.go | 47 ++++++++++++-------- pkg/conversion/scheme.go | 8 ++-- pkg/kubectl/cmd/cmd_test.go | 3 +- 4 files changed, 55 insertions(+), 27 deletions(-) diff --git a/pkg/apiserver/resthandler.go b/pkg/apiserver/resthandler.go index 618fbab3694..0fadf604428 100644 --- a/pkg/apiserver/resthandler.go +++ b/pkg/apiserver/resthandler.go @@ -149,15 +149,31 @@ func getRequestOptions(req *restful.Request, scope RequestScope, kind string, su newQuery[subpathKey] = []string{req.PathParameter("path")} query = newQuery } - versioned, err := scope.Creater.New(scope.ServerAPIVersion, kind) + + // TODO Options a mess. Basically the intent is: + // 1. try to decode using the expected external GroupVersion + // 2. if that fails, fall back to the old external serialization being used before, which was + // "v1" and decode into the unversioned/legacykube group + gvString := scope.APIVersion + internalGVString := scope.InternalVersion.String() + + versioned, err := scope.Creater.New(gvString, kind) if err != nil { - // programmer error - return nil, err + gvString = "v1" + internalGVString = "" + + var secondErr error + versioned, secondErr = scope.Creater.New(gvString, kind) + // if we have an error, return the original failure + if secondErr != nil { + return nil, err + } } + if err := scope.Codec.DecodeParametersInto(query, versioned); err != nil { return nil, errors.NewBadRequest(err.Error()) } - out, err := scope.Convertor.ConvertToVersion(versioned, scope.InternalVersion.String()) + out, err := scope.Convertor.ConvertToVersion(versioned, internalGVString) if err != nil { // programmer error return nil, err diff --git a/pkg/client/unversioned/testclient/fixture.go b/pkg/client/unversioned/testclient/fixture.go index 271a0177e51..1a4e008a680 100644 --- a/pkg/client/unversioned/testclient/fixture.go +++ b/pkg/client/unversioned/testclient/fixture.go @@ -38,7 +38,7 @@ import ( type ObjectRetriever interface { // Kind should return a resource or a list of resources (depending on the provided kind and // name). It should return an error if the caller should communicate an error to the server. - Kind(kind, name string) (runtime.Object, error) + Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) // Add adds a runtime object for test purposes into this object. Add(runtime.Object) error } @@ -59,23 +59,29 @@ type ObjectScheme interface { func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { return func(action Action) (bool, runtime.Object, error) { - _, kind, err := mapper.VersionAndKindForResource(action.GetResource()) + gvString, kind, err := mapper.VersionAndKindForResource(action.GetResource()) if err != nil { return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) } + gv, err := unversioned.ParseGroupVersion(gvString) + if err != nil { + return false, nil, err + } + gvk := gv.WithKind(kind) // TODO: have mapper return a Kind for a subresource? switch castAction := action.(type) { case ListAction: - resource, err := o.Kind(kind+"List", "") + gvk.Kind += "List" + resource, err := o.Kind(gvk, "") return true, resource, err case GetAction: - resource, err := o.Kind(kind, castAction.GetName()) + resource, err := o.Kind(gvk, castAction.GetName()) return true, resource, err case DeleteAction: - resource, err := o.Kind(kind, castAction.GetName()) + resource, err := o.Kind(gvk, castAction.GetName()) return true, resource, err case CreateAction: @@ -83,7 +89,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { if err != nil { return true, nil, err } - resource, err := o.Kind(kind, meta.Name) + resource, err := o.Kind(gvk, meta.Name) return true, resource, err case UpdateAction: @@ -91,7 +97,7 @@ func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { if err != nil { return true, nil, err } - resource, err := o.Kind(kind, meta.Name) + resource, err := o.Kind(gvk, meta.Name) return true, resource, err default: @@ -151,19 +157,24 @@ func NewObjects(scheme ObjectScheme, decoder runtime.ObjectDecoder) ObjectRetrie } } -func (o objects) Kind(kind, name string) (runtime.Object, error) { - empty, _ := o.scheme.New("", kind) +func (o objects) Kind(gvk 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 = "" + + empty, _ := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) - arr, ok := o.types[kind] + arr, ok := o.types[gvk.Kind] if !ok { - if strings.HasSuffix(kind, "List") { - itemKind := kind[:len(kind)-4] + if strings.HasSuffix(gvk.Kind, "List") { + itemKind := gvk.Kind[:len(gvk.Kind)-4] arr, ok := o.types[itemKind] if !ok { return empty, nil } - out, err := o.scheme.New("", kind) + out, err := o.scheme.New(gvk.GroupVersion().String(), gvk.Kind) if err != nil { return nilValue, err } @@ -175,25 +186,25 @@ func (o objects) Kind(kind, name string) (runtime.Object, error) { } return out, nil } - return nilValue, errors.NewNotFound(kind, name) + return nilValue, errors.NewNotFound(gvk.Kind, name) } - index := o.last[kind] + index := o.last[gvk.Kind] if index >= len(arr) { index = len(arr) - 1 } if index < 0 { - return nilValue, errors.NewNotFound(kind, name) + return nilValue, errors.NewNotFound(gvk.Kind, name) } out, err := o.scheme.Copy(arr[index]) if err != nil { return nilValue, err } - o.last[kind] = index + 1 + o.last[gvk.Kind] = index + 1 if status, ok := out.(*unversioned.Status); ok { if status.Details != nil { - status.Details.Kind = kind + status.Details.Kind = gvk.Kind } if status.Status != unversioned.StatusSuccess { return nilValue, &errors.StatusError{ErrStatus: *status} diff --git a/pkg/conversion/scheme.go b/pkg/conversion/scheme.go index a532a3b15cd..19013ab6802 100644 --- a/pkg/conversion/scheme.go +++ b/pkg/conversion/scheme.go @@ -72,10 +72,10 @@ func NewScheme() *Scheme { cloner: NewCloner(), // TODO remove this hard coded list. As step one, hardcode it here so this pull doesn't become even bigger InternalVersions: map[string]unversioned.GroupVersion{ - "": unversioned.GroupVersion{}, - "componentconfig": unversioned.GroupVersion{Group: "componentconfig"}, - "extensions": unversioned.GroupVersion{Group: "extensions"}, - "metrics": unversioned.GroupVersion{Group: "metrics"}, + "": {}, + "componentconfig": {Group: "componentconfig"}, + "extensions": {Group: "extensions"}, + "metrics": {Group: "metrics"}, }, MetaFactory: DefaultMetaFactory, } diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index f99c946f7fd..9c7be7bbdae 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -84,7 +84,8 @@ var validVersionGV = unversioned.GroupVersion{Group: "apitest", Version: validVe func newExternalScheme() (*runtime.Scheme, meta.RESTMapper, runtime.Codec) { scheme := runtime.NewScheme() - scheme.AddKnownTypeWithName(internalGV.Version, "Type", &internalType{}) + scheme.AddInternalGroupVersion(internalGV) + scheme.AddKnownTypeWithName(internalGV.String(), "Type", &internalType{}) scheme.AddKnownTypeWithName(unlikelyGV.String(), "Type", &externalType{}) //This tests that kubectl will not confuse the external scheme with the internal scheme, even when they accidentally have versions of the same name. scheme.AddKnownTypeWithName(validVersionGV.String(), "Type", &ExternalType2{})