mirror of
https://github.com/niusmallnan/steve.git
synced 2025-06-28 15:36:54 +00:00
Add namespace filtering
This commit is contained in:
parent
ae42b9422b
commit
6b6ff53373
@ -14,11 +14,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
impersonate bool
|
impersonate bool
|
||||||
clientCfg *rest.Config
|
tableClientCfg *rest.Config
|
||||||
watchClientCfg *rest.Config
|
tableWatchClientCfg *rest.Config
|
||||||
metadata metadata.Interface
|
clientCfg *rest.Config
|
||||||
Config *rest.Config
|
watchClientCfg *rest.Config
|
||||||
|
metadata metadata.Interface
|
||||||
|
Config *rest.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
type addQuery struct {
|
type addQuery struct {
|
||||||
@ -41,17 +43,23 @@ func NewFactory(cfg *rest.Config, impersonate bool) (*Factory, error) {
|
|||||||
clientCfg.QPS = 10000
|
clientCfg.QPS = 10000
|
||||||
clientCfg.Burst = 100
|
clientCfg.Burst = 100
|
||||||
clientCfg.AcceptContentTypes = "application/json;as=Table;v=v1;g=meta.k8s.io"
|
clientCfg.AcceptContentTypes = "application/json;as=Table;v=v1;g=meta.k8s.io"
|
||||||
clientCfg.Wrap(func(rt http.RoundTripper) http.RoundTripper {
|
|
||||||
|
watchClientCfg := rest.CopyConfig(clientCfg)
|
||||||
|
watchClientCfg.Timeout = 30 * time.Minute
|
||||||
|
|
||||||
|
setTable := func(rt http.RoundTripper) http.RoundTripper {
|
||||||
return &addQuery{
|
return &addQuery{
|
||||||
values: map[string]string{
|
values: map[string]string{
|
||||||
"includeObject": "Object",
|
"includeObject": "Object",
|
||||||
},
|
},
|
||||||
next: rt,
|
next: rt,
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
watchClientCfg := rest.CopyConfig(clientCfg)
|
tableClientCfg := rest.CopyConfig(clientCfg)
|
||||||
watchClientCfg.Timeout = 30 * time.Minute
|
tableClientCfg.Wrap(setTable)
|
||||||
|
tableWatchClientCfg := rest.CopyConfig(watchClientCfg)
|
||||||
|
tableWatchClientCfg.Wrap(setTable)
|
||||||
|
|
||||||
md, err := metadata.NewForConfig(cfg)
|
md, err := metadata.NewForConfig(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,11 +67,13 @@ func NewFactory(cfg *rest.Config, impersonate bool) (*Factory, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Factory{
|
return &Factory{
|
||||||
metadata: md,
|
metadata: md,
|
||||||
impersonate: impersonate,
|
impersonate: impersonate,
|
||||||
clientCfg: clientCfg,
|
tableClientCfg: tableClientCfg,
|
||||||
watchClientCfg: watchClientCfg,
|
tableWatchClientCfg: tableWatchClientCfg,
|
||||||
Config: watchClientCfg,
|
clientCfg: clientCfg,
|
||||||
|
watchClientCfg: watchClientCfg,
|
||||||
|
Config: watchClientCfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,12 +89,20 @@ func (p *Factory) AdminClient(ctx *types.APIRequest, s *types.APISchema, namespa
|
|||||||
return newClient(ctx, p.clientCfg, s, namespace, false)
|
return newClient(ctx, p.clientCfg, s, namespace, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Factory) ClientForWatch(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
func (p *Factory) TableClient(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
||||||
return newClient(ctx, p.watchClientCfg, s, namespace, p.impersonate)
|
return newClient(ctx, p.tableClientCfg, s, namespace, p.impersonate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Factory) AdminClientForWatch(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
func (p *Factory) TableAdminClient(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
||||||
return newClient(ctx, p.watchClientCfg, s, namespace, false)
|
return newClient(ctx, p.tableClientCfg, s, namespace, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Factory) TableClientForWatch(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
||||||
|
return newClient(ctx, p.tableWatchClientCfg, s, namespace, p.impersonate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Factory) TableAdminClientForWatch(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
||||||
|
return newClient(ctx, p.tableWatchClientCfg, s, namespace, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClient(ctx *types.APIRequest, cfg *rest.Config, s *types.APISchema, namespace string, impersonate bool) (dynamic.ResourceInterface, error) {
|
func newClient(ctx *types.APIRequest, cfg *rest.Config, s *types.APISchema, namespace string, impersonate bool) (dynamic.ResourceInterface, error) {
|
||||||
|
@ -2,17 +2,20 @@ package schema
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/rancher/steve/pkg/accesscontrol"
|
"github.com/rancher/steve/pkg/accesscontrol"
|
||||||
"github.com/rancher/steve/pkg/attributes"
|
"github.com/rancher/steve/pkg/attributes"
|
||||||
|
"github.com/rancher/steve/pkg/schemaserver/server"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
"github.com/rancher/wrangler/pkg/name"
|
"github.com/rancher/wrangler/pkg/name"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/cache"
|
"k8s.io/apimachinery/pkg/util/cache"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
|
"k8s.io/apiserver/pkg/endpoints/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Factory interface {
|
type Factory interface {
|
||||||
@ -47,6 +50,28 @@ type Template struct {
|
|||||||
StoreFactory func(types.Store) types.Store
|
StoreFactory func(types.Store) types.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WrapServer(factory Factory, server *server.Server) http.Handler {
|
||||||
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||||
|
user, ok := request.UserFrom(req.Context())
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
schemas, err := factory.Schemas(user)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("failed to lookup schemas for user %v: %v", user, err)
|
||||||
|
http.Error(rw, "schemas failed", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
server.Handle(&types.APIRequest{
|
||||||
|
Request: req,
|
||||||
|
Response: rw,
|
||||||
|
Schemas: schemas,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func NewCollection(ctx context.Context, baseSchema *types.APISchemas, access accesscontrol.AccessSetLookup) *Collection {
|
func NewCollection(ctx context.Context, baseSchema *types.APISchemas, access accesscontrol.AccessSetLookup) *Collection {
|
||||||
return &Collection{
|
return &Collection{
|
||||||
baseSchema: baseSchema,
|
baseSchema: baseSchema,
|
||||||
|
@ -7,16 +7,53 @@ import (
|
|||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Vars struct {
|
||||||
|
Type string
|
||||||
|
Name string
|
||||||
|
Namespace string
|
||||||
|
Link string
|
||||||
|
Prefix string
|
||||||
|
Action string
|
||||||
|
}
|
||||||
|
|
||||||
|
func Set(v Vars) mux.MatcherFunc {
|
||||||
|
return func(request *http.Request, match *mux.RouteMatch) bool {
|
||||||
|
if match.Vars == nil {
|
||||||
|
match.Vars = map[string]string{}
|
||||||
|
}
|
||||||
|
if v.Type != "" {
|
||||||
|
match.Vars["type"] = v.Type
|
||||||
|
}
|
||||||
|
if v.Name != "" {
|
||||||
|
match.Vars["name"] = v.Name
|
||||||
|
}
|
||||||
|
if v.Link != "" {
|
||||||
|
match.Vars["link"] = v.Link
|
||||||
|
}
|
||||||
|
if v.Prefix != "" {
|
||||||
|
match.Vars["prefix"] = v.Prefix
|
||||||
|
}
|
||||||
|
if v.Action != "" {
|
||||||
|
match.Vars["action"] = v.Action
|
||||||
|
}
|
||||||
|
if v.Namespace != "" {
|
||||||
|
match.Vars["namespace"] = v.Namespace
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func MuxURLParser(rw http.ResponseWriter, req *http.Request, schemas *types.APISchemas) (ParsedURL, error) {
|
func MuxURLParser(rw http.ResponseWriter, req *http.Request, schemas *types.APISchemas) (ParsedURL, error) {
|
||||||
vars := mux.Vars(req)
|
vars := mux.Vars(req)
|
||||||
url := ParsedURL{
|
url := ParsedURL{
|
||||||
Type: vars["type"],
|
Type: vars["type"],
|
||||||
Name: vars["name"],
|
Name: vars["name"],
|
||||||
Link: vars["link"],
|
Namespace: vars["namespace"],
|
||||||
Prefix: vars["prefix"],
|
Link: vars["link"],
|
||||||
Method: req.Method,
|
Prefix: vars["prefix"],
|
||||||
Action: vars["action"],
|
Method: req.Method,
|
||||||
Query: req.URL.Query(),
|
Action: vars["action"],
|
||||||
|
Query: req.URL.Query(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return url, nil
|
return url, nil
|
||||||
|
@ -24,6 +24,7 @@ var (
|
|||||||
type ParsedURL struct {
|
type ParsedURL struct {
|
||||||
Type string
|
Type string
|
||||||
Name string
|
Name string
|
||||||
|
Namespace string
|
||||||
Link string
|
Link string
|
||||||
Method string
|
Method string
|
||||||
Action string
|
Action string
|
||||||
@ -80,6 +81,9 @@ func Parse(apiOp *types.APIRequest, urlParser URLParser) error {
|
|||||||
if apiOp.URLPrefix == "" {
|
if apiOp.URLPrefix == "" {
|
||||||
apiOp.URLPrefix = parsedURL.Prefix
|
apiOp.URLPrefix = parsedURL.Prefix
|
||||||
}
|
}
|
||||||
|
if apiOp.Namespace == "" {
|
||||||
|
apiOp.Namespace = parsedURL.Namespace
|
||||||
|
}
|
||||||
|
|
||||||
if apiOp.URLBuilder == nil {
|
if apiOp.URLBuilder == nil {
|
||||||
// make error local to not override the outer error we have yet to check
|
// make error local to not override the outer error we have yet to check
|
||||||
|
@ -6,9 +6,9 @@ import (
|
|||||||
"github.com/rancher/steve/pkg/schemaserver/builtin"
|
"github.com/rancher/steve/pkg/schemaserver/builtin"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/handlers"
|
"github.com/rancher/steve/pkg/schemaserver/handlers"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/parse"
|
"github.com/rancher/steve/pkg/schemaserver/parse"
|
||||||
|
"github.com/rancher/steve/pkg/schemaserver/subscribe"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/writer"
|
"github.com/rancher/steve/pkg/schemaserver/writer"
|
||||||
"github.com/rancher/wrangler/pkg/merr"
|
|
||||||
"github.com/rancher/wrangler/pkg/schemas/validation"
|
"github.com/rancher/wrangler/pkg/schemas/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +34,6 @@ type Defaults struct {
|
|||||||
CreateHandler types.RequestHandler
|
CreateHandler types.RequestHandler
|
||||||
DeleteHandler types.RequestHandler
|
DeleteHandler types.RequestHandler
|
||||||
UpdateHandler types.RequestHandler
|
UpdateHandler types.RequestHandler
|
||||||
Store types.Store
|
|
||||||
ErrorHandler types.ErrorHandler
|
ErrorHandler types.ErrorHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +69,7 @@ func DefaultAPIServer() *Server {
|
|||||||
URLParser: parse.MuxURLParser,
|
URLParser: parse.MuxURLParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subscribe.Register(s.Schemas)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,57 +88,6 @@ func (s *Server) setDefaults(ctx *types.APIRequest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) AddSchemas(schemas *types.APISchemas) error {
|
|
||||||
var errs []error
|
|
||||||
|
|
||||||
for _, schema := range schemas.Schemas {
|
|
||||||
if err := s.addSchema(*schema); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return merr.NewErrors(errs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) addSchema(schema types.APISchema) error {
|
|
||||||
s.setupDefaults(&schema)
|
|
||||||
return s.Schemas.AddSchema(schema)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) setupDefaults(schema *types.APISchema) {
|
|
||||||
if schema.Store == nil {
|
|
||||||
schema.Store = s.Defaults.Store
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.ListHandler == nil {
|
|
||||||
schema.ListHandler = s.Defaults.ListHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.CreateHandler == nil {
|
|
||||||
schema.CreateHandler = s.Defaults.CreateHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.ByIDHandler == nil {
|
|
||||||
schema.ByIDHandler = s.Defaults.ByIDHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.UpdateHandler == nil {
|
|
||||||
schema.UpdateHandler = s.Defaults.UpdateHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.DeleteHandler == nil {
|
|
||||||
schema.DeleteHandler = s.Defaults.DeleteHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
if schema.ErrorHandler == nil {
|
|
||||||
schema.ErrorHandler = s.Defaults.ErrorHandler
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) GetSchemas() *types.APISchemas {
|
|
||||||
return s.Schemas
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
func (s *Server) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||||
s.Handle(&types.APIRequest{
|
s.Handle(&types.APIRequest{
|
||||||
Request: req,
|
Request: req,
|
||||||
|
@ -29,16 +29,30 @@ func (a *APISchemas) MustAddSchema(obj APISchema) *APISchemas {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *APISchemas) MustImportAndCustomize(obj interface{}, f func(*APISchema)) {
|
func (a *APISchemas) addInternalSchema(schema *schemas.Schema) *APISchema {
|
||||||
schema, err := a.InternalSchemas.Import(obj)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
apiSchema := &APISchema{
|
apiSchema := &APISchema{
|
||||||
Schema: schema,
|
Schema: schema,
|
||||||
}
|
}
|
||||||
a.Schemas[schema.ID] = apiSchema
|
a.Schemas[schema.ID] = apiSchema
|
||||||
a.addToIndex(apiSchema)
|
a.addToIndex(apiSchema)
|
||||||
|
|
||||||
|
for _, f := range schema.ResourceFields {
|
||||||
|
if subType := a.InternalSchemas.Schema(f.Type); subType == nil {
|
||||||
|
continue
|
||||||
|
} else if _, ok := a.Schemas[subType.ID]; !ok {
|
||||||
|
a.addInternalSchema(subType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *APISchemas) MustImportAndCustomize(obj interface{}, f func(*APISchema)) {
|
||||||
|
schema, err := a.InternalSchemas.Import(obj)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
apiSchema := a.addInternalSchema(schema)
|
||||||
f(apiSchema)
|
f(apiSchema)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/rancher/steve/pkg/accesscontrol"
|
"github.com/rancher/steve/pkg/accesscontrol"
|
||||||
"github.com/rancher/steve/pkg/auth"
|
"github.com/rancher/steve/pkg/auth"
|
||||||
|
"github.com/rancher/steve/pkg/client"
|
||||||
"github.com/rancher/steve/pkg/schema"
|
"github.com/rancher/steve/pkg/schema"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
"github.com/rancher/steve/pkg/server/router"
|
"github.com/rancher/steve/pkg/server/router"
|
||||||
@ -29,6 +30,7 @@ type Server struct {
|
|||||||
|
|
||||||
RestConfig *rest.Config
|
RestConfig *rest.Config
|
||||||
|
|
||||||
|
ClientFactory *client.Factory
|
||||||
BaseSchemas *types.APISchemas
|
BaseSchemas *types.APISchemas
|
||||||
AccessSetLookup accesscontrol.AccessSetLookup
|
AccessSetLookup accesscontrol.AccessSetLookup
|
||||||
SchemaTemplates []schema.Template
|
SchemaTemplates []schema.Template
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/rancher/steve/pkg/clustercache"
|
"github.com/rancher/steve/pkg/clustercache"
|
||||||
"github.com/rancher/steve/pkg/schema"
|
"github.com/rancher/steve/pkg/schema"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/store/apiroot"
|
"github.com/rancher/steve/pkg/schemaserver/store/apiroot"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/subscribe"
|
|
||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
"github.com/rancher/steve/pkg/server/resources/apigroups"
|
"github.com/rancher/steve/pkg/server/resources/apigroups"
|
||||||
"github.com/rancher/steve/pkg/server/resources/common"
|
"github.com/rancher/steve/pkg/server/resources/common"
|
||||||
@ -16,7 +15,6 @@ import (
|
|||||||
|
|
||||||
func DefaultSchemas(baseSchema *types.APISchemas, discovery discovery.DiscoveryInterface, ccache clustercache.ClusterCache) *types.APISchemas {
|
func DefaultSchemas(baseSchema *types.APISchemas, discovery discovery.DiscoveryInterface, ccache clustercache.ClusterCache) *types.APISchemas {
|
||||||
counts.Register(baseSchema, ccache)
|
counts.Register(baseSchema, ccache)
|
||||||
subscribe.Register(baseSchema)
|
|
||||||
apigroups.Register(baseSchema, discovery)
|
apigroups.Register(baseSchema, discovery)
|
||||||
apiroot.Register(baseSchema, []string{"v1"}, []string{"proxy:/apis"})
|
apiroot.Register(baseSchema, []string{"v1"}, []string{"proxy:/apis"})
|
||||||
return baseSchema
|
return baseSchema
|
||||||
|
@ -45,13 +45,18 @@ func setDefaults(server *Server) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setup(ctx context.Context, server *Server) (http.Handler, *schema.Collection, error) {
|
func setup(ctx context.Context, server *Server) (http.Handler, *schema.Collection, error) {
|
||||||
if err := setDefaults(server); err != nil {
|
err := setDefaults(server)
|
||||||
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cf, err := client.NewFactory(server.RestConfig, server.AuthMiddleware != nil)
|
cf := server.ClientFactory
|
||||||
if err != nil {
|
if cf == nil {
|
||||||
return nil, nil, err
|
cf, err = client.NewFactory(server.RestConfig, server.AuthMiddleware != nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
server.ClientFactory = cf
|
||||||
}
|
}
|
||||||
|
|
||||||
asl := server.AccessSetLookup
|
asl := server.AccessSetLookup
|
||||||
|
@ -32,8 +32,10 @@ var (
|
|||||||
type ClientGetter interface {
|
type ClientGetter interface {
|
||||||
Client(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
Client(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
AdminClient(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
AdminClient(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
ClientForWatch(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
TableClient(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
AdminClientForWatch(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
TableAdminClient(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
|
TableClientForWatch(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
|
TableAdminClientForWatch(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
@ -92,7 +94,7 @@ func toAPI(schema *types.APISchema, obj runtime.Object) types.APIObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) byID(apiOp *types.APIRequest, schema *types.APISchema, id string) (*unstructured.Unstructured, error) {
|
func (s *Store) byID(apiOp *types.APIRequest, schema *types.APISchema, id string) (*unstructured.Unstructured, error) {
|
||||||
k8sClient, err := s.clientGetter.Client(apiOp, schema, apiOp.Namespace)
|
k8sClient, err := s.clientGetter.TableClient(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -184,7 +186,7 @@ func tableToObjects(obj map[string]interface{}) []unstructured.Unstructured {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) ByNames(apiOp *types.APIRequest, schema *types.APISchema, names sets.String) (types.APIObjectList, error) {
|
func (s *Store) ByNames(apiOp *types.APIRequest, schema *types.APISchema, names sets.String) (types.APIObjectList, error) {
|
||||||
adminClient, err := s.clientGetter.AdminClient(apiOp, schema, apiOp.Namespace)
|
adminClient, err := s.clientGetter.TableAdminClient(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.APIObjectList{}, err
|
return types.APIObjectList{}, err
|
||||||
}
|
}
|
||||||
@ -206,7 +208,7 @@ func (s *Store) ByNames(apiOp *types.APIRequest, schema *types.APISchema, names
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
|
func (s *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
|
||||||
client, err := s.clientGetter.Client(apiOp, schema, apiOp.Namespace)
|
client, err := s.clientGetter.TableClient(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.APIObjectList{}, err
|
return types.APIObjectList{}, err
|
||||||
}
|
}
|
||||||
@ -287,7 +289,7 @@ func (s *Store) listAndWatch(apiOp *types.APIRequest, k8sClient dynamic.Resource
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) WatchNames(apiOp *types.APIRequest, schema *types.APISchema, w types.WatchRequest, names sets.String) (chan types.APIEvent, error) {
|
func (s *Store) WatchNames(apiOp *types.APIRequest, schema *types.APISchema, w types.WatchRequest, names sets.String) (chan types.APIEvent, error) {
|
||||||
adminClient, err := s.clientGetter.ClientForWatch(apiOp, schema, apiOp.Namespace)
|
adminClient, err := s.clientGetter.TableClientForWatch(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -310,7 +312,7 @@ func (s *Store) WatchNames(apiOp *types.APIRequest, schema *types.APISchema, w t
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Watch(apiOp *types.APIRequest, schema *types.APISchema, w types.WatchRequest) (chan types.APIEvent, error) {
|
func (s *Store) Watch(apiOp *types.APIRequest, schema *types.APISchema, w types.WatchRequest) (chan types.APIEvent, error) {
|
||||||
client, err := s.clientGetter.ClientForWatch(apiOp, schema, apiOp.Namespace)
|
client, err := s.clientGetter.TableClientForWatch(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -374,7 +376,7 @@ func (s *Store) Create(apiOp *types.APIRequest, schema *types.APISchema, params
|
|||||||
gvk := attributes.GVK(schema)
|
gvk := attributes.GVK(schema)
|
||||||
input["apiVersion"], input["kind"] = gvk.ToAPIVersionAndKind()
|
input["apiVersion"], input["kind"] = gvk.ToAPIVersionAndKind()
|
||||||
|
|
||||||
k8sClient, err := s.clientGetter.Client(apiOp, schema, ns)
|
k8sClient, err := s.clientGetter.TableClient(apiOp, schema, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.APIObject{}, err
|
return types.APIObject{}, err
|
||||||
}
|
}
|
||||||
@ -395,7 +397,7 @@ func (s *Store) Update(apiOp *types.APIRequest, schema *types.APISchema, params
|
|||||||
)
|
)
|
||||||
|
|
||||||
ns := types.Namespace(input)
|
ns := types.Namespace(input)
|
||||||
k8sClient, err := s.clientGetter.Client(apiOp, schema, ns)
|
k8sClient, err := s.clientGetter.TableClient(apiOp, schema, ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.APIObject{}, err
|
return types.APIObject{}, err
|
||||||
}
|
}
|
||||||
@ -460,7 +462,7 @@ func (s *Store) Delete(apiOp *types.APIRequest, schema *types.APISchema, id stri
|
|||||||
return types.APIObject{}, nil
|
return types.APIObject{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
k8sClient, err := s.clientGetter.Client(apiOp, schema, apiOp.Namespace)
|
k8sClient, err := s.clientGetter.TableClient(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.APIObject{}, err
|
return types.APIObject{}, err
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,19 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type filterKey struct{}
|
||||||
|
|
||||||
|
func AddNamespaceConstraint(req *http.Request, names ...string) *http.Request {
|
||||||
|
set := sets.NewString(names...)
|
||||||
|
ctx := context.WithValue(req.Context(), filterKey{}, set)
|
||||||
|
return req.WithContext(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNamespaceConstraint(req *http.Request) (sets.String, bool) {
|
||||||
|
set, ok := req.Context().Value(filterKey{}).(sets.String)
|
||||||
|
return set, ok
|
||||||
|
}
|
||||||
|
|
||||||
type RBACStore struct {
|
type RBACStore struct {
|
||||||
*Store
|
*Store
|
||||||
}
|
}
|
||||||
@ -24,6 +37,34 @@ type Partition struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isPassthrough(apiOp *types.APIRequest, schema *types.APISchema, verb string) ([]Partition, bool) {
|
func isPassthrough(apiOp *types.APIRequest, schema *types.APISchema, verb string) ([]Partition, bool) {
|
||||||
|
partitions, passthrough := isPassthroughUnconstrained(apiOp, schema, verb)
|
||||||
|
namespaces, ok := getNamespaceConstraint(apiOp.Request)
|
||||||
|
if !ok {
|
||||||
|
return partitions, passthrough
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []Partition
|
||||||
|
|
||||||
|
if passthrough {
|
||||||
|
for namespace := range namespaces {
|
||||||
|
result = append(result, Partition{
|
||||||
|
Namespace: namespace,
|
||||||
|
All: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result, false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, partition := range partitions {
|
||||||
|
if namespaces.Has(partition.Namespace) {
|
||||||
|
result = append(result, partition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func isPassthroughUnconstrained(apiOp *types.APIRequest, schema *types.APISchema, verb string) ([]Partition, bool) {
|
||||||
accessListByVerb, _ := attributes.Access(schema).(accesscontrol.AccessListByVerb)
|
accessListByVerb, _ := attributes.Access(schema).(accesscontrol.AccessListByVerb)
|
||||||
if accessListByVerb.All(verb) {
|
if accessListByVerb.All(verb) {
|
||||||
return nil, true
|
return nil, true
|
||||||
|
Loading…
Reference in New Issue
Block a user