terraform-provider-stackitp.../stackit/internal/wait/sqlserverflexbeta/wait.go
Marcel S. Henselin 7b43d2fe52
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 6s
CI Workflow / CI (pull_request) Failing after 10m15s
CI Workflow / Code coverage report (pull_request) Has been skipped
CI Workflow / Test readiness for publishing provider (pull_request) Failing after 12m58s
feat: refactor testing
2026-02-09 08:24:41 +01:00

157 lines
5.7 KiB
Go

package sqlserverflexbeta
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/wait"
sqlserverflex "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
)
// READY, PENDING, PROGRESSING, FAILURE, UNKNOWN,
const (
InstanceStateEmpty = ""
InstanceStateSuccess = "READY"
InstanceStatePending = "PENDING"
InstanceStateProcessing = "PROGRESSING"
InstanceStateFailed = "FAILURE"
InstanceStateUnknown = "UNKNOWN"
InstanceStateTerminating = "TERMINATING"
)
// APIClientInterface Interface needed for tests
type APIClientInterface interface {
GetInstanceRequestExecute(ctx context.Context, projectId, region, instanceId string) (*sqlserverflex.GetInstanceResponse, error)
GetDatabaseRequestExecute(ctx context.Context, projectId string, region string, instanceId string, databaseName string) (*sqlserverflex.GetDatabaseResponse, error)
GetUserRequestExecute(ctx context.Context, projectId string, region string, instanceId string, userId int64) (*sqlserverflex.GetUserResponse, error)
}
// CreateInstanceWaitHandler will wait for instance creation
func CreateInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
case strings.ToLower(InstanceStateSuccess):
if *s.Network.AccessScope == "SNA" {
if s.Network.InstanceAddress == nil {
tflog.Info(ctx, "Waiting for instance_address")
return false, nil, nil
}
if s.Network.RouterAddress == nil {
tflog.Info(ctx, "Waiting for router_address")
return false, nil, nil
}
}
return true, s, nil
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
return true, s, fmt.Errorf("create failed for instance with id %s", instanceId)
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
})
return false, nil, nil
default:
tflog.Info(ctx, "Wait (create) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
})
return false, s, nil
}
})
return handler
}
// UpdateInstanceWaitHandler will wait for instance update
func UpdateInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId, region string) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
if err != nil {
return false, nil, err
}
if s == nil || s.Id == nil || *s.Id != instanceId || s.Status == nil {
return false, nil, nil
}
switch strings.ToLower(string(*s.Status)) {
case strings.ToLower(InstanceStateSuccess):
return true, s, nil
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
return true, s, fmt.Errorf("update failed for instance with id %s", instanceId)
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(ctx, "request is being handled", map[string]interface{}{
"status": *s.Status,
})
return false, s, nil
default:
tflog.Info(ctx, "Wait (update) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
})
return false, s, nil
}
})
return handler
}
// DeleteInstanceWaitHandler will wait for instance deletion
func DeleteInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId, region string) *wait.AsyncActionHandler[sqlserverflex.GetInstanceResponse] {
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequestExecute(ctx, projectId, region, instanceId)
if err == nil {
return false, s, 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 {
return false, nil, err
}
return true, nil, nil
})
handler.SetTimeout(30 * time.Minute)
return handler
}
// CreateDatabaseWaitHandler will wait for instance creation
func CreateDatabaseWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region, databaseName string,
) *wait.AsyncActionHandler[sqlserverflex.GetDatabaseResponse] {
handler := wait.New(func() (waitFinished bool, response *sqlserverflex.GetDatabaseResponse, err error) {
s, err := a.GetDatabaseRequestExecute(ctx, projectId, region, instanceId, databaseName)
if err != nil {
return false, nil, err
}
if s == nil || s.Name == nil || *s.Name != databaseName {
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 {
return false, nil, err
}
return true, nil, nil
})
return handler
}