mirror of
https://github.com/niusmallnan/steve.git
synced 2025-09-10 09:30:01 +00:00
Manager timeouts and ratelimit
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/rancher/steve/pkg/attributes"
|
"github.com/rancher/steve/pkg/attributes"
|
||||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
@@ -9,6 +11,7 @@ import (
|
|||||||
|
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
client dynamic.Interface
|
client dynamic.Interface
|
||||||
|
watchClient dynamic.Interface
|
||||||
Config *rest.Config
|
Config *rest.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,8 +23,16 @@ func NewFactory(cfg *rest.Config) (*Factory, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newCfg = rest.CopyConfig(cfg)
|
||||||
|
newCfg.Timeout = 30 * time.Minute
|
||||||
|
wc, err := dynamic.NewForConfig(newCfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return &Factory{
|
return &Factory{
|
||||||
client: c,
|
client: c,
|
||||||
|
watchClient: wc,
|
||||||
Config: newCfg,
|
Config: newCfg,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -34,3 +45,8 @@ func (p *Factory) Client(ctx *types.APIRequest, s *types.APISchema, namespace st
|
|||||||
gvr := attributes.GVR(s)
|
gvr := attributes.GVR(s)
|
||||||
return p.client.Resource(gvr).Namespace(namespace), nil
|
return p.client.Resource(gvr).Namespace(namespace), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Factory) ClientForWatch(ctx *types.APIRequest, s *types.APISchema, namespace string) (dynamic.ResourceInterface, error) {
|
||||||
|
gvr := attributes.GVR(s)
|
||||||
|
return p.watchClient.Resource(gvr).Namespace(namespace), nil
|
||||||
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/rancher/steve/pkg/auth"
|
"github.com/rancher/steve/pkg/auth"
|
||||||
"github.com/rancher/steve/pkg/schema"
|
"github.com/rancher/steve/pkg/schema"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
corev1 "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1"
|
corev1 "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1"
|
||||||
"github.com/rancher/wrangler-api/pkg/generated/controllers/rbac"
|
"github.com/rancher/wrangler-api/pkg/generated/controllers/rbac"
|
||||||
rbacv1 "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1"
|
rbacv1 "github.com/rancher/wrangler-api/pkg/generated/controllers/rbac/v1"
|
||||||
|
"github.com/rancher/wrangler/pkg/ratelimit"
|
||||||
"github.com/rancher/wrangler/pkg/start"
|
"github.com/rancher/wrangler/pkg/start"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
@@ -37,6 +39,7 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Controllers struct {
|
type Controllers struct {
|
||||||
|
RestConfig *rest.Config
|
||||||
K8s kubernetes.Interface
|
K8s kubernetes.Interface
|
||||||
Core corev1.Interface
|
Core corev1.Interface
|
||||||
RBAC rbacv1.Interface
|
RBAC rbacv1.Interface
|
||||||
@@ -49,6 +52,14 @@ func (c *Controllers) Start(ctx context.Context) error {
|
|||||||
return start.All(ctx, 5, c.starters...)
|
return start.All(ctx, 5, c.starters...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RestConfigDefaults(cfg *rest.Config) *rest.Config {
|
||||||
|
cfg = rest.CopyConfig(cfg)
|
||||||
|
cfg.Timeout = 15 * time.Minute
|
||||||
|
cfg.RateLimiter = ratelimit.None
|
||||||
|
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
func NewController(cfg *rest.Config) (*Controllers, error) {
|
func NewController(cfg *rest.Config) (*Controllers, error) {
|
||||||
c := &Controllers{}
|
c := &Controllers{}
|
||||||
|
|
||||||
@@ -84,6 +95,7 @@ func NewController(cfg *rest.Config) (*Controllers, error) {
|
|||||||
c.RBAC = rbac.Rbac().V1()
|
c.RBAC = rbac.Rbac().V1()
|
||||||
c.API = api.Apiregistration().V1()
|
c.API = api.Apiregistration().V1()
|
||||||
c.CRD = crd.Apiextensions().V1beta1()
|
c.CRD = crd.Apiextensions().V1beta1()
|
||||||
|
c.RestConfig = cfg
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/rancher/wrangler/pkg/data"
|
"github.com/rancher/wrangler/pkg/data"
|
||||||
"github.com/rancher/wrangler/pkg/schemas/validation"
|
"github.com/rancher/wrangler/pkg/schemas/validation"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
@@ -27,6 +28,7 @@ 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)
|
||||||
|
ClientForWatch(ctx *types.APIRequest, schema *types.APISchema, namespace string) (dynamic.ResourceInterface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
@@ -50,24 +52,32 @@ func decodeParams(apiOp *types.APIRequest, target runtime.Object) error {
|
|||||||
return metav1.ParameterCodec.DecodeParameters(apiOp.Request.URL.Query(), metav1.SchemeGroupVersion, target)
|
return metav1.ParameterCodec.DecodeParameters(apiOp.Request.URL.Query(), metav1.SchemeGroupVersion, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toAPI(schema *types.APISchema, obj *unstructured.Unstructured) types.APIObject {
|
func toAPI(schema *types.APISchema, obj runtime.Object) types.APIObject {
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
return types.APIObject{}
|
return types.APIObject{}
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr := attributes.GVR(schema)
|
gvr := attributes.GVR(schema)
|
||||||
|
|
||||||
id := obj.GetName()
|
t := fmt.Sprintf("%s/%s/%s", gvr.Group, gvr.Version, gvr.Resource)
|
||||||
ns := obj.GetNamespace()
|
apiObject := types.APIObject{
|
||||||
|
Type: t,
|
||||||
|
Object: obj,
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return apiObject
|
||||||
|
}
|
||||||
|
|
||||||
|
id := m.GetName()
|
||||||
|
ns := m.GetNamespace()
|
||||||
if ns != "" {
|
if ns != "" {
|
||||||
id = fmt.Sprintf("%s/%s", ns, id)
|
id = fmt.Sprintf("%s/%s", ns, id)
|
||||||
}
|
}
|
||||||
t := fmt.Sprintf("%s/%s/%s", gvr.Group, gvr.Version, gvr.Resource)
|
|
||||||
return types.APIObject{
|
apiObject.ID = id
|
||||||
Type: t,
|
return apiObject
|
||||||
ID: id,
|
|
||||||
Object: obj,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -153,13 +163,15 @@ func (s *Store) listAndWatch(apiOp *types.APIRequest, k8sClient dynamic.Resource
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
for event := range watcher.ResultChan() {
|
for event := range watcher.ResultChan() {
|
||||||
data := event.Object.(*unstructured.Unstructured)
|
if event.Type == watch.Error {
|
||||||
result <- s.toAPIEvent(apiOp, schema, event.Type, data)
|
continue
|
||||||
|
}
|
||||||
|
result <- s.toAPIEvent(apiOp, schema, event.Type, event.Object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
k8sClient, err := s.clientGetter.Client(apiOp, schema, apiOp.Namespace)
|
k8sClient, err := s.clientGetter.ClientForWatch(apiOp, schema, apiOp.Namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -173,7 +185,7 @@ func (s *Store) Watch(apiOp *types.APIRequest, schema *types.APISchema, w types.
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) toAPIEvent(apiOp *types.APIRequest, schema *types.APISchema, et watch.EventType, obj *unstructured.Unstructured) types.APIEvent {
|
func (s *Store) toAPIEvent(apiOp *types.APIRequest, schema *types.APISchema, et watch.EventType, obj runtime.Object) types.APIEvent {
|
||||||
name := types.ChangeAPIEvent
|
name := types.ChangeAPIEvent
|
||||||
switch et {
|
switch et {
|
||||||
case watch.Deleted:
|
case watch.Deleted:
|
||||||
@@ -182,11 +194,18 @@ func (s *Store) toAPIEvent(apiOp *types.APIRequest, schema *types.APISchema, et
|
|||||||
name = types.CreateAPIEvent
|
name = types.CreateAPIEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.APIEvent{
|
event := types.APIEvent{
|
||||||
Name: name,
|
Name: name,
|
||||||
Revision: obj.GetResourceVersion(),
|
|
||||||
Object: toAPI(schema, obj),
|
Object: toAPI(schema, obj),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m, err := meta.Accessor(obj)
|
||||||
|
if err != nil {
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
event.Revision = m.GetResourceVersion()
|
||||||
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) Create(apiOp *types.APIRequest, schema *types.APISchema, params types.APIObject) (types.APIObject, error) {
|
func (s *Store) Create(apiOp *types.APIRequest, schema *types.APISchema, params types.APIObject) (types.APIObject, error) {
|
||||||
|
Reference in New Issue
Block a user