mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-16 22:53:22 +00:00
Plumb restmapper properly through apiserver and tests
This commit is contained in:
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/admission"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/healthz"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
@@ -56,9 +56,9 @@ type defaultAPIServer struct {
|
||||
// as RESTful resources at prefix, serialized by codec, and also includes the support
|
||||
// http resources.
|
||||
// Note: This method is used only in tests.
|
||||
func Handle(storage map[string]RESTStorage, codec runtime.Codec, root string, version string, selfLinker runtime.SelfLinker, admissionControl admission.Interface) http.Handler {
|
||||
func Handle(storage map[string]RESTStorage, codec runtime.Codec, root string, version string, selfLinker runtime.SelfLinker, admissionControl admission.Interface, mapper meta.RESTMapper) http.Handler {
|
||||
prefix := root + "/" + version
|
||||
group := NewAPIGroupVersion(storage, codec, prefix, selfLinker, admissionControl)
|
||||
group := NewAPIGroupVersion(storage, codec, prefix, selfLinker, admissionControl, mapper)
|
||||
container := restful.NewContainer()
|
||||
mux := container.ServeMux
|
||||
group.InstallREST(container, mux, root, version)
|
||||
@@ -77,6 +77,7 @@ func Handle(storage map[string]RESTStorage, codec runtime.Codec, root string, ve
|
||||
// TODO: consider migrating this to go-restful which is a more full-featured version of the same thing.
|
||||
type APIGroupVersion struct {
|
||||
handler RESTHandler
|
||||
mapper meta.RESTMapper
|
||||
}
|
||||
|
||||
// NewAPIGroupVersion returns an object that will serve a set of REST resources and their
|
||||
@@ -84,15 +85,18 @@ type APIGroupVersion struct {
|
||||
// This is a helper method for registering multiple sets of REST handlers under different
|
||||
// prefixes onto a server.
|
||||
// TODO: add multitype codec serialization
|
||||
func NewAPIGroupVersion(storage map[string]RESTStorage, codec runtime.Codec, canonicalPrefix string, selfLinker runtime.SelfLinker, admissionControl admission.Interface) *APIGroupVersion {
|
||||
return &APIGroupVersion{RESTHandler{
|
||||
storage: storage,
|
||||
codec: codec,
|
||||
canonicalPrefix: canonicalPrefix,
|
||||
selfLinker: selfLinker,
|
||||
ops: NewOperations(),
|
||||
admissionControl: admissionControl,
|
||||
}}
|
||||
func NewAPIGroupVersion(storage map[string]RESTStorage, codec runtime.Codec, canonicalPrefix string, selfLinker runtime.SelfLinker, admissionControl admission.Interface, mapper meta.RESTMapper) *APIGroupVersion {
|
||||
return &APIGroupVersion{
|
||||
handler: RESTHandler{
|
||||
storage: storage,
|
||||
codec: codec,
|
||||
canonicalPrefix: canonicalPrefix,
|
||||
selfLinker: selfLinker,
|
||||
ops: NewOperations(),
|
||||
admissionControl: admissionControl,
|
||||
},
|
||||
mapper: mapper,
|
||||
}
|
||||
}
|
||||
|
||||
// This magic incantation returns *ptrToObject for an arbitrary pointer
|
||||
@@ -100,7 +104,7 @@ func indirectArbitraryPointer(ptrToObject interface{}) interface{} {
|
||||
return reflect.Indirect(reflect.ValueOf(ptrToObject)).Interface()
|
||||
}
|
||||
|
||||
func registerResourceHandlers(ws *restful.WebService, version string, path string, storage RESTStorage, h restful.RouteFunction) error {
|
||||
func registerResourceHandlers(ws *restful.WebService, version string, path string, storage RESTStorage, h restful.RouteFunction, mapper meta.RESTMapper) error {
|
||||
object := storage.New()
|
||||
_, kind, err := api.Scheme.ObjectVersionAndKind(object)
|
||||
if err != nil {
|
||||
@@ -112,7 +116,6 @@ func registerResourceHandlers(ws *restful.WebService, version string, path strin
|
||||
}
|
||||
versionedObject := indirectArbitraryPointer(versionedPtr)
|
||||
|
||||
mapper := latest.RESTMapper
|
||||
mapping, err := mapper.RESTMapping(kind, version)
|
||||
if err != nil {
|
||||
glog.V(1).Infof("OH NOES kind %s version %s err: %v", kind, version, err)
|
||||
@@ -124,9 +127,9 @@ func registerResourceHandlers(ws *restful.WebService, version string, path strin
|
||||
// check if this
|
||||
scope := mapping.Scope
|
||||
var scopeParam *restful.Parameter
|
||||
if len(scope.ParamName) > 0 && scope.ParamPath {
|
||||
path = scope.ParamName + "/{" + scope.ParamName + "}/" + path
|
||||
scopeParam = ws.PathParameter(scope.ParamName, scope.ParamDescription).DataType("string")
|
||||
if len(scope.ParamName()) > 0 && scope.ParamPath() {
|
||||
path = scope.ParamName() + "/{" + scope.ParamName() + "}/" + path
|
||||
scopeParam = ws.PathParameter(scope.ParamName(), scope.ParamDescription()).DataType("string")
|
||||
}
|
||||
|
||||
glog.V(5).Infof("Installing version=/%s, kind=/%s, path=/%s", version, kind, path)
|
||||
@@ -263,7 +266,7 @@ func (g *APIGroupVersion) InstallREST(container *restful.Container, mux Mux, roo
|
||||
registrationErrors := make([]error, 0)
|
||||
|
||||
for path, storage := range g.handler.storage {
|
||||
if err := registerResourceHandlers(ws, version, path, storage, h); err != nil {
|
||||
if err := registerResourceHandlers(ws, version, path, storage, h, g.mapper); err != nil {
|
||||
registrationErrors = append(registrationErrors, err)
|
||||
}
|
||||
}
|
||||
|
@@ -93,7 +93,15 @@ func init() {
|
||||
return interfaces, true
|
||||
},
|
||||
)
|
||||
defMapper.Add(api.Scheme, true, versions...)
|
||||
// enumerate all supported versions, get the kinds, and register with the mapper how to address our resources
|
||||
for _, version := range versions {
|
||||
for kind := range api.Scheme.KnownTypes(version) {
|
||||
mixedCase := true
|
||||
scope := meta.RESTScopeNamespaceLegacy
|
||||
defMapper.Add(scope, kind, version, mixedCase)
|
||||
}
|
||||
}
|
||||
|
||||
mapper = defMapper
|
||||
admissionControl = admit.NewAlwaysAdmit()
|
||||
}
|
||||
@@ -270,7 +278,7 @@ func TestNotFound(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": &SimpleRESTStorage{},
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -287,6 +295,7 @@ func TestNotFound(t *testing.T) {
|
||||
|
||||
if response.StatusCode != v.Status {
|
||||
t.Errorf("Expected %d for %s (%s), Got %#v", v.Status, v.Method, k, response)
|
||||
t.Errorf("MAPPER: %v", mapper)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,7 +324,7 @@ func TestMethodNotAllowed(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": UnimplementedRESTStorage{},
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -354,7 +363,7 @@ func TestMethodNotAllowed(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVersion(t *testing.T) {
|
||||
handler := Handle(map[string]RESTStorage{}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(map[string]RESTStorage{}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -389,7 +398,7 @@ func TestSimpleList(t *testing.T) {
|
||||
namespace: "other",
|
||||
expectedSet: "/prefix/version/simple?namespace=other",
|
||||
}
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -412,7 +421,7 @@ func TestErrorList(t *testing.T) {
|
||||
errors: map[string]error{"list": fmt.Errorf("test Error")},
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -438,7 +447,7 @@ func TestNonEmptyList(t *testing.T) {
|
||||
},
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -484,7 +493,7 @@ func TestGet(t *testing.T) {
|
||||
expectedSet: "/prefix/version/simple/id",
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -509,7 +518,7 @@ func TestGetMissing(t *testing.T) {
|
||||
errors: map[string]error{"get": apierrs.NewNotFound("simple", "id")},
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -528,7 +537,7 @@ func TestDelete(t *testing.T) {
|
||||
simpleStorage := SimpleRESTStorage{}
|
||||
ID := "id"
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -549,7 +558,7 @@ func TestDeleteInvokesAdmissionControl(t *testing.T) {
|
||||
simpleStorage := SimpleRESTStorage{}
|
||||
ID := "id"
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny())
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny(), mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -571,7 +580,7 @@ func TestDeleteMissing(t *testing.T) {
|
||||
errors: map[string]error{"delete": apierrs.NewNotFound("simple", ID)},
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -596,7 +605,7 @@ func TestUpdate(t *testing.T) {
|
||||
t: t,
|
||||
expectedSet: "/prefix/version/simple/" + ID,
|
||||
}
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -633,7 +642,7 @@ func TestUpdateInvokesAdmissionControl(t *testing.T) {
|
||||
t: t,
|
||||
expectedSet: "/prefix/version/simple/" + ID,
|
||||
}
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny())
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny(), mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -664,7 +673,7 @@ func TestUpdateMissing(t *testing.T) {
|
||||
errors: map[string]error{"update": apierrs.NewNotFound("simple", ID)},
|
||||
}
|
||||
storage["simple"] = &simpleStorage
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(storage, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -695,7 +704,7 @@ func TestCreateNotFound(t *testing.T) {
|
||||
// See https://github.com/GoogleCloudPlatform/kubernetes/pull/486#discussion_r15037092.
|
||||
errors: map[string]error{"create": apierrs.NewNotFound("simple", "id")},
|
||||
},
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -759,11 +768,11 @@ func TestCreate(t *testing.T) {
|
||||
t: t,
|
||||
name: "bar",
|
||||
namespace: "other",
|
||||
expectedSet: "/prefix/version/ns/other/foo/bar",
|
||||
expectedSet: "/prefix/version/foo/bar?namespace=other",
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": &storage,
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -772,7 +781,7 @@ func TestCreate(t *testing.T) {
|
||||
Other: "bar",
|
||||
}
|
||||
data, _ := codec.Encode(simple)
|
||||
request, err := http.NewRequest("POST", server.URL+"/prefix/version/ns/other/foo", bytes.NewBuffer(data))
|
||||
request, err := http.NewRequest("POST", server.URL+"/prefix/version/foo?namespace=other", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -817,11 +826,11 @@ func TestCreateInvokesAdmissionControl(t *testing.T) {
|
||||
t: t,
|
||||
name: "bar",
|
||||
namespace: "other",
|
||||
expectedSet: "/prefix/version/ns/other/foo/bar",
|
||||
expectedSet: "/prefix/version/foo/bar?namespace=other",
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": &storage,
|
||||
}, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny())
|
||||
}, codec, "/prefix", testVersion, selfLinker, deny.NewAlwaysDeny(), mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -830,7 +839,7 @@ func TestCreateInvokesAdmissionControl(t *testing.T) {
|
||||
Other: "bar",
|
||||
}
|
||||
data, _ := codec.Encode(simple)
|
||||
request, err := http.NewRequest("POST", server.URL+"/prefix/version/ns/other/foo", bytes.NewBuffer(data))
|
||||
request, err := http.NewRequest("POST", server.URL+"/prefix/version/foo?namespace=other", bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -881,7 +890,7 @@ func TestDelayReturnsError(t *testing.T) {
|
||||
return nil, apierrs.NewAlreadyExists("foo", "bar")
|
||||
},
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
handler := Handle(map[string]RESTStorage{"foo": &storage}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -947,7 +956,7 @@ func TestCreateTimeout(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": &storage,
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl)
|
||||
}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -979,7 +988,7 @@ func TestCORSAllowedOrigins(t *testing.T) {
|
||||
}
|
||||
|
||||
handler := CORS(
|
||||
Handle(map[string]RESTStorage{}, codec, "/prefix", testVersion, selfLinker, admissionControl),
|
||||
Handle(map[string]RESTStorage{}, codec, "/prefix", testVersion, selfLinker, admissionControl, mapper),
|
||||
allowedOriginRegexps, nil, nil, "true",
|
||||
)
|
||||
server := httptest.NewServer(handler)
|
||||
|
@@ -230,7 +230,7 @@ func TestProxy(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl)
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
|
@@ -31,7 +31,7 @@ func TestRedirect(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl)
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestRedirectWithNamespaces(t *testing.T) {
|
||||
}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl)
|
||||
}, codec, "/prefix", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
|
@@ -50,7 +50,7 @@ func TestWatchWebsocket(t *testing.T) {
|
||||
_ = ResourceWatcher(simpleStorage) // Give compile error if this doesn't work.
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/api", "version", selfLinker, admissionControl)
|
||||
}, codec, "/api", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -104,7 +104,7 @@ func TestWatchHTTP(t *testing.T) {
|
||||
simpleStorage := &SimpleRESTStorage{}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/api", "version", selfLinker, admissionControl)
|
||||
}, codec, "/api", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
client := http.Client{}
|
||||
@@ -167,7 +167,7 @@ func TestWatchParamParsing(t *testing.T) {
|
||||
simpleStorage := &SimpleRESTStorage{}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/api", "version", selfLinker, admissionControl)
|
||||
}, codec, "/api", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
@@ -239,7 +239,7 @@ func TestWatchProtocolSelection(t *testing.T) {
|
||||
simpleStorage := &SimpleRESTStorage{}
|
||||
handler := Handle(map[string]RESTStorage{
|
||||
"foo": simpleStorage,
|
||||
}, codec, "/api", "version", selfLinker, admissionControl)
|
||||
}, codec, "/api", "version", selfLinker, admissionControl, mapper)
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
defer server.CloseClientConnections()
|
||||
|
Reference in New Issue
Block a user