Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Release (upcoming)
- `rabbitmq`:
- [v1.1.0](/services/rabbitmq/CHANGELOG.md#v110)
- `v2api`:
- **Feature**: Added wait handlers

## Release (2026-06-18)
- `core`:
- [v0.25.0](core/CHANGELOG.md#v0250)
Expand Down
33 changes: 29 additions & 4 deletions examples/rabbitmq/rabbitmq.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (
"os"

"github.com/stackitcloud/stackit-sdk-go/core/config"
rabbitmq "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v1api"
rabbitmq "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v2api"
wait "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v2api/wait"
)

func main() {
projectId := "PROJECT_ID" // the uuid of your STACKIT project
region := "eu01"
planId := "PLAN_ID"

// Create a new API client, that uses default authentication and configuration

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't comment the correct line, but with the change from v1 to v2, the configuration of the client should be without the region, because they will be configured on endpoint level.
Can you remove config.WithRegion("eu01") of the client configuration?

Expand All @@ -23,15 +25,15 @@ func main() {
}

// Get the rabbitmq instances for your project
getInstancesResp, err := rabbitmqClient.DefaultAPI.ListInstances(context.Background(), projectId).Execute()
getInstancesResp, err := rabbitmqClient.DefaultAPI.ListInstances(context.Background(), projectId, region).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `GetInstances`: %v\n", err)
} else {
Comment on lines 30 to 31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add an os.Exit(1) in the error case?

fmt.Printf("Number of instances: %v\n", len(getInstancesResp.Instances))
}

// Get the rabbitmq offerings for your project
getOfferingsResp, err := rabbitmqClient.DefaultAPI.ListOfferings(context.Background(), projectId).Execute()
getOfferingsResp, err := rabbitmqClient.DefaultAPI.ListOfferings(context.Background(), projectId, region).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `GetOfferings`: %v\n", err)
} else {
Comment on lines 38 to 39

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Expand All @@ -44,10 +46,33 @@ func main() {
Parameters: &rabbitmq.InstanceParameters{},
PlanId: planId,
}
createInstanceResp, err := rabbitmqClient.DefaultAPI.CreateInstance(context.Background(), projectId).CreateInstancePayload(createInstancePayload).Execute()
createInstanceResp, err := rabbitmqClient.DefaultAPI.CreateInstance(context.Background(), projectId, region).CreateInstancePayload(createInstancePayload).Execute()
Comment thread
marceljk marked this conversation as resolved.
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `CreateInstance`: %v\n", err)
} else {
Comment on lines 51 to 52

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here. otherwise it will fail in the call of waithandler with a nil pointer exception

fmt.Printf("Created instance with instance id \"%s\".\n", createInstanceResp.InstanceId)
}

// Wait for creation of rabbitmq instance
instance, err := wait.CreateInstanceWaitHandler(context.Background(), rabbitmqClient.DefaultAPI, projectId, region, createInstanceResp.InstanceId).WaitWithContext(context.Background())
if err != nil {
fmt.Fprintf(os.Stderr, "Error when waiting for creation: %v\n", err)
os.Exit(1)
}
fmt.Printf("Rabbitmq instance %v has been successfully created.", instance.InstanceId)

// Delete a rabbitmq instance
err = rabbitmqClient.DefaultAPI.DeleteInstance(context.Background(), projectId, region, *instance.InstanceId).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling 'DeleteInstance': %v\n", err)
os.Exit(1)
}

// Wait for deletaion of rabbitmq instance
_, err = wait.DeleteInstanceWaitHandler(context.Background(), rabbitmqClient.DefaultAPI, projectId, region, *instance.InstanceId).WaitWithContext(context.Background())
if err != nil {
fmt.Fprintf(os.Stderr, "Error when waiting for deletion: %v\n", err)
os.Exit(1)
}
fmt.Printf("Rabbitmq instance %v has been successfully deleted.", instance.InstanceId)
}
4 changes: 4 additions & 0 deletions services/rabbitmq/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v1.1.0
- `v2api`:
- **Feature**: Added wait handlers

## v1.0.0
- **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.
- `v2api`:
Expand Down
2 changes: 1 addition & 1 deletion services/rabbitmq/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1.0.0
v1.1.0
134 changes: 134 additions & 0 deletions services/rabbitmq/v2api/wait/wait.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package wait

import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"time"

"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/wait"
rabbitmq "github.com/stackitcloud/stackit-sdk-go/services/rabbitmq/v2api"
)

// CreateInstanceWaitHandler will wait for instance creation
func CreateInstanceWaitHandler(ctx context.Context, client rabbitmq.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[rabbitmq.Instance] {
waitConfig := wait.WaiterHelper[rabbitmq.Instance, rabbitmq.InstanceStatus]{
FetchInstance: client.GetInstance(ctx, projectId, region, instanceId).Execute,
GetState: func(response *rabbitmq.Instance) (rabbitmq.InstanceStatus, error) {
if response == nil {
return "", errors.New("empty response")
}
if response.Status == nil {
return "", errors.New("status is missing in response")
}
return *response.Status, nil
},
ActiveState: []rabbitmq.InstanceStatus{rabbitmq.INSTANCESTATUS_ACTIVE},
ErrorState: []rabbitmq.InstanceStatus{rabbitmq.INSTANCESTATUS_FAILED},
}

handler := wait.New(waitConfig.Wait())
handler.SetTimeout(45 * time.Minute)
return handler
}

// PartialUpdateInstanceWaitHandler will wait for instance update
func PartialUpdateInstanceWaitHandler(ctx context.Context, client rabbitmq.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[rabbitmq.Instance] {
waitConfig := wait.WaiterHelper[rabbitmq.Instance, rabbitmq.InstanceStatus]{
FetchInstance: client.GetInstance(ctx, projectId, region, instanceId).Execute,
GetState: func(response *rabbitmq.Instance) (rabbitmq.InstanceStatus, error) {
if response == nil {
return "", errors.New("empty response")
}
if response.Status == nil {
return "", errors.New("status is missing in response")
}
return *response.Status, nil
},
ActiveState: []rabbitmq.InstanceStatus{rabbitmq.INSTANCESTATUS_ACTIVE},
ErrorState: []rabbitmq.InstanceStatus{rabbitmq.INSTANCESTATUS_FAILED},
}

handler := wait.New(waitConfig.Wait())
handler.SetTimeout(45 * time.Minute)
return handler
}

// DeleteInstanceWaitHandler will wait for instance deletion
func DeleteInstanceWaitHandler(ctx context.Context, a rabbitmq.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
s, err := a.GetInstance(ctx, projectId, region, instanceId).Execute()
if err == nil {
if s.Status == nil {
return false, nil, fmt.Errorf("delete failed for instance with id %s. The response is not valid: The status is missing", instanceId)
}
if *s.Status == rabbitmq.INSTANCESTATUS_ACTIVE {
if strings.Contains(s.LastOperation.Description, "DeleteFailed") || strings.Contains(s.LastOperation.Description, "failed") {
return true, nil, fmt.Errorf("instance was deleted successfully but has errors: %s", s.LastOperation.Description)
}
return true, nil, nil
}
return false, nil, nil
}
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusGone {
return false, nil, err
}
return true, nil, nil
})
handler.SetTimeout(15 * time.Minute)
return handler
}

// CreateCredentialsWaitHandler will wait for credentials creation
func CreateCredentialsWaitHandler(ctx context.Context, a rabbitmq.DefaultAPI, projectId, region, instanceId, credentialsId string) *wait.AsyncActionHandler[rabbitmq.CredentialsResponse] {
handler := wait.New(func() (waitFinished bool, response *rabbitmq.CredentialsResponse, err error) {
s, err := a.GetCredentials(ctx, projectId, region, instanceId, credentialsId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
// If the request returns 404, the credentials have not been created yet
if oapiErr.StatusCode == http.StatusNotFound {
return false, nil, nil
}
return false, nil, err
}
if s.Id == credentialsId {
return true, s, nil
}
return false, nil, nil
})
handler.SetTimeout(1 * time.Minute)
return handler
}

// DeleteCredentialsWaitHandler will wait for credentials deletion
func DeleteCredentialsWaitHandler(ctx context.Context, a rabbitmq.DefaultAPI, projectId, region, instanceId, credentialsId string) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
_, err = a.GetCredentials(ctx, projectId, region, instanceId, credentialsId).Execute()
if err == nil {
return false, nil, nil
}
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusNotFound && oapiErr.StatusCode != http.StatusGone {
return false, nil, err
}
return true, nil, nil
})
handler.SetTimeout(1 * time.Minute)
return handler
}
Loading
Loading