Skip to content

Commit 1fbd35d

Browse files
authored
feat(iaas): add ReadyForNetworkAreaDeletionWaiter (#3522)
* add ReadyForNetworkAreaDeletionWaitHandler
1 parent ca62545 commit 1fbd35d

File tree

7 files changed

+268
-23
lines changed

7 files changed

+268
-23
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## Release (2025-MM-DD)
2+
- `iaas`: [v0.30.0](services/iaas/CHANGELOG.md#v0300)
3+
- **Feature:** Add waiter to wait until the preconditions for network area deletion are met: `ReadyForNetworkAreaDeletionWaitHandler`
4+
5+
16
## Release (2025-09-11)
27
- `cdn`: [v1.5.0](services/cdn/CHANGELOG.md#v150)
38
- **Feature:** Added Attribute `LogSink` to `ConfigPatch`

services/iaas/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v0.30.0
2+
- **Feature:** Add waiter to wait until the preconditions for network area deletion are met: `ReadyForNetworkAreaDeletionWaitHandler`
3+
14
## v0.29.2
25
- Increase Timeouts for network area and network wait handlers to 30 minutes
36

services/iaas/VERSION

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

services/iaas/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.21
55
require (
66
github.com/google/go-cmp v0.7.0
77
github.com/stackitcloud/stackit-sdk-go/core v0.17.3
8+
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1
89
)
910

1011
require (

services/iaas/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
66
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
77
github.com/stackitcloud/stackit-sdk-go/core v0.17.3 h1:GsZGmRRc/3GJLmCUnsZswirr5wfLRrwavbnL/renOqg=
88
github.com/stackitcloud/stackit-sdk-go/core v0.17.3/go.mod h1:HBCXJGPgdRulplDzhrmwC+Dak9B/x0nzNtmOpu+1Ahg=
9+
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1 h1:r7oaINTwLmIG31AaqKTuQHHFF8YNuYGzi+46DOuSjw4=
10+
github.com/stackitcloud/stackit-sdk-go/services/resourcemanager v0.17.1/go.mod h1:ipcrPRbwfQXHH18dJVfY7K5ujHF5dTT6isoXgmA7YwQ=

services/iaas/wait/wait.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ package wait
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"net/http"
8+
"strings"
79
"time"
810

9-
"errors"
10-
1111
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
1212
"github.com/stackitcloud/stackit-sdk-go/core/wait"
1313
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
14+
"github.com/stackitcloud/stackit-sdk-go/services/resourcemanager"
1415
)
1516

1617
const (
@@ -48,6 +49,7 @@ const (
4849
// Interfaces needed for tests
4950
type APIClientInterface interface {
5051
GetNetworkAreaExecute(ctx context.Context, organizationId, areaId string) (*iaas.NetworkArea, error)
52+
ListNetworkAreaProjectsExecute(ctx context.Context, organizationId, areaId string) (*iaas.ProjectListResponse, error)
5153
GetProjectRequestExecute(ctx context.Context, projectId string, requestId string) (*iaas.Request, error)
5254
GetNetworkExecute(ctx context.Context, projectId, networkId string) (*iaas.Network, error)
5355
GetVolumeExecute(ctx context.Context, projectId string, volumeId string) (*iaas.Volume, error)
@@ -58,6 +60,10 @@ type APIClientInterface interface {
5860
GetSnapshotExecute(ctx context.Context, projectId string, snapshotId string) (*iaas.Snapshot, error)
5961
}
6062

63+
type ResourceManagerAPIClientInterface interface {
64+
GetProjectExecute(ctx context.Context, id string) (*resourcemanager.GetProjectResponse, error)
65+
}
66+
6167
// CreateNetworkAreaWaitHandler will wait for network area creation
6268
func CreateNetworkAreaWaitHandler(ctx context.Context, a APIClientInterface, organizationId, areaId string) *wait.AsyncActionHandler[iaas.NetworkArea] {
6369
handler := wait.New(func() (waitFinished bool, response *iaas.NetworkArea, err error) {
@@ -98,6 +104,52 @@ func UpdateNetworkAreaWaitHandler(ctx context.Context, a APIClientInterface, org
98104
return handler
99105
}
100106

107+
// ReadyForNetworkAreaDeletionWaitHandler will wait until a deletion of network area is possible
108+
// Workaround for https://github.com/stackitcloud/terraform-provider-stackit/issues/907.
109+
// When the deletion for a project is triggered, the backend starts a workflow in the background which cleans up all resources
110+
// within a project and deletes the project in each service. When the project is attached to an SNA, the SNA can't be
111+
// deleted until the workflow inform the IaaS-API that the project is deleted.
112+
func ReadyForNetworkAreaDeletionWaitHandler(ctx context.Context, a APIClientInterface, r ResourceManagerAPIClientInterface, organizationId, areaId string) *wait.AsyncActionHandler[iaas.ProjectListResponse] {
113+
handler := wait.New(func() (waitFinished bool, response *iaas.ProjectListResponse, err error) {
114+
projectList, err := a.ListNetworkAreaProjectsExecute(ctx, organizationId, areaId)
115+
if err != nil {
116+
return false, projectList, err
117+
}
118+
if projectList == nil || projectList.Items == nil {
119+
return false, nil, fmt.Errorf("read failed for projects in network area with id %s, the response is not valid: the items are missing", areaId)
120+
}
121+
if len(*projectList.Items) == 0 {
122+
return true, projectList, nil
123+
}
124+
var activeProjects, forbiddenProjects []string
125+
for _, projectId := range *projectList.Items {
126+
_, err := r.GetProjectExecute(ctx, projectId)
127+
if err == nil {
128+
activeProjects = append(activeProjects, projectId)
129+
continue
130+
}
131+
var oapiErr *oapierror.GenericOpenAPIError
132+
ok := errors.As(err, &oapiErr)
133+
if !ok {
134+
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
135+
}
136+
// The resource manager api responds with StatusForbidden(=403) when a project is deleted or if the project does not exist
137+
if oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusForbidden {
138+
forbiddenProjects = append(forbiddenProjects, projectId)
139+
}
140+
}
141+
if len(activeProjects) > 0 {
142+
return false, nil, fmt.Errorf("network area with id %s has still active projects: %s", areaId, strings.Join(activeProjects, ","))
143+
}
144+
if len(forbiddenProjects) > 0 {
145+
return false, nil, nil
146+
}
147+
return true, projectList, nil
148+
})
149+
handler.SetTimeout(1 * time.Minute)
150+
return handler
151+
}
152+
101153
// DeleteNetworkAreaWaitHandler will wait for network area deletion
102154
func DeleteNetworkAreaWaitHandler(ctx context.Context, a APIClientInterface, organizationId, areaId string) *wait.AsyncActionHandler[iaas.NetworkArea] {
103155
handler := wait.New(func() (waitFinished bool, response *iaas.NetworkArea, err error) {

0 commit comments

Comments
 (0)