Add InclusionList to Alert CRD
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com> Co-authored-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
parent
18c49ad361
commit
9b7a80942f
|
@ -45,6 +45,11 @@ type AlertSpec struct {
|
|||
// +required
|
||||
EventSources []v1.CrossNamespaceObjectReference `json:"eventSources"`
|
||||
|
||||
// InclusionList specifies a list of Golang regular expressions
|
||||
// to be used for including messages.
|
||||
// +optional
|
||||
InclusionList []string `json:"inclusionList,omitempty"`
|
||||
|
||||
// ExclusionList specifies a list of Golang regular expressions
|
||||
// to be used for excluding messages.
|
||||
// +optional
|
||||
|
|
|
@ -98,6 +98,11 @@ func (in *AlertSpec) DeepCopyInto(out *AlertSpec) {
|
|||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.InclusionList != nil {
|
||||
in, out := &in.InclusionList, &out.InclusionList
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ExclusionList != nil {
|
||||
in, out := &in.ExclusionList, &out.ExclusionList
|
||||
*out = make([]string, len(*in))
|
||||
|
|
|
@ -303,6 +303,12 @@ spec:
|
|||
items:
|
||||
type: string
|
||||
type: array
|
||||
inclusionList:
|
||||
description: InclusionList specifies a list of Golang regular expressions
|
||||
to be used for including messages.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
providerRef:
|
||||
description: ProviderRef specifies which Provider this Alert should
|
||||
use.
|
||||
|
|
|
@ -114,6 +114,19 @@ on the involved object kind, name and namespace.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>inclusionList</code><br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>InclusionList specifies a list of Golang regular expressions
|
||||
to be used for including messages.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>exclusionList</code><br>
|
||||
<em>
|
||||
[]string
|
||||
|
@ -589,6 +602,19 @@ on the involved object kind, name and namespace.</p>
|
|||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>inclusionList</code><br>
|
||||
<em>
|
||||
[]string
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<em>(Optional)</em>
|
||||
<p>InclusionList specifies a list of Golang regular expressions
|
||||
to be used for including messages.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<code>exclusionList</code><br>
|
||||
<em>
|
||||
[]string
|
||||
|
|
|
@ -171,7 +171,8 @@ To receive alerts only on errors, set the field value to `error`.
|
|||
### Event exclusion
|
||||
|
||||
`.spec.exclusionList` is an optional field to specify a list of regex expressions to filter
|
||||
events based on message content.
|
||||
events based on message content. The event will be excluded if the message matches at least
|
||||
one of the expressions in the list.
|
||||
|
||||
#### Example
|
||||
|
||||
|
@ -198,6 +199,39 @@ 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
|
||||
```
|
||||
|
||||
### Event inclusion
|
||||
|
||||
`.spec.inclusionList` is an optional field to specify a list of regex expressions to filter
|
||||
events based on message content. The event will be sent if the message matches at least one
|
||||
of the expressions in the list, and discarded otherwise. If the message matches one of the
|
||||
expressions in the inclusion list but also matches one of the expressions in the exclusion
|
||||
list, then the event is still discarded (exclusion is stronger than inclusion).
|
||||
|
||||
#### Example
|
||||
|
||||
Alert if the message matches a [Go regex](https://golang.org/pkg/regexp/syntax)
|
||||
from the inclusion list:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: notification.toolkit.fluxcd.io/v1beta2
|
||||
kind: Alert
|
||||
metadata:
|
||||
name: <name>
|
||||
spec:
|
||||
eventSources:
|
||||
- kind: HelmRelease
|
||||
name: '*'
|
||||
inclusionList:
|
||||
- ".*succeeded.*"
|
||||
exclusionList:
|
||||
- ".*uninstall.*"
|
||||
- ".*test.*"
|
||||
```
|
||||
|
||||
The above definition will send alerts for successful Helm installs, upgrades and rollbacks,
|
||||
but not uninstalls and tests.
|
||||
|
||||
### Suspend
|
||||
|
||||
`.spec.suspend` is an optional field to suspend the altering.
|
||||
|
|
|
@ -274,6 +274,8 @@ func TestAlertReconciler_EventHandler(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
inclusionAlert := alert.DeepCopy()
|
||||
inclusionAlert.Spec.InclusionList = []string{"^included"}
|
||||
|
||||
g.Expect(k8sClient.Create(context.Background(), alert)).To(Succeed())
|
||||
|
||||
|
@ -424,4 +426,71 @@ func TestAlertReconciler_EventHandler(t *testing.T) {
|
|||
req = nil
|
||||
})
|
||||
}
|
||||
|
||||
// update alert for testing inclusion list
|
||||
var obj apiv1beta2.Alert
|
||||
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(alert), &obj)).To(Succeed())
|
||||
inclusionAlert.ResourceVersion = obj.ResourceVersion
|
||||
g.Expect(k8sClient.Update(context.Background(), inclusionAlert)).To(Succeed())
|
||||
|
||||
// wait for ready
|
||||
g.Eventually(func() bool {
|
||||
var obj apiv1beta2.Alert
|
||||
g.Expect(k8sClient.Get(context.Background(), client.ObjectKeyFromObject(inclusionAlert), &obj))
|
||||
return conditions.IsReady(&obj)
|
||||
}, 30*time.Second, time.Second).Should(BeTrue())
|
||||
|
||||
event = eventv1.Event{
|
||||
InvolvedObject: corev1.ObjectReference{
|
||||
Kind: "Bucket",
|
||||
Name: "hyacinth",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Severity: "info",
|
||||
Timestamp: metav1.Now(),
|
||||
Message: "included",
|
||||
Reason: "event-happened",
|
||||
ReportingController: "source-controller",
|
||||
}
|
||||
|
||||
tests = []struct {
|
||||
name string
|
||||
modifyEventFunc func(e eventv1.Event) eventv1.Event
|
||||
forwarded bool
|
||||
}{
|
||||
{
|
||||
name: "forwards when message matches inclusion list",
|
||||
modifyEventFunc: func(e eventv1.Event) eventv1.Event { return e },
|
||||
forwarded: true,
|
||||
},
|
||||
{
|
||||
name: "drops when message does not match inclusion list",
|
||||
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
|
||||
e.Message = "not included"
|
||||
return e
|
||||
},
|
||||
forwarded: false,
|
||||
},
|
||||
{
|
||||
name: "drops when message matches inclusion list and exclusion list",
|
||||
modifyEventFunc: func(e eventv1.Event) eventv1.Event {
|
||||
e.Message = "included excluded"
|
||||
return e
|
||||
},
|
||||
forwarded: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
event = tt.modifyEventFunc(event)
|
||||
testSent()
|
||||
if tt.forwarded {
|
||||
testForwarded()
|
||||
} else {
|
||||
testFiltered()
|
||||
}
|
||||
req = nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,15 +85,33 @@ func (s *EventServer) handleEvent() func(w http.ResponseWriter, r *http.Request)
|
|||
continue each_alert
|
||||
}
|
||||
|
||||
// skip alert if the message does not match any regex from the inclusion list
|
||||
if len(alert.Spec.InclusionList) > 0 {
|
||||
var include bool
|
||||
for _, inclusionRegex := range alert.Spec.InclusionList {
|
||||
if r, err := regexp.Compile(inclusionRegex); err == nil {
|
||||
if r.Match([]byte(event.Message)) {
|
||||
include = true
|
||||
break
|
||||
}
|
||||
} else {
|
||||
s.logger.Error(err, fmt.Sprintf("failed to compile inclusion regex: %s", inclusionRegex))
|
||||
}
|
||||
}
|
||||
if !include {
|
||||
continue each_alert
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
for _, exclusionRegex := range alert.Spec.ExclusionList {
|
||||
if r, err := regexp.Compile(exclusionRegex); err == nil {
|
||||
if r.Match([]byte(event.Message)) {
|
||||
continue each_alert
|
||||
}
|
||||
} else {
|
||||
s.logger.Error(err, fmt.Sprintf("failed to compile regex: %s", exp))
|
||||
s.logger.Error(err, fmt.Sprintf("failed to compile exclusion regex: %s", exclusionRegex))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue