Reconcile triggers again on creating a secret owned by custom resource

627 views Asked by At

I used the operator-sdk to create a custom resource DatabaseService. Creation a DatabaseService CR should trigger the Reconcile function that would create a secret in the CR namespace after getting it from a third party.

I set the CR as the owner of the secret so that whenever the secret is manually deleted, the reconcile function will trigger again and recreate the secret.

Here is the code:

func (r *DatabaseServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    requeueResult := ctrl.Result{Requeue: true, RequeueAfter: time.Minute}
    emptyResult := ctrl.Result{Requeue: false, RequeueAfter: 0}

    ds := &operatorsv1alpha1.DatabaseService{}
    if err := r.Client.Get(context.Background(), req.NamespacedName, ds); err != nil {
        if misc.IsNotFound(err) {
            return emptyResult, nil
        })
        return requeueResult, err
    }

    secret, err := getSecretFromThirdParty(ds)
    if err != nil {
        return requeueResult, err
    }

    if err := controllerutil.SetControllerReference(ds, secret, r.Scheme); err != nil {
        logger.Error("failed to set controller reference for the secret", zap.Error(err))
        return requeueResult, err
    }

    if err := r.createOrUpdateSecret(secret, logger); err != nil {
        return requeueResult, err
    }

    return emptyResult, nil
}

func (r *DatabaseServiceReconciler) createOrUpdateSecret(secret *corev1.Secret) error {
    if err := r.createNamespaceIfNotExist(secret.Namespace, logger); err != nil {
        return err
    }
    if err := r.Client.Create(context.TODO(), secret); err == nil {
        return nil
    }
    if !apierrors.IsAlreadyExists(err) {
        return err
    }
    if err := r.Client.Update(context.TODO(), secret); err != nil {
        return err
    }
    return nil
}

I am observing that if I set the CR as the owner of the secret before calling createOrUpdateSecret - Reconcile function will be triggered again, because something in the owned object (the secret) has changed.

My Reconcile logic is idempotent so it is not a big problem. However, I've no need for Reconcile to run again after changes to the owned object that took place from inside Reconcile. Right now, every time Reconcile creates / updates a secret it would run again. This behavior seems a bit clunky and results in extra work for the operator and extra calls to the third party.

Is there a way to bypass the re-activation of Reconcile creation / update of owned object from inside Reconcile? Or is it not recommended and I should allow reconcile run repeatedly until nothing is changed?

0

There are 0 answers