diff --git a/stackit/internal/services/sqlserverflex/database/resource.go b/stackit/internal/services/sqlserverflex/database/resource.go index e47852549..1e6bacb93 100644 --- a/stackit/internal/services/sqlserverflex/database/resource.go +++ b/stackit/internal/services/sqlserverflex/database/resource.go @@ -202,7 +202,9 @@ func (r *databaseResource) Create(ctx context.Context, req resource.CreateReques ctx = core.InitProviderContext(ctx) - _, err = r.client.DefaultAPI.CreateDatabase(ctx, projectId, region, instanceId).CreateDatabasePayload(*payload).Execute() + // Workaround: The database creation will be tried 5 times. In some cases the instance might be + // in maintenance mode and the database API is temporarily unavailable. Usually this is only for 1-2 seconds. + _, err = utils.RetryRequest(ctx, r.client.DefaultAPI.CreateDatabase(ctx, projectId, region, instanceId).CreateDatabasePayload(*payload).Execute, sqlserverflexUtils.RetryConfig) if err != nil { resp.Diagnostics.AddError("Error creating database", err.Error()) return @@ -314,7 +316,9 @@ func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteReques ctx = core.InitProviderContext(ctx) - err := r.client.DefaultAPI.DeleteDatabase(ctx, projectId, region, instanceId, name).Execute() + // Workaround: The database deletion will be tried 5 times. In some cases the instance might be + // in maintenance mode and the database API is temporarily unavailable. Usually this is only for 1-2 seconds. + err := utils.RetryRequestWithoutResponse(ctx, r.client.DefaultAPI.DeleteDatabase(ctx, projectId, region, instanceId, name).Execute, sqlserverflexUtils.RetryConfig) if err != nil { if oapiErr, ok := errors.AsType[*oapierror.GenericOpenAPIError](err); ok && oapiErr.StatusCode == http.StatusNotFound { return diff --git a/stackit/internal/services/sqlserverflex/user/resource.go b/stackit/internal/services/sqlserverflex/user/resource.go index 6f2b11401..627a83dc8 100644 --- a/stackit/internal/services/sqlserverflex/user/resource.go +++ b/stackit/internal/services/sqlserverflex/user/resource.go @@ -263,7 +263,9 @@ func (r *userResource) Create(ctx context.Context, req resource.CreateRequest, r return } // Create new user - userResp, err := r.client.DefaultAPI.CreateUser(ctx, projectId, region, instanceId).CreateUserPayload(*payload).Execute() + // Workaround: The user creation will be tried 5 times. In some cases the instance might be + // in maintenance mode and the user API is temporarily unavailable. Usually this is only for 1-2 seconds. + userResp, err := utils.RetryRequest(ctx, r.client.DefaultAPI.CreateUser(ctx, projectId, region, instanceId).CreateUserPayload(*payload).Execute, sqlserverflexUtils.RetryConfig) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating user", fmt.Sprintf("Calling API: %v", err)) return @@ -389,7 +391,9 @@ func (r *userResource) Delete(ctx context.Context, req resource.DeleteRequest, r } // Delete existing user - err = r.client.DefaultAPI.DeleteUser(ctx, projectId, region, instanceId, userId).Execute() + // Workaround: The user deletion will be tried 5 times. In some cases the instance might be + // in maintenance mode and the user API is temporarily unavailable. Usually this is only for 1-2 seconds. + err = utils.RetryRequestWithoutResponse(ctx, r.client.DefaultAPI.DeleteUser(ctx, projectId, region, instanceId, userId).Execute, sqlserverflexUtils.RetryConfig) if err != nil { if oapiErr, ok := errors.AsType[*oapierror.GenericOpenAPIError](err); ok && oapiErr.StatusCode == http.StatusNotFound { return diff --git a/stackit/internal/services/sqlserverflex/utils/util.go b/stackit/internal/services/sqlserverflex/utils/util.go index f4b50fe52..07e48c1c1 100644 --- a/stackit/internal/services/sqlserverflex/utils/util.go +++ b/stackit/internal/services/sqlserverflex/utils/util.go @@ -3,6 +3,8 @@ package utils import ( "context" "fmt" + "net/http" + "time" sqlserverflex "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3api" @@ -29,3 +31,15 @@ func ConfigureClient(ctx context.Context, providerData *core.ProviderData, diags return apiClient } + +var RetryConfig = utils.RetryConfig{ + Attempts: 5, + Backoff: func(attempt int) time.Duration { + // Wait for every attempt 5 seconds longer. 5s, 10s, 15s and so on + return time.Duration(attempt*5) * time.Second + }, + RetryStatusCodes: []int{ + http.StatusLocked, + http.StatusTooEarly, + }, +}