mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
audit: wire through non-nil context everywhere
This commit is contained in:
parent
0b5bcb0219
commit
ce942d19c3
@ -27,6 +27,7 @@ import (
|
|||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
openapigen "k8s.io/kubernetes/pkg/generated/openapi"
|
openapigen "k8s.io/kubernetes/pkg/generated/openapi"
|
||||||
@ -59,7 +60,7 @@ func TestValidOpenAPISpec(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure swagger.json is not registered before calling PrepareRun.
|
// make sure swagger.json is not registered before calling PrepareRun.
|
||||||
server := httptest.NewServer(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux)
|
server := httptest.NewServer(apirequest.WithRequestContext(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux, master.GenericAPIServer.RequestContextMapper()))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
resp, err := http.Get(server.URL + "/swagger.json")
|
resp, err := http.Get(server.URL + "/swagger.json")
|
||||||
if !assert.NoError(err) {
|
if !assert.NoError(err) {
|
||||||
|
@ -234,7 +234,7 @@ func TestAPIVersionOfDiscoveryEndpoints(t *testing.T) {
|
|||||||
master, etcdserver, _, assert := newMaster(t)
|
master, etcdserver, _, assert := newMaster(t)
|
||||||
defer etcdserver.Terminate(t)
|
defer etcdserver.Terminate(t)
|
||||||
|
|
||||||
server := httptest.NewServer(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux)
|
server := httptest.NewServer(genericapirequest.WithRequestContext(master.GenericAPIServer.Handler.GoRestfulContainer.ServeMux, master.GenericAPIServer.RequestContextMapper()))
|
||||||
|
|
||||||
// /api exists in release-1.1
|
// /api exists in release-1.1
|
||||||
resp, err := http.Get(server.URL + "/api")
|
resp, err := http.Get(server.URL + "/api")
|
||||||
|
2
pkg/master/thirdparty/thirdparty.go
vendored
2
pkg/master/thirdparty/thirdparty.go
vendored
@ -287,7 +287,7 @@ func (m *ThirdPartyResourceServer) InstallThirdPartyResource(rsrc *extensions.Th
|
|||||||
if err := thirdparty.InstallREST(m.genericAPIServer.Handler.GoRestfulContainer); err != nil {
|
if err := thirdparty.InstallREST(m.genericAPIServer.Handler.GoRestfulContainer); err != nil {
|
||||||
glog.Errorf("Unable to setup thirdparty api: %v", err)
|
glog.Errorf("Unable to setup thirdparty api: %v", err)
|
||||||
}
|
}
|
||||||
m.genericAPIServer.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(api.Codecs, apiGroup).WebService())
|
m.genericAPIServer.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(api.Codecs, apiGroup, m.genericAPIServer.RequestContextMapper()).WebService())
|
||||||
|
|
||||||
m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup)
|
m.addThirdPartyResourceStorage(path, plural.Resource, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedatastore.REST), apiGroup)
|
||||||
api.Registry.AddThirdPartyAPIGroupVersions(schema.GroupVersion{Group: group, Version: rsrc.Versions[0].Name})
|
api.Registry.AddThirdPartyAPIGroupVersions(schema.GroupVersion{Group: group, Version: rsrc.Versions[0].Name})
|
||||||
|
@ -3254,7 +3254,7 @@ func (obj *UnregisteredAPIObject) GetObjectKind() schema.ObjectKind {
|
|||||||
|
|
||||||
func TestWriteJSONDecodeError(t *testing.T) {
|
func TestWriteJSONDecodeError(t *testing.T) {
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
responsewriters.WriteObjectNegotiated(nil, codecs, newGroupVersion, w, req, http.StatusOK, &UnregisteredAPIObject{"Undecodable"})
|
responsewriters.WriteObjectNegotiated(request.NewContext(), codecs, newGroupVersion, w, req, http.StatusOK, &UnregisteredAPIObject{"Undecodable"})
|
||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
// We send a 200 status code before we encode the object, so we expect OK, but there will
|
// We send a 200 status code before we encode the object, so we expect OK, but there will
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package discovery
|
package discovery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
@ -26,17 +27,18 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// APIGroupHandler creates a webservice serving the supported versions, preferred version, and name
|
// APIGroupHandler creates a webservice serving the supported versions, preferred version, and name
|
||||||
// of a group. E.g., such a web service will be registered at /apis/extensions.
|
// of a group. E.g., such a web service will be registered at /apis/extensions.
|
||||||
type APIGroupHandler struct {
|
type APIGroupHandler struct {
|
||||||
serializer runtime.NegotiatedSerializer
|
serializer runtime.NegotiatedSerializer
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
group metav1.APIGroup
|
group metav1.APIGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.APIGroup) *APIGroupHandler {
|
func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.APIGroup, contextMapper request.RequestContextMapper) *APIGroupHandler {
|
||||||
if keepUnversioned(group.Name) {
|
if keepUnversioned(group.Name) {
|
||||||
// Because in release 1.1, /apis/extensions returns response with empty
|
// Because in release 1.1, /apis/extensions returns response with empty
|
||||||
// APIVersion, we use stripVersionNegotiatedSerializer to keep the
|
// APIVersion, we use stripVersionNegotiatedSerializer to keep the
|
||||||
@ -46,6 +48,7 @@ func NewAPIGroupHandler(serializer runtime.NegotiatedSerializer, group metav1.AP
|
|||||||
|
|
||||||
return &APIGroupHandler{
|
return &APIGroupHandler{
|
||||||
serializer: serializer,
|
serializer: serializer,
|
||||||
|
contextMapper: contextMapper,
|
||||||
group: group,
|
group: group,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,5 +73,10 @@ func (s *APIGroupHandler) handle(req *restful.Request, resp *restful.Response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *APIGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (s *APIGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
responsewriters.WriteObjectNegotiated(nil, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, &s.group)
|
ctx, ok := s.contextMapper.Get(req)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(w, req, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK, &s.group)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package discovery
|
package discovery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
@ -27,6 +28,7 @@ import (
|
|||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// legacyRootAPIHandler creates a webservice serving api group discovery.
|
// legacyRootAPIHandler creates a webservice serving api group discovery.
|
||||||
@ -36,9 +38,10 @@ type legacyRootAPIHandler struct {
|
|||||||
apiPrefix string
|
apiPrefix string
|
||||||
serializer runtime.NegotiatedSerializer
|
serializer runtime.NegotiatedSerializer
|
||||||
apiVersions []string
|
apiVersions []string
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string) *legacyRootAPIHandler {
|
func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, apiPrefix string, apiVersions []string, contextMapper request.RequestContextMapper) *legacyRootAPIHandler {
|
||||||
// Because in release 1.1, /apis returns response with empty APIVersion, we
|
// Because in release 1.1, /apis returns response with empty APIVersion, we
|
||||||
// use stripVersionNegotiatedSerializer to keep the response backwards
|
// use stripVersionNegotiatedSerializer to keep the response backwards
|
||||||
// compatible.
|
// compatible.
|
||||||
@ -49,6 +52,7 @@ func NewLegacyRootAPIHandler(addresses Addresses, serializer runtime.NegotiatedS
|
|||||||
apiPrefix: apiPrefix,
|
apiPrefix: apiPrefix,
|
||||||
serializer: serializer,
|
serializer: serializer,
|
||||||
apiVersions: apiVersions,
|
apiVersions: apiVersions,
|
||||||
|
contextMapper: contextMapper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,11 +72,17 @@ func (s *legacyRootAPIHandler) WebService() *restful.WebService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Response) {
|
func (s *legacyRootAPIHandler) handle(req *restful.Request, resp *restful.Response) {
|
||||||
|
ctx, ok := s.contextMapper.Get(req.Request)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(resp.ResponseWriter, req.Request, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
clientIP := utilnet.GetClientIP(req.Request)
|
clientIP := utilnet.GetClientIP(req.Request)
|
||||||
apiVersions := &metav1.APIVersions{
|
apiVersions := &metav1.APIVersions{
|
||||||
ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP),
|
ServerAddressByClientCIDRs: s.addresses.ServerAddressByClientCIDRs(clientIP),
|
||||||
Versions: s.apiVersions,
|
Versions: s.apiVersions,
|
||||||
}
|
}
|
||||||
|
|
||||||
responsewriters.WriteObjectNegotiated(nil, s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions)
|
responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, resp.ResponseWriter, req.Request, http.StatusOK, apiVersions)
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,11 @@ limitations under the License.
|
|||||||
package discovery
|
package discovery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
restful "github.com/emicklei/go-restful"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@ -28,6 +29,7 @@ import (
|
|||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GroupManager is an interface that allows dynamic mutation of the existing webservice to handle
|
// GroupManager is an interface that allows dynamic mutation of the existing webservice to handle
|
||||||
@ -47,6 +49,7 @@ type rootAPIsHandler struct {
|
|||||||
addresses Addresses
|
addresses Addresses
|
||||||
|
|
||||||
serializer runtime.NegotiatedSerializer
|
serializer runtime.NegotiatedSerializer
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
|
|
||||||
// Map storing information about all groups to be exposed in discovery response.
|
// Map storing information about all groups to be exposed in discovery response.
|
||||||
// The map is from name to the group.
|
// The map is from name to the group.
|
||||||
@ -56,7 +59,7 @@ type rootAPIsHandler struct {
|
|||||||
apiGroupNames []string
|
apiGroupNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRootAPIsHandler(addresses Addresses, serializer runtime.NegotiatedSerializer) *rootAPIsHandler {
|
func NewRootAPIsHandler(addresses Addresses, serializer runtime.NegotiatedSerializer, contextMapper request.RequestContextMapper) *rootAPIsHandler {
|
||||||
// Because in release 1.1, /apis returns response with empty APIVersion, we
|
// Because in release 1.1, /apis returns response with empty APIVersion, we
|
||||||
// use stripVersionNegotiatedSerializer to keep the response backwards
|
// use stripVersionNegotiatedSerializer to keep the response backwards
|
||||||
// compatible.
|
// compatible.
|
||||||
@ -66,6 +69,7 @@ func NewRootAPIsHandler(addresses Addresses, serializer runtime.NegotiatedSerial
|
|||||||
addresses: addresses,
|
addresses: addresses,
|
||||||
serializer: serializer,
|
serializer: serializer,
|
||||||
apiGroups: map[string]metav1.APIGroup{},
|
apiGroups: map[string]metav1.APIGroup{},
|
||||||
|
contextMapper: contextMapper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,6 +99,12 @@ func (s *rootAPIsHandler) RemoveGroup(groupName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
|
||||||
|
ctx, ok := s.contextMapper.Get(req)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(resp, req, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
|
|
||||||
@ -111,7 +121,7 @@ func (s *rootAPIsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request)
|
|||||||
groups[i].ServerAddressByClientCIDRs = serverCIDR
|
groups[i].ServerAddressByClientCIDRs = serverCIDR
|
||||||
}
|
}
|
||||||
|
|
||||||
responsewriters.WriteObjectNegotiated(nil, s.serializer, schema.GroupVersion{}, resp, req, http.StatusOK, &metav1.APIGroupList{Groups: groups})
|
responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, resp, req, http.StatusOK, &metav1.APIGroupList{Groups: groups})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *rootAPIsHandler) restfulHandle(req *restful.Request, resp *restful.Response) {
|
func (s *rootAPIsHandler) restfulHandle(req *restful.Request, resp *restful.Response) {
|
||||||
|
@ -33,6 +33,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -83,9 +84,10 @@ func getGroupList(t *testing.T, server *httptest.Server) (*metav1.APIGroupList,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDiscoveryAtAPIS(t *testing.T) {
|
func TestDiscoveryAtAPIS(t *testing.T) {
|
||||||
handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs)
|
mapper := request.NewRequestContextMapper()
|
||||||
|
handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs, mapper)
|
||||||
|
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(request.WithRequestContext(handler, mapper))
|
||||||
groupList, err := getGroupList(t, server)
|
groupList, err := getGroupList(t, server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
@ -133,9 +135,10 @@ func TestDiscoveryAtAPIS(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDiscoveryOrdering(t *testing.T) {
|
func TestDiscoveryOrdering(t *testing.T) {
|
||||||
handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs)
|
mapper := request.NewRequestContextMapper()
|
||||||
|
handler := NewRootAPIsHandler(DefaultAddresses{DefaultAddress: "192.168.1.1"}, codecs, mapper)
|
||||||
|
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(request.WithRequestContext(handler, mapper))
|
||||||
groupList, err := getGroupList(t, server)
|
groupList, err := getGroupList(t, server)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
@ -17,15 +17,17 @@ limitations under the License.
|
|||||||
package discovery
|
package discovery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful"
|
restful "github.com/emicklei/go-restful"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
"k8s.io/apiserver/pkg/endpoints/handlers/negotiation"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
type APIResourceLister interface {
|
type APIResourceLister interface {
|
||||||
@ -42,12 +44,13 @@ func (f APIResourceListerFunc) ListAPIResources() []metav1.APIResource {
|
|||||||
// E.g., such a web service will be registered at /apis/extensions/v1beta1.
|
// E.g., such a web service will be registered at /apis/extensions/v1beta1.
|
||||||
type APIVersionHandler struct {
|
type APIVersionHandler struct {
|
||||||
serializer runtime.NegotiatedSerializer
|
serializer runtime.NegotiatedSerializer
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
|
|
||||||
groupVersion schema.GroupVersion
|
groupVersion schema.GroupVersion
|
||||||
apiResourceLister APIResourceLister
|
apiResourceLister APIResourceLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion schema.GroupVersion, apiResourceLister APIResourceLister) *APIVersionHandler {
|
func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion schema.GroupVersion, apiResourceLister APIResourceLister, contextMapper request.RequestContextMapper) *APIVersionHandler {
|
||||||
if keepUnversioned(groupVersion.Group) {
|
if keepUnversioned(groupVersion.Group) {
|
||||||
// Because in release 1.1, /apis/extensions returns response with empty
|
// Because in release 1.1, /apis/extensions returns response with empty
|
||||||
// APIVersion, we use stripVersionNegotiatedSerializer to keep the
|
// APIVersion, we use stripVersionNegotiatedSerializer to keep the
|
||||||
@ -59,6 +62,7 @@ func NewAPIVersionHandler(serializer runtime.NegotiatedSerializer, groupVersion
|
|||||||
serializer: serializer,
|
serializer: serializer,
|
||||||
groupVersion: groupVersion,
|
groupVersion: groupVersion,
|
||||||
apiResourceLister: apiResourceLister,
|
apiResourceLister: apiResourceLister,
|
||||||
|
contextMapper: contextMapper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +82,12 @@ func (s *APIVersionHandler) handle(req *restful.Request, resp *restful.Response)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *APIVersionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (s *APIVersionHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
responsewriters.WriteObjectNegotiated(nil, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK,
|
ctx, ok := s.contextMapper.Get(req)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(w, req, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responsewriters.WriteObjectNegotiated(ctx, s.serializer, schema.GroupVersion{}, w, req, http.StatusOK,
|
||||||
&metav1.APIResourceList{GroupVersion: s.groupVersion.String(), APIResources: s.apiResourceLister.ListAPIResources()})
|
&metav1.APIResourceList{GroupVersion: s.groupVersion.String(), APIResources: s.apiResourceLister.ListAPIResources()})
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ func (g *APIGroupVersion) InstallREST(container *restful.Container) error {
|
|||||||
if lister == nil {
|
if lister == nil {
|
||||||
lister = staticLister{apiResources}
|
lister = staticLister{apiResources}
|
||||||
}
|
}
|
||||||
versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, lister)
|
versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, lister, g.Context)
|
||||||
versionDiscoveryHandler.AddToWebService(ws)
|
versionDiscoveryHandler.AddToWebService(ws)
|
||||||
container.Add(ws)
|
container.Add(ws)
|
||||||
return utilerrors.NewAggregate(registrationErrors)
|
return utilerrors.NewAggregate(registrationErrors)
|
||||||
@ -129,7 +129,7 @@ func (g *APIGroupVersion) UpdateREST(container *restful.Container) error {
|
|||||||
if lister == nil {
|
if lister == nil {
|
||||||
lister = staticLister{apiResources}
|
lister = staticLister{apiResources}
|
||||||
}
|
}
|
||||||
versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, lister)
|
versionDiscoveryHandler := discovery.NewAPIVersionHandler(g.Serializer, g.GroupVersion, lister, g.Context)
|
||||||
versionDiscoveryHandler.AddToWebService(ws)
|
versionDiscoveryHandler.AddToWebService(ws)
|
||||||
return utilerrors.NewAggregate(registrationErrors)
|
return utilerrors.NewAggregate(registrationErrors)
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
// TODO convert this entire proxy to an UpgradeAwareProxy similar to
|
// TODO convert this entire proxy to an UpgradeAwareProxy similar to
|
||||||
// https://github.com/openshift/origin/blob/master/pkg/util/httpproxy/upgradeawareproxy.go.
|
// https://github.com/openshift/origin/blob/master/pkg/util/httpproxy/upgradeawareproxy.go.
|
||||||
// That proxy needs to be modified to support multiple backends, not just 1.
|
// That proxy needs to be modified to support multiple backends, not just 1.
|
||||||
if r.tryUpgrade(w, req, newReq, location, roundTripper, gv, ctx) {
|
if r.tryUpgrade(ctx, w, req, newReq, location, roundTripper, gv) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ func (r *ProxyHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tryUpgrade returns true if the request was handled.
|
// tryUpgrade returns true if the request was handled.
|
||||||
func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Request, location *url.URL, transport http.RoundTripper, gv schema.GroupVersion, ctx request.Context) bool {
|
func (r *ProxyHandler) tryUpgrade(ctx request.Context, w http.ResponseWriter, req, newReq *http.Request, location *url.URL, transport http.RoundTripper, gv schema.GroupVersion) bool {
|
||||||
if !httpstream.IsUpgradeRequest(req) {
|
if !httpstream.IsUpgradeRequest(req) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ func (c completedConfig) New(delegationTarget DelegationTarget) (*GenericAPIServ
|
|||||||
|
|
||||||
healthzChecks: c.HealthzChecks,
|
healthzChecks: c.HealthzChecks,
|
||||||
|
|
||||||
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer),
|
DiscoveryGroupManager: discovery.NewRootAPIsHandler(c.DiscoveryAddresses, c.Serializer, c.RequestContextMapper),
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range delegationTarget.PostStartHooks() {
|
for k, v := range delegationTarget.PostStartHooks() {
|
||||||
|
@ -334,7 +334,7 @@ func (s *GenericAPIServer) InstallLegacyAPIGroup(apiPrefix string, apiGroupInfo
|
|||||||
}
|
}
|
||||||
// Install the version handler.
|
// Install the version handler.
|
||||||
// Add a handler at /<apiPrefix> to enumerate the supported api versions.
|
// Add a handler at /<apiPrefix> to enumerate the supported api versions.
|
||||||
s.Handler.GoRestfulContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions).WebService())
|
s.Handler.GoRestfulContainer.Add(discovery.NewLegacyRootAPIHandler(s.discoveryAddresses, s.Serializer, apiPrefix, apiVersions, s.requestContextMapper).WebService())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ func (s *GenericAPIServer) InstallAPIGroup(apiGroupInfo *APIGroupInfo) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.DiscoveryGroupManager.AddGroup(apiGroup)
|
s.DiscoveryGroupManager.AddGroup(apiGroup)
|
||||||
s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup).WebService())
|
s.Handler.GoRestfulContainer.Add(discovery.NewAPIGroupHandler(s.Serializer, apiGroup, s.requestContextMapper).WebService())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
rt "runtime"
|
rt "runtime"
|
||||||
@ -30,6 +31,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/server/mux"
|
"k8s.io/apiserver/pkg/server/mux"
|
||||||
genericmux "k8s.io/apiserver/pkg/server/mux"
|
genericmux "k8s.io/apiserver/pkg/server/mux"
|
||||||
)
|
)
|
||||||
@ -52,7 +54,7 @@ type APIServerHandler struct {
|
|||||||
// It is normally used to apply filtering like authentication and authorization
|
// It is normally used to apply filtering like authentication and authorization
|
||||||
type HandlerChainBuilderFn func(apiHandler http.Handler) http.Handler
|
type HandlerChainBuilderFn func(apiHandler http.Handler) http.Handler
|
||||||
|
|
||||||
func NewAPIServerHandler(s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
|
func NewAPIServerHandler(contextMapper request.RequestContextMapper, s runtime.NegotiatedSerializer, handlerChainBuilder HandlerChainBuilderFn, notFoundHandler http.Handler) *APIServerHandler {
|
||||||
postGoRestfulMux := genericmux.NewPathRecorderMux()
|
postGoRestfulMux := genericmux.NewPathRecorderMux()
|
||||||
if notFoundHandler != nil {
|
if notFoundHandler != nil {
|
||||||
postGoRestfulMux.NotFoundHandler(notFoundHandler)
|
postGoRestfulMux.NotFoundHandler(notFoundHandler)
|
||||||
@ -65,7 +67,11 @@ func NewAPIServerHandler(s runtime.NegotiatedSerializer, handlerChainBuilder Han
|
|||||||
logStackOnRecover(s, panicReason, httpWriter)
|
logStackOnRecover(s, panicReason, httpWriter)
|
||||||
})
|
})
|
||||||
gorestfulContainer.ServiceErrorHandler(func(serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) {
|
gorestfulContainer.ServiceErrorHandler(func(serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) {
|
||||||
serviceErrorHandler(s, serviceErr, request, response)
|
ctx, ok := contextMapper.Get(request.Request)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(response.ResponseWriter, request.Request, errors.New("no context found for request"))
|
||||||
|
}
|
||||||
|
serviceErrorHandler(ctx, s, serviceErr, request, response)
|
||||||
})
|
})
|
||||||
|
|
||||||
// register the defaultHandler for everything. This will allow an unhandled request to fall through to another handler instead of
|
// register the defaultHandler for everything. This will allow an unhandled request to fall through to another handler instead of
|
||||||
@ -109,12 +115,13 @@ func logStackOnRecover(s runtime.NegotiatedSerializer, panicReason interface{},
|
|||||||
if ct := w.Header().Get("Content-Type"); len(ct) > 0 {
|
if ct := w.Header().Get("Content-Type"); len(ct) > 0 {
|
||||||
headers.Set("Accept", ct)
|
headers.Set("Accept", ct)
|
||||||
}
|
}
|
||||||
responsewriters.ErrorNegotiated(nil, apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", schema.GroupResource{}, "", "", 0, false), s, schema.GroupVersion{}, w, &http.Request{Header: headers})
|
emptyContext := request.NewContext() // best we can do here: we don't know the request
|
||||||
|
responsewriters.ErrorNegotiated(emptyContext, apierrors.NewGenericServerResponse(http.StatusInternalServerError, "", schema.GroupResource{}, "", "", 0, false), s, schema.GroupVersion{}, w, &http.Request{Header: headers})
|
||||||
}
|
}
|
||||||
|
|
||||||
func serviceErrorHandler(s runtime.NegotiatedSerializer, serviceErr restful.ServiceError, request *restful.Request, resp *restful.Response) {
|
func serviceErrorHandler(ctx request.Context, s runtime.NegotiatedSerializer, serviceErr restful.ServiceError, request *restful.Request, resp *restful.Response) {
|
||||||
responsewriters.ErrorNegotiated(
|
responsewriters.ErrorNegotiated(
|
||||||
nil,
|
ctx,
|
||||||
apierrors.NewGenericServerResponse(serviceErr.Code, "", schema.GroupResource{}, "", serviceErr.Message, 0, false),
|
apierrors.NewGenericServerResponse(serviceErr.Code, "", schema.GroupResource{}, "", serviceErr.Message, 0, false),
|
||||||
s,
|
s,
|
||||||
schema.GroupVersion{},
|
schema.GroupVersion{},
|
||||||
|
@ -172,6 +172,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg
|
|||||||
apisHandler := &apisHandler{
|
apisHandler := &apisHandler{
|
||||||
codecs: Codecs,
|
codecs: Codecs,
|
||||||
lister: s.lister,
|
lister: s.lister,
|
||||||
|
mapper: s.contextMapper,
|
||||||
}
|
}
|
||||||
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", apisHandler)
|
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", apisHandler)
|
||||||
s.GenericAPIServer.Handler.PostGoRestfulMux.UnlistedHandle("/apis/", apisHandler)
|
s.GenericAPIServer.Handler.PostGoRestfulMux.UnlistedHandle("/apis/", apisHandler)
|
||||||
@ -246,6 +247,7 @@ func (s *APIAggregator) AddAPIService(apiService *apiregistration.APIService, de
|
|||||||
groupName: apiService.Spec.Group,
|
groupName: apiService.Spec.Group,
|
||||||
lister: s.lister,
|
lister: s.lister,
|
||||||
delegate: s.delegateHandler,
|
delegate: s.delegateHandler,
|
||||||
|
contextMapper: s.contextMapper,
|
||||||
}
|
}
|
||||||
// aggregation is protected
|
// aggregation is protected
|
||||||
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
|
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle(groupPath, groupDiscoveryHandler)
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package apiserver
|
package apiserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -25,6 +26,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
|
|
||||||
apiregistrationapi "k8s.io/kube-aggregator/pkg/apis/apiregistration"
|
apiregistrationapi "k8s.io/kube-aggregator/pkg/apis/apiregistration"
|
||||||
apiregistrationv1beta1api "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
apiregistrationv1beta1api "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||||
@ -36,6 +38,7 @@ import (
|
|||||||
type apisHandler struct {
|
type apisHandler struct {
|
||||||
codecs serializer.CodecFactory
|
codecs serializer.CodecFactory
|
||||||
lister listers.APIServiceLister
|
lister listers.APIServiceLister
|
||||||
|
mapper request.RequestContextMapper
|
||||||
}
|
}
|
||||||
|
|
||||||
var discoveryGroup = metav1.APIGroup{
|
var discoveryGroup = metav1.APIGroup{
|
||||||
@ -53,6 +56,12 @@ var discoveryGroup = metav1.APIGroup{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ctx, ok := r.mapper.Get(req)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(w, req, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
discoveryGroupList := &metav1.APIGroupList{
|
discoveryGroupList := &metav1.APIGroupList{
|
||||||
// always add OUR api group to the list first. Since we'll never have a registered APIService for it
|
// always add OUR api group to the list first. Since we'll never have a registered APIService for it
|
||||||
// and since this is the crux of the API, having this first will give our names priority. It's good to be king.
|
// and since this is the crux of the API, having this first will give our names priority. It's good to be king.
|
||||||
@ -76,7 +85,7 @@ func (r *apisHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
responsewriters.WriteObjectNegotiated(nil, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList)
|
responsewriters.WriteObjectNegotiated(ctx, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroupList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// convertToDiscoveryAPIGroup takes apiservices in a single group and returns a discovery compatible object.
|
// convertToDiscoveryAPIGroup takes apiservices in a single group and returns a discovery compatible object.
|
||||||
@ -117,6 +126,7 @@ func convertToDiscoveryAPIGroup(apiServices []*apiregistrationapi.APIService) *m
|
|||||||
type apiGroupHandler struct {
|
type apiGroupHandler struct {
|
||||||
codecs serializer.CodecFactory
|
codecs serializer.CodecFactory
|
||||||
groupName string
|
groupName string
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
|
|
||||||
lister listers.APIServiceLister
|
lister listers.APIServiceLister
|
||||||
|
|
||||||
@ -124,6 +134,12 @@ type apiGroupHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ctx, ok := r.contextMapper.Get(req)
|
||||||
|
if !ok {
|
||||||
|
responsewriters.InternalError(w, req, errors.New("no context found for request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
apiServices, err := r.lister.List(labels.Everything())
|
apiServices, err := r.lister.List(labels.Everything())
|
||||||
if statusErr, ok := err.(*apierrors.StatusError); ok && err != nil {
|
if statusErr, ok := err.(*apierrors.StatusError); ok && err != nil {
|
||||||
responsewriters.WriteRawJSON(int(statusErr.Status().Code), statusErr.Status(), w)
|
responsewriters.WriteRawJSON(int(statusErr.Status().Code), statusErr.Status(), w)
|
||||||
@ -151,5 +167,5 @@ func (r *apiGroupHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
http.Error(w, "", http.StatusNotFound)
|
http.Error(w, "", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
responsewriters.WriteObjectNegotiated(nil, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup)
|
responsewriters.WriteObjectNegotiated(ctx, r.codecs, schema.GroupVersion{}, w, req, http.StatusOK, discoveryGroup)
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
"k8s.io/kube-aggregator/pkg/apis/apiregistration"
|
"k8s.io/kube-aggregator/pkg/apis/apiregistration"
|
||||||
@ -236,16 +237,18 @@ func TestAPIs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
mapper := request.NewRequestContextMapper()
|
||||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||||
handler := &apisHandler{
|
handler := &apisHandler{
|
||||||
codecs: Codecs,
|
codecs: Codecs,
|
||||||
lister: listers.NewAPIServiceLister(indexer),
|
lister: listers.NewAPIServiceLister(indexer),
|
||||||
|
mapper: mapper,
|
||||||
}
|
}
|
||||||
for _, o := range tc.apiservices {
|
for _, o := range tc.apiservices {
|
||||||
indexer.Add(o)
|
indexer.Add(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(request.WithRequestContext(handler, mapper))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
resp, err := http.Get(server.URL + "/apis")
|
resp, err := http.Get(server.URL + "/apis")
|
||||||
@ -272,6 +275,7 @@ func TestAPIs(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIGroupMissing(t *testing.T) {
|
func TestAPIGroupMissing(t *testing.T) {
|
||||||
|
mapper := request.NewRequestContextMapper()
|
||||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||||
handler := &apiGroupHandler{
|
handler := &apiGroupHandler{
|
||||||
codecs: Codecs,
|
codecs: Codecs,
|
||||||
@ -280,9 +284,10 @@ func TestAPIGroupMissing(t *testing.T) {
|
|||||||
delegate: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
delegate: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
}),
|
}),
|
||||||
|
contextMapper: mapper,
|
||||||
}
|
}
|
||||||
|
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(request.WithRequestContext(handler, mapper))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
// this call should delegate
|
// this call should delegate
|
||||||
@ -415,17 +420,19 @@ func TestAPIGroup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
mapper := request.NewRequestContextMapper()
|
||||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||||
handler := &apiGroupHandler{
|
handler := &apiGroupHandler{
|
||||||
codecs: Codecs,
|
codecs: Codecs,
|
||||||
lister: listers.NewAPIServiceLister(indexer),
|
lister: listers.NewAPIServiceLister(indexer),
|
||||||
groupName: "foo",
|
groupName: "foo",
|
||||||
|
contextMapper: mapper,
|
||||||
}
|
}
|
||||||
for _, o := range tc.apiservices {
|
for _, o := range tc.apiservices {
|
||||||
indexer.Add(o)
|
indexer.Add(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
server := httptest.NewServer(handler)
|
server := httptest.NewServer(request.WithRequestContext(handler, mapper))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
resp, err := http.Get(server.URL + "/apis/" + tc.group)
|
resp, err := http.Get(server.URL + "/apis/" + tc.group)
|
||||||
|
@ -160,7 +160,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
|
|||||||
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", crdHandler)
|
s.GenericAPIServer.Handler.PostGoRestfulMux.Handle("/apis", crdHandler)
|
||||||
s.GenericAPIServer.Handler.PostGoRestfulMux.HandlePrefix("/apis/", crdHandler)
|
s.GenericAPIServer.Handler.PostGoRestfulMux.HandlePrefix("/apis/", crdHandler)
|
||||||
|
|
||||||
crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler)
|
crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler, c.GenericConfig.RequestContextMapper)
|
||||||
namingController := status.NewNamingConditionController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient)
|
namingController := status.NewNamingConditionController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient)
|
||||||
finalizingController := finalizer.NewCRDFinalizer(
|
finalizingController := finalizer.NewCRDFinalizer(
|
||||||
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
|
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
"k8s.io/client-go/util/workqueue"
|
"k8s.io/client-go/util/workqueue"
|
||||||
|
|
||||||
@ -39,6 +40,7 @@ import (
|
|||||||
type DiscoveryController struct {
|
type DiscoveryController struct {
|
||||||
versionHandler *versionDiscoveryHandler
|
versionHandler *versionDiscoveryHandler
|
||||||
groupHandler *groupDiscoveryHandler
|
groupHandler *groupDiscoveryHandler
|
||||||
|
contextMapper request.RequestContextMapper
|
||||||
|
|
||||||
crdLister listers.CustomResourceDefinitionLister
|
crdLister listers.CustomResourceDefinitionLister
|
||||||
crdsSynced cache.InformerSynced
|
crdsSynced cache.InformerSynced
|
||||||
@ -49,12 +51,13 @@ type DiscoveryController struct {
|
|||||||
queue workqueue.RateLimitingInterface
|
queue workqueue.RateLimitingInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler) *DiscoveryController {
|
func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler, contextMapper request.RequestContextMapper) *DiscoveryController {
|
||||||
c := &DiscoveryController{
|
c := &DiscoveryController{
|
||||||
versionHandler: versionHandler,
|
versionHandler: versionHandler,
|
||||||
groupHandler: groupHandler,
|
groupHandler: groupHandler,
|
||||||
crdLister: crdInformer.Lister(),
|
crdLister: crdInformer.Lister(),
|
||||||
crdsSynced: crdInformer.Informer().HasSynced,
|
crdsSynced: crdInformer.Informer().HasSynced,
|
||||||
|
contextMapper: contextMapper,
|
||||||
|
|
||||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DiscoveryController"),
|
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DiscoveryController"),
|
||||||
}
|
}
|
||||||
@ -129,7 +132,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
// the preferred versions for a group is arbitrary since there cannot be duplicate resources
|
// the preferred versions for a group is arbitrary since there cannot be duplicate resources
|
||||||
PreferredVersion: apiVersionsForDiscovery[0],
|
PreferredVersion: apiVersionsForDiscovery[0],
|
||||||
}
|
}
|
||||||
c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup))
|
c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup, c.contextMapper))
|
||||||
|
|
||||||
if !foundVersion {
|
if !foundVersion {
|
||||||
c.versionHandler.unsetDiscovery(version)
|
c.versionHandler.unsetDiscovery(version)
|
||||||
@ -137,7 +140,7 @@ func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
|||||||
}
|
}
|
||||||
c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource {
|
c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource {
|
||||||
return apiResourcesForDiscovery
|
return apiResourcesForDiscovery
|
||||||
})))
|
}), c.contextMapper))
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user