Skip to content

Commit 1f6151e

Browse files
fapo85marceljkFyusel
authored
feat(scf): add delete scf org waiter (#3498)
* add delete scf org waiter * add delete scf org waiter * fix changelog * Update services/scf/wait/wait.go Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> * create new release section * fix statusDeletingFailed in scf waiter --------- Co-authored-by: Marcel Jacek <72880145+marceljk@users.noreply.github.com> Co-authored-by: Alexander Dahmen <alexander.dahmen@inovex.de>
1 parent 1d60643 commit 1f6151e

File tree

5 files changed

+150
-2
lines changed

5 files changed

+150
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
## Release (2025-XX-XX)
1+
## Release (2025-xx-xx)
2+
- `scf`: [v0.2.1](services/scf/CHANGELOG.md#v021)
3+
- **Feature:** Add waiter for deletion of organization
24
- `iaas`: [v0.29.1](services/iaas/CHANGELOG.md#v0291)
35
- **Bugfix:** Parsing oneOf with enum and string value
46

services/scf/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v0.2.1
2+
- **Feature:** Add waiter for deletion of organization
3+
14
## v0.2.0
25
- **Feature:** Add field `OrgId` in model `OrgManager`
36
- **Feature:** Add new model `OrganizationCreateBffResponse` and `SpaceCreatedBffResponse`

services/scf/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.2.0
1+
v0.2.1

services/scf/wait/wait.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
"time"
9+
10+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
11+
"github.com/stackitcloud/stackit-sdk-go/core/wait"
12+
"github.com/stackitcloud/stackit-sdk-go/services/scf"
13+
)
14+
15+
const statusDeletingFailed = "deleting_failed"
16+
17+
// Interfaces needed for tests
18+
type APIClientInterface interface {
19+
GetOrganizationExecute(ctx context.Context, projectId, region, orgId string) (*scf.Organization, error)
20+
}
21+
22+
// DeleteOrganizationWaitHandler will wait for Organization deletion
23+
func DeleteOrganizationWaitHandler(ctx context.Context, a APIClientInterface, projectId, region, orgId string) *wait.AsyncActionHandler[scf.Organization] {
24+
handler := wait.New(func() (waitFinished bool, response *scf.Organization, err error) {
25+
s, err := a.GetOrganizationExecute(ctx, projectId, region, orgId)
26+
if err != nil {
27+
var oapiErr *oapierror.GenericOpenAPIError
28+
ok := errors.As(err, &oapiErr)
29+
if ok && oapiErr.StatusCode == http.StatusNotFound {
30+
return true, s, nil
31+
}
32+
return false, s, err
33+
}
34+
if s == nil {
35+
return false, nil, errors.New("organization is nil")
36+
}
37+
if *s.Status == statusDeletingFailed {
38+
return true, nil, fmt.Errorf("delete failed for Organization with id %s", orgId)
39+
}
40+
return false, s, nil
41+
})
42+
handler.SetTimeout(20 * time.Minute)
43+
return handler
44+
}

services/scf/wait/wait_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/google/uuid"
9+
10+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
11+
"github.com/stackitcloud/stackit-sdk-go/services/scf"
12+
)
13+
14+
var PROJECT_ID = uuid.New().String()
15+
var INSTANCE_ID = uuid.New().String()
16+
17+
const REGION = "eu01"
18+
19+
type apiClientMocked struct {
20+
getFails bool
21+
errorCode int
22+
returnInstance bool
23+
projectId string
24+
instanceId string
25+
getSCFResponse *scf.Organization
26+
}
27+
28+
func (a *apiClientMocked) GetOrganizationExecute(_ context.Context, _, _, _ string) (*scf.Organization, error) {
29+
if a.getFails {
30+
return nil, &oapierror.GenericOpenAPIError{
31+
StatusCode: a.errorCode,
32+
}
33+
}
34+
if !a.returnInstance {
35+
return nil, nil
36+
}
37+
return a.getSCFResponse, nil
38+
}
39+
40+
func TestDeleteOrganizationWaitHandler(t *testing.T) {
41+
statusDeletingFailed := "deleting_failed"
42+
tests := []struct {
43+
desc string
44+
wantErr bool
45+
wantReturnedInstance bool
46+
getFails bool
47+
errorCode int
48+
returnInstance bool
49+
getOrgResponse *scf.Organization
50+
}{
51+
{
52+
desc: "Instance deletion failed with error",
53+
wantErr: true,
54+
getFails: true,
55+
},
56+
{
57+
desc: "Instance is not found",
58+
wantErr: false,
59+
getFails: true,
60+
errorCode: 404,
61+
},
62+
{
63+
desc: "Instance is in error state",
64+
wantErr: true,
65+
returnInstance: true,
66+
getOrgResponse: &scf.Organization{
67+
Status: &statusDeletingFailed,
68+
},
69+
},
70+
{
71+
desc: "Instance is nil",
72+
wantErr: true,
73+
returnInstance: true,
74+
getOrgResponse: nil,
75+
},
76+
}
77+
for _, tt := range tests {
78+
t.Run(tt.desc, func(t *testing.T) {
79+
apiClient := &apiClientMocked{
80+
projectId: PROJECT_ID,
81+
instanceId: INSTANCE_ID,
82+
getFails: tt.getFails,
83+
errorCode: tt.errorCode,
84+
returnInstance: tt.returnInstance,
85+
getSCFResponse: tt.getOrgResponse,
86+
}
87+
88+
handler := DeleteOrganizationWaitHandler(context.Background(), apiClient, apiClient.projectId, REGION, apiClient.instanceId)
89+
response, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
90+
91+
if (err != nil) != tt.wantErr {
92+
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
93+
}
94+
if (response != nil) != tt.wantReturnedInstance {
95+
t.Fatalf("handler gotRes = %v, want nil", response)
96+
}
97+
})
98+
}
99+
}

0 commit comments

Comments
 (0)