Skip to content

Commit c666d15

Browse files
authored
feat(cockpit): add waiters for alerts (scaleway#2828)
1 parent aaf52ba commit c666d15

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

api/cockpit/v1/cockpit_utils.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package cockpit
2+
3+
import (
4+
"time"
5+
6+
"github.com/scaleway/scaleway-sdk-go/errors"
7+
"github.com/scaleway/scaleway-sdk-go/internal/async"
8+
"github.com/scaleway/scaleway-sdk-go/scw"
9+
)
10+
11+
const (
12+
defaultRetryInterval = 5 * time.Second
13+
defaultTimeout = 5 * time.Minute
14+
)
15+
16+
// WaitForPreconfiguredAlertsRequest is used by WaitForPreconfiguredAlerts method.
17+
type WaitForPreconfiguredAlertsRequest struct {
18+
Region scw.Region
19+
ProjectID string
20+
PreconfiguredRules []string
21+
TargetStatus AlertStatus
22+
Timeout *time.Duration
23+
RetryInterval *time.Duration
24+
}
25+
26+
// WaitForPreconfiguredAlerts waits for multiple preconfigured alerts to reach a target status.
27+
// This function can be used to wait for alerts to be enabled or disabled after calling
28+
// EnableAlertRules or DisableAlertRules.
29+
func (s *RegionalAPI) WaitForPreconfiguredAlerts(req *WaitForPreconfiguredAlertsRequest, opts ...scw.RequestOption) ([]*Alert, error) {
30+
if req == nil {
31+
return nil, errors.New("WaitForPreconfiguredAlertsRequest cannot be nil")
32+
}
33+
34+
if len(req.PreconfiguredRules) == 0 {
35+
return []*Alert{}, nil
36+
}
37+
38+
timeout := defaultTimeout
39+
if req.Timeout != nil {
40+
timeout = *req.Timeout
41+
}
42+
retryInterval := defaultRetryInterval
43+
if req.RetryInterval != nil {
44+
retryInterval = *req.RetryInterval
45+
}
46+
47+
listOpts := append([]scw.RequestOption{scw.WithAllPages()}, opts...)
48+
49+
result, err := async.WaitSync(&async.WaitSyncConfig{
50+
Get: func() (any, bool, error) {
51+
res, err := s.ListAlerts(&RegionalAPIListAlertsRequest{
52+
Region: req.Region,
53+
ProjectID: req.ProjectID,
54+
IsPreconfigured: scw.BoolPtr(true),
55+
}, listOpts...)
56+
if err != nil {
57+
return nil, false, err
58+
}
59+
60+
alertsByRuleID := make(map[string]*Alert, len(res.Alerts))
61+
for _, alert := range res.Alerts {
62+
if alert.PreconfiguredData != nil && alert.PreconfiguredData.PreconfiguredRuleID != "" {
63+
alertsByRuleID[alert.PreconfiguredData.PreconfiguredRuleID] = alert
64+
}
65+
}
66+
67+
matchedAlerts := make([]*Alert, 0, len(req.PreconfiguredRules))
68+
for _, ruleID := range req.PreconfiguredRules {
69+
alert, found := alertsByRuleID[ruleID]
70+
if !found {
71+
return nil, false, nil
72+
}
73+
74+
if !isAlertInTargetStatus(req.TargetStatus, alert.RuleStatus) {
75+
return nil, false, nil
76+
}
77+
78+
matchedAlerts = append(matchedAlerts, alert)
79+
}
80+
81+
return matchedAlerts, true, nil
82+
},
83+
Timeout: timeout,
84+
IntervalStrategy: async.LinearIntervalStrategy(retryInterval),
85+
})
86+
if err != nil {
87+
return nil, errors.Wrap(err, "waiting for preconfigured alerts failed")
88+
}
89+
return result.([]*Alert), nil
90+
}
91+
92+
func isAlertInTargetStatus(target, current AlertStatus) bool {
93+
switch target {
94+
case AlertStatusEnabled:
95+
return current == AlertStatusEnabled
96+
case AlertStatusDisabled:
97+
return current == AlertStatusDisabled
98+
default:
99+
return current == target
100+
}
101+
}

0 commit comments

Comments
 (0)