Merge pull request #3373 from chaunceyjiang/wildcards
feat: Allows setting wildcards for SkippedPropagatingNamespaces
This commit is contained in:
commit
507e66f6c6
|
@ -411,14 +411,10 @@ func startWorkStatusController(ctx controllerscontext.Context) (enabled bool, er
|
||||||
}
|
}
|
||||||
|
|
||||||
func startNamespaceController(ctx controllerscontext.Context) (enabled bool, err error) {
|
func startNamespaceController(ctx controllerscontext.Context) (enabled bool, err error) {
|
||||||
skippedPropagatingNamespaces := map[string]struct{}{}
|
|
||||||
for _, ns := range ctx.Opts.SkippedPropagatingNamespaces {
|
|
||||||
skippedPropagatingNamespaces[ns] = struct{}{}
|
|
||||||
}
|
|
||||||
namespaceSyncController := &namespace.Controller{
|
namespaceSyncController := &namespace.Controller{
|
||||||
Client: ctx.Mgr.GetClient(),
|
Client: ctx.Mgr.GetClient(),
|
||||||
EventRecorder: ctx.Mgr.GetEventRecorderFor(namespace.ControllerName),
|
EventRecorder: ctx.Mgr.GetEventRecorderFor(namespace.ControllerName),
|
||||||
SkippedPropagatingNamespaces: skippedPropagatingNamespaces,
|
SkippedPropagatingNamespaces: ctx.Opts.SkippedPropagatingNamespaces,
|
||||||
OverrideManager: ctx.OverrideManager,
|
OverrideManager: ctx.OverrideManager,
|
||||||
}
|
}
|
||||||
if err := namespaceSyncController.SetupWithManager(ctx.Mgr); err != nil {
|
if err := namespaceSyncController.SetupWithManager(ctx.Mgr); err != nil {
|
||||||
|
@ -543,11 +539,6 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
skippedPropagatingNamespaces := map[string]struct{}{}
|
|
||||||
for _, ns := range opts.SkippedPropagatingNamespaces {
|
|
||||||
skippedPropagatingNamespaces[ns] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
controlPlaneInformerManager := genericmanager.NewSingleClusterInformerManager(dynamicClientSet, 0, stopChan)
|
controlPlaneInformerManager := genericmanager.NewSingleClusterInformerManager(dynamicClientSet, 0, stopChan)
|
||||||
|
|
||||||
resourceInterpreter := resourceinterpreter.NewResourceInterpreter(controlPlaneInformerManager)
|
resourceInterpreter := resourceinterpreter.NewResourceInterpreter(controlPlaneInformerManager)
|
||||||
|
@ -564,12 +555,13 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
|
||||||
RESTMapper: mgr.GetRESTMapper(),
|
RESTMapper: mgr.GetRESTMapper(),
|
||||||
DynamicClient: dynamicClientSet,
|
DynamicClient: dynamicClientSet,
|
||||||
SkippedResourceConfig: skippedResourceConfig,
|
SkippedResourceConfig: skippedResourceConfig,
|
||||||
SkippedPropagatingNamespaces: skippedPropagatingNamespaces,
|
SkippedPropagatingNamespaces: opts.SkippedNamespacesRegexps(),
|
||||||
ResourceInterpreter: resourceInterpreter,
|
ResourceInterpreter: resourceInterpreter,
|
||||||
EventRecorder: mgr.GetEventRecorderFor("resource-detector"),
|
EventRecorder: mgr.GetEventRecorderFor("resource-detector"),
|
||||||
ConcurrentResourceTemplateSyncs: opts.ConcurrentResourceTemplateSyncs,
|
ConcurrentResourceTemplateSyncs: opts.ConcurrentResourceTemplateSyncs,
|
||||||
RateLimiterOptions: opts.RateLimiterOpts,
|
RateLimiterOptions: opts.RateLimiterOpts,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := mgr.Add(resourceDetector); err != nil {
|
if err := mgr.Add(resourceDetector); err != nil {
|
||||||
klog.Fatalf("Failed to setup resource detector: %v", err)
|
klog.Fatalf("Failed to setup resource detector: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -606,7 +598,7 @@ func setupControllers(mgr controllerruntime.Manager, opts *options.Options, stop
|
||||||
ClusterCacheSyncTimeout: opts.ClusterCacheSyncTimeout,
|
ClusterCacheSyncTimeout: opts.ClusterCacheSyncTimeout,
|
||||||
ClusterAPIQPS: opts.ClusterAPIQPS,
|
ClusterAPIQPS: opts.ClusterAPIQPS,
|
||||||
ClusterAPIBurst: opts.ClusterAPIBurst,
|
ClusterAPIBurst: opts.ClusterAPIBurst,
|
||||||
SkippedPropagatingNamespaces: opts.SkippedPropagatingNamespaces,
|
SkippedPropagatingNamespaces: opts.SkippedNamespacesRegexps(),
|
||||||
ConcurrentWorkSyncs: opts.ConcurrentWorkSyncs,
|
ConcurrentWorkSyncs: opts.ConcurrentWorkSyncs,
|
||||||
EnableTaintManager: opts.EnableTaintManager,
|
EnableTaintManager: opts.EnableTaintManager,
|
||||||
RateLimiterOptions: opts.RateLimiterOpts,
|
RateLimiterOptions: opts.RateLimiterOpts,
|
||||||
|
|
|
@ -2,6 +2,7 @@ package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -211,3 +212,12 @@ func (o *Options) AddFlags(flags *pflag.FlagSet, allControllers, disabledByDefau
|
||||||
o.ProfileOpts.AddFlags(flags)
|
o.ProfileOpts.AddFlags(flags)
|
||||||
features.FeatureGate.AddFlag(flags)
|
features.FeatureGate.AddFlag(flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkippedNamespacesRegexps precompiled regular expressions
|
||||||
|
func (o *Options) SkippedNamespacesRegexps() []*regexp.Regexp {
|
||||||
|
skippedPropagatingNamespaces := make([]*regexp.Regexp, len(o.SkippedPropagatingNamespaces))
|
||||||
|
for index, ns := range o.SkippedPropagatingNamespaces {
|
||||||
|
skippedPropagatingNamespaces[index] = regexp.MustCompile(fmt.Sprintf("^%s$", ns))
|
||||||
|
}
|
||||||
|
return skippedPropagatingNamespaces
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package options
|
package options
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
|
||||||
"github.com/karmada-io/karmada/pkg/util"
|
"github.com/karmada-io/karmada/pkg/util"
|
||||||
|
@ -33,6 +36,10 @@ func (o *Options) Validate() field.ErrorList {
|
||||||
if o.ClusterStartupGracePeriod.Duration <= 0 {
|
if o.ClusterStartupGracePeriod.Duration <= 0 {
|
||||||
errs = append(errs, field.Invalid(newPath.Child("ClusterStartupGracePeriod"), o.ClusterStartupGracePeriod, "must be greater than 0"))
|
errs = append(errs, field.Invalid(newPath.Child("ClusterStartupGracePeriod"), o.ClusterStartupGracePeriod, "must be greater than 0"))
|
||||||
}
|
}
|
||||||
|
for index, ns := range o.SkippedPropagatingNamespaces {
|
||||||
|
if _, err := regexp.Compile(fmt.Sprintf("^%s$", ns)); err != nil {
|
||||||
|
errs = append(errs, field.Invalid(newPath.Child("SkippedPropagatingNamespaces").Index(index), ns, "Invalid namespace regular expression"))
|
||||||
|
}
|
||||||
|
}
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
@ -52,8 +53,8 @@ type Options struct {
|
||||||
ClusterAPIQPS float32
|
ClusterAPIQPS float32
|
||||||
// ClusterAPIBurst is the burst to allow while talking with cluster kube-apiserver.
|
// ClusterAPIBurst is the burst to allow while talking with cluster kube-apiserver.
|
||||||
ClusterAPIBurst int
|
ClusterAPIBurst int
|
||||||
// SkippedPropagatingNamespaces is a list of namespaces that will be skipped for propagating.
|
// SkippedPropagatingNamespaces is a list of namespace regular expressions, matching namespaces will be skipped propagating.
|
||||||
SkippedPropagatingNamespaces []string
|
SkippedPropagatingNamespaces []*regexp.Regexp
|
||||||
// ClusterName is the name of cluster.
|
// ClusterName is the name of cluster.
|
||||||
ClusterName string
|
ClusterName string
|
||||||
// ConcurrentWorkSyncs is the number of Works that are allowed to sync concurrently.
|
// ConcurrentWorkSyncs is the number of Works that are allowed to sync concurrently.
|
||||||
|
|
|
@ -3,6 +3,7 @@ package namespace
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
@ -41,7 +42,7 @@ const (
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
client.Client // used to operate Work resources.
|
client.Client // used to operate Work resources.
|
||||||
EventRecorder record.EventRecorder
|
EventRecorder record.EventRecorder
|
||||||
SkippedPropagatingNamespaces map[string]struct{}
|
SkippedPropagatingNamespaces []*regexp.Regexp
|
||||||
OverrideManager overridemanager.OverrideManager
|
OverrideManager overridemanager.OverrideManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +97,11 @@ func (c *Controller) namespaceShouldBeSynced(namespace string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := c.SkippedPropagatingNamespaces[namespace]; ok {
|
for _, nsRegexp := range c.SkippedPropagatingNamespaces {
|
||||||
|
if match := nsRegexp.MatchString(namespace); match {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package detector
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ type ResourceDetector struct {
|
||||||
EventHandler cache.ResourceEventHandler
|
EventHandler cache.ResourceEventHandler
|
||||||
Processor util.AsyncWorker
|
Processor util.AsyncWorker
|
||||||
SkippedResourceConfig *util.SkippedResourceConfig
|
SkippedResourceConfig *util.SkippedResourceConfig
|
||||||
SkippedPropagatingNamespaces map[string]struct{}
|
SkippedPropagatingNamespaces []*regexp.Regexp
|
||||||
// ResourceInterpreter knows the details of resource structure.
|
// ResourceInterpreter knows the details of resource structure.
|
||||||
ResourceInterpreter resourceinterpreter.ResourceInterpreter
|
ResourceInterpreter resourceinterpreter.ResourceInterpreter
|
||||||
EventRecorder record.EventRecorder
|
EventRecorder record.EventRecorder
|
||||||
|
@ -253,9 +254,11 @@ func (d *ResourceDetector) EventFilter(obj interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if SkippedPropagatingNamespaces is set, skip object events in these namespaces.
|
// if SkippedPropagatingNamespaces is set, skip object events in these namespaces.
|
||||||
if _, ok := d.SkippedPropagatingNamespaces[clusterWideKey.Namespace]; ok {
|
for _, nsRegexp := range d.SkippedPropagatingNamespaces {
|
||||||
|
if match := nsRegexp.MatchString(clusterWideKey.Namespace); match {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if unstructObj, ok := obj.(*unstructured.Unstructured); ok {
|
if unstructObj, ok := obj.(*unstructured.Unstructured); ok {
|
||||||
switch unstructObj.GroupVersionKind() {
|
switch unstructObj.GroupVersionKind() {
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
package detector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkEventFilterNoSkipNameSpaces(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = nil
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "benchmark",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEventFilterNoMatchSkipNameSpaces(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = append(dt.SkippedPropagatingNamespaces, regexp.MustCompile("^benchmark-.*$"))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "benchmark",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEventFilterNoWildcards(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = append(dt.SkippedPropagatingNamespaces, regexp.MustCompile("^benchmark$"))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "benchmark-1",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEventFilterPrefixMatchSkipNameSpaces(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = append(dt.SkippedPropagatingNamespaces, regexp.MustCompile("^benchmark-.*$"))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "benchmark-1",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func BenchmarkEventFilterSuffixMatchSkipNameSpaces(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = append(dt.SkippedPropagatingNamespaces, regexp.MustCompile("^.*-benchmark$"))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "example-benchmark",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEventFilterMultiSkipNameSpaces(b *testing.B) {
|
||||||
|
dt := &ResourceDetector{}
|
||||||
|
dt.SkippedPropagatingNamespaces = append(dt.SkippedPropagatingNamespaces, regexp.MustCompile("^.*-benchmark$"), regexp.MustCompile("^benchmark-.*$"))
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
dt.EventFilter(&unstructured.Unstructured{
|
||||||
|
Object: map[string]interface{}{
|
||||||
|
"apiVersion": "apps/v1",
|
||||||
|
"kind": "Deployment",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": "demo-deployment",
|
||||||
|
"namespace": "benchmark-1",
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"replicas": 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue