Skip to content

Commit a9e1e3d

Browse files
authored
feat(mongodb): add waiters for v1 (scaleway#2646)
1 parent 00313fc commit a9e1e3d

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

api/mongodb/v1/mongodb_utils.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package mongodb
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sort"
7+
"time"
8+
9+
"github.com/scaleway/scaleway-sdk-go/errors"
10+
"github.com/scaleway/scaleway-sdk-go/internal/async"
11+
"github.com/scaleway/scaleway-sdk-go/scw"
12+
)
13+
14+
const (
15+
defaultInstanceRetryInterval = 15 * time.Second
16+
defaultInstanceTimeout = 15 * time.Minute
17+
)
18+
19+
// WaitForInstanceRequest is used by WaitForInstance method.
20+
type WaitForInstanceRequest struct {
21+
InstanceID string
22+
Region scw.Region
23+
Timeout *time.Duration
24+
RetryInterval *time.Duration
25+
}
26+
27+
type WaitForSnapshotRequest struct {
28+
InstanceID string
29+
SnapshotID string
30+
Region scw.Region
31+
Timeout *time.Duration
32+
RetryInterval *time.Duration
33+
}
34+
35+
// WaitForInstance waits for the instance to be in a "terminal state" before returning.
36+
// This function can be used to wait for an instance to be ready or in another final state.
37+
func (s *API) WaitForInstance(req *WaitForInstanceRequest, opts ...scw.RequestOption) (*Instance, error) {
38+
timeout := defaultInstanceTimeout
39+
if req.Timeout != nil {
40+
timeout = *req.Timeout
41+
}
42+
retryInterval := defaultInstanceRetryInterval
43+
if req.RetryInterval != nil {
44+
retryInterval = *req.RetryInterval
45+
}
46+
47+
terminalStatus := map[InstanceStatus]struct{}{
48+
InstanceStatusReady: {},
49+
InstanceStatusLocked: {},
50+
InstanceStatusError: {},
51+
}
52+
53+
instance, err := async.WaitSync(&async.WaitSyncConfig{
54+
Get: func() (any, bool, error) {
55+
res, err := s.GetInstance(&GetInstanceRequest{
56+
Region: req.Region,
57+
InstanceID: req.InstanceID,
58+
}, opts...)
59+
if err != nil {
60+
return nil, false, err
61+
}
62+
63+
// Check if the instance has reached a terminal state
64+
_, isTerminal := terminalStatus[res.Status]
65+
66+
return res, isTerminal, nil
67+
},
68+
Timeout: timeout,
69+
IntervalStrategy: async.LinearIntervalStrategy(retryInterval),
70+
})
71+
if err != nil {
72+
return nil, errors.Wrap(err, "waiting for instance failed")
73+
}
74+
return instance.(*Instance), nil
75+
}
76+
77+
// WaitForSnapshot waits for the snapshot to reach a "terminal state" before returning.
78+
func (s *API) WaitForSnapshot(req *WaitForSnapshotRequest, opts ...scw.RequestOption) (*Snapshot, error) {
79+
timeout := defaultInstanceTimeout
80+
if req.Timeout != nil {
81+
timeout = *req.Timeout
82+
}
83+
retryInterval := defaultInstanceRetryInterval
84+
if req.RetryInterval != nil {
85+
retryInterval = *req.RetryInterval
86+
}
87+
88+
terminalStatus := map[SnapshotStatus]struct{}{
89+
SnapshotStatusReady: {},
90+
SnapshotStatusError: {},
91+
SnapshotStatusLocked: {},
92+
}
93+
94+
snapshot, err := async.WaitSync(&async.WaitSyncConfig{
95+
Get: func() (any, bool, error) {
96+
getSnapshotResponse, err := s.GetSnapshot(&GetSnapshotRequest{
97+
Region: req.Region,
98+
SnapshotID: req.SnapshotID,
99+
}, opts...)
100+
if err != nil {
101+
return nil, false, err
102+
}
103+
104+
_, isTerminal := terminalStatus[getSnapshotResponse.Status]
105+
return getSnapshotResponse, isTerminal, nil
106+
},
107+
Timeout: timeout,
108+
IntervalStrategy: async.LinearIntervalStrategy(retryInterval),
109+
})
110+
if err != nil {
111+
return nil, errors.Wrap(err, "waiting for snapshot failed")
112+
}
113+
return snapshot.(*Snapshot), nil
114+
}
115+
116+
func (s *API) FetchLatestEngineVersion() (*Version, error) {
117+
resp, err := s.ListVersions(&ListVersionsRequest{}, scw.WithContext(context.Background()))
118+
if err != nil {
119+
return nil, fmt.Errorf("error fetching MongoDB versions: %w", err)
120+
}
121+
122+
if len(resp.Versions) == 0 {
123+
return nil, errors.New("no MongoDB versions found")
124+
}
125+
126+
sort.Slice(resp.Versions, func(i, j int) bool {
127+
return resp.Versions[i].Version > resp.Versions[j].Version
128+
})
129+
130+
return resp.Versions[0], nil
131+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package sweepers
2+
3+
import (
4+
"fmt"
5+
6+
mongodb "github.com/scaleway/scaleway-sdk-go/api/mongodb/v1alpha1"
7+
"github.com/scaleway/scaleway-sdk-go/logger"
8+
"github.com/scaleway/scaleway-sdk-go/scw"
9+
)
10+
11+
func SweepInstances(scwClient *scw.Client, region scw.Region) error {
12+
mongodbAPI := mongodb.NewAPI(scwClient)
13+
logger.Warningf("sweeper: destroying the mongodb instance in (%s)", region)
14+
listInstance, err := mongodbAPI.ListInstances(&mongodb.ListInstancesRequest{
15+
Region: region,
16+
})
17+
if err != nil {
18+
return fmt.Errorf("error listing mongodb instance in (%s) in sweeper: %w", region, err)
19+
}
20+
21+
for _, instance := range listInstance.Instances {
22+
_, err := mongodbAPI.DeleteInstance(&mongodb.DeleteInstanceRequest{
23+
Region: region,
24+
InstanceID: instance.ID,
25+
})
26+
if err != nil {
27+
return fmt.Errorf("error deleting mongodb instance in sweeper: %w", err)
28+
}
29+
}
30+
31+
return nil
32+
}
33+
34+
func SweepAllLocalities(scwClient *scw.Client) error {
35+
for _, region := range (&mongodb.API{}).Regions() {
36+
err := SweepInstances(scwClient, region)
37+
if err != nil {
38+
return err
39+
}
40+
}
41+
42+
return nil
43+
}

0 commit comments

Comments
 (0)