func()

in internal/controller/generic_controller.go [109:223]


func (r *genericReconciler[O]) reconcile(ctx context.Context, logger logr.Logger, acrBinding O, serviceAccount *corev1.ServiceAccount, pullSecrets []corev1.Secret, referencingServiceAccounts []corev1.ServiceAccount) *action[O] {
	// examine DeletionTimestamp to determine if acr pull binding is under deletion
	if acrBinding.GetDeletionTimestamp().IsZero() {
		// the object is not being deleted, so if it does not have our finalizer,
		// then need to add the finalizer and update the object.
		if !slices.Contains(acrBinding.GetFinalizers(), msiAcrPullFinalizerName) {
			logger.Info("adding finalizer to pull binding")
			return &action[O]{updatePullBinding: r.AddFinalizer(acrBinding, msiAcrPullFinalizerName)}
		}
	} else {
		// the object is being deleted, do cleanup as necessary
		return r.cleanUp(acrBinding, serviceAccount, pullSecrets, logger)
	}

	// if the user changed which service account should be bound to this credential, we need to
	// un-bind the credential from any service accounts it was bound to previously; if we're in
	// the middle of cleaning up old pull secrets from this binding, we need to make sure all of
	// them are removed from the previous service account
	pullSecretNames := sets.Set[string]{}
	for _, pullSecret := range pullSecrets {
		pullSecretNames.Insert(pullSecret.ObjectMeta.Name)
	}
	extraneousServiceAccounts := slices.DeleteFunc(referencingServiceAccounts, func(other corev1.ServiceAccount) bool {
		return serviceAccount != nil && other.Name == serviceAccount.Name
	})
	for _, extraneous := range extraneousServiceAccounts {
		updated := extraneous.DeepCopy()
		updated.ImagePullSecrets = slices.DeleteFunc(updated.ImagePullSecrets, func(reference corev1.LocalObjectReference) bool {
			return reference.Name == r.GetPullSecretName(acrBinding) || pullSecretNames.Has(reference.Name)
		})
		if len(updated.ImagePullSecrets) != len(extraneous.ImagePullSecrets) {
			logger.WithValues("serviceAccount", crclient.ObjectKeyFromObject(&extraneous).String()).Info("updating service account to remove image pull secret")
			return &action[O]{updateServiceAccount: updated}
		}
	}

	if serviceAccount == nil {
		err := fmt.Sprintf("service account %q not found", r.GetServiceAccountName(acrBinding))
		logger.Info(err)
		return &action[O]{updatePullBindingStatus: r.UpdateStatusError(acrBinding, err)}
	}

	expectedPullSecretName := r.GetPullSecretName(acrBinding)
	var pullSecret *corev1.Secret
	for _, secret := range pullSecrets {
		if secret.Name == expectedPullSecretName {
			pullSecret = &secret
		}
	}
	inputHash := r.GetInputsHash(acrBinding)
	pullSecretMissing := pullSecret == nil
	pullSecretNeedsRefresh := !pullSecretMissing && r.NeedsRefresh(r.Logger, pullSecret, r.now)
	pullSecretInputsChanged := !pullSecretMissing && pullSecret.Annotations[tokenInputsAnnotation] != inputHash
	if pullSecretMissing || pullSecretNeedsRefresh || pullSecretInputsChanged {
		logger.WithValues("pullSecretMissing", pullSecretMissing, "pullSecretNeedsRefresh", pullSecretNeedsRefresh, "pullSecretInputsChanged", pullSecretInputsChanged).Info("generating new pull credential")

		dockerConfig, expiresOn, err := r.CreatePullCredential(ctx, acrBinding, serviceAccount)
		if err != nil {
			logger.Info(err.Error())
			return &action[O]{updatePullBindingStatus: r.UpdateStatusError(acrBinding, err.Error())}
		}

		newSecret := newPullSecret(acrBinding, r.GetPullSecretName(acrBinding), dockerConfig, r.Scheme, expiresOn, r.now, inputHash)
		logger = logger.WithValues("secret", crclient.ObjectKeyFromObject(newSecret).String())
		if pullSecret == nil {
			logger.Info("creating pull credential secret")
			return &action[O]{createSecret: newSecret}
		} else {
			logger.Info("updating pull credential secret")
			return &action[O]{updateSecret: newSecret}
		}
	}

	if !slices.ContainsFunc(serviceAccount.ImagePullSecrets, func(reference corev1.LocalObjectReference) bool {
		return reference.Name == pullSecret.Name
	}) {
		updated := serviceAccount.DeepCopy()
		updated.ImagePullSecrets = append(updated.ImagePullSecrets, corev1.LocalObjectReference{
			Name: pullSecret.Name,
		})
		sortPullSecrets(updated)
		logger.WithValues("serviceAccount", crclient.ObjectKeyFromObject(serviceAccount).String()).Info("updating service account to add image pull secret")
		return &action[O]{updateServiceAccount: updated}
	}

	// clean up references to any extraneous pull secrets that refer to this binding
	extraneous := sets.Set[string]{}
	for _, secret := range pullSecrets {
		if secret.ObjectMeta.Name != expectedPullSecretName {
			extraneous.Insert(secret.ObjectMeta.Name)
		}
	}
	if slices.ContainsFunc(serviceAccount.ImagePullSecrets, func(reference corev1.LocalObjectReference) bool {
		return extraneous.Has(reference.Name)
	}) {
		updated := serviceAccount.DeepCopy()
		updated.ImagePullSecrets = slices.DeleteFunc(updated.ImagePullSecrets, func(reference corev1.LocalObjectReference) bool {
			return extraneous.Has(reference.Name)
		})
		sortPullSecrets(updated)
		logger.WithValues("serviceAccount", crclient.ObjectKeyFromObject(serviceAccount).String()).Info("updating service account to remove extraneous image pull secrets")
		return &action[O]{updateServiceAccount: updated}
	}

	// clean up any extraneous pull secrets that refer to this binding
	for _, secret := range pullSecrets {
		if secret.ObjectMeta.Name != expectedPullSecretName {
			deleted := secret.DeepCopy()
			logger.WithValues("secret", crclient.ObjectKeyFromObject(deleted).String()).Info("cleaning up extraneous pull credential")
			return &action[O]{deleteSecret: deleted}
		}
	}

	return r.setSuccessStatus(logger, acrBinding, pullSecret)
}