diff --git a/extensions/pkg/controller/controlplane/genericactuator/actuator.go b/extensions/pkg/controller/controlplane/genericactuator/actuator.go index 8ce0121e749..1a5c18a95ca 100644 --- a/extensions/pkg/controller/controlplane/genericactuator/actuator.go +++ b/extensions/pkg/controller/controlplane/genericactuator/actuator.go @@ -414,19 +414,19 @@ func (a *actuator) Delete( return fmt.Errorf("failed to create secrets manager for ControlPlane: %w", err) } - if err := a.delete(ctx, log, cp); err != nil { + if err := a.delete(ctx, log, cp, cluster); err != nil { return err } return sm.Cleanup(ctx) } -func (a *actuator) delete(ctx context.Context, log logr.Logger, cp *extensionsv1alpha1.ControlPlane) error { +func (a *actuator) delete(ctx context.Context, log logr.Logger, cp *extensionsv1alpha1.ControlPlane, cluster *extensionscontroller.Cluster) error { if cp.Spec.Purpose != nil && *cp.Spec.Purpose == extensionsv1alpha1.Exposure { return a.deleteControlPlaneExposure(ctx, log, cp) } - return a.deleteControlPlane(ctx, log, cp) + return a.deleteControlPlane(ctx, log, cp, cluster) } // deleteControlPlaneExposure reconciles the given controlplane and cluster, deleting the additional Seed @@ -461,7 +461,22 @@ func (a *actuator) deleteControlPlane( ctx context.Context, log logr.Logger, cp *extensionsv1alpha1.ControlPlane, + cluster *extensionscontroller.Cluster, ) error { + // Get config chart values + if a.configChart != nil { + values, err := a.vp.GetConfigChartValues(ctx, cp, cluster) + if err != nil { + return fmt.Errorf("failed to get configuration chart values before deletion of controlplane %s: %w", kubernetesutils.ObjectName(cp), err) + } + + // Apply config chart + log.Info("Applying configuration chart before deletion") + if err := a.configChart.Apply(ctx, a.chartApplier, cp.Namespace, nil, "", "", values); err != nil { + return fmt.Errorf("could not apply configuration chart before deletion of controlplane '%s': %w", kubernetesutils.ObjectName(cp), err) + } + } + // Delete the managed resources if err := managedresources.Delete(ctx, a.client, cp.Namespace, StorageClassesChartResourceName, false); err != nil { return fmt.Errorf("could not delete managed resource containing storage classes chart for controlplane '%s': %w", kubernetesutils.ObjectName(cp), err) @@ -605,7 +620,7 @@ func (a *actuator) Migrate( return fmt.Errorf("could not keep objects of managed resource containing storage classes chart for controlplane '%s': %w", kubernetesutils.ObjectName(cp), err) } - return a.delete(ctx, log, cp) + return a.delete(ctx, log, cp, cluster) } func (a *actuator) newSecretsManagerForControlPlane(ctx context.Context, log logr.Logger, cp *extensionsv1alpha1.ControlPlane, cluster *extensionscontroller.Cluster, secretConfigs []extensionssecretsmanager.SecretConfigWithOptions) (secretsmanager.Interface, error) { diff --git a/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go b/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go index f3509d49190..4b808202034 100644 --- a/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go +++ b/extensions/pkg/controller/controlplane/genericactuator/actuator_test.go @@ -470,6 +470,12 @@ webhooks: atomicWebhookConfig.Store(webhookConfig) } + // Create mock values provider + vp := extensionsmockgenericactuator.NewMockValuesProvider(ctrl) + + // Create mock chart applier + chartApplier := kubernetesmock.NewMockChartApplier(ctrl) + // Create mock clients client := mockclient.NewMockClient(ctrl) @@ -494,6 +500,8 @@ webhooks: var configChart chart.Interface if configName != "" { configChartMock := mockchartutil.NewMockInterface(ctrl) + vp.EXPECT().GetConfigChartValues(ctx, cp, cluster).Return(configChartValues, nil) + configChartMock.EXPECT().Apply(ctx, chartApplier, namespace, nil, "", "", configChartValues).Return(nil) configChartMock.EXPECT().Delete(ctx, client, namespace).Return(nil) configChart = configChartMock } @@ -511,9 +519,10 @@ webhooks: client.EXPECT().Delete(ctx, &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: shootAccessSecretsFunc(namespace)[0].Secret.Name, Namespace: namespace}}) // Create actuator - a := NewActuator(providerName, getSecretsConfigs, shootAccessSecretsFunc, nil, nil, configChart, ccmChart, nil, cpShootCRDsChart, nil, nil, nil, nil, nil, configName, atomicWebhookConfig, webhookServerNamespace, webhookServerPort) + a := NewActuator(providerName, getSecretsConfigs, shootAccessSecretsFunc, nil, nil, configChart, ccmChart, nil, cpShootCRDsChart, nil, nil, vp, nil, nil, configName, atomicWebhookConfig, webhookServerNamespace, webhookServerPort) Expect(a.(inject.Client).InjectClient(client)).To(Succeed()) a.(*actuator).newSecretsManager = newSecretsManager + a.(*actuator).chartApplier = chartApplier // Call Delete method and check the result Expect(a.Delete(ctx, logger, cp, cluster)).To(Succeed())