diff --git a/pkg/api/meta/restmapper_test.go b/pkg/api/meta/restmapper_test.go index 427392b68d0..477db07abef 100644 --- a/pkg/api/meta/restmapper_test.go +++ b/pkg/api/meta/restmapper_test.go @@ -19,6 +19,7 @@ package meta import ( "errors" "io" + "net/url" "testing" "k8s.io/kubernetes/pkg/api/unversioned" @@ -51,6 +52,10 @@ func (fakeCodec) DecodeIntoWithSpecifiedVersionKind([]byte, runtime.Object, stri return nil } +func (fakeCodec) DecodeParametersInto(parameters url.Values, obj runtime.Object) error { + return nil +} + type fakeConvertor struct{} func (fakeConvertor) Convert(in, out interface{}) error { diff --git a/pkg/apiserver/resthandler.go b/pkg/apiserver/resthandler.go index d9eaa916fd5..8c098631c2d 100644 --- a/pkg/apiserver/resthandler.go +++ b/pkg/apiserver/resthandler.go @@ -147,7 +147,20 @@ func getRequestOptions(req *restful.Request, scope RequestScope, kind string, su newQuery[subpathKey] = []string{req.PathParameter("path")} query = newQuery } - return queryToObject(query, scope, kind) + versioned, err := scope.Creater.New(scope.ServerAPIVersion, kind) + if err != nil { + // programmer error + return nil, err + } + if err := scope.Codec.DecodeParametersInto(query, versioned); err != nil { + return nil, errors.NewBadRequest(err.Error()) + } + out, err := scope.Convertor.ConvertToVersion(versioned, "") + if err != nil { + // programmer error + return nil, err + } + return out, nil } // ConnectResource returns a function that handles a connect request on a rest.Storage object. @@ -226,15 +239,23 @@ func ListResource(r rest.Lister, rw rest.Watcher, scope RequestScope, forceWatch ctx := scope.ContextFunc(req) ctx = api.WithNamespace(ctx, namespace) - out, err := queryToObject(req.Request.URL.Query(), scope, "ListOptions") + versioned, err := scope.Creater.New(scope.ServerAPIVersion, "ListOptions") if err != nil { errorJSON(err, scope.Codec, w) return } - opts := *out.(*api.ListOptions) + if err := scope.Codec.DecodeParametersInto(req.Request.URL.Query(), versioned); err != nil { + errorJSON(err, scope.Codec, w) + return + } + opts := api.ListOptions{} + if err := scope.Convertor.Convert(versioned, &opts); err != nil { + errorJSON(err, scope.Codec, w) + return + } // transform fields - // TODO: queryToObject should do this. + // TODO: Should this be done as part of convertion? fn := func(label, value string) (newLabel, newValue string, err error) { return scope.Convertor.ConvertFieldLabel(scope.APIVersion, scope.Kind, label, value) } @@ -679,27 +700,6 @@ func DeleteResource(r rest.GracefulDeleter, checkBody bool, scope RequestScope, } } -// queryToObject converts query parameters into a structured internal object by -// kind. The caller must cast the returned object to the matching internal Kind -// to use it. -// TODO: add appropriate structured error responses -func queryToObject(query url.Values, scope RequestScope, kind string) (runtime.Object, error) { - versioned, err := scope.Creater.New(scope.ServerAPIVersion, kind) - if err != nil { - // programmer error - return nil, err - } - if err := scope.Convertor.Convert(&query, versioned); err != nil { - return nil, errors.NewBadRequest(err.Error()) - } - out, err := scope.Convertor.ConvertToVersion(versioned, "") - if err != nil { - // programmer error - return nil, err - } - return out, nil -} - // resultFunc is a function that returns a rest result and can be run in a goroutine type resultFunc func() (runtime.Object, error) diff --git a/pkg/conversion/decode.go b/pkg/conversion/decode.go index 4ecf632c9d0..d799cfffb85 100644 --- a/pkg/conversion/decode.go +++ b/pkg/conversion/decode.go @@ -19,6 +19,7 @@ package conversion import ( "errors" "fmt" + "net/url" "github.com/ugorji/go/codec" ) @@ -151,3 +152,11 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj interface{} // Version and Kind should be blank in memory. return s.SetVersionAndKind("", "", obj) } + +func (s *Scheme) DecodeParametersInto(parameters url.Values, obj interface{}) error { + if err := s.Convert(¶meters, obj); err != nil { + return err + } + // TODO: Should we do any convertion here? + return nil +} diff --git a/pkg/registry/thirdpartyresourcedata/codec.go b/pkg/registry/thirdpartyresourcedata/codec.go index c7eb8fd55ee..4b31cc6bbaf 100644 --- a/pkg/registry/thirdpartyresourcedata/codec.go +++ b/pkg/registry/thirdpartyresourcedata/codec.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "io" + "net/url" "strings" "k8s.io/kubernetes/pkg/api/latest" @@ -221,6 +222,10 @@ func (t *thirdPartyResourceDataCodec) DecodeIntoWithSpecifiedVersionKind(data [] return nil } +func (t *thirdPartyResourceDataCodec) DecodeParametersInto(parameters url.Values, obj runtime.Object) error { + return t.delegate.DecodeParametersInto(parameters, obj) +} + const template = `{ "kind": "%s", "items": [ %s ] diff --git a/pkg/runtime/interfaces.go b/pkg/runtime/interfaces.go index eda8b8d9b24..c367a4f364a 100644 --- a/pkg/runtime/interfaces.go +++ b/pkg/runtime/interfaces.go @@ -18,6 +18,7 @@ package runtime import ( "io" + "net/url" ) // Codec defines methods for serializing and deserializing API objects. @@ -35,8 +36,7 @@ type Decoder interface { // TODO: Remove this method? DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, kind, version string) error - // TODO: Add method for processing url parameters. - // DecodeParametersInto(parameters url.Values, obj Object) error + DecodeParametersInto(parameters url.Values, obj Object) error } // Encoder defines methods for serializing API objects into bytes diff --git a/pkg/runtime/scheme.go b/pkg/runtime/scheme.go index c21e9bc0750..147c1a26fc3 100644 --- a/pkg/runtime/scheme.go +++ b/pkg/runtime/scheme.go @@ -480,6 +480,10 @@ func (s *Scheme) DecodeIntoWithSpecifiedVersionKind(data []byte, obj Object, ver return s.raw.DecodeIntoWithSpecifiedVersionKind(data, obj, version, kind) } +func (s *Scheme) DecodeParametersInto(parameters url.Values, obj Object) error { + return s.raw.DecodeParametersInto(parameters, obj) +} + // Copy does a deep copy of an API object. Useful mostly for tests. func (s *Scheme) Copy(src Object) (Object, error) { dst, err := s.raw.DeepCopy(src) diff --git a/pkg/runtime/unstructured.go b/pkg/runtime/unstructured.go index 303300ccd0f..3c524236059 100644 --- a/pkg/runtime/unstructured.go +++ b/pkg/runtime/unstructured.go @@ -19,6 +19,7 @@ package runtime import ( "encoding/json" "fmt" + "net/url" "reflect" "k8s.io/kubernetes/pkg/conversion" @@ -82,6 +83,10 @@ func (unstructuredJSONScheme) DecodeToVersion(data []byte, version string) (Obje return nil, nil } +func (unstructuredJSONScheme) DecodeParametersInto(paramaters url.Values, obj Object) error { + return nil +} + func (unstructuredJSONScheme) DataVersionAndKind(data []byte) (version, kind string, err error) { obj := TypeMeta{} if err := json.Unmarshal(data, &obj); err != nil {