diff --git a/api/v1beta1/alert_types.go b/api/v1beta1/alert_types.go index 30d3a284e..4a9693438 100644 --- a/api/v1beta1/alert_types.go +++ b/api/v1beta1/alert_types.go @@ -27,7 +27,7 @@ const ( // AlertSpec defines an alerting rule for events involving a list of objects type AlertSpec struct { - // Send events using this provider + // Send events using this provider. // +required ProviderRef meta.LocalObjectReference `json:"providerRef"` @@ -38,10 +38,14 @@ type AlertSpec struct { // +optional EventSeverity string `json:"eventSeverity,omitempty"` - // Filter events based on the involved objects + // Filter events based on the involved objects. // +required EventSources []CrossNamespaceObjectReference `json:"eventSources"` + // A list of Golang regular expressions to be used for excluding messages. + // +optional + ExclusionList []string `json:"exclusionList,omitempty"` + // Short description of the impact and affected cluster. // +optional Summary string `json:"summary,omitempty"` diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index c31060bee..e0d004c0b 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -94,6 +94,11 @@ func (in *AlertSpec) DeepCopyInto(out *AlertSpec) { *out = make([]CrossNamespaceObjectReference, len(*in)) copy(*out, *in) } + if in.ExclusionList != nil { + in, out := &in.ExclusionList, &out.ExclusionList + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertSpec. diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml index 483ed1167..671d7ae15 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml @@ -56,7 +56,7 @@ spec: - error type: string eventSources: - description: Filter events based on the involved objects + description: Filter events based on the involved objects. items: description: CrossNamespaceObjectReference contains enough information to let you locate the typed referenced object at cluster level @@ -91,8 +91,14 @@ spec: - name type: object type: array + exclusionList: + description: A list of Golang regular expressions to be used for excluding + messages. + items: + type: string + type: array providerRef: - description: Send events using this provider + description: Send events using this provider. properties: name: description: Name of the referent diff --git a/docs/api/notification.md b/docs/api/notification.md index 8839d6c46..7664d35f5 100644 --- a/docs/api/notification.md +++ b/docs/api/notification.md @@ -80,7 +80,7 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference -

Send events using this provider

+

Send events using this provider.

@@ -106,7 +106,19 @@ If set to ‘info’ no events will be filtered.

-

Filter events based on the involved objects

+

Filter events based on the involved objects.

+ + + + +exclusionList
+ +[]string + + + +(Optional) +

A list of Golang regular expressions to be used for excluding messages.

@@ -465,7 +477,7 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference -

Send events using this provider

+

Send events using this provider.

@@ -491,7 +503,19 @@ If set to ‘info’ no events will be filtered.

-

Filter events based on the involved objects

+

Filter events based on the involved objects.

+ + + + +exclusionList
+ +[]string + + + +(Optional) +

A list of Golang regular expressions to be used for excluding messages.

diff --git a/docs/spec/v1beta1/alert.md b/docs/spec/v1beta1/alert.md index c04bab6c4..5c15d1665 100644 --- a/docs/spec/v1beta1/alert.md +++ b/docs/spec/v1beta1/alert.md @@ -8,7 +8,7 @@ Spec: ```go type AlertSpec struct { - // Send events using this provider + // Send events using this provider. // +required ProviderRef meta.LocalObjectReference `json:"providerRef"` @@ -17,10 +17,14 @@ type AlertSpec struct { // +optional EventSeverity string `json:"eventSeverity,omitempty"` - // Filter events based on the involved objects + // Filter events based on the involved objects. // +required EventSources []CrossNamespaceObjectReference `json:"eventSources"` + // A list of Golang regular expressions to be used for excluding messages. + // +optional + ExclusionList []string `json:"exclusionList,omitempty"` + // Short description of the impact and affected cluster. // +optional Summary string `json:"summary,omitempty"` @@ -115,3 +119,29 @@ spec: - kind: HelmRelease name: nginx-ingress ``` + +Skip alerting if the message matches a [Go regex](https://golang.org/pkg/regexp/syntax) +from the exclusion list: + +```yaml +apiVersion: notification.toolkit.fluxcd.io/v1beta1 +kind: Alert +metadata: + name: flux-system + namespace: flux-system +spec: + providerRef: + name: on-call-slack + eventSeverity: error + eventSources: + - kind: GitRepository + name: flux-system + exclusionList: + - "waiting.*socket" +``` + +The above definition will not send alerts for transient Git clone errors like: + +``` +unable to clone 'ssh://git@ssh.dev.azure.com/v3/...', error: SSH could not read data: Error waiting on socket +``` diff --git a/internal/server/event_handlers.go b/internal/server/event_handlers.go index 03a01c73a..00402e3d7 100644 --- a/internal/server/event_handlers.go +++ b/internal/server/event_handlers.go @@ -19,8 +19,10 @@ package server import ( "context" "encoding/json" + "fmt" "io/ioutil" "net/http" + "regexp" "time" corev1 "k8s.io/api/core/v1" @@ -72,6 +74,19 @@ func (s *EventServer) handleEvent() func(w http.ResponseWriter, r *http.Request) continue } + // skip alert if the message matches a regex from the exclusion list + if len(alert.Spec.ExclusionList) > 0 { + for _, exp := range alert.Spec.ExclusionList { + if r, err := regexp.Compile(exp); err == nil { + if r.Match([]byte(event.Message)) { + continue + } + } else { + s.logger.Error(err, fmt.Sprintf("failed to compile regex: %s", exp)) + } + } + } + // filter alerts by object and severity for _, source := range alert.Spec.EventSources { if source.Namespace == "" {