From 5fc59648fe3954e7d809069cf0759d3fac663484 Mon Sep 17 00:00:00 2001 From: Carlo Goetz Date: Wed, 5 Aug 2026 16:21:04 +0200 Subject: [PATCH 1/3] fix(sqlserverflex): add missing Create- and DeleteUserWaithandler STACKITSDK-524 --- CHANGELOG.md | 4 + services/sqlserverflex/CHANGELOG.md | 4 + services/sqlserverflex/VERSION | 2 +- services/sqlserverflex/v3api/wait/wait.go | 47 ++++++ .../sqlserverflex/v3api/wait/wait_test.go | 142 ++++++++++++++++++ 5 files changed, 198 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 104463855..c5ec4996b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,6 +100,10 @@ - **Feature:** Add fields `Labels` and `Maintenance` to model struct `Cluster` and `CreateOrUpdateClusterPayload` - **Feature:** Add field `ApplicationLoadBalancer` to model struct `Extension` - **Feature:** Add field `Cni` to model struct `Network` +- `sqlserverflex`: + - [v1.16.2](services/sqlserverflex/CHANGELOG.md#v1162) + - `v3api`: + - **Bugfix:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` - `telemetrylink`: - [v0.5.0](services/telemetrylink/CHANGELOG.md#v050) - **Improvement:** Add validation for `Description` field diff --git a/services/sqlserverflex/CHANGELOG.md b/services/sqlserverflex/CHANGELOG.md index bdfff88df..21de69d5a 100644 --- a/services/sqlserverflex/CHANGELOG.md +++ b/services/sqlserverflex/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.16.2 +- `v3api`: + - **Bugfix:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` + ## v1.16.1 - **Improvement**: Improve http error handling - `v3api`: **Improvement**: Improve http error handling diff --git a/services/sqlserverflex/VERSION b/services/sqlserverflex/VERSION index 2171feba4..2d1081d67 100644 --- a/services/sqlserverflex/VERSION +++ b/services/sqlserverflex/VERSION @@ -1 +1 @@ -v1.16.1 \ No newline at end of file +v1.16.2 diff --git a/services/sqlserverflex/v3api/wait/wait.go b/services/sqlserverflex/v3api/wait/wait.go index 6881f1d54..e6cc761ce 100644 --- a/services/sqlserverflex/v3api/wait/wait.go +++ b/services/sqlserverflex/v3api/wait/wait.go @@ -6,6 +6,7 @@ import ( "net/http" "time" + "github.com/stackitcloud/stackit-sdk-go/core/oapierror" "github.com/stackitcloud/stackit-sdk-go/core/wait" sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3api" ) @@ -66,3 +67,49 @@ func DeleteInstanceWaitHandler(ctx context.Context, client sqlserverflex.Default handler.SetTimeout(15 * time.Minute) return handler } + +const userActiveState = "PROCESSED" + +// CreateUserWaitHandler will wait for user creation +func CreateUserWaitHandler(ctx context.Context, client sqlserverflex.DefaultAPI, projectId, region, instanceId string, userId int64) *wait.AsyncActionHandler[sqlserverflex.GetUserResponse] { + waitConfig := wait.WaiterHelper[sqlserverflex.GetUserResponse, string]{ + FetchInstance: client.GetUser(ctx, projectId, region, instanceId, userId).Execute, + GetState: func(resp *sqlserverflex.GetUserResponse) (string, error) { + if resp == nil { + return "", errors.New("empty response") + } + if resp.Status == "" { + return "", errors.New("state is missing in response") + } + return resp.Status, nil + }, + ActiveState: []string{userActiveState}, + ErrorState: []string{}, + // The API does not have a dedicated failure state for this resource, + // so we rely on the timeout for cases where it never becomes active. + } + handler := wait.New(waitConfig.Wait()) + handler.SetSleepBeforeWait(5 * time.Second) + handler.SetTimeout(15 * time.Minute) + return handler +} + +// DeleteUserWaitHandler will wait for user deletion +func DeleteUserWaitHandler(ctx context.Context, a sqlserverflex.DefaultAPI, projectId, region, instanceId string, userId int64) *wait.AsyncActionHandler[struct{}] { + handler := wait.New(func() (waitFinished bool, response *struct{}, err error) { + _, err = a.GetUser(ctx, projectId, region, instanceId, userId).Execute() + if err == nil { + return false, nil, nil + } + 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 + if !ok { + return false, nil, err + } + if oapiErr.StatusCode != 404 { + return false, nil, err + } + return true, nil, nil + }) + handler.SetTimeout(1 * time.Minute) + return handler +} diff --git a/services/sqlserverflex/v3api/wait/wait_test.go b/services/sqlserverflex/v3api/wait/wait_test.go index 3f61f0156..8c7c8210e 100644 --- a/services/sqlserverflex/v3api/wait/wait_test.go +++ b/services/sqlserverflex/v3api/wait/wait_test.go @@ -20,6 +20,10 @@ type mockSettings struct { instanceState sqlserverflex.State instanceIsDeleted bool instanceGetFails bool + userGetFails bool + userId int64 + userIsDeleted bool + userStatus string } // Used for testing instance operations @@ -43,6 +47,24 @@ func newAPIMock(settings mockSettings) sqlserverflex.DefaultAPI { State: settings.instanceState, }, nil }), + GetUserExecuteMock: utils.Ptr(func(_ sqlserverflex.ApiGetUserRequest) (*sqlserverflex.GetUserResponse, error) { + if settings.userGetFails { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: 423, + } + } + + if settings.userIsDeleted { + return nil, &oapierror.GenericOpenAPIError{ + StatusCode: 404, + } + } + + return &sqlserverflex.GetUserResponse{ + Id: settings.userId, + Status: settings.userStatus, + }, nil + }), } } @@ -189,3 +211,123 @@ func TestDeleteInstanceWaitHandler(t *testing.T) { }) } } + +func TestCreateUserWaitHandler(t *testing.T) { + tests := []struct { + desc string + userGetFails bool + userStatus string + usersGetErrorStatus int + wantErr bool + wantResp bool + }{ + { + desc: "create_succeeded", + userGetFails: false, + userStatus: userActiveState, + wantErr: false, + wantResp: true, + }, + { + desc: "user_get_fails", + userGetFails: true, + wantErr: true, + wantResp: false, + }, + { + desc: "users_get_fails", + userGetFails: true, + usersGetErrorStatus: 423, + wantErr: true, + wantResp: false, + }, + { + desc: "timeout", + userGetFails: false, + userStatus: "", + wantErr: true, + wantResp: false, + }, + } + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + userId := int64(34) + + apiClient := newAPIMock(mockSettings{ + userGetFails: tt.userGetFails, + userId: userId, + userStatus: tt.userStatus, + }) + + var wantRes *sqlserverflex.GetUserResponse + if tt.wantResp { + wantRes = &sqlserverflex.GetUserResponse{ + Id: userId, + Status: tt.userStatus, + } + } + + handler := CreateUserWaitHandler(context.Background(), apiClient, "", "", "", userId) + + gotRes, err := handler.WaitWithContext(context.Background()) + + if (err != nil) != tt.wantErr { + t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr) + } + if !cmp.Equal(gotRes, wantRes) { + t.Fatalf("handler gotRes = %v, want %v", gotRes, wantRes) + } + }) + }) + } +} + +func TestDeleteUserWaitHandler(t *testing.T) { + tests := []struct { + desc string + deleteFails bool + getFails bool + wantErr bool + }{ + { + desc: "delete_succeeded", + deleteFails: false, + getFails: false, + wantErr: false, + }, + { + desc: "delete_failed", + deleteFails: true, + getFails: false, + wantErr: true, + }, + { + desc: "get_fails", + deleteFails: false, + getFails: true, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.desc, func(t *testing.T) { + synctest.Test(t, func(t *testing.T) { + userId := int64(34) + + apiClient := newAPIMock(mockSettings{ + userGetFails: tt.getFails, + userId: userId, + userIsDeleted: !tt.deleteFails, + }) + + handler := DeleteUserWaitHandler(context.Background(), apiClient, "", "", "", userId) + + _, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background()) + + if (err != nil) != tt.wantErr { + t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr) + } + }) + }) + } +} From 784d5f805239b0361479bd9c272dfc4a9abeaba6 Mon Sep 17 00:00:00 2001 From: Carlo Goetz Date: Wed, 5 Aug 2026 17:07:53 +0200 Subject: [PATCH 2/3] fix(sqlserverflex): move const, use errors.As --- services/sqlserverflex/v3api/wait/wait.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/sqlserverflex/v3api/wait/wait.go b/services/sqlserverflex/v3api/wait/wait.go index e6cc761ce..0b78fbbdb 100644 --- a/services/sqlserverflex/v3api/wait/wait.go +++ b/services/sqlserverflex/v3api/wait/wait.go @@ -11,6 +11,8 @@ import ( sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3api" ) +const userActiveState = "PROCESSED" + func createOrUpdateInstanceWaitHandler(ctx context.Context, client sqlserverflex.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] { waitConfig := wait.WaiterHelper[sqlserverflex.GetInstanceResponse, sqlserverflex.State]{ FetchInstance: client.GetInstance(ctx, projectId, region, instanceId).Execute, @@ -68,8 +70,6 @@ func DeleteInstanceWaitHandler(ctx context.Context, client sqlserverflex.Default return handler } -const userActiveState = "PROCESSED" - // CreateUserWaitHandler will wait for user creation func CreateUserWaitHandler(ctx context.Context, client sqlserverflex.DefaultAPI, projectId, region, instanceId string, userId int64) *wait.AsyncActionHandler[sqlserverflex.GetUserResponse] { waitConfig := wait.WaiterHelper[sqlserverflex.GetUserResponse, string]{ @@ -101,8 +101,8 @@ func DeleteUserWaitHandler(ctx context.Context, a sqlserverflex.DefaultAPI, proj if err == nil { return false, nil, nil } - 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 - if !ok { + var oapiErr *oapierror.GenericOpenAPIError + if !errors.As(err, &oapiErr) { return false, nil, err } if oapiErr.StatusCode != 404 { From 74b349d09998f6559b6c3078f7b4a16130414522 Mon Sep 17 00:00:00 2001 From: Carlo Goetz Date: Wed, 5 Aug 2026 17:19:44 +0200 Subject: [PATCH 3/3] fix(sqlserverflex): use feature instead of bugfix, adjust version --- CHANGELOG.md | 4 ++-- services/sqlserverflex/CHANGELOG.md | 4 ++-- services/sqlserverflex/VERSION | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ec4996b..1823cf28f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -101,9 +101,9 @@ - **Feature:** Add field `ApplicationLoadBalancer` to model struct `Extension` - **Feature:** Add field `Cni` to model struct `Network` - `sqlserverflex`: - - [v1.16.2](services/sqlserverflex/CHANGELOG.md#v1162) + - [v1.17.0](services/sqlserverflex/CHANGELOG.md#v1170) - `v3api`: - - **Bugfix:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` + - **Feature:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` - `telemetrylink`: - [v0.5.0](services/telemetrylink/CHANGELOG.md#v050) - **Improvement:** Add validation for `Description` field diff --git a/services/sqlserverflex/CHANGELOG.md b/services/sqlserverflex/CHANGELOG.md index 21de69d5a..8d80b37c3 100644 --- a/services/sqlserverflex/CHANGELOG.md +++ b/services/sqlserverflex/CHANGELOG.md @@ -1,6 +1,6 @@ -## v1.16.2 +## v1.17.0 - `v3api`: - - **Bugfix:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` + - **Feature:** add missing `DeleteUserWaitHandler` and `CreateUserWaitHandler` ## v1.16.1 - **Improvement**: Improve http error handling diff --git a/services/sqlserverflex/VERSION b/services/sqlserverflex/VERSION index 2d1081d67..07c3efad8 100644 --- a/services/sqlserverflex/VERSION +++ b/services/sqlserverflex/VERSION @@ -1 +1 @@ -v1.16.2 +v1.17.0