Skip to content

Commit 9aa8b99

Browse files
feat(rabbitmq): Add wait handlers for v2 package (#7949)
Relates to STACKITSDK-465
1 parent 9bed949 commit 9aa8b99

7 files changed

Lines changed: 592 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
- `modelexperiments`:
2020
- [v0.2.0](services/modelexperiments/CHANGELOG.md#v020)
2121
- **New**: STACKIT Model Experiments module wait handler added.
22+
- `rabbitmq`:
23+
- [v1.1.0](/services/rabbitmq/CHANGELOG.md#v110)
24+
- `v2api`:
25+
- **Feature**: Added wait handlers
2226

2327
## Release (2026-06-18)
2428
- `core`:

examples/rabbitmq/go.mod

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ go 1.25
55
// This is not needed in production. This is only here to point the golangci linter to the local version instead of the last release on GitHub.
66
replace github.com/stackitcloud/stackit-sdk-go/services/rabbitmq => ../../services/rabbitmq
77

8-
require (
9-
github.com/stackitcloud/stackit-sdk-go/core v0.26.0
10-
github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.31.0
11-
)
8+
require github.com/stackitcloud/stackit-sdk-go/services/rabbitmq v0.31.0
129

1310
require (
1411
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
1512
github.com/google/uuid v1.6.0 // indirect
13+
github.com/stackitcloud/stackit-sdk-go/core v0.26.0 // indirect
1614
)

examples/rabbitmq/rabbitmq.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,72 @@ import (
55
"fmt"
66
"os"
77

8-
"github.com/stackitcloud/stackit-sdk-go/core/config"
9-
rabbitmq "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v1api"
8+
rabbitmq "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v2api"
9+
wait "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v2api/wait"
1010
)
1111

1212
func main() {
1313
projectId := "PROJECT_ID" // the uuid of your STACKIT project
14+
region := "eu01"
1415
planId := "PLAN_ID"
1516

1617
// Create a new API client, that uses default authentication and configuration
17-
rabbitmqClient, err := rabbitmq.NewAPIClient(
18-
config.WithRegion("eu01"),
19-
)
18+
rabbitmqClient, err := rabbitmq.NewAPIClient()
2019
if err != nil {
2120
fmt.Fprintf(os.Stderr, "Creating API client: %v\n", err)
2221
os.Exit(1)
2322
}
2423

2524
// Get the rabbitmq instances for your project
26-
getInstancesResp, err := rabbitmqClient.DefaultAPI.ListInstances(context.Background(), projectId).Execute()
25+
getInstancesResp, err := rabbitmqClient.DefaultAPI.ListInstances(context.Background(), projectId, region).Execute()
2726
if err != nil {
2827
fmt.Fprintf(os.Stderr, "Error when calling `GetInstances`: %v\n", err)
29-
} else {
30-
fmt.Printf("Number of instances: %v\n", len(getInstancesResp.Instances))
28+
os.Exit(1)
3129
}
30+
fmt.Printf("Number of instances: %v\n", len(getInstancesResp.Instances))
3231

3332
// Get the rabbitmq offerings for your project
34-
getOfferingsResp, err := rabbitmqClient.DefaultAPI.ListOfferings(context.Background(), projectId).Execute()
33+
getOfferingsResp, err := rabbitmqClient.DefaultAPI.ListOfferings(context.Background(), projectId, region).Execute()
3534
if err != nil {
3635
fmt.Fprintf(os.Stderr, "Error when calling `GetOfferings`: %v\n", err)
37-
} else {
38-
fmt.Printf("Offerings: %+v\n", getOfferingsResp.Offerings)
36+
os.Exit(1)
3937
}
38+
fmt.Printf("Offerings: %+v\n", getOfferingsResp.Offerings)
4039

4140
// Create a rabbitmq Instance
4241
createInstancePayload := rabbitmq.CreateInstancePayload{
4342
InstanceName: "exampleInstance",
4443
Parameters: &rabbitmq.InstanceParameters{},
4544
PlanId: planId,
4645
}
47-
createInstanceResp, err := rabbitmqClient.DefaultAPI.CreateInstance(context.Background(), projectId).CreateInstancePayload(createInstancePayload).Execute()
46+
createInstanceResp, err := rabbitmqClient.DefaultAPI.CreateInstance(context.Background(), projectId, region).CreateInstancePayload(createInstancePayload).Execute()
4847
if err != nil {
4948
fmt.Fprintf(os.Stderr, "Error when calling `CreateInstance`: %v\n", err)
50-
} else {
51-
fmt.Printf("Created instance with instance id \"%s\".\n", createInstanceResp.InstanceId)
49+
os.Exit(1)
50+
}
51+
fmt.Printf("Created instance with instance id %q.\n", createInstanceResp.InstanceId)
52+
53+
// Wait for creation of rabbitmq instance
54+
instance, err := wait.CreateInstanceWaitHandler(context.Background(), rabbitmqClient.DefaultAPI, projectId, region, createInstanceResp.InstanceId).WaitWithContext(context.Background())
55+
if err != nil {
56+
fmt.Fprintf(os.Stderr, "Error when waiting for creation: %v\n", err)
57+
os.Exit(1)
58+
}
59+
fmt.Printf("Rabbitmq instance %q has been successfully created.\n", *instance.InstanceId)
60+
61+
// Delete a rabbitmq instance
62+
err = rabbitmqClient.DefaultAPI.DeleteInstance(context.Background(), projectId, region, *instance.InstanceId).Execute()
63+
if err != nil {
64+
fmt.Fprintf(os.Stderr, "Error when calling 'DeleteInstance': %v\n", err)
65+
os.Exit(1)
66+
}
67+
fmt.Printf("Deleting instance with instance id %q.\n", createInstanceResp.InstanceId)
68+
69+
// Wait for deletion of rabbitmq instance
70+
_, err = wait.DeleteInstanceWaitHandler(context.Background(), rabbitmqClient.DefaultAPI, projectId, region, *instance.InstanceId).WaitWithContext(context.Background())
71+
if err != nil {
72+
fmt.Fprintf(os.Stderr, "Error when waiting for deletion: %v\n", err)
73+
os.Exit(1)
5274
}
75+
fmt.Printf("Rabbitmq instance %q has been successfully deleted.\n", *instance.InstanceId)
5376
}

services/rabbitmq/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**: Added wait handlers
4+
15
## v1.0.0
26
- **Breaking Change:** The region is no longer specified within the client configuration. Instead, the region must be passed as a parameter to any region-specific request.
37
- `v2api`:

services/rabbitmq/VERSION

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

0 commit comments

Comments
 (0)