Skip to content

Commit 869e99a

Browse files
Merge pull request #28262 from dgoodwin/cluster-operator-intervals
Port the clusteroperator intervals to new structured format
2 parents d1d55fa + bed4363 commit 869e99a

File tree

9 files changed

+252
-113
lines changed

9 files changed

+252
-113
lines changed

pkg/monitor/monitorapi/construction.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,12 @@ func (b *LocatorBuilder) E2ETest(testName string) Locator {
317317
return b.Build()
318318
}
319319

320+
func (b *LocatorBuilder) ClusterOperator(name string) Locator {
321+
b.targetType = LocatorTypeClusterOperator
322+
b.annotations[LocatorClusterOperatorKey] = name
323+
return b.Build()
324+
}
325+
320326
func (b *LocatorBuilder) Build() Locator {
321327
ret := Locator{
322328
Type: b.targetType,
Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,27 @@
11
package monitorapi
22

33
import (
4-
"strings"
5-
64
configv1 "github.com/openshift/api/config/v1"
75
)
86

9-
// condition/Degraded status/True reason/DNSDegraded changed: DNS default is degraded
10-
func GetOperatorConditionStatus(message string) *configv1.ClusterOperatorStatusCondition {
11-
if !strings.HasPrefix(message, "condition/") {
7+
// GetOperatorConditionStatus reconstructs a ClusterOperatorStatusCondition from an interval.
8+
func GetOperatorConditionStatus(interval Interval) *configv1.ClusterOperatorStatusCondition {
9+
c, ok := interval.StructuredMessage.Annotations[AnnotationCondition]
10+
if !ok {
1211
return nil
1312
}
14-
stanzas := strings.Split(message, " ")
15-
condition := &configv1.ClusterOperatorStatusCondition{}
16-
17-
for _, stanza := range stanzas {
18-
keyValue := strings.SplitN(stanza, "/", 2)
19-
if len(keyValue) != 2 {
20-
continue
21-
}
2213

23-
switch keyValue[0] {
24-
case "condition":
25-
if condition.Type == "" {
26-
condition.Type = configv1.ClusterStatusConditionType(keyValue[1])
27-
}
28-
case "status":
29-
if condition.Status == "" {
30-
condition.Status = configv1.ConditionStatus(keyValue[1])
31-
}
32-
case "reason":
33-
if condition.Reason == "" {
34-
condition.Reason = keyValue[1]
35-
}
36-
}
14+
condition := &configv1.ClusterOperatorStatusCondition{}
15+
condition.Type = configv1.ClusterStatusConditionType(c)
16+
s, ok := interval.StructuredMessage.Annotations[AnnotationStatus]
17+
if ok {
18+
condition.Status = configv1.ConditionStatus(s)
3719
}
38-
39-
messages := strings.SplitN(message, ": ", 2)
40-
if len(messages) < 2 {
41-
return condition
20+
r, ok := interval.StructuredMessage.Annotations[AnnotationReason]
21+
if ok {
22+
condition.Reason = r
4223
}
43-
condition.Message = messages[1]
4424

25+
condition.Message = interval.StructuredMessage.HumanMessage
4526
return condition
4627
}
Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
package monitorapi
22

33
import (
4-
"reflect"
54
"testing"
65

76
configv1 "github.com/openshift/api/config/v1"
7+
"github.com/stretchr/testify/assert"
88
)
99

1010
func TestGetOperatorConditionStatus(t *testing.T) {
1111
tests := []struct {
12-
name string
13-
message string
14-
want *configv1.ClusterOperatorStatusCondition
12+
name string
13+
interval Interval
14+
want *configv1.ClusterOperatorStatusCondition
1515
}{
1616
{
17-
name: "simple",
18-
message: "condition/Degraded status/True reason/DNSDegraded changed: DNS default is degraded",
17+
name: "simple",
18+
interval: Interval{
19+
Source: SourceClusterOperatorMonitor,
20+
Condition: Condition{
21+
StructuredMessage: Message{
22+
Reason: "DNSDegraded",
23+
HumanMessage: "DNS default is degraded",
24+
Annotations: map[AnnotationKey]string{
25+
AnnotationCondition: "Degraded",
26+
AnnotationStatus: "True",
27+
AnnotationReason: "DNSDegraded",
28+
},
29+
},
30+
},
31+
},
1932
want: &configv1.ClusterOperatorStatusCondition{
2033
Type: configv1.OperatorDegraded,
2134
Status: configv1.ConditionTrue,
@@ -24,31 +37,33 @@ func TestGetOperatorConditionStatus(t *testing.T) {
2437
},
2538
},
2639
{
27-
name: "unknown",
28-
message: "condition/Upgradeable status/Unknown reason/NoData changed: blah blah",
40+
name: "unknown",
41+
interval: Interval{
42+
Source: SourceClusterOperatorMonitor,
43+
Condition: Condition{
44+
StructuredMessage: Message{
45+
Reason: "NoData",
46+
HumanMessage: "blah blah",
47+
Annotations: map[AnnotationKey]string{
48+
AnnotationCondition: "Upgradeable",
49+
AnnotationStatus: "Unknown",
50+
AnnotationReason: "NoData",
51+
},
52+
},
53+
},
54+
},
2955
want: &configv1.ClusterOperatorStatusCondition{
3056
Type: configv1.OperatorUpgradeable,
3157
Status: configv1.ConditionUnknown,
3258
Reason: "NoData",
3359
Message: "blah blah",
3460
},
3561
},
36-
{
37-
name: "repeat reason",
38-
message: "condition/Available status/True reason/AsExpected changed: reason/again",
39-
want: &configv1.ClusterOperatorStatusCondition{
40-
Type: configv1.OperatorAvailable,
41-
Status: configv1.ConditionTrue,
42-
Reason: "AsExpected",
43-
Message: "reason/again",
44-
},
45-
},
4662
}
4763
for _, tt := range tests {
4864
t.Run(tt.name, func(t *testing.T) {
49-
if got := GetOperatorConditionStatus(tt.message); !reflect.DeepEqual(got, tt.want) {
50-
t.Errorf("GetOperatorConditionStatus() got = %v, want %v", got, tt.want)
51-
}
65+
got := GetOperatorConditionStatus(tt.interval)
66+
assert.Equal(t, tt.want, got)
5267
})
5368
}
5469
}

pkg/monitor/monitorapi/types.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ const (
243243
SourceKubeEvent IntervalSource = "KubeEvent"
244244
SourceTestData IntervalSource = "TestData" // some tests have no real source to assign
245245
SourcePathologicalEventMarker IntervalSource = "PathologicalEventMarker" // not sure if this is really helpful since the events all have a different origin
246+
SourceClusterOperatorMonitor IntervalSource = "ClusterOperatorMonitor"
247+
SourceOperatorState IntervalSource = "OperatorState"
246248
)
247249

248250
type Interval struct {
@@ -264,9 +266,20 @@ func (i Interval) String() string {
264266
}
265267
duration := i.To.Sub(i.From)
266268
if duration < time.Second {
267-
return fmt.Sprintf("%s.%03d - %-5s %s %s %s", i.From.Format("Jan 02 15:04:05"), i.From.Nanosecond()/int(time.Millisecond), strconv.Itoa(int(duration/time.Millisecond))+"ms", i.Level.String()[:1], i.Locator, strings.Replace(i.Message, "\n", "\\n", -1))
268-
}
269-
return fmt.Sprintf("%s.%03d - %-5s %s %s %s", i.From.Format("Jan 02 15:04:05"), i.From.Nanosecond()/int(time.Millisecond), strconv.Itoa(int(duration/time.Second))+"s", i.Level.String()[:1], i.Locator, strings.Replace(i.Message, "\n", "\\n", -1))
269+
return fmt.Sprintf("%s.%03d - %-5s %s %s %s",
270+
i.From.Format("Jan 02 15:04:05"),
271+
i.From.Nanosecond()/int(time.Millisecond),
272+
strconv.Itoa(int(duration/time.Millisecond))+"ms",
273+
i.Level.String()[:1],
274+
i.Locator,
275+
strings.Replace(i.Message, "\n", "\\n", -1))
276+
}
277+
return fmt.Sprintf("%s.%03d - %-5s %s %s %s",
278+
i.From.Format("Jan 02 15:04:05"),
279+
i.From.Nanosecond()/int(time.Millisecond), strconv.Itoa(int(duration/time.Second))+"s",
280+
i.Level.String()[:1],
281+
i.Locator,
282+
strings.Replace(i.Message, "\n", "\\n", -1))
270283
}
271284

272285
func (i Message) OldMessage() string {

pkg/monitor/serialization/serialize.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ type EventInterval struct {
1919
Locator string `json:"locator"`
2020
Message string `json:"message"`
2121

22+
// TODO: Remove the omitempty, just here to keep from having to repeatedly updated the json
23+
// files used in some new tests
24+
Source string `json:"tempSource,omitempty"` // also temporary, unsure if this concept will survive
25+
2226
// TODO: we're hoping to move these to just locator/message when everything is ready.
2327
StructuredLocator monitorapi.Locator `json:"tempStructuredLocator"`
2428
StructuredMessage monitorapi.Message `json:"tempStructuredMessage"`
@@ -60,6 +64,7 @@ func EventsFromJSON(data []byte) (monitorapi.Intervals, error) {
6064
return nil, err
6165
}
6266
events = append(events, monitorapi.Interval{
67+
Source: monitorapi.IntervalSource(interval.Source),
6368
Condition: monitorapi.Condition{
6469
Level: level,
6570
Locator: interval.Locator,
@@ -84,10 +89,13 @@ func IntervalFromJSON(data []byte) (*monitorapi.Interval, error) {
8489
return nil, err
8590
}
8691
return &monitorapi.Interval{
92+
Source: monitorapi.IntervalSource(serializedInterval.Source),
8793
Condition: monitorapi.Condition{
88-
Level: level,
89-
Locator: serializedInterval.Locator,
90-
Message: serializedInterval.Message,
94+
Level: level,
95+
Locator: serializedInterval.Locator,
96+
Message: serializedInterval.Message,
97+
StructuredLocator: serializedInterval.StructuredLocator,
98+
StructuredMessage: serializedInterval.StructuredMessage,
9199
},
92100

93101
From: serializedInterval.From.Time,
@@ -150,6 +158,7 @@ func monitorEventIntervalToEventInterval(interval monitorapi.Interval) EventInte
150158
Message: interval.Message,
151159
StructuredLocator: interval.StructuredLocator,
152160
StructuredMessage: interval.StructuredMessage,
161+
Source: string(interval.Source),
153162

154163
From: metav1.Time{Time: interval.From},
155164
To: metav1.Time{Time: interval.To},

pkg/monitortestframework/panic.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package monitortestframework
33
import (
44
"context"
55
"fmt"
6+
"runtime/debug"
67
"time"
78

9+
"github.com/sirupsen/logrus"
810
"k8s.io/client-go/rest"
911

1012
"github.com/openshift/origin/pkg/monitor/monitorapi"
@@ -15,6 +17,8 @@ func startCollectionWithPanicProtection(ctx context.Context, monitortest Monitor
1517
defer func() {
1618
if r := recover(); r != nil {
1719
err = fmt.Errorf("caught panic: %v", r)
20+
logrus.Error("recovering from panic")
21+
fmt.Print(debug.Stack())
1822
}
1923
}()
2024

@@ -26,6 +30,8 @@ func collectDataWithPanicProtection(ctx context.Context, monitortest MonitorTest
2630
defer func() {
2731
if r := recover(); r != nil {
2832
err = fmt.Errorf("caught panic: %v", r)
33+
logrus.Error("recovering from panic")
34+
fmt.Print(debug.Stack())
2935
}
3036
}()
3137

@@ -37,6 +43,8 @@ func constructComputedIntervalsWithPanicProtection(ctx context.Context, monitort
3743
defer func() {
3844
if r := recover(); r != nil {
3945
err = fmt.Errorf("caught panic: %v", r)
46+
logrus.Error("recovering from panic")
47+
fmt.Print(debug.Stack())
4048
}
4149
}()
4250

@@ -48,6 +56,8 @@ func evaluateTestsFromConstructedIntervalsWithPanicProtection(ctx context.Contex
4856
defer func() {
4957
if r := recover(); r != nil {
5058
err = fmt.Errorf("caught panic: %v", r)
59+
logrus.Error("recovering from panic")
60+
fmt.Print(debug.Stack())
5161
}
5262
}()
5363

@@ -59,6 +69,8 @@ func writeContentToStorageWithPanicProtection(ctx context.Context, monitortest M
5969
defer func() {
6070
if r := recover(); r != nil {
6171
err = fmt.Errorf("caught panic: %v", r)
72+
logrus.Error("recovering from panic")
73+
fmt.Print(debug.Stack())
6274
}
6375
}()
6476

@@ -70,6 +82,8 @@ func cleanupWithPanicProtection(ctx context.Context, monitortest MonitorTest) (e
7082
defer func() {
7183
if r := recover(); r != nil {
7284
err = fmt.Errorf("caught panic: %v", r)
85+
logrus.Error("recovering from panic")
86+
fmt.Print(debug.Stack())
7387
}
7488
}()
7589

0 commit comments

Comments
 (0)