diff --git a/api/cockpit/v1/cockpit_utils.go b/api/cockpit/v1/cockpit_utils.go new file mode 100644 index 000000000..30c8a285f --- /dev/null +++ b/api/cockpit/v1/cockpit_utils.go @@ -0,0 +1,99 @@ +package cockpit + +import ( + "time" + + "github.com/scaleway/scaleway-sdk-go/errors" + "github.com/scaleway/scaleway-sdk-go/internal/async" + "github.com/scaleway/scaleway-sdk-go/scw" +) + +const ( + defaultRetryInterval = 5 * time.Second + defaultTimeout = 5 * time.Minute +) + +// WaitForPreconfiguredAlertsRequest is used by WaitForPreconfiguredAlerts method. +type WaitForPreconfiguredAlertsRequest struct { + Region scw.Region + ProjectID string + PreconfiguredRules []string + TargetStatus AlertStatus + Timeout *time.Duration + RetryInterval *time.Duration +} + +// WaitForPreconfiguredAlerts waits for multiple preconfigured alerts to reach a target status. +// This function can be used to wait for alerts to be enabled or disabled after calling +// EnableAlertRules or DisableAlertRules. +func (s *RegionalAPI) WaitForPreconfiguredAlerts(req *WaitForPreconfiguredAlertsRequest, opts ...scw.RequestOption) ([]*Alert, error) { + timeout := defaultTimeout + if req.Timeout != nil { + timeout = *req.Timeout + } + retryInterval := defaultRetryInterval + if req.RetryInterval != nil { + retryInterval = *req.RetryInterval + } + + var terminalStatus map[AlertStatus]struct{} + switch req.TargetStatus { + case AlertStatusEnabled: + terminalStatus = map[AlertStatus]struct{}{ + AlertStatusEnabled: {}, + AlertStatusEnabling: {}, + } + case AlertStatusDisabled: + terminalStatus = map[AlertStatus]struct{}{ + AlertStatusDisabled: {}, + AlertStatusDisabling: {}, + } + default: + terminalStatus = map[AlertStatus]struct{}{ + req.TargetStatus: {}, + } + } + + result, err := async.WaitSync(&async.WaitSyncConfig{ + Get: func() (any, bool, error) { + res, err := s.ListAlerts(&RegionalAPIListAlertsRequest{ + Region: req.Region, + ProjectID: req.ProjectID, + IsPreconfigured: scw.BoolPtr(true), + }, opts...) + if err != nil { + return nil, false, err + } + + alertsByRuleID := make(map[string]*Alert) + for _, alert := range res.Alerts { + if alert.PreconfiguredData != nil && alert.PreconfiguredData.PreconfiguredRuleID != "" { + alertsByRuleID[alert.PreconfiguredData.PreconfiguredRuleID] = alert + } + } + + var matchedAlerts []*Alert + for _, ruleID := range req.PreconfiguredRules { + alert, found := alertsByRuleID[ruleID] + if !found { + return nil, false, errors.New("preconfigured alert with rule ID %s not found", ruleID) + } + + _, isTerminal := terminalStatus[alert.RuleStatus] + if !isTerminal { + return nil, false, nil + } + + matchedAlerts = append(matchedAlerts, alert) + } + + return matchedAlerts, true, nil + }, + Timeout: timeout, + IntervalStrategy: async.LinearIntervalStrategy(retryInterval), + }) + if err != nil { + return nil, errors.Wrap(err, "waiting for preconfigured alerts failed") + } + return result.([]*Alert), nil +} diff --git a/api/cockpit/v1/sweepers/sweepers.go b/api/cockpit/v1/sweepers/sweepers.go index 4a401332d..58c9eacf4 100644 --- a/api/cockpit/v1/sweepers/sweepers.go +++ b/api/cockpit/v1/sweepers/sweepers.go @@ -57,6 +57,7 @@ func SweepGrafanaUser(scwClient *scw.Client) error { continue } + //nolint:staticcheck // Deprecated functions are still functional and needed for sweepers listGrafanaUsers, err := cockpitAPI.ListGrafanaUsers(&cockpit.GlobalAPIListGrafanaUsersRequest{ ProjectID: project.ID, }, scw.WithAllPages()) @@ -65,6 +66,7 @@ func SweepGrafanaUser(scwClient *scw.Client) error { } for _, grafanaUser := range listGrafanaUsers.GrafanaUsers { + //nolint:staticcheck // Deprecated functions are still functional and needed for sweepers err = cockpitAPI.DeleteGrafanaUser(&cockpit.GlobalAPIDeleteGrafanaUserRequest{ ProjectID: project.ID, GrafanaUserID: grafanaUser.ID, diff --git a/api/domain/v2beta1/domain_utils.go b/api/domain/v2beta1/domain_utils.go index 909b7064f..2deacac7a 100644 --- a/api/domain/v2beta1/domain_utils.go +++ b/api/domain/v2beta1/domain_utils.go @@ -58,7 +58,6 @@ func (s *API) WaitForDNSZone( listReq.DNSZone = &req.DNSZone } - // listing dnsZone zones and take the first one DNSZones, err := s.ListDNSZones(listReq, opts...) if err != nil { return nil, false, err @@ -108,7 +107,6 @@ func (s *API) WaitForDNSRecordExist( dns, err := async.WaitSync(&async.WaitSyncConfig{ Get: func() (any, bool, error) { - // listing dns zone records and take the first one DNSRecords, err := s.ListDNSZoneRecords(&ListDNSZoneRecordsRequest{ Name: req.RecordName, Type: req.RecordType, @@ -157,7 +155,6 @@ func (s *RegistrarAPI) WaitForOrderDomain( retryInterval = *req.RetryInterval } - // Terminal statuses indicating success or error. terminalStatuses := map[DomainStatus]struct{}{ DomainStatusActive: {}, DomainStatusExpired: {}, @@ -205,7 +202,6 @@ type WaitForAutoRenewStatusRequest struct { // WaitForAutoRenewStatus polls the domain until its auto‑renew feature reaches a terminal state // (either "enabled" or "disabled"). It uses GetDomain() to fetch the current status. func (s *RegistrarAPI) WaitForAutoRenewStatus(req *WaitForAutoRenewStatusRequest, opts ...scw.RequestOption) (*Domain, error) { - // Use default timeout and retry interval if not provided. timeout := defaultTimeout if req.Timeout != nil { timeout = *req.Timeout @@ -215,7 +211,6 @@ func (s *RegistrarAPI) WaitForAutoRenewStatus(req *WaitForAutoRenewStatusRequest retryInterval = *req.RetryInterval } - // Terminal statuses for auto_renew: enabled or disabled. terminalStatuses := map[DomainFeatureStatus]struct{}{ DomainFeatureStatusEnabled: {}, DomainFeatureStatusDisabled: {}, @@ -257,7 +252,6 @@ type WaitForDNSSECStatusRequest struct { // WaitForDNSSECStatus polls the domain until its DNSSEC feature reaches a terminal state // (either "enabled" or "disabled"). It uses GetDomain() to fetch the current status. func (s *RegistrarAPI) WaitForDNSSECStatus(req *WaitForDNSSECStatusRequest, opts ...scw.RequestOption) (*Domain, error) { - // Use default timeout and retry interval if not provided. timeout := defaultTimeout if req.Timeout != nil { timeout = *req.Timeout @@ -267,7 +261,6 @@ func (s *RegistrarAPI) WaitForDNSSECStatus(req *WaitForDNSSECStatusRequest, opts retryInterval = *req.RetryInterval } - // Terminal statuses for DNSSEC: enabled or disabled. terminalStatuses := map[DomainFeatureStatus]struct{}{ DomainFeatureStatusEnabled: {}, DomainFeatureStatusDisabled: {}, @@ -277,7 +270,6 @@ func (s *RegistrarAPI) WaitForDNSSECStatus(req *WaitForDNSSECStatusRequest, opts domainResult, err := async.WaitSync(&async.WaitSyncConfig{ Get: func() (any, bool, error) { - // Retrieve the domain. resp, err := s.GetDomain(&RegistrarAPIGetDomainRequest{ Domain: req.Domain, }, opts...) @@ -285,7 +277,6 @@ func (s *RegistrarAPI) WaitForDNSSECStatus(req *WaitForDNSSECStatusRequest, opts return nil, false, err } - // Check the current DNSSEC status. lastStatus = resp.Dnssec.Status if _, isTerminal := terminalStatuses[resp.Dnssec.Status]; isTerminal { return resp, true, nil