diff --git a/config.yaml b/config.yaml index 2907f2dee..a5303c73e 100644 --- a/config.yaml +++ b/config.yaml @@ -1,30 +1,43 @@ ## Resources you want to watch resources: - name: pod # Name of the resources e.g pod, deployment, ingress, etc. - namespaces: # List of namespaces, "all" will watch all the namespaces - - all - events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all + namespaces: # List of namespaces, "all" will watch all the namespaces + include: + - all + ignore: # List of namespaces to be ignored (omitempty), used only with include: all + - # example : include [all], ignore [x,y,z] + events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all - create - delete - error - name: service namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: deployment namespaces: - - all + include: + - all + ignore: + - events: - create - update - delete + - update - error - name: statefulset namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -32,63 +45,90 @@ resources: - error - name: ingress namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: node namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: namespace namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolume namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolumeclaim namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: secret namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: configmap namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: daemonset namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: job namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -96,28 +136,40 @@ resources: - error - name: role namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: rolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: clusterrolebindings namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: clusterrolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete diff --git a/deploy-all-in-one-tls.yaml b/deploy-all-in-one-tls.yaml index b1138cd70..9852fd906 100644 --- a/deploy-all-in-one-tls.yaml +++ b/deploy-all-in-one-tls.yaml @@ -10,23 +10,31 @@ data: config.yaml: | ## Resources you want to watch resources: - - name: pod # Name of the resources e.g pod, deployment, ingress, etc. (Resource name must be in singular form) - namespaces: # List of namespaces, "all" will watch all the namespaces - - all - events: # List of lifecycle events you want to receive, e.g create, update, delete OR all + namespaces: + include: + - all + ignore: # List of namespaces to be ignored (omitempty), used only with include: all + - # example : include [all], ignore [x,y,z] + events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all - create - delete - error - name: service namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: deployment namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -34,7 +42,10 @@ data: - error - name: statefulset namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -42,63 +53,91 @@ data: - error - name: ingress namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: node namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: namespace namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolume namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolumeclaim namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: secret namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: configmap namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: daemonset namespaces: - - all + include: + - all + ignore: + - events: - create - delete + - update - error - name: job namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -106,14 +145,20 @@ data: - error - name: role namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: rolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete @@ -127,7 +172,10 @@ data: - error - name: clusterrolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete diff --git a/deploy-all-in-one.yaml b/deploy-all-in-one.yaml index f699fc37a..b564981e8 100644 --- a/deploy-all-in-one.yaml +++ b/deploy-all-in-one.yaml @@ -11,22 +11,31 @@ data: ## Resources you want to watch resources: - name: pod # Name of the resources e.g pod, deployment, ingress, etc. (Resource name must be in singular form) - namespaces: # List of namespaces, "all" will watch all the namespaces - - all - events: # List of lifecycle events you want to receive, e.g create, update, delete OR all + namespaces: + include: + - all + ignore: # List of namespaces to be ignored (omitempty), used only with include: all + - # example : include [all], ignore [x,y,z] + events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all - create - delete - error - name: service namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: deployment namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -34,7 +43,10 @@ data: - error - name: statefulset namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -42,63 +54,91 @@ data: - error - name: ingress namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: node namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: namespace namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolume namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolumeclaim namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: secret namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: configmap namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: daemonset namespaces: - - all + include: + - all + ignore: + - events: - create + - update - delete - error - name: job namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -106,14 +146,20 @@ data: - error - name: role namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: rolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete @@ -127,7 +173,10 @@ data: - error - name: clusterrolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete diff --git a/helm/botkube/values.yaml b/helm/botkube/values.yaml index 7a974f07b..7f11b77ee 100644 --- a/helm/botkube/values.yaml +++ b/helm/botkube/values.yaml @@ -21,22 +21,31 @@ config: ## Resources you want to watch resources: - name: pod # Name of the resources e.g pod, deployment, ingress, etc. (Resource name must be in singular form) - namespaces: # List of namespaces, "all" will watch all the namespaces - - all - events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all + namespaces: + include: + - all + ignore: # List of namespaces to be ignored (omitempty), used only with include: all + - # example : include [all], ignore [x,y,z] + events: # List of lifecycle events you want to receive, e.g create, update, delete, error OR all - create - delete - error - name: service namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: deployment namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -44,7 +53,10 @@ config: - error - name: statefulset namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -52,63 +64,90 @@ config: - error - name: ingress namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: node namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: namespace namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolume namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: persistentvolumeclaim namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: secret namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: configmap namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: daemonset namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: job namespaces: - - all + include: + - all + ignore: + - events: - create - update @@ -116,14 +155,20 @@ config: - error - name: role namespaces: - - all + include: + - all + ignore: + - events: - create - delete - error - name: rolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete @@ -137,7 +182,10 @@ config: - error - name: clusterrolebinding namespaces: - - all + include: + - all + ignore: + - events: - create - delete diff --git a/pkg/config/config.go b/pkg/config/config.go index 8f40cbd7f..b428cf6a4 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -53,10 +53,21 @@ type Config struct { // Resource contains resources to watch type Resource struct { Name string - Namespaces []string + Namespaces Namespaces Events []EventType } +// Namespaces contains namespaces to include and ignore +// Include contains a list of namespaces to be watched, +// - "all" to watch all the namespaces +// Ignore contains a list of namespaces to be ignored when all namespaces are included +// It is an optional (omitempty) field which is tandem with Include [all] +// example : include [all], ignore [x,y,z] +type Namespaces struct { + Include []string + Ignore []string `yaml:",omitempty"` +} + // Communications channels to send events to type Communications struct { Slack Slack diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 6a40af6e1..2c8a9bc2c 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -122,6 +122,7 @@ func sendEvent(obj, oldObj interface{}, c *config.Config, kind string, eventType objectMeta := utils.GetObjectMetaData(obj) if !utils.AllowedEventKindsMap[utils.EventKind{Resource: kind, Namespace: "all", EventType: eventType}] && !utils.AllowedEventKindsMap[utils.EventKind{Resource: kind, Namespace: objectMeta.Namespace, EventType: eventType}] { + log.Logger.Debugf("Ignoring %s to %s/%v in %s namespaces", eventType, kind, objectMeta.Name, objectMeta.Namespace) return } log.Logger.Debugf("Processing %s to %s/%v in %s namespaces", eventType, kind, objectMeta.Name, objectMeta.Namespace) diff --git a/pkg/filterengine/filters/namespace-filter/namespace_checker.go b/pkg/filterengine/filters/namespace-filter/namespace_checker.go new file mode 100644 index 000000000..45eb97687 --- /dev/null +++ b/pkg/filterengine/filters/namespace-filter/namespace_checker.go @@ -0,0 +1,63 @@ +package filters + +import ( + "fmt" + "strings" + + "github.com/infracloudio/botkube/pkg/config" + "github.com/infracloudio/botkube/pkg/events" + "github.com/infracloudio/botkube/pkg/filterengine" + log "github.com/infracloudio/botkube/pkg/logging" +) + +// NamespaceChecker ignore events from blocklisted namespaces +type NamespaceChecker struct { + Description string +} + +// Register filter +func init() { + filterengine.DefaultFilterEngine.Register(NamespaceChecker{ + Description: "Checks if event belongs to blocklisted namespaces and filter them.", + }) +} + +// Run filters and modifies event struct +func (f NamespaceChecker) Run(object interface{}, event *events.Event) { + // load config.yaml + botkubeConfig, err := config.New() + if err != nil { + log.Logger.Errorf(fmt.Sprintf("Error in loading configuration. Error:%s", err.Error())) + log.Logger.Debug("Skipping ignore namespace filter.") + } + if botkubeConfig != nil { + for _, resource := range botkubeConfig.Resources { + if resource.Name == strings.ToLower(event.Kind) { + // check if namespace to be ignored + if isNamespaceIgnored(resource.Namespaces, event.Namespace) { + event.Skip = true + } + } + } + + } + log.Logger.Debug("Ignore Namespaces filter successful!") +} + +// Describe filter +func (f NamespaceChecker) Describe() string { + return f.Description +} + +// isNamespaceIgnored checks if a event to be ignored from user config +func isNamespaceIgnored(resourceNamespaces config.Namespaces, eventNamespace string) bool { + if len(resourceNamespaces.Include) == 1 && resourceNamespaces.Include[0] == "all" { + if len(resourceNamespaces.Ignore) > 0 { + ignoredNamespaces := fmt.Sprintf("%#v", resourceNamespaces.Ignore) + if strings.Contains(ignoredNamespaces, eventNamespace) { + return true + } + } + } + return false +} diff --git a/pkg/filterengine/filters/namespace-filter/namespace_checker_test.go b/pkg/filterengine/filters/namespace-filter/namespace_checker_test.go new file mode 100644 index 000000000..97bc0d3d2 --- /dev/null +++ b/pkg/filterengine/filters/namespace-filter/namespace_checker_test.go @@ -0,0 +1,29 @@ +package filters + +import ( + "testing" + + "github.com/infracloudio/botkube/pkg/config" +) + +func TestIsNamespaceIgnored(t *testing.T) { + tests := map[string]struct { + Namespaces config.Namespaces + eventNamespace string + expected bool + }{ + `include all and ignore few --> watch all except ignored`: {config.Namespaces{Include: []string{"all"}, Ignore: []string{"demo", "abc"}}, "demo", true}, + `include all and ignore is "" --> watch all`: {config.Namespaces{Include: []string{"all"}, Ignore: []string{""}}, "demo", false}, + `include all and ignore is [] --> watch all`: {config.Namespaces{Include: []string{"all"}, Ignore: []string{}}, "demo", false}, + // utils.AllowedEventKindsMap inherently handles remaining test case + } + for name, test := range tests { + name, test := name, test + t.Run(name, func(t *testing.T) { + actual := isNamespaceIgnored(test.Namespaces, test.eventNamespace) + if actual != test.expected { + t.Errorf("expected: %+v != actual: %+v\n", test.expected, actual) + } + }) + } +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 16ab26195..0dedb9153 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -120,7 +120,7 @@ func InitInformerMap() { allEvents = true break } - for _, ns := range r.Namespaces { + for _, ns := range r.Namespaces.Include { AllowedEventKindsMap[EventKind{Resource: r.Name, Namespace: ns, EventType: e}] = true } } @@ -129,7 +129,7 @@ func InitInformerMap() { if allEvents { events := []config.EventType{config.CreateEvent, config.UpdateEvent, config.DeleteEvent, config.ErrorEvent} for _, ev := range events { - for _, ns := range r.Namespaces { + for _, ns := range r.Namespaces.Include { AllowedEventKindsMap[EventKind{Resource: r.Name, Namespace: ns, EventType: ev}] = true } }