From 4ea5da9243f900a38194b414a9e803226bee0ccd Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Wed, 25 Feb 2026 11:26:40 +0100 Subject: [PATCH 01/10] add graceful deletion in infraflow delete # Conflicts: # pkg/apis/stackit/helper/error_codes.go --- pkg/apis/stackit/helper/error_codes.go | 2 +- .../infrastructure/openstack/infraflow/delete.go | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/apis/stackit/helper/error_codes.go b/pkg/apis/stackit/helper/error_codes.go index 68176dc4..70fc3c12 100644 --- a/pkg/apis/stackit/helper/error_codes.go +++ b/pkg/apis/stackit/helper/error_codes.go @@ -15,7 +15,7 @@ var ( unauthorizedRegexp = regexp.MustCompile(`(?i)(Unauthorized|SignatureDoesNotMatch|invalid_grant|Authorization Profile was not found|no active subscriptions|not authorized|AccessDenied|PolicyNotAuthorized)`) quotaExceededRegexp = regexp.MustCompile(`(?i)((?:^|[^t]|(?:[^s]|^)t|(?:[^e]|^)st|(?:[^u]|^)est|(?:[^q]|^)uest|(?:[^e]|^)quest|(?:[^r]|^)equest)LimitExceeded|Quotas|Quota.*exceeded|exceeded quota|Quota has been met|QUOTA_EXCEEDED|Maximum number of ports exceeded|VolumeSizeExceedsAvailableQuota)`) rateLimitsExceededRegexp = regexp.MustCompile(`(?i)(RequestLimitExceeded|Throttling|Too many requests)`) - dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled)`) + dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled|409)`) retryableDependenciesRegexp = regexp.MustCompile(`(?i)(RetryableError|internal server error)`) resourcesDepletedRegexp = regexp.MustCompile(`(?i)(not available in the current hardware cluster|out of stock)`) configurationProblemRegexp = regexp.MustCompile(`(?i)(missing expected router|Policy doesn't allow .* to be performed|overlaps with cidr|not supported in your requested Availability Zone|notFound|Invalid value|violates constraint|no attached internet gateway found|Your query returned no results|invalid VPC attributes|unrecognized feature gate|runtime-config invalid key|strict decoder error|not allowed to configure an unsupported|error during apply of object .* is invalid:|duplicate zones|overlapping zones)`) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index bcf0d6d7..0144d555 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -6,8 +6,11 @@ package infraflow import ( "context" + "fmt" + "github.com/gardener/gardener/extensions/pkg/util" "github.com/gardener/gardener/pkg/utils/flow" + "github.com/stackitcloud/gardener-extension-provider-stackit/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" @@ -117,7 +120,7 @@ func (fctx *FlowContext) deleteRouter(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "router", *routerID) if err := fctx.networking.DeleteRouter(ctx, *routerID); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete router: %w", err), helper.KnownCodes) } fctx.state.Set(IdentifierRouter, "") @@ -132,7 +135,7 @@ func (fctx *FlowContext) deleteNetwork(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "network", *networkID) if err := fctx.networking.DeleteNetwork(ctx, *networkID); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete network: %w", err), helper.KnownCodes) } fctx.state.Set(NameNetwork, "") @@ -148,7 +151,7 @@ func (fctx *FlowContext) deleteSubnet(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "subnet", *subnetID) if err := fctx.networking.DeleteSubnet(ctx, *subnetID); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete subnet: %w", err), helper.KnownCodes) } fctx.state.Set(IdentifierSubnet, "") return nil @@ -229,7 +232,7 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.ID) if err := fctx.networking.DeleteSecurityGroup(ctx, current.ID); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete security groups: %w", err), helper.KnownCodes) } } fctx.state.Set(NameSecGroup, "") @@ -266,7 +269,7 @@ func (fctx *FlowContext) deleteSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting ssh keypair...") if err := fctx.compute.DeleteKeyPair(ctx, current.Name); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete SSH key pair: %w", err), helper.KnownCodes) } } return nil @@ -281,7 +284,7 @@ func (fctx *FlowContext) deleteStackitSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting stackit ssh keypair...") if err := fctx.iaasClient.DeleteKeypair(ctx, *current.Name); client.IgnoreNotFoundError(err) != nil { - return err + return util.DetermineError(fmt.Errorf("failed to delete STACKIT SSH key pair: %w", err), helper.KnownCodes) } } return nil From d0ed8d7a62054cb658d0334c46fd141b4639f0ec Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Wed, 25 Feb 2026 12:11:50 +0100 Subject: [PATCH 02/10] add graceful deletion in infraflow delete --- pkg/controller/infrastructure/openstack/infraflow/delete.go | 3 +-- pkg/controller/infrastructure/stackit/infraflow/delete.go | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index 0144d555..0788c152 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -10,8 +10,7 @@ import ( "github.com/gardener/gardener/extensions/pkg/util" "github.com/gardener/gardener/pkg/utils/flow" - "github.com/stackitcloud/gardener-extension-provider-stackit/pkg/apis/stackit/helper" - + "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" diff --git a/pkg/controller/infrastructure/stackit/infraflow/delete.go b/pkg/controller/infrastructure/stackit/infraflow/delete.go index 108e900a..2eed1eaa 100644 --- a/pkg/controller/infrastructure/stackit/infraflow/delete.go +++ b/pkg/controller/infrastructure/stackit/infraflow/delete.go @@ -4,7 +4,9 @@ import ( "context" "fmt" + "github.com/gardener/gardener/extensions/pkg/util" "github.com/gardener/gardener/pkg/utils/flow" + "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" @@ -110,7 +112,7 @@ func (fctx *FlowContext) deleteIsolatedNetwork(ctx context.Context) error { } if err := fctx.iaasClient.DeleteNetwork(ctx, *networkID); stackitclient.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete network: %w", err) + return util.DetermineError(fmt.Errorf("failed to delete network: %w", err), helper.KnownCodes) } fctx.state.Set(NameNetwork, "") fctx.state.Set(IdentifierNetwork, "") @@ -126,7 +128,7 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.GetId()) if err := fctx.iaasClient.DeleteSecurityGroup(ctx, current.GetId()); stackitclient.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete security group: %w", err) + return util.DetermineError(fmt.Errorf("failed to delete security group: %w", err), helper.KnownCodes) } } fctx.state.Set(NameSecGroup, "") From 8fc33101a4d09ee6c31b6881853ecf61123b88ee Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Wed, 25 Feb 2026 13:03:28 +0100 Subject: [PATCH 03/10] wip --- pkg/controller/infrastructure/openstack/infraflow/delete.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index 0788c152..2ab883de 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -150,7 +150,7 @@ func (fctx *FlowContext) deleteSubnet(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "subnet", *subnetID) if err := fctx.networking.DeleteSubnet(ctx, *subnetID); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete subnet: %w", err), helper.KnownCodes) + return fmt.Errorf("failed to delete subnet: %w", err) } fctx.state.Set(IdentifierSubnet, "") return nil @@ -283,7 +283,7 @@ func (fctx *FlowContext) deleteStackitSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting stackit ssh keypair...") if err := fctx.iaasClient.DeleteKeypair(ctx, *current.Name); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete STACKIT SSH key pair: %w", err), helper.KnownCodes) + return fmt.Errorf("failed to delete STACKIT SSH key pair: %w", err) } } return nil From a5b831aaa37ca3916b03c15dbaa295bbe1b683c5 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Wed, 25 Feb 2026 14:18:02 +0100 Subject: [PATCH 04/10] wip --- pkg/controller/infrastructure/openstack/infraflow/delete.go | 6 +++++- pkg/stackit/client/errors.go | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index 2ab883de..d39aff17 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -16,6 +16,7 @@ import ( "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/internal/infrastructure" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/openstack/client" + stackitclient "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/stackit/client" ) // Delete creates and runs the flow to delete the AWS infrastructure. @@ -119,7 +120,10 @@ func (fctx *FlowContext) deleteRouter(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "router", *routerID) if err := fctx.networking.DeleteRouter(ctx, *routerID); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete router: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete router due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete router: %w", err) } fctx.state.Set(IdentifierRouter, "") diff --git a/pkg/stackit/client/errors.go b/pkg/stackit/client/errors.go index 2bda6833..5a4a15bb 100644 --- a/pkg/stackit/client/errors.go +++ b/pkg/stackit/client/errors.go @@ -51,6 +51,8 @@ func IsNotFound(err error) bool { return GetStatusCode(err) == http.StatusNotFound } +func IsConflict(err error) bool { return GetStatusCode(err) == http.StatusConflict } + // IgnoreNotFoundError ignore not found error func IgnoreNotFoundError(err error) error { if IsNotFound(err) { From 5609a3c8922fd3a67012a5191ad4576075b6692a Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Wed, 25 Feb 2026 14:50:16 +0100 Subject: [PATCH 05/10] wip --- pkg/apis/stackit/helper/error_codes.go | 2 +- .../openstack/infraflow/delete.go | 17 ++++++++++++----- .../infrastructure/stackit/infraflow/delete.go | 13 ++++++++----- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/pkg/apis/stackit/helper/error_codes.go b/pkg/apis/stackit/helper/error_codes.go index 70fc3c12..634208d3 100644 --- a/pkg/apis/stackit/helper/error_codes.go +++ b/pkg/apis/stackit/helper/error_codes.go @@ -15,7 +15,7 @@ var ( unauthorizedRegexp = regexp.MustCompile(`(?i)(Unauthorized|SignatureDoesNotMatch|invalid_grant|Authorization Profile was not found|no active subscriptions|not authorized|AccessDenied|PolicyNotAuthorized)`) quotaExceededRegexp = regexp.MustCompile(`(?i)((?:^|[^t]|(?:[^s]|^)t|(?:[^e]|^)st|(?:[^u]|^)est|(?:[^q]|^)uest|(?:[^e]|^)quest|(?:[^r]|^)equest)LimitExceeded|Quotas|Quota.*exceeded|exceeded quota|Quota has been met|QUOTA_EXCEEDED|Maximum number of ports exceeded|VolumeSizeExceedsAvailableQuota)`) rateLimitsExceededRegexp = regexp.MustCompile(`(?i)(RequestLimitExceeded|Throttling|Too many requests)`) - dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled|409)`) + dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled|due to 409 conflict)`) retryableDependenciesRegexp = regexp.MustCompile(`(?i)(RetryableError|internal server error)`) resourcesDepletedRegexp = regexp.MustCompile(`(?i)(not available in the current hardware cluster|out of stock)`) configurationProblemRegexp = regexp.MustCompile(`(?i)(missing expected router|Policy doesn't allow .* to be performed|overlaps with cidr|not supported in your requested Availability Zone|notFound|Invalid value|violates constraint|no attached internet gateway found|Your query returned no results|invalid VPC attributes|unrecognized feature gate|runtime-config invalid key|strict decoder error|not allowed to configure an unsupported|error during apply of object .* is invalid:|duplicate zones|overlapping zones)`) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index d39aff17..2bf0291e 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -8,9 +8,7 @@ import ( "context" "fmt" - "github.com/gardener/gardener/extensions/pkg/util" "github.com/gardener/gardener/pkg/utils/flow" - "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" @@ -138,7 +136,10 @@ func (fctx *FlowContext) deleteNetwork(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "network", *networkID) if err := fctx.networking.DeleteNetwork(ctx, *networkID); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete network: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete network due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete network: %w", err) } fctx.state.Set(NameNetwork, "") @@ -235,7 +236,10 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.ID) if err := fctx.networking.DeleteSecurityGroup(ctx, current.ID); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete security groups: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete security group due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete security groups: %w", err) } } fctx.state.Set(NameSecGroup, "") @@ -272,7 +276,10 @@ func (fctx *FlowContext) deleteSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting ssh keypair...") if err := fctx.compute.DeleteKeyPair(ctx, current.Name); client.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete SSH key pair: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete ssh key pair due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete SSH key pair: %w", err) } } return nil diff --git a/pkg/controller/infrastructure/stackit/infraflow/delete.go b/pkg/controller/infrastructure/stackit/infraflow/delete.go index 2eed1eaa..d6b3832d 100644 --- a/pkg/controller/infrastructure/stackit/infraflow/delete.go +++ b/pkg/controller/infrastructure/stackit/infraflow/delete.go @@ -4,10 +4,7 @@ import ( "context" "fmt" - "github.com/gardener/gardener/extensions/pkg/util" "github.com/gardener/gardener/pkg/utils/flow" - "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" - "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" @@ -112,7 +109,10 @@ func (fctx *FlowContext) deleteIsolatedNetwork(ctx context.Context) error { } if err := fctx.iaasClient.DeleteNetwork(ctx, *networkID); stackitclient.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete network: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete network r due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete network: %w", err) } fctx.state.Set(NameNetwork, "") fctx.state.Set(IdentifierNetwork, "") @@ -128,7 +128,10 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.GetId()) if err := fctx.iaasClient.DeleteSecurityGroup(ctx, current.GetId()); stackitclient.IgnoreNotFoundError(err) != nil { - return util.DetermineError(fmt.Errorf("failed to delete security group: %w", err), helper.KnownCodes) + if stackitclient.IsConflict(err) { + return fmt.Errorf("failed to delete security group r due to 409 conflict: %w", err) + } + return fmt.Errorf("failed to delete security group: %w", err) } } fctx.state.Set(NameSecGroup, "") From 15ec0626557decd1e6f7886438d8ddb2ffa3bd0c Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 26 Feb 2026 11:40:31 +0100 Subject: [PATCH 06/10] fix linting --- pkg/controller/infrastructure/openstack/infraflow/delete.go | 1 + pkg/controller/infrastructure/stackit/infraflow/delete.go | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index 2bf0291e..574094b4 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/gardener/gardener/pkg/utils/flow" + "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" diff --git a/pkg/controller/infrastructure/stackit/infraflow/delete.go b/pkg/controller/infrastructure/stackit/infraflow/delete.go index d6b3832d..247f3bdb 100644 --- a/pkg/controller/infrastructure/stackit/infraflow/delete.go +++ b/pkg/controller/infrastructure/stackit/infraflow/delete.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/gardener/gardener/pkg/utils/flow" + "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/controlplane" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow/shared" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" From 749384ba1f7fbfb245c4f7f47623393de0863caf Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 26 Feb 2026 12:42:41 +0100 Subject: [PATCH 07/10] minimize the setup --- pkg/apis/stackit/helper/error_codes.go | 2 +- .../infrastructure/openstack/actuator_delete.go | 9 ++++++++- .../infrastructure/openstack/infraflow/delete.go | 13 ------------- .../infrastructure/stackit/actuator_delete.go | 9 ++++++++- .../infrastructure/stackit/infraflow/delete.go | 6 ------ 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pkg/apis/stackit/helper/error_codes.go b/pkg/apis/stackit/helper/error_codes.go index 634208d3..68176dc4 100644 --- a/pkg/apis/stackit/helper/error_codes.go +++ b/pkg/apis/stackit/helper/error_codes.go @@ -15,7 +15,7 @@ var ( unauthorizedRegexp = regexp.MustCompile(`(?i)(Unauthorized|SignatureDoesNotMatch|invalid_grant|Authorization Profile was not found|no active subscriptions|not authorized|AccessDenied|PolicyNotAuthorized)`) quotaExceededRegexp = regexp.MustCompile(`(?i)((?:^|[^t]|(?:[^s]|^)t|(?:[^e]|^)st|(?:[^u]|^)est|(?:[^q]|^)uest|(?:[^e]|^)quest|(?:[^r]|^)equest)LimitExceeded|Quotas|Quota.*exceeded|exceeded quota|Quota has been met|QUOTA_EXCEEDED|Maximum number of ports exceeded|VolumeSizeExceedsAvailableQuota)`) rateLimitsExceededRegexp = regexp.MustCompile(`(?i)(RequestLimitExceeded|Throttling|Too many requests)`) - dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled|due to 409 conflict)`) + dependenciesRegexp = regexp.MustCompile(`(?i)(PendingVerification|Access Not Configured|accessNotConfigured|DependencyViolation|OptInRequired|Conflict|inactive billing state|timeout while waiting for state to become|InvalidCidrBlock|already busy for|A resource with the ID|There are not enough hosts available|No Router found|Service not enabled)`) retryableDependenciesRegexp = regexp.MustCompile(`(?i)(RetryableError|internal server error)`) resourcesDepletedRegexp = regexp.MustCompile(`(?i)(not available in the current hardware cluster|out of stock)`) configurationProblemRegexp = regexp.MustCompile(`(?i)(missing expected router|Policy doesn't allow .* to be performed|overlaps with cidr|not supported in your requested Availability Zone|notFound|Invalid value|violates constraint|no attached internet gateway found|Your query returned no results|invalid VPC attributes|unrecognized feature gate|runtime-config invalid key|strict decoder error|not allowed to configure an unsupported|error during apply of object .* is invalid:|duplicate zones|overlapping zones)`) diff --git a/pkg/controller/infrastructure/openstack/actuator_delete.go b/pkg/controller/infrastructure/openstack/actuator_delete.go index 68ac72ba..db52cca8 100644 --- a/pkg/controller/infrastructure/openstack/actuator_delete.go +++ b/pkg/controller/infrastructure/openstack/actuator_delete.go @@ -10,6 +10,8 @@ import ( extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/util" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + gardenerapihelper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/go-logr/logr" @@ -23,8 +25,13 @@ import ( // Delete the Infrastructure config. func (a *actuator) Delete(ctx context.Context, log logr.Logger, infra *extensionsv1alpha1.Infrastructure, cluster *extensionscontroller.Cluster) error { + err := a.delete(ctx, log, infra, cluster) + if stackitclient.IsConflict(err) { + return gardenerapihelper.NewErrorWithCodes(err, gardencorev1beta1.ErrorInfraDependencies) + } + return util.DetermineError( - a.delete(ctx, log, infra, cluster), + err, helper.KnownCodes, ) } diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index 574094b4..a49f43af 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -15,7 +15,6 @@ import ( "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/feature" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/internal/infrastructure" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/openstack/client" - stackitclient "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/stackit/client" ) // Delete creates and runs the flow to delete the AWS infrastructure. @@ -119,9 +118,6 @@ func (fctx *FlowContext) deleteRouter(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "router", *routerID) if err := fctx.networking.DeleteRouter(ctx, *routerID); client.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete router due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete router: %w", err) } @@ -137,9 +133,6 @@ func (fctx *FlowContext) deleteNetwork(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "network", *networkID) if err := fctx.networking.DeleteNetwork(ctx, *networkID); client.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete network due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete network: %w", err) } @@ -237,9 +230,6 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.ID) if err := fctx.networking.DeleteSecurityGroup(ctx, current.ID); client.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete security group due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete security groups: %w", err) } } @@ -277,9 +267,6 @@ func (fctx *FlowContext) deleteSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting ssh keypair...") if err := fctx.compute.DeleteKeyPair(ctx, current.Name); client.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete ssh key pair due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete SSH key pair: %w", err) } } diff --git a/pkg/controller/infrastructure/stackit/actuator_delete.go b/pkg/controller/infrastructure/stackit/actuator_delete.go index fb58913e..4019314a 100644 --- a/pkg/controller/infrastructure/stackit/actuator_delete.go +++ b/pkg/controller/infrastructure/stackit/actuator_delete.go @@ -10,6 +10,8 @@ import ( extensionscontroller "github.com/gardener/gardener/extensions/pkg/controller" "github.com/gardener/gardener/extensions/pkg/util" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + gardenerapihelper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/go-logr/logr" @@ -23,8 +25,13 @@ import ( // Delete the Infrastructure config. func (a *actuator) Delete(ctx context.Context, log logr.Logger, infra *extensionsv1alpha1.Infrastructure, cluster *extensionscontroller.Cluster) error { + err := a.delete(ctx, log, infra, cluster) + if stackitclient.IsConflict(err) { + return gardenerapihelper.NewErrorWithCodes(err, gardencorev1beta1.ErrorInfraDependencies) + } + return util.DetermineError( - a.delete(ctx, log, infra, cluster), + err, helper.KnownCodes, ) } diff --git a/pkg/controller/infrastructure/stackit/infraflow/delete.go b/pkg/controller/infrastructure/stackit/infraflow/delete.go index 247f3bdb..108e900a 100644 --- a/pkg/controller/infrastructure/stackit/infraflow/delete.go +++ b/pkg/controller/infrastructure/stackit/infraflow/delete.go @@ -110,9 +110,6 @@ func (fctx *FlowContext) deleteIsolatedNetwork(ctx context.Context) error { } if err := fctx.iaasClient.DeleteNetwork(ctx, *networkID); stackitclient.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete network r due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete network: %w", err) } fctx.state.Set(NameNetwork, "") @@ -129,9 +126,6 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.GetId()) if err := fctx.iaasClient.DeleteSecurityGroup(ctx, current.GetId()); stackitclient.IgnoreNotFoundError(err) != nil { - if stackitclient.IsConflict(err) { - return fmt.Errorf("failed to delete security group r due to 409 conflict: %w", err) - } return fmt.Errorf("failed to delete security group: %w", err) } } From aa46c7db7d8a34d6762a784476c6a5dff0072588 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 26 Feb 2026 12:50:01 +0100 Subject: [PATCH 08/10] minimize the setup --- .../infrastructure/openstack/infraflow/delete.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/controller/infrastructure/openstack/infraflow/delete.go b/pkg/controller/infrastructure/openstack/infraflow/delete.go index a49f43af..bcf0d6d7 100644 --- a/pkg/controller/infrastructure/openstack/infraflow/delete.go +++ b/pkg/controller/infrastructure/openstack/infraflow/delete.go @@ -6,7 +6,6 @@ package infraflow import ( "context" - "fmt" "github.com/gardener/gardener/pkg/utils/flow" @@ -118,7 +117,7 @@ func (fctx *FlowContext) deleteRouter(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "router", *routerID) if err := fctx.networking.DeleteRouter(ctx, *routerID); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete router: %w", err) + return err } fctx.state.Set(IdentifierRouter, "") @@ -133,7 +132,7 @@ func (fctx *FlowContext) deleteNetwork(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "network", *networkID) if err := fctx.networking.DeleteNetwork(ctx, *networkID); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete network: %w", err) + return err } fctx.state.Set(NameNetwork, "") @@ -149,7 +148,7 @@ func (fctx *FlowContext) deleteSubnet(ctx context.Context) error { shared.LogFromContext(ctx).Info("deleting...", "subnet", *subnetID) if err := fctx.networking.DeleteSubnet(ctx, *subnetID); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete subnet: %w", err) + return err } fctx.state.Set(IdentifierSubnet, "") return nil @@ -230,7 +229,7 @@ func (fctx *FlowContext) deleteSecGroup(ctx context.Context) error { if current != nil { log.Info("deleting...", "securityGroup", current.ID) if err := fctx.networking.DeleteSecurityGroup(ctx, current.ID); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete security groups: %w", err) + return err } } fctx.state.Set(NameSecGroup, "") @@ -267,7 +266,7 @@ func (fctx *FlowContext) deleteSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting ssh keypair...") if err := fctx.compute.DeleteKeyPair(ctx, current.Name); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete SSH key pair: %w", err) + return err } } return nil @@ -282,7 +281,7 @@ func (fctx *FlowContext) deleteStackitSSHKeyPair(ctx context.Context) error { if current != nil { log.Info("deleting stackit ssh keypair...") if err := fctx.iaasClient.DeleteKeypair(ctx, *current.Name); client.IgnoreNotFoundError(err) != nil { - return fmt.Errorf("failed to delete STACKIT SSH key pair: %w", err) + return err } } return nil From caf49034a37fe5e88a7a5ef0dff36e6ae7cd5f73 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 26 Feb 2026 15:54:57 +0100 Subject: [PATCH 09/10] minimize the setup --- .../openstack/actuator_delete.go | 3 +-- pkg/openstack/client/errors.go | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 pkg/openstack/client/errors.go diff --git a/pkg/controller/infrastructure/openstack/actuator_delete.go b/pkg/controller/infrastructure/openstack/actuator_delete.go index db52cca8..d75ca34f 100644 --- a/pkg/controller/infrastructure/openstack/actuator_delete.go +++ b/pkg/controller/infrastructure/openstack/actuator_delete.go @@ -14,7 +14,6 @@ import ( gardenerapihelper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/go-logr/logr" - "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow" openstackutils "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/openstack" @@ -26,7 +25,7 @@ import ( // Delete the Infrastructure config. func (a *actuator) Delete(ctx context.Context, log logr.Logger, infra *extensionsv1alpha1.Infrastructure, cluster *extensionscontroller.Cluster) error { err := a.delete(ctx, log, infra, cluster) - if stackitclient.IsConflict(err) { + if openstackclient.IsConflict(err) { return gardenerapihelper.NewErrorWithCodes(err, gardencorev1beta1.ErrorInfraDependencies) } diff --git a/pkg/openstack/client/errors.go b/pkg/openstack/client/errors.go new file mode 100644 index 00000000..d5584ad5 --- /dev/null +++ b/pkg/openstack/client/errors.go @@ -0,0 +1,24 @@ +package client + +import ( + "errors" + "net/http" +) + +// StatusCodeError is a common interface implemented by Error and the SDK's GenericOpenAPIError. +type StatusCodeError interface { + error + GetStatusCode() int +} + +// GetStatusCode returns the attached error code if the given error implements StatusCodeError or 0 otherwise. +func GetStatusCode(err error) int { + var statusCodeError StatusCodeError + if ok := errors.As(err, &statusCodeError); !ok { + return 0 + } + + return statusCodeError.GetStatusCode() +} + +func IsConflict(err error) bool { return GetStatusCode(err) == http.StatusConflict } From 281fccbb65697c8de24dfb3dbe0ac1cd38e6c094 Mon Sep 17 00:00:00 2001 From: Aniruddha Basak Date: Thu, 26 Feb 2026 16:10:38 +0100 Subject: [PATCH 10/10] minimize the setup --- pkg/controller/infrastructure/openstack/actuator_delete.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/controller/infrastructure/openstack/actuator_delete.go b/pkg/controller/infrastructure/openstack/actuator_delete.go index d75ca34f..eeb5612d 100644 --- a/pkg/controller/infrastructure/openstack/actuator_delete.go +++ b/pkg/controller/infrastructure/openstack/actuator_delete.go @@ -14,6 +14,7 @@ import ( gardenerapihelper "github.com/gardener/gardener/pkg/apis/core/v1beta1/helper" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/go-logr/logr" + "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/apis/stackit/helper" "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/controller/infrastructure/openstack/infraflow" openstackutils "github.com/stackitcloud/gardener-extension-provider-stackit/v2/pkg/openstack"