fix: adjust to new generator and sdk use
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 5s
CI Workflow / Test readiness for publishing provider (pull_request) Failing after 3m33s
CI Workflow / CI run tests (pull_request) Failing after 4m51s
CI Workflow / CI run build and linting (pull_request) Failing after 4m37s
CI Workflow / Code coverage report (pull_request) Has been skipped

This commit is contained in:
Marcel S. Henselin 2026-03-09 10:26:18 +01:00
parent ca0f646526
commit 826bb5b36a
36 changed files with 2089 additions and 1166 deletions

View file

@ -10,101 +10,34 @@ import (
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
postgresflex "github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
"github.com/stackitcloud/stackit-sdk-go/services/postgresflex/v3alpha1api"
)
// Used for testing instance operations
type apiClientInstanceMocked struct {
instanceId string
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceIsForceDeleted bool
instanceGetFails bool
usersGetErrorStatus int
}
func (a *apiClientInstanceMocked) GetInstanceRequest(
_ context.Context,
_, _, _ string,
) postgresflex.ApiGetInstanceRequestRequest {
return postgresflex.ApiGetInstanceRequestRequest{}
}
func (a *apiClientInstanceMocked) GetInstanceRequestExecute(
_ context.Context,
_, _, _ string,
) (*postgresflex.GetInstanceResponse, error) {
if a.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if a.instanceIsForceDeleted {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &postgresflex.GetInstanceResponse{
Id: a.instanceId,
Status: postgresflex.Status(a.instanceState),
Network: a.instanceNetwork,
}, nil
}
func (a *apiClientInstanceMocked) ListUsersRequest(
_ context.Context,
_, _, _ string,
) postgresflex.ApiListUsersRequestRequest {
return postgresflex.ApiListUsersRequestRequest{}
}
func (a *apiClientInstanceMocked) ListUsersRequestExecute(
_ context.Context,
_, _, _ string,
) (*postgresflex.ListUserResponse, error) {
if a.usersGetErrorStatus != 0 {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: a.usersGetErrorStatus,
}
}
aux := int32(0)
return &postgresflex.ListUserResponse{
Pagination: postgresflex.Pagination{
TotalRows: aux,
},
Users: []postgresflex.ListUser{},
}, nil
}
func TestCreateInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceNetwork v3alpha1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *postgresflex.GetInstanceResponse
wantRes *v3alpha1api.GetInstanceResponse
}{
{
desc: "create_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: false,
wantRes: &postgresflex.GetInstanceResponse{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: InstanceStateSuccess,
Network: postgresflex.InstanceNetwork{
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -116,7 +49,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "create_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -129,7 +62,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "create_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -148,7 +81,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "users_get_fails",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -162,7 +95,7 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "users_get_fails_2",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -170,10 +103,10 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
},
usersGetErrorStatus: 400,
wantErr: true,
wantRes: &postgresflex.GetInstanceResponse{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: InstanceStateSuccess,
Network: postgresflex.InstanceNetwork{
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -185,8 +118,8 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "fail when response has no instance address",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
AccessScope: (*postgresflex.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: (*v3alpha1api.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
Acl: nil,
InstanceAddress: nil,
RouterAddress: utils.Ptr("10.0.0.1"),
@ -198,8 +131,8 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProgressing,
instanceNetwork: postgresflex.InstanceNetwork{
AccessScope: (*postgresflex.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: (*v3alpha1api.InstanceNetworkAccessScope)(utils.Ptr("SNA")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
@ -211,22 +144,44 @@ func TestCreateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClientMock := postgresflex.DefaultAPIServiceMock{
CreateInstanceRequestExecuteMock: nil,
GetInstanceRequestExecuteMock: nil,
listUsersMock := func(_ v3alpha1api.ApiListUsersRequestRequest) (*v3alpha1api.ListUserResponse, error) {
if tt.usersGetErrorStatus != 0 {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: tt.usersGetErrorStatus,
}
}
aux := int32(0)
return &v3alpha1api.ListUserResponse{
Pagination: v3alpha1api.Pagination{
TotalRows: aux,
},
Users: []v3alpha1api.ListUser{},
}, nil
}
//apiClient := &apiClientInstanceMocked{
// instanceId: instanceId,
// instanceState: tt.instanceState,
// instanceNetwork: tt.instanceNetwork,
// instanceGetFails: tt.instanceGetFails,
// usersGetErrorStatus: tt.usersGetErrorStatus,
//}
getInstanceMock := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
handler := CreateInstanceWaitHandler(context.Background(), apiClientMock, "", "", instanceId)
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
apiClientMock := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &getInstanceMock,
ListUsersRequestExecuteMock: &listUsersMock,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClientMock, "", "", instanceID)
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
@ -246,25 +201,25 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc string
instanceGetFails bool
instanceState string
instanceNetwork postgresflex.InstanceNetwork
instanceNetwork v3alpha1api.InstanceNetwork
wantErr bool
wantRes *postgresflex.GetInstanceResponse
wantRes *v3alpha1api.GetInstanceResponse
}{
{
desc: "update_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: false,
wantRes: &postgresflex.GetInstanceResponse{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: postgresflex.Status(InstanceStateSuccess),
Network: postgresflex.InstanceNetwork{
Status: v3alpha1api.Status(InstanceStateSuccess),
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -276,17 +231,17 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "update_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.1"),
},
wantErr: true,
wantRes: &postgresflex.GetInstanceResponse{
wantRes: &v3alpha1api.GetInstanceResponse{
Id: "foo-bar",
Status: postgresflex.Status(InstanceStateFailed),
Network: postgresflex.InstanceNetwork{
Status: v3alpha1api.Status(InstanceStateFailed),
Network: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -298,7 +253,7 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "update_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -317,7 +272,7 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProgressing,
instanceNetwork: postgresflex.InstanceNetwork{
instanceNetwork: v3alpha1api.InstanceNetwork{
AccessScope: nil,
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
@ -330,16 +285,38 @@ func TestUpdateInstanceWaitHandler(t *testing.T) {
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceId := "foo-bar"
instanceID := "foo-bar"
apiClient := &apiClientInstanceMocked{
instanceId: instanceId,
instanceState: tt.instanceState,
instanceNetwork: tt.instanceNetwork,
instanceGetFails: tt.instanceGetFails,
listUsersMock := func(_ v3alpha1api.ApiListUsersRequestRequest) (*v3alpha1api.ListUserResponse, error) {
aux := int32(0)
return &v3alpha1api.ListUserResponse{
Pagination: v3alpha1api.Pagination{
TotalRows: aux,
},
Users: []v3alpha1api.ListUser{},
}, nil
}
handler := PartialUpdateInstanceWaitHandler(context.Background(), apiClient, "", "", instanceId)
getInstanceMock := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
apiClientMock := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &getInstanceMock,
ListUsersRequestExecuteMock: &listUsersMock,
}
handler := PartialUpdateInstanceWaitHandler(context.Background(), apiClientMock, "", "", instanceID)
gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {

View file

@ -0,0 +1,387 @@
package sqlserverflexalpha
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"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
// 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 {
GetInstanceRequest(
ctx context.Context,
projectId, region, instanceId string,
) v3alpha1api.ApiGetInstanceRequestRequest
GetDatabaseRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
databaseName string,
) v3alpha1api.ApiGetDatabaseRequestRequest
GetUserRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) v3alpha1api.ApiGetUserRequestRequest
ListRolesRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) v3alpha1api.ApiListRolesRequestRequest
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) v3alpha1api.ApiListUsersRequestRequest
}
// APIClientUserInterface Interface needed for tests
type APIClientUserInterface interface {
DeleteUserRequestExecute(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) error
}
// CreateInstanceWaitHandler will wait for instance creation
func CreateInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
if s.Network.AccessScope != nil && *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
}
}
tflog.Info(ctx, "trying to get roles")
time.Sleep(10 * time.Second)
_, rolesErr := a.ListRolesRequest(ctx, projectId, region, instanceId).Execute()
if rolesErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(rolesErr, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusInternalServerError {
tflog.Info(
ctx, "got error from api", map[string]interface{}{
"error": rolesErr.Error(),
},
)
return false, nil, rolesErr
}
tflog.Info(
ctx, "wait for get-roles to work hack", map[string]interface{}{},
)
time.Sleep(10 * time.Second)
return false, nil, nil
}
tflog.Info(ctx, "trying to get users")
time.Sleep(10 * time.Second)
_, usersErr := a.ListUsersRequest(ctx, projectId, region, instanceId).Execute()
if usersErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(usersErr, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusInternalServerError {
tflog.Info(
ctx, "got error from api", map[string]interface{}{
"error": rolesErr.Error(),
},
)
return false, nil, usersErr
}
tflog.Info(
ctx, "wait for get-users to work hack", map[string]interface{}{},
)
time.Sleep(10 * time.Second)
return false, nil, nil
}
return true, s, nil
case strings.ToLower(InstanceStateUnknown), strings.ToLower(InstanceStateFailed):
return true, nil, 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,
},
)
time.Sleep(10 * time.Second)
return false, nil, nil
default:
tflog.Info(
ctx, "Wait (create) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
},
)
return true, nil, errors.New("unknown status received")
}
},
)
return handler
}
// UpdateInstanceWaitHandler will wait for instance update
func UpdateInstanceWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
) *wait.AsyncActionHandler[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id != instanceId {
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[v3alpha1api.GetInstanceResponse] {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetInstanceResponse, err error) {
s, err := a.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
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[v3alpha1api.GetDatabaseResponse] {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetDatabaseResponse, err error) {
s, err := a.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf(
"get database - could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
return false, nil, nil
}
if s == nil || s.Name != databaseName {
return false, nil, errors.New("response did return different result")
}
return true, s, nil
},
)
return handler
}
// CreateUserWaitHandler will wait for instance creation
func CreateUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
userId int64,
) *wait.AsyncActionHandler[v3alpha1api.GetUserResponse] {
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.GetUserResponse, err error) {
s, err := a.GetUserRequest(ctx, projectId, region, instanceId, userId).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 oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
return false, nil, nil
}
return true, s, nil
},
)
return handler
}
// WaitForUserWaitHandler will wait for instance creation
func WaitForUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region, userName string,
) *wait.AsyncActionHandler[v3alpha1api.ListUserResponse] {
startTime := time.Now()
timeOut := 2 * time.Minute
handler := wait.New(
func() (waitFinished bool, response *v3alpha1api.ListUserResponse, err error) {
if time.Since(startTime) > timeOut {
return false, nil, errors.New("ran into timeout")
}
s, err := a.ListUsersRequest(ctx, projectId, region, instanceId).Size(100).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf(
"wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
tflog.Info(
ctx, "Wait (list users) still waiting", map[string]interface{}{},
)
return false, nil, nil
}
users, ok := s.GetUsersOk()
if !ok {
return false, nil, errors.New("no users found")
}
for _, u := range users {
if u.GetUsername() == userName {
return true, s, nil
}
}
tflog.Info(
ctx, "Wait (list users) user still not present", map[string]interface{}{},
)
return false, nil, nil
},
)
return handler
}
// DeleteUserWaitHandler will wait for instance deletion
func DeleteUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, region, instanceId string,
userId int64,
) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(
func() (waitFinished bool, response *struct{}, err error) {
_, err = a.GetUserRequest(ctx, projectId, region, instanceId, userId).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")
}
switch oapiErr.StatusCode {
case http.StatusNotFound:
return true, nil, nil
default:
return false, nil, err
}
},
)
handler.SetTimeout(15 * time.Minute)
handler.SetSleepBeforeWait(15 * time.Second)
return handler
}

View file

@ -0,0 +1,290 @@
package sqlserverflexalpha
import (
"context"
"reflect"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3alpha1api"
)
// Used for testing instance operations
type apiClientInstanceMocked struct {
instanceID string
instanceState string
instanceNetwork v3alpha1api.InstanceNetwork
instanceIsDeleted bool
instanceGetFails bool
}
func TestCreateInstanceWaitHandler(t *testing.T) {
instanceID := utils.Ptr("foo")
tests := []struct {
desc string
instanceID string
instanceGetFails bool
instanceState string
instanceNetwork v3alpha1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *v3alpha1api.GetInstanceResponse
}{
//{
// desc: "create_succeeded",
// instanceId: *instanceId,
// instanceGetFails: false,
// instanceState: *stateSuccess,
// instanceNetwork: v3alpha1api.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
// RouterAddress: utils.Ptr("10.0.0.2"),
// },
// wantErr: false,
// wantRes: &v3alpha1api.GetInstanceResponse{
// BackupSchedule: nil,
// Edition: nil,
// Encryption: nil,
// FlavorId: nil,
// Id: instanceId,
// IsDeletable: nil,
// Name: nil,
// Network: &v3alpha1api.InstanceNetwork{
// AccessScope: nil,
// Acl: nil,
// InstanceAddress: utils.Ptr("10.0.0.1"),
// RouterAddress: utils.Ptr("10.0.0.2"),
// },
// Replicas: nil,
// RetentionDays: nil,
// Status: v3alpha1api.GetInstanceResponseGetStatusAttributeType(stateSuccess),
// Storage: nil,
// Version: nil,
// },
// },
{
desc: "create_failed",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
wantRes: nil,
},
{
desc: "create_failed_2",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
wantRes: nil,
},
{
desc: "instance_get_fails",
instanceID: *instanceID,
instanceGetFails: true,
wantErr: true,
wantRes: nil,
},
{
desc: "timeout",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
wantRes: nil,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: tt.instanceID,
Status: v3alpha1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
}, nil
}
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
if !reflect.DeepEqual(gotRes, tt.wantRes) {
t.Fatalf("handler gotRes = %v, want %v", gotRes, tt.wantRes)
}
},
)
}
}
func TestUpdateInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
wantErr bool
wantResp bool
}{
{
desc: "update_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
wantErr: false,
wantResp: true,
},
{
desc: "update_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
wantResp: true,
},
{
desc: "update_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
wantResp: true,
},
{
desc: "get_fails",
instanceGetFails: true,
wantErr: true,
wantResp: false,
},
{
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
wantResp: true,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceID := "foo-bar"
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
var wantRes *v3alpha1api.GetInstanceResponse
if tt.wantResp {
wantRes = &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
}
}
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).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 TestDeleteInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
wantErr bool
}{
{
desc: "delete_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
wantErr: false,
},
{
desc: "delete_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
},
{
desc: "get_fails",
instanceGetFails: true,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceID := "foo-bar"
mockCall := func(_ v3alpha1api.ApiGetInstanceRequestRequest) (*v3alpha1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if tt.instanceState == InstanceStateSuccess {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &v3alpha1api.GetInstanceResponse{
Id: instanceID,
Status: v3alpha1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
apiClient := v3alpha1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
},
)
}
}

View file

@ -0,0 +1,405 @@
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 "github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
// 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 {
GetInstanceRequest(
ctx context.Context,
projectId, region, instanceId string,
) sqlserverflex.ApiGetInstanceRequestRequest
GetDatabaseRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
databaseName string,
) sqlserverflex.ApiGetDatabaseRequestRequest
GetUserRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) sqlserverflex.ApiGetUserRequestRequest
ListRolesRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) sqlserverflex.ApiListRolesRequestRequest
ListUsersRequest(
ctx context.Context,
projectId string,
region string,
instanceId string,
) sqlserverflex.ApiListUsersRequestRequest
}
// APIClientUserInterface Interface needed for tests
type APIClientUserInterface interface {
DeleteUserRequestExecute(
ctx context.Context,
projectId string,
region string,
instanceId string,
userId int64,
) 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.GetInstanceRequest(ctx, projectId, region, instanceId).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: %w", err)
}
switch oapiErr.StatusCode {
case http.StatusNotFound:
return false, nil, nil
default:
return false, nil, fmt.Errorf("api error: %w", err)
}
}
if s == nil || s.Id != instanceId {
return false, nil, nil
}
switch strings.ToLower(string(s.Status)) {
case strings.ToLower(InstanceStateSuccess):
if s.Network.AccessScope != nil && *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
}
}
tflog.Info(ctx, "trying to get roles")
time.Sleep(10 * time.Second)
_, rolesErr := a.ListRolesRequest(ctx, projectId, region, instanceId).Execute()
if rolesErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(rolesErr, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusInternalServerError {
tflog.Info(
ctx, "got error from api", map[string]interface{}{
"error": rolesErr.Error(),
},
)
return false, nil, rolesErr
}
tflog.Info(
ctx, "wait for get-roles to work hack", map[string]interface{}{},
)
time.Sleep(10 * time.Second)
return false, nil, nil
}
tflog.Info(ctx, "trying to get users")
time.Sleep(10 * time.Second)
_, usersErr := a.ListUsersRequest(ctx, projectId, region, instanceId).Execute()
if usersErr != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(usersErr, &oapiErr)
if !ok {
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
}
if oapiErr.StatusCode != http.StatusInternalServerError {
tflog.Info(
ctx, "got error from api", map[string]interface{}{
"error": rolesErr.Error(),
},
)
return false, nil, usersErr
}
tflog.Info(
ctx, "wait for get-users to work hack", map[string]interface{}{},
)
time.Sleep(10 * time.Second)
return false, nil, nil
}
return true, s, nil
case strings.ToLower(InstanceStateUnknown):
return true, nil, fmt.Errorf(
"create failed for instance %s with status %s",
instanceId,
InstanceStateUnknown,
)
case strings.ToLower(InstanceStateFailed):
return true, nil, fmt.Errorf(
"create failed for instance %s with status %s",
instanceId,
InstanceStateFailed,
)
case strings.ToLower(InstanceStatePending), strings.ToLower(InstanceStateProcessing):
tflog.Info(
ctx, "request is being handled", map[string]interface{}{
"status": s.Status,
},
)
time.Sleep(10 * time.Second)
return false, nil, nil
default:
tflog.Info(
ctx, "Wait (create) received unknown status", map[string]interface{}{
"instanceId": instanceId,
"status": s.Status,
},
)
return true, nil, errors.New("unknown status received")
}
},
)
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.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
if err != nil {
return false, nil, err
}
if s == nil || s.Id != instanceId {
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.GetInstanceRequest(ctx, projectId, region, instanceId).Execute()
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.GetDatabaseRequest(ctx, projectId, region, instanceId, databaseName).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf(
"get database - could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
return false, nil, nil
}
if s == nil || s.Name != databaseName {
return false, nil, errors.New("response did return different result")
}
return true, s, nil
},
)
return handler
}
// CreateUserWaitHandler will wait for instance creation
func CreateUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region string,
userId int64,
) *wait.AsyncActionHandler[sqlserverflex.GetUserResponse] {
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.GetUserResponse, err error) {
s, err := a.GetUserRequest(ctx, projectId, region, instanceId, userId).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 oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
return false, nil, nil
}
return true, s, nil
},
)
return handler
}
// WaitForUserWaitHandler will wait for instance creation
func WaitForUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, instanceId, region, userName string,
) *wait.AsyncActionHandler[sqlserverflex.ListUserResponse] {
startTime := time.Now()
timeOut := 2 * time.Minute
handler := wait.New(
func() (waitFinished bool, response *sqlserverflex.ListUserResponse, err error) {
if time.Since(startTime) > timeOut {
return false, nil, errors.New("ran into timeout")
}
s, err := a.ListUsersRequest(ctx, projectId, region, instanceId).Size(100).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if !ok {
return false, nil, fmt.Errorf(
"wait (list users) could not convert error to oapierror.GenericOpenAPIError: %s",
err.Error(),
)
}
if oapiErr.StatusCode != http.StatusNotFound {
return false, nil, err
}
tflog.Info(
ctx, "Wait (list users) still waiting", map[string]interface{}{},
)
return false, nil, nil
}
users, ok := s.GetUsersOk()
if !ok {
return false, nil, errors.New("no users found")
}
for _, u := range users {
if u.GetUsername() == userName {
return true, s, nil
}
}
tflog.Info(
ctx, "Wait (list users) user still not present", map[string]interface{}{},
)
return false, nil, nil
},
)
return handler
}
// DeleteUserWaitHandler will wait for instance deletion
func DeleteUserWaitHandler(
ctx context.Context,
a APIClientInterface,
projectId, region, instanceId string,
userId int64,
) *wait.AsyncActionHandler[struct{}] {
handler := wait.New(
func() (waitFinished bool, response *struct{}, err error) {
_, err = a.GetUserRequest(ctx, projectId, region, instanceId, userId).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")
}
switch oapiErr.StatusCode {
case http.StatusNotFound:
return true, nil, nil
default:
return false, nil, err
}
},
)
handler.SetTimeout(15 * time.Minute)
handler.SetSleepBeforeWait(15 * time.Second)
return handler
}

View file

@ -0,0 +1,306 @@
package sqlserverflexbeta
import (
"context"
"reflect"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex/v3beta1api"
)
func TestCreateInstanceWaitHandler(t *testing.T) {
instanceID := utils.Ptr("foo")
tests := []struct {
desc string
instanceID string
instanceGetFails bool
instanceState string
instanceNetwork v3beta1api.InstanceNetwork
usersGetErrorStatus int
wantErr bool
wantRes *v3beta1api.GetInstanceResponse
}{
{
desc: "create_succeeded_default_values",
instanceID: "instance1",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
instanceNetwork: v3beta1api.InstanceNetwork{
AccessScope: (*v3beta1api.InstanceNetworkAccessScope)(utils.Ptr("PUBLIC")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.2"),
},
wantErr: false,
wantRes: &v3beta1api.GetInstanceResponse{
BackupSchedule: "",
Edition: "",
Encryption: nil,
FlavorId: "",
Id: "instance1",
IsDeletable: false,
Name: "",
Network: v3beta1api.InstanceNetwork{
AccessScope: (*v3beta1api.InstanceNetworkAccessScope)(utils.Ptr("PUBLIC")),
Acl: nil,
InstanceAddress: utils.Ptr("10.0.0.1"),
RouterAddress: utils.Ptr("10.0.0.2"),
},
Replicas: 0,
RetentionDays: 0,
Status: v3beta1api.Status(InstanceStateSuccess),
Storage: v3beta1api.Storage{},
Version: "",
},
},
{
desc: "create_failed",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
wantRes: nil,
},
{
desc: "create_failed_2",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
wantRes: nil,
},
{
desc: "instance_get_fails",
instanceID: *instanceID,
instanceGetFails: true,
wantErr: true,
wantRes: nil,
},
{
desc: "timeout",
instanceID: *instanceID,
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
wantRes: nil,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
listRolesMock := func(_ v3beta1api.ApiListRolesRequestRequest) (*v3beta1api.ListRolesResponse, error) {
return &v3beta1api.ListRolesResponse{
Roles: []string{},
}, nil
}
listUsersMock := func(_ v3beta1api.ApiListUsersRequestRequest) (*v3beta1api.ListUserResponse, error) {
aux := int64(0)
return &v3beta1api.ListUserResponse{
Pagination: v3beta1api.Pagination{
TotalRows: aux,
},
Users: []v3beta1api.ListUser{},
}, nil
}
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3beta1api.GetInstanceResponse{
Id: tt.instanceID,
Status: v3beta1api.Status(tt.instanceState),
Network: tt.instanceNetwork,
Storage: v3beta1api.Storage{},
}, nil
}
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
ListUsersRequestExecuteMock: &listUsersMock,
ListRolesRequestExecuteMock: &listRolesMock,
}
handler := CreateInstanceWaitHandler(context.Background(), apiClient, "", tt.instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
if err == nil {
if diff := cmp.Diff(tt.wantRes, gotRes); diff != "" {
t.Errorf("model mismatch (-want +got):\n%s", diff)
}
}
if !reflect.DeepEqual(gotRes, tt.wantRes) {
t.Fatalf("handler gotRes = %v, want %v", gotRes, tt.wantRes)
}
},
)
}
}
func TestUpdateInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
wantErr bool
wantResp bool
}{
{
desc: "update_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
wantErr: false,
wantResp: true,
},
{
desc: "update_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
wantResp: true,
},
{
desc: "update_failed_2",
instanceGetFails: false,
instanceState: InstanceStateEmpty,
wantErr: true,
wantResp: true,
},
{
desc: "get_fails",
instanceGetFails: true,
wantErr: true,
wantResp: false,
},
{
desc: "timeout",
instanceGetFails: false,
instanceState: InstanceStateProcessing,
wantErr: true,
wantResp: true,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceID := "foo-bar"
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
return &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
var wantRes *v3beta1api.GetInstanceResponse
if tt.wantResp {
wantRes = &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
}
}
handler := UpdateInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
gotRes, err := handler.SetTimeout(10 * time.Millisecond).SetSleepBeforeWait(1 * time.Millisecond).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 TestDeleteInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
instanceGetFails bool
instanceState string
wantErr bool
}{
{
desc: "delete_succeeded",
instanceGetFails: false,
instanceState: InstanceStateSuccess,
wantErr: false,
},
{
desc: "delete_failed",
instanceGetFails: false,
instanceState: InstanceStateFailed,
wantErr: true,
},
{
desc: "get_fails",
instanceGetFails: true,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(
tt.desc, func(t *testing.T) {
instanceID := "foo-bar"
mockCall := func(_ v3beta1api.ApiGetInstanceRequestRequest) (*v3beta1api.GetInstanceResponse, error) {
if tt.instanceGetFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 500,
}
}
if tt.instanceState == InstanceStateSuccess {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: 404,
}
}
return &v3beta1api.GetInstanceResponse{
Id: instanceID,
Status: v3beta1api.Status(tt.instanceState),
//Network: tt.instanceNetwork,
}, nil
}
apiClient := v3beta1api.DefaultAPIServiceMock{
GetInstanceRequestExecuteMock: &mockCall,
}
handler := DeleteInstanceWaitHandler(context.Background(), apiClient, "", instanceID, "")
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
},
)
}
}