Skip to content

Commit 0d82944

Browse files
feat(opensearch): add wait handlers to v2 opensearch api (#8484)
1 parent 8c9cba6 commit 0d82944

5 files changed

Lines changed: 464 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
## Release (2026-MM-DD)
22

3-
43
- `alb`
54
- [v0.16.0](services/alb/CHANGELOG.md#v0160)
65
- **Breaking change**: Remove `v2beta2api` API
@@ -37,6 +36,9 @@
3736
- [v0.2.0](services/modelexperiments/CHANGELOG.md#v020)
3837
- **New**: STACKIT Model Experiments module wait handler added.
3938
- `opensearch`:
39+
- [v1.1.0](services/opensearch/CHANGELOG.md#v110)
40+
- `v2api`
41+
- **Feature**: Add `wait` handlers
4042
- [v1.0.1](services/opensearch/CHANGELOG.md#v101)
4143
- `v1api`:
4244
- **Improvement**: Improve http error handling

services/opensearch/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## v1.1.0
2+
- `v2api`
3+
- **Feature**: Add `wait` handlers
4+
15
## v1.0.1
26
- `v1api`:
37
- **Improvement**: Improve http error handling

services/opensearch/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.0.1
1+
v1.1.0
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
"strings"
9+
"time"
10+
11+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
12+
"github.com/stackitcloud/stackit-sdk-go/core/wait"
13+
opensearch "github.com/stackitcloud/stackit-sdk-go/services/opensearch/v2api"
14+
)
15+
16+
// CreateInstanceWaitHandler will wait for instance creation
17+
func CreateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] {
18+
return createOrUpdateInstanceWaitHandler(ctx, a, projectId, region, instanceId)
19+
}
20+
21+
// PartialUpdateInstanceWaitHandler will wait for instance update
22+
func PartialUpdateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] {
23+
return createOrUpdateInstanceWaitHandler(ctx, a, projectId, region, instanceId)
24+
}
25+
26+
// DeleteInstanceWaitHandler will wait for instance deletion
27+
func DeleteInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[struct{}] {
28+
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
29+
s, err := a.GetInstance(ctx, projectId, region, instanceId).Execute()
30+
if err == nil {
31+
if s.Status == nil {
32+
return false, nil, fmt.Errorf("delete failed for instance with id %s. The response is not valid: The status is missing", instanceId)
33+
}
34+
if *s.Status != opensearch.INSTANCESTATUS_DELETING {
35+
return false, nil, nil
36+
}
37+
if *s.Status == opensearch.INSTANCESTATUS_ACTIVE {
38+
if strings.Contains(s.LastOperation.Description, "DeleteFailed") || strings.Contains(s.LastOperation.Description, "failed") {
39+
return true, nil, fmt.Errorf("instance was deleted successfully but has errors: %s", s.LastOperation.Description)
40+
}
41+
return true, nil, nil
42+
}
43+
return false, nil, nil
44+
}
45+
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
46+
if !ok {
47+
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
48+
}
49+
if oapiErr.StatusCode != http.StatusGone {
50+
return false, nil, err
51+
}
52+
return true, nil, nil
53+
})
54+
handler.SetTimeout(15 * time.Minute)
55+
return handler
56+
}
57+
58+
// CreateCredentialsWaitHandler will wait for credentials creation
59+
func CreateCredentialsWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId, credentialsId string) *wait.AsyncActionHandler[opensearch.CredentialsResponse] {
60+
handler := wait.New(func() (waitFinished bool, response *opensearch.CredentialsResponse, err error) {
61+
s, err := a.GetCredentials(ctx, projectId, region, instanceId, credentialsId).Execute()
62+
if err != nil {
63+
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
64+
if !ok {
65+
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
66+
}
67+
// If the request returns 404, the credentials have not been created yet
68+
if oapiErr.StatusCode == http.StatusNotFound {
69+
return false, nil, nil
70+
}
71+
return false, nil, err
72+
}
73+
if s.Id == credentialsId {
74+
return true, s, nil
75+
}
76+
return false, nil, nil
77+
})
78+
handler.SetTimeout(1 * time.Minute)
79+
return handler
80+
}
81+
82+
// DeleteCredentialsWaitHandler will wait for credentials deletion
83+
func DeleteCredentialsWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId, credentialsId string) *wait.AsyncActionHandler[struct{}] {
84+
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
85+
_, err = a.GetCredentials(ctx, projectId, region, instanceId, credentialsId).Execute()
86+
if err == nil {
87+
return false, nil, nil
88+
}
89+
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
90+
if !ok {
91+
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
92+
}
93+
if oapiErr.StatusCode != http.StatusNotFound && oapiErr.StatusCode != http.StatusGone {
94+
return false, nil, err
95+
}
96+
return true, nil, nil
97+
})
98+
handler.SetTimeout(1 * time.Minute)
99+
return handler
100+
}
101+
102+
func createOrUpdateInstanceWaitHandler(ctx context.Context, a opensearch.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[opensearch.Instance] {
103+
waitConfig := wait.WaiterHelper[opensearch.Instance, opensearch.InstanceStatus]{
104+
FetchInstance: a.GetInstance(ctx, projectId, region, instanceId).Execute,
105+
GetState: func(s *opensearch.Instance) (opensearch.InstanceStatus, error) {
106+
if s == nil {
107+
return "", errors.New("empty response")
108+
}
109+
if s.Status == nil {
110+
return "", errors.New("status is missing")
111+
}
112+
return *s.Status, nil
113+
},
114+
ActiveState: []opensearch.InstanceStatus{opensearch.INSTANCESTATUS_ACTIVE},
115+
ErrorState: []opensearch.InstanceStatus{opensearch.INSTANCESTATUS_FAILED},
116+
}
117+
118+
handler := wait.New(waitConfig.Wait())
119+
handler.SetTimeout(45 * time.Minute)
120+
return handler
121+
}

0 commit comments

Comments
 (0)