Skip to content

Commit 2aac745

Browse files
authored
Fix/ensuring existing secrets resulting in panic(#23)
* fix subreconciler requeue handling for setting controller reference * add webhook validation for existing secrets * add validation webhook test phase for existing secrets * revise forbidden error in validate secrets webhook
1 parent 5052540 commit 2aac745

File tree

6 files changed

+58
-3
lines changed

6 files changed

+58
-3
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ Dockerfile.cross
2424
*.swp
2525
*.swo
2626
*~
27-
27+
.vscode
2828
vendor/
29+
2930
# Downloaded go release for building testing Dockerfile
3031
testing/go*.tar.gz
3132
# Container id files of dev env containers

api/v1alpha1/s3userclaim_webhook.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ func (suc *S3UserClaim) ValidateCreate() error {
7171

7272
allErrs = validateQuota(suc, allErrs)
7373

74+
secretNames := []string{suc.Spec.AdminSecret, suc.Spec.ReadonlySecret}
75+
allErrs = validateSecrets(secretNames, suc.Namespace, allErrs)
76+
7477
if len(allErrs) == 0 {
7578
return nil
7679
}
@@ -97,6 +100,17 @@ func (suc *S3UserClaim) ValidateUpdate(old runtime.Object) error {
97100

98101
allErrs = validateQuota(suc, allErrs)
99102

103+
// validate against updated secret names
104+
var secretNames []string
105+
if oldS3UserClaim.Spec.AdminSecret != suc.Spec.AdminSecret {
106+
secretNames = append(secretNames, suc.Spec.AdminSecret)
107+
}
108+
if oldS3UserClaim.Spec.ReadonlySecret != suc.Spec.ReadonlySecret {
109+
secretNames = append(secretNames, suc.Spec.ReadonlySecret)
110+
}
111+
112+
allErrs = validateSecrets(secretNames, suc.Namespace, allErrs)
113+
100114
if len(allErrs) == 0 {
101115
return nil
102116
}
@@ -224,3 +238,23 @@ func validateAgainstClusterQuota(ctx context.Context, suc *S3UserClaim) error {
224238

225239
return nil
226240
}
241+
242+
func validateSecrets(secretNames []string, namespace string, allErrs field.ErrorList) field.ErrorList {
243+
ctx, cancel := context.WithTimeout(context.Background(), ValidationTimeout)
244+
defer cancel()
245+
for _, secretName := range secretNames {
246+
existingSecret := &v1.Secret{}
247+
switch err := runtimeClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: secretName}, existingSecret); {
248+
case apierrors.IsNotFound(err):
249+
continue
250+
case err != nil:
251+
allErrs = append(allErrs,
252+
field.InternalError(field.NewPath("spec"), fmt.Errorf("error with getting secret '%s': %w", secretName, err)))
253+
default:
254+
allErrs = append(allErrs,
255+
field.Forbidden(field.NewPath("spec"), fmt.Sprintf("secret %s exists", secretName)))
256+
}
257+
}
258+
return allErrs
259+
260+
}

internal/controllers/s3userclaim/provisioner.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ func (r *Reconciler) ensureSecret(ctx context.Context, secret *corev1.Secret) (*
327327
!metav1.IsControlledBy(existingSecret, r.s3UserClaim) {
328328
existingSecret.Data = secret.Data
329329
if err := ctrl.SetControllerReference(r.s3UserClaim, existingSecret, r.scheme); err != nil {
330-
return nil, err
330+
r.logger.Error(err, "failed to set controller reference", "secret name", secret.Name)
331+
return subreconciler.Requeue()
331332
}
332333
if err := r.Update(ctx, existingSecret); err != nil {
333334
r.logger.Error(err, "failed to update secret", "name", secret.Name)

pkg/consts/consts.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const (
2525
ErrClusterQuotaNotDefined = CustomError("cluster quota is not defined")
2626
S3UserClassImmutableErrMessage = "s3UserClass is immutable"
2727
S3UserRefImmutableErrMessage = "s3UserRef is immutable"
28-
S3UserRefNotFoundErrMessage = "There is no s3UserClaim regarding the defined s3UserRef"
28+
S3UserRefNotFoundErrMessage = "there is no s3UserClaim regarding the defined s3UserRef"
2929
ContactCloudTeamErrMessage = "please contact the cloud team"
3030

3131
FinalizerPrefix = "s3.snappcloud.io/"

testing/e2e/04-validation-webhook.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ commands:
55
ignoreFailure: true
66
- command: kubectl apply -f s3bucket-wrong-s3userref.yaml
77
ignoreFailure: true
8+
- command: kubectl apply -f create-s3user-with-existing-secret.yaml
9+
ignoreFailure: true
810
- command: kubectl delete s3userclaim s3userclaim-sample -n s3-test
911
ignoreFailure: true
1012
assert:
1113
- s3bucket-ok.yaml
1214
- 02-assert.yaml
1315
error:
1416
- s3bucket-wrong-s3userref.yaml
17+
- create-s3user-with-existing-secret.yaml
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Creating s3userclaim with existing secrets must be deined
2+
apiVersion: s3.snappcloud.io/v1alpha1
3+
kind: S3UserClaim
4+
metadata:
5+
name: s3userclaim-sample2
6+
namespace: s3-test
7+
spec:
8+
s3UserClass: ceph-default
9+
# existing secrets
10+
readonlySecret: s3-sample-readonly-secret
11+
adminSecret: s3-sample-admin-secret
12+
quota:
13+
maxSize: 100
14+
maxObjects: 50
15+
maxBuckets: 5
16+

0 commit comments

Comments
 (0)