Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pkg/monitor/monitorapi/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,18 @@ type Message struct {
Annotations map[AnnotationKey]string `json:"annotations"`
}

// HumanMessageDoesNotMatchAny is a function that returns true if the message
// does not match any of the provided regular expressions. It is useful when
// filtering out events that contain a given pattern.
func (m Message) HumanMessageDoesNotMatchAny(res ...*regexp.Regexp) bool {
for _, re := range res {
if re.MatchString(m.HumanMessage) {
return false
}
}
return true
}

// IntervalSource is used to type/categorize all intervals based on what created them.
// This is intended to be used to group, and when combined with the display flag, signal that
// they should be visible by default in the UIs that render interval charts.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package legacyetcdmonitortests

import (
"regexp"

"github.com/openshift/origin/pkg/monitor/monitorapi"
"github.com/openshift/origin/pkg/monitortestlibrary/pathologicaleventlibrary"
"github.com/openshift/origin/pkg/test/ginkgo/junitapi"
Expand All @@ -14,8 +16,24 @@ import (
// flake threshold. See https://bugzilla.redhat.com/show_bug.cgi?id=2031564.
func testRequiredInstallerResourcesMissing(events monitorapi.Intervals) []*junitapi.JUnitTestCase {
testName := "[bz-etcd] pathological event should not see excessive RequiredInstallerResourcesMissing secrets"
return pathologicaleventlibrary.NewSingleEventThresholdCheck(testName,
pathologicaleventlibrary.EtcdRequiredResourcesMissing, pathologicaleventlibrary.DuplicateEventThreshold, pathologicaleventlibrary.RequiredResourceMissingFlakeThreshold).Test(events)

return pathologicaleventlibrary.NewSingleEventThresholdCheck(
testName,
pathologicaleventlibrary.EtcdRequiredResourcesMissing,
pathologicaleventlibrary.DuplicateEventThreshold,
pathologicaleventlibrary.RequiredResourceMissingFlakeThreshold,
).Test(
events.Filter(
func(event monitorapi.Interval) bool {
return event.Message.HumanMessageDoesNotMatchAny(
// XXX configmap check-endpoints-config was added on 4.22 so
// we expect events referring to it to show up when testing the
// upgrade from 4.21.
regexp.MustCompile(`^configmaps: check-endpoints-config-\d+$`),
)
},
),
)
}

func testOperatorStatusChanged(events monitorapi.Intervals) []*junitapi.JUnitTestCase {
Expand Down
141 changes: 100 additions & 41 deletions pkg/monitortests/etcd/legacyetcdmonitortests/pathological_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,83 +10,142 @@ import (

func Test_testRequiredInstallerResourcesMissing(t *testing.T) {
tests := []struct {
name string
interval monitorapi.Interval
kind string
name string
intervals monitorapi.Intervals
kind string
}{
{
name: "Reason doesn't match but results in passing junit",
interval: monitorapi.Interval{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.NodeUpdateReason, // anything but the one we're looking for
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "25",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.NodeUpdateReason, // anything but the one we're looking for
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "25",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
Source: monitorapi.SourceKubeEvent,
},
kind: "pass",
},
{
name: "Test failing case",
interval: monitorapi.Interval{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "21",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "21",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
Source: monitorapi.SourceKubeEvent,
},
kind: "fail",
},
{
name: "Test flaking case",
interval: monitorapi.Interval{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "16",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "16",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
Source: monitorapi.SourceKubeEvent,
},
kind: "flake",
},
{
name: "Test passing case",
interval: monitorapi.Interval{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "7",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "7",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
},
kind: "pass",
},
{
name: "Test passes because the event is ignored",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "configmaps: check-endpoints-config-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "21",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
Source: monitorapi.SourceKubeEvent,
},
kind: "pass",
},
{
name: "Test fails with ignored events",
intervals: monitorapi.Intervals{
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "configmaps: check-endpoints-config-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "21",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
{
Condition: monitorapi.Condition{
Level: monitorapi.Info,
Message: monitorapi.Message{
Reason: monitorapi.IntervalReason("RequiredInstallerResourcesMissing"),
HumanMessage: "secrets: etcd-all-certs-3",
Annotations: map[monitorapi.AnnotationKey]string{
monitorapi.AnnotationCount: "21",
},
},
},
Source: monitorapi.SourceKubeEvent,
},
},
kind: "fail",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := tt.interval
junit_tests := testRequiredInstallerResourcesMissing(monitorapi.Intervals{e})
e := tt.intervals
junit_tests := testRequiredInstallerResourcesMissing(e)
switch tt.kind {
case "pass":
if len(junit_tests) != 1 {
Expand Down