Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions services/git/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/stackitcloud/stackit-sdk-go/services/git
go 1.21

require (
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/stackitcloud/stackit-sdk-go/core v0.17.1
)
Expand Down
57 changes: 57 additions & 0 deletions services/git/wait/wait.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package wait

import (
"context"
"fmt"
"time"

"github.com/stackitcloud/stackit-sdk-go/core/wait"
"github.com/stackitcloud/stackit-sdk-go/services/git"
)

const (
InstanceStateReady = "Ready"
InstanceStateCreating = "Creating"
InstanceStateError = "Error"
)

// APIClientInterface Interfaces needed for tests
type APIClientInterface interface {
GetInstanceExecute(ctx context.Context, projectId string, instanceId string) (*git.Instance, error)
}

func CreateGitInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId string) *wait.AsyncActionHandler[git.Instance] {
handler := wait.New(func() (waitFinished bool, response *git.Instance, err error) {
instance, err := a.GetInstanceExecute(ctx, projectId, instanceId)
if err != nil {
return false, nil, err
}
if instance.Id == nil || instance.State == nil {
return false, nil, fmt.Errorf("could not get Instance id or State from response for project %s and instanceId %s", projectId, instanceId)
}
if *instance.Id == instanceId && *instance.State == InstanceStateReady {
return true, instance, nil
}
if *instance.Id == instanceId && *instance.State == InstanceStateError {
return true, instance, fmt.Errorf("create failed for Instance with id %s", instanceId)
}
return false, nil, nil
})
handler.SetTimeout(10 * time.Minute)
return handler
}

func DeleteGitInstanceWaitHandler(ctx context.Context, a APIClientInterface, projectId, instanceId string) *wait.AsyncActionHandler[git.Instance] {
handler := wait.New(func() (waitFinished bool, response *git.Instance, err error) {
instance, err := a.GetInstanceExecute(ctx, projectId, instanceId)
if err != nil {
return false, nil, err
}
if instance != nil {
return false, instance, nil
}
return true, nil, nil
})
handler.SetTimeout(10 * time.Minute)
return handler
}
221 changes: 221 additions & 0 deletions services/git/wait/wait_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
package wait

import (
"context"
"net/http"
"testing"
"time"

"github.com/google/go-cmp/cmp"
"github.com/google/uuid"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/git"
)

type apiClientMocked struct {
getFails bool
returnInstance bool
projectId string
instanceId string
getGitResponse *git.Instance
}

func (a *apiClientMocked) GetInstanceExecute(_ context.Context, _, _ string) (*git.Instance, error) {
if a.getFails {
return nil, &oapierror.GenericOpenAPIError{
StatusCode: http.StatusInternalServerError,
}
}
if !a.returnInstance {
return nil, nil
}
return a.getGitResponse, nil
}

var PROJECT_ID = uuid.New().String()
var INSTANCE_ID = uuid.New().String()

func TestCreateGitInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
getFails bool
wantErr bool
wantResp bool
projectId string
instanceId string
returnInstance bool
getGitResponse *git.Instance
}{
{
desc: "Creation of an instance succeeded",
getFails: false,
wantErr: false,
wantResp: true,
projectId: uuid.New().String(),
instanceId: INSTANCE_ID,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Id: utils.Ptr(INSTANCE_ID),
Name: utils.Ptr("instance-test"),
State: utils.Ptr(InstanceStateReady),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},
{
desc: "Creation of an instance failed with error",
getFails: true,
wantErr: true,
wantResp: false,
projectId: uuid.New().String(),
instanceId: INSTANCE_ID,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Id: utils.Ptr(INSTANCE_ID),
Name: utils.Ptr("instance-test"),
State: utils.Ptr(InstanceStateReady),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},
{
desc: "Creation of an instance with response failed and without error",
getFails: false,
wantErr: true,
wantResp: true,
projectId: uuid.New().String(),
instanceId: INSTANCE_ID,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Id: utils.Ptr(INSTANCE_ID),
Name: utils.Ptr("instance-test"),
State: utils.Ptr(InstanceStateError),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},
{
desc: "Creation of an instance failed without id on the response",
getFails: false,
wantErr: true,
wantResp: false,
projectId: PROJECT_ID,
instanceId: INSTANCE_ID,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Name: utils.Ptr("instance-test"),
State: utils.Ptr(InstanceStateError),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},

{
desc: "Creation of an instance without state on the response",
getFails: false,
wantErr: true,
wantResp: false,
projectId: PROJECT_ID,
instanceId: INSTANCE_ID,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Id: utils.Ptr(INSTANCE_ID),
Name: utils.Ptr("instance-test"),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
apiClient := &apiClientMocked{
getFails: tt.getFails,
projectId: tt.projectId,
instanceId: tt.instanceId,
getGitResponse: tt.getGitResponse,
returnInstance: tt.returnInstance,
}
var instanceWanted *git.Instance
if tt.wantResp {
instanceWanted = tt.getGitResponse
}

handler := CreateGitInstanceWaitHandler(context.Background(), apiClient, apiClient.projectId, apiClient.instanceId)

response, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())

if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
if !cmp.Equal(response, instanceWanted) {
t.Fatalf("handler gotRes = %v, want %v", response, instanceWanted)
}
})
}
}

func TestDeleteGitInstanceWaitHandler(t *testing.T) {
tests := []struct {
desc string
wantErr bool
wantReturnedInstance bool
getFails bool
returnInstance bool
getGitResponse *git.Instance
}{
{
desc: "Instance deletion failed with error",
wantErr: true,
getFails: true,
},
{
desc: "Instance deletion failed returning existing instance",
wantErr: true,
getFails: false,
wantReturnedInstance: true,
returnInstance: true,
getGitResponse: &git.Instance{
Created: utils.Ptr(time.Now()),
Id: utils.Ptr(INSTANCE_ID),
Name: utils.Ptr("instance-test"),
State: utils.Ptr(InstanceStateReady),
Url: utils.Ptr("https://testing.git.onstackit.cloud"),
Version: utils.Ptr("v1.6.0"),
},
},
{
desc: "Instance deletion successful",
wantErr: false,
getFails: false,
wantReturnedInstance: false,
returnInstance: false,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
apiClient := &apiClientMocked{

projectId: uuid.New().String(),
getFails: tt.getFails,
returnInstance: tt.returnInstance,
getGitResponse: tt.getGitResponse,
}

handler := DeleteGitInstanceWaitHandler(context.Background(), apiClient, apiClient.projectId, apiClient.instanceId)
response, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())

if (err != nil) != tt.wantErr {
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
}
if (response != nil) != tt.wantReturnedInstance {
t.Fatalf("handler gotRes = %v, want nil", response)
}
})
}
}