Skip to content

Commit 299d06f

Browse files
committed
Updated PR to satisfy comments
1 parent 6fb9622 commit 299d06f

File tree

2 files changed

+94
-75
lines changed

2 files changed

+94
-75
lines changed

controllers/hcpvaultsecretsapp_controller.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ func (r *HCPVaultSecretsAppReconciler) cleanupOrphanedShadowSecrets(ctx context.
322322
nameLabelKey := hvsaLabelPrefix + "/name"
323323

324324
// filtering only for dynamic secrets, also checking if namespace and name labels are present
325-
secrets := corev1.SecretList{}
325+
secrets := secretsv1beta1.VaultDynamicSecretList{}
326326
if err := r.List(ctx, &secrets, client.InNamespace(common.OperatorNamespace),
327327
client.MatchingLabels{"app.kubernetes.io/component": "hvs-dynamic-secret-cache"},
328328
client.HasLabels{namespaceLabelKey, nameLabelKey}); err != nil {
@@ -345,16 +345,30 @@ func (r *HCPVaultSecretsAppReconciler) cleanupOrphanedShadowSecrets(ctx context.
345345
continue
346346
}
347347

348-
// if the HCPVaultSecretsApp has been deleted, and the shadow secret belongs to it, delete both
348+
// delete the HCPVaultSecretsApp and all resources associated with it the secret belongs to it
349+
// and the HCPVaultSecretsApp has a deletion timestamp
349350
if o.GetDeletionTimestamp() != nil && o.GetUID() == types.UID(secret.Labels[helpers.LabelOwnerRefUID]) {
350351
if err := r.handleDeletion(ctx, o); err != nil {
351352
errs = errors.Join(errs, fmt.Errorf("failed to handle deletion of HCPVaultSecretsApp %s: %w", o.Spec.AppName, err))
352353
}
353354

354355
logger.Info("Deleted orphaned resources associated with HCPVaultSecretsApp", "app", o.Name)
355-
} else if apierrors.IsNotFound(err) || secret.GetDeletionTimestamp() != nil {
356-
// otherwise, delete the single shadow secret if it has a deletion timestamp
357-
if err := helpers.DeleteSecret(ctx, r.Client, objKey); err != nil {
356+
} else if apierrors.IsNotFound(err) && secret.GetDeletionTimestamp() != nil {
357+
// otherwise, delete the shadow secret if we can't find the HCPVaultSecretsApp it belongs to and
358+
// the shadow secret has a deletion timestamp
359+
if controllerutil.ContainsFinalizer(&secret, vaultDynamicSecretFinalizer) {
360+
logger.Info("Removing finalizer from shadow secret")
361+
if controllerutil.RemoveFinalizer(&secret, vaultDynamicSecretFinalizer) {
362+
if err := r.Update(ctx, &secret); err != nil {
363+
errs = errors.Join(errs, fmt.Errorf("failed to remove the finalizer from shadow secret %s: %w", secret.Name, err))
364+
continue
365+
}
366+
367+
logger.Info("Successfully removed the finalizer from shadow secret")
368+
}
369+
}
370+
371+
if err := r.Delete(ctx, &secret); err != nil {
358372
errs = errors.Join(errs, fmt.Errorf("failed to delete shadow secret %s: %w", secret.Name, err))
359373
}
360374

@@ -458,10 +472,20 @@ func (r *HCPVaultSecretsAppReconciler) handleDeletion(ctx context.Context, o *se
458472
objKey := client.ObjectKeyFromObject(o)
459473
r.referenceCache.Remove(SecretTransformation, objKey)
460474
r.BackOffRegistry.Delete(objKey)
461-
shadowObjKey := makeShadowObjKey(o)
462-
if err := helpers.DeleteSecret(ctx, r.Client, shadowObjKey); err != nil {
463-
logger.Error(err, "Failed to delete shadow secret", "shadow secret", shadowObjKey)
464-
}
475+
// retrieve all shadow secrets that belong to the HCPVaultSecretsApp, remove their finalizers, and delete them
476+
secrets := secretsv1beta1.VaultDynamicSecretList{}
477+
if err := r.List(ctx, &secrets,
478+
client.InNamespace(common.OperatorNamespace),
479+
client.MatchingLabels{helpers.LabelOwnerRefUID: string(o.GetUID())}); err != nil {
480+
return fmt.Errorf("failed to list secrets in namespace %s: %w", o.GetNamespace(), err)
481+
}
482+
removeFinalizers(ctx, r.Client, logger, &secrets)
483+
if err := r.DeleteAllOf(ctx, &secretsv1beta1.VaultDynamicSecret{},
484+
client.InNamespace(common.OperatorNamespace),
485+
client.MatchingLabels{helpers.LabelOwnerRefUID: string(o.GetUID())}); err != nil {
486+
return fmt.Errorf("failed to delete secrets in namespace %s: %w", o.GetNamespace(), err)
487+
}
488+
// then remove the finalizer from the HCPVaultSecretsApp and delete it
465489
if controllerutil.ContainsFinalizer(o, hcpVaultSecretsAppFinalizer) {
466490
logger.Info("Removing finalizer")
467491
if controllerutil.RemoveFinalizer(o, hcpVaultSecretsAppFinalizer) {
@@ -472,6 +496,9 @@ func (r *HCPVaultSecretsAppReconciler) handleDeletion(ctx context.Context, o *se
472496
logger.Info("Successfully removed the finalizer")
473497
}
474498
}
499+
if err := r.Delete(ctx, o); err != nil {
500+
return fmt.Errorf("failed to delete HCPVaultSecretsApp %s: %w", o.Spec.AppName, err)
501+
}
475502
return nil
476503
}
477504

controllers/hcpvaultsecretsapp_controller_test.go

Lines changed: 58 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/hashicorp/hcp-sdk-go/clients/cloud-vault-secrets/preview/2023-11-28/models"
1919
"github.com/stretchr/testify/assert"
2020
"github.com/stretchr/testify/require"
21-
corev1 "k8s.io/api/core/v1"
2221
apierrors "k8s.io/apimachinery/pkg/api/errors"
2322
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2423
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -1230,111 +1229,103 @@ func Test_makeShadowObjKey(t *testing.T) {
12301229
}
12311230

12321231
func Test_CleanupOrphanedShadowSecrets(t *testing.T) {
1233-
deletionTimestamp := metav1.Now()
1232+
hvsApp := secretsv1beta1.HCPVaultSecretsApp{
1233+
TypeMeta: metav1.TypeMeta{
1234+
Kind: HCPVaultSecretsApp.String(),
1235+
APIVersion: secretsv1beta1.GroupVersion.Version,
1236+
},
1237+
ObjectMeta: metav1.ObjectMeta{
1238+
UID: "hvsAppUID",
1239+
Namespace: "hvsAppNamespace",
1240+
Name: "hvsApp",
1241+
Finalizers: []string{hcpVaultSecretsAppFinalizer},
1242+
},
1243+
}
12341244

12351245
tests := map[string]struct {
12361246
o *secretsv1beta1.HCPVaultSecretsApp
1237-
secret *corev1.Secret
1247+
secret *secretsv1beta1.VaultDynamicSecret
12381248
isHCPVaultSecretsAppDeletionExpected bool
12391249
isShadowSecretDeletionExpected bool
12401250
}{
12411251
"deleted-secret-hvsapp-owner": {
1242-
o: &secretsv1beta1.HCPVaultSecretsApp{
1252+
o: hvsApp.DeepCopy(),
1253+
secret: &secretsv1beta1.VaultDynamicSecret{
12431254
TypeMeta: metav1.TypeMeta{
1244-
Kind: HCPVaultSecretsApp.String(),
1255+
Kind: VaultDynamicSecret.String(),
12451256
APIVersion: secretsv1beta1.GroupVersion.Version,
12461257
},
12471258
ObjectMeta: metav1.ObjectMeta{
1248-
UID: "hvsApp1UID",
1249-
Namespace: "hvsApp1Namespace",
1250-
Name: "hvsApp1",
1251-
Finalizers: []string{hcpVaultSecretsAppFinalizer},
1252-
},
1253-
},
1254-
secret: &corev1.Secret{
1255-
ObjectMeta: metav1.ObjectMeta{
1256-
Namespace: common.OperatorNamespace,
1257-
Name: "shadowSecret1",
1258-
DeletionTimestamp: &deletionTimestamp,
1259-
Finalizers: []string{vaultDynamicSecretFinalizer},
1259+
Namespace: common.OperatorNamespace,
1260+
Name: "shadowSecret",
1261+
Finalizers: []string{vaultDynamicSecretFinalizer},
12601262
Labels: map[string]string{
1261-
hvsaLabelPrefix + "/namespace": "hvsApp1Namespace",
1262-
hvsaLabelPrefix + "/name": "hvsApp1",
1263+
hvsaLabelPrefix + "/namespace": hvsApp.GetNamespace(),
1264+
hvsaLabelPrefix + "/name": hvsApp.GetName(),
1265+
helpers.LabelOwnerRefUID: string(hvsApp.GetUID()),
12631266
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
1264-
helpers.LabelOwnerRefUID: "hvsApp1UID",
12651267
},
12661268
},
12671269
},
12681270
isHCPVaultSecretsAppDeletionExpected: true,
12691271
isShadowSecretDeletionExpected: true,
12701272
},
12711273
"deleted-secret-hvsapp-not-owner": {
1272-
o: &secretsv1beta1.HCPVaultSecretsApp{
1274+
o: hvsApp.DeepCopy(),
1275+
secret: &secretsv1beta1.VaultDynamicSecret{
12731276
TypeMeta: metav1.TypeMeta{
1274-
Kind: HCPVaultSecretsApp.String(),
1277+
Kind: VaultDynamicSecret.String(),
12751278
APIVersion: secretsv1beta1.GroupVersion.Version,
12761279
},
12771280
ObjectMeta: metav1.ObjectMeta{
1278-
UID: "hvsApp2UID",
1279-
Namespace: "hvsApp2Namespace",
1280-
Name: "hvsApp2",
1281-
Finalizers: []string{hcpVaultSecretsAppFinalizer},
1282-
},
1283-
},
1284-
secret: &corev1.Secret{
1285-
ObjectMeta: metav1.ObjectMeta{
1286-
Namespace: common.OperatorNamespace,
1287-
Name: "shadowSecret2",
1288-
DeletionTimestamp: &deletionTimestamp,
1289-
Finalizers: []string{vaultDynamicSecretFinalizer},
1281+
Namespace: common.OperatorNamespace,
1282+
Name: "shadowSecret",
1283+
Finalizers: []string{vaultDynamicSecretFinalizer},
12901284
Labels: map[string]string{
1291-
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
1285+
hvsaLabelPrefix + "/namespace": "",
1286+
hvsaLabelPrefix + "/name": "",
1287+
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
12921288
},
12931289
},
12941290
},
12951291
isShadowSecretDeletionExpected: true,
12961292
},
12971293
"deleted-secret-hvsapp-not-found": {
1298-
secret: &corev1.Secret{
1294+
secret: &secretsv1beta1.VaultDynamicSecret{
1295+
TypeMeta: metav1.TypeMeta{
1296+
Kind: VaultDynamicSecret.String(),
1297+
APIVersion: secretsv1beta1.GroupVersion.Version,
1298+
},
12991299
ObjectMeta: metav1.ObjectMeta{
1300-
Namespace: common.OperatorNamespace,
1301-
Name: "shadowSecret3",
1300+
Namespace: common.OperatorNamespace,
1301+
Name: "shadowSecret",
1302+
Finalizers: []string{vaultDynamicSecretFinalizer},
13021303
Labels: map[string]string{
1303-
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
1304+
hvsaLabelPrefix + "/namespace": "",
1305+
hvsaLabelPrefix + "/name": "",
1306+
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
13041307
},
1305-
DeletionTimestamp: &deletionTimestamp,
1306-
Finalizers: []string{hcpVaultSecretsAppFinalizer},
13071308
},
13081309
},
13091310
isShadowSecretDeletionExpected: true,
13101311
},
1311-
"secret-not-dynamic": {
1312-
o: &secretsv1beta1.HCPVaultSecretsApp{
1312+
"non-deleted-secret-hvsapp-not-found": {
1313+
secret: &secretsv1beta1.VaultDynamicSecret{
13131314
TypeMeta: metav1.TypeMeta{
1314-
Kind: HCPVaultSecretsApp.String(),
1315+
Kind: VaultDynamicSecret.String(),
13151316
APIVersion: secretsv1beta1.GroupVersion.Version,
13161317
},
13171318
ObjectMeta: metav1.ObjectMeta{
1318-
UID: "hvsApp4UID",
1319-
Namespace: "hvsApp4Namespace",
1320-
Name: "hvsApp4",
1321-
Finalizers: []string{hcpVaultSecretsAppFinalizer},
1322-
},
1323-
},
1324-
secret: &corev1.Secret{
1325-
ObjectMeta: metav1.ObjectMeta{
1326-
Namespace: common.OperatorNamespace,
1327-
Name: "nonShadowSecret",
1328-
DeletionTimestamp: &deletionTimestamp,
1329-
Finalizers: []string{vaultDynamicSecretFinalizer},
1319+
Namespace: common.OperatorNamespace,
1320+
Name: "shadowSecret",
1321+
Finalizers: []string{vaultDynamicSecretFinalizer},
13301322
Labels: map[string]string{
1331-
hvsaLabelPrefix + "/namespace": "hvsApp4Namespace",
1332-
hvsaLabelPrefix + "/name": "hvsApp4",
1333-
helpers.LabelOwnerRefUID: "hvsApp4UID",
1323+
hvsaLabelPrefix + "/namespace": "",
1324+
hvsaLabelPrefix + "/name": "",
1325+
"app.kubernetes.io/component": "hvs-dynamic-secret-cache",
13341326
},
13351327
},
13361328
},
1337-
isShadowSecretDeletionExpected: false,
13381329
},
13391330
}
13401331

@@ -1358,11 +1349,14 @@ func Test_CleanupOrphanedShadowSecrets(t *testing.T) {
13581349
// create the secret for the test case
13591350
assert.NoError(t, client.Create(ctx, tt.secret))
13601351

1361-
// DeleteTimestamp is a read-only field, so Delete will need to be called to
1362-
// simulate deletion of the HCPVaultSecretsApp
1352+
// DeleteTimestamp is a read-only field, so Delete() will need
1353+
// to be called to simulate deletion of both the HCPVaultSecretsApp and the secret
13631354
if tt.isHCPVaultSecretsAppDeletionExpected {
13641355
assert.NoError(t, client.Delete(ctx, tt.o))
13651356
}
1357+
if tt.isShadowSecretDeletionExpected {
1358+
assert.NoError(t, client.Delete(ctx, tt.secret))
1359+
}
13661360

13671361
r.cleanupOrphanedShadowSecrets(ctx)
13681362

@@ -1372,13 +1366,11 @@ func Test_CleanupOrphanedShadowSecrets(t *testing.T) {
13721366
assert.True(t, apierrors.IsNotFound(err))
13731367
}
13741368

1369+
secret := &secretsv1beta1.VaultDynamicSecret{}
1370+
err := r.Get(ctx, ctrlclient.ObjectKeyFromObject(tt.secret), secret)
13751371
if tt.isShadowSecretDeletionExpected {
1376-
deletedSecret := &corev1.Secret{}
1377-
err := r.Get(ctx, makeShadowObjKey(tt.secret), deletedSecret)
13781372
assert.True(t, apierrors.IsNotFound(err))
13791373
} else {
1380-
secret := &corev1.Secret{}
1381-
err := r.Get(ctx, ctrlclient.ObjectKeyFromObject(tt.secret), secret)
13821374
assert.False(t, apierrors.IsNotFound(err))
13831375
}
13841376
})

0 commit comments

Comments
 (0)