func()

in operator/pkg/controllers/configconnector/configconnector_controller.go [440:544]


func (r *Reconciler) finalizeSystemComponentsDeletion(ctx context.Context, c client.Client) error {
	// Delete the global controller manager workload (deployed by the ConfigConnector controller when in cluster mode) if any.
	sts := &appsv1.StatefulSet{}
	sts.Namespace = k8s.CNRMSystemNamespace
	sts.Name = k8s.KCCControllerManagerComponent
	if err := controllers.DeleteObject(ctx, c, sts); err != nil {
		return err
	}

	// Wait until all the controller manager pods are removed first; this is an additional safeguard to ensure that we will NOT delete any resource on uninstallation.
	b := wait.Backoff{
		Duration: 1 * time.Second,
		Factor:   1.2,
		Steps:    12,
	}

	podLabelSelector, err := labels.Parse(k8s.KCCControllerPodLabelSelectorRaw)
	if err != nil {
		return fmt.Errorf("error parsing '%v' as a label selector: %w", k8s.KCCControllerPodLabelSelectorRaw, err)
	}
	podList := &corev1.PodList{}
	podOpts := &client.ListOptions{
		Namespace:     k8s.CNRMSystemNamespace,
		LabelSelector: podLabelSelector,
	}
	if err := wait.ExponentialBackoff(b, func() (done bool, err error) {
		if err := c.List(ctx, podList, podOpts); err != nil {
			return false, errors.Wrap(err, "error listing controller manager pods")
		}
		podNames := make([]string, 0, len(podList.Items))
		for _, p := range podList.Items {
			podNames = append(podNames, p.Name)
		}
		r.log.Info("waiting for controller manager pods to be deleted", "pods", podNames)
		return len(podList.Items) == 0, nil
	}); err != nil {
		return errors.Wrap(err, "error waiting for controller manager pods to be deleted")
	}
	r.log.Info("Successfully deleted all controller manager StatefulSets")

	// KCC adds finalizers to all its CRs. We need to delete each CRD that KCC
	// owns, and then wait for its controllers to finalize the deletion. Once the
	// CRDs are all cleaned up, we can delete the rest of KCC.
	b = wait.Backoff{
		Duration: 1 * time.Second,
		Factor:   1.2,
		Steps:    12,
	}
	if err := wait.ExponentialBackoff(b, func() (done bool, err error) {
		allDeleted := true
		crdList, _, err := k8s.ListCRDs(ctx, c, "")
		if err != nil {
			return false, err
		}
		for _, crd := range crdList {
			allDeleted = false
			r.log.Info("deleting CRD", "name", crd.GetName())
			if err := c.Delete(ctx, &crd); err != nil && !apierrors.IsNotFound(err) {
				return false, fmt.Errorf("error deleting CRD %v: %w", crd.GetName(), err)
			}
		}
		return allDeleted, nil
	}); err != nil {
		return errors.Wrap(err, "error waiting for CRDs to be deleted")
	}
	r.log.Info("Successfully finalized resource CRDs deletion.")

	// Specifically delete other resources set up by KCC on the fly.
	resources := []client.Object{
		&admissionregistration.ValidatingWebhookConfiguration{
			ObjectMeta: metav1.ObjectMeta{
				Name: "validating-webhook.cnrm.cloud.google.com",
			},
		},
		&admissionregistration.ValidatingWebhookConfiguration{
			ObjectMeta: metav1.ObjectMeta{
				Name: "abandon-on-uninstall.cnrm.cloud.google.com",
			},
		},
		&admissionregistration.MutatingWebhookConfiguration{
			ObjectMeta: metav1.ObjectMeta{
				Name: "mutating-webhook.cnrm.cloud.google.com",
			},
		},
		&corev1.Service{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "cnrm-validating-webhook",
				Namespace: k8s.CNRMSystemNamespace,
			},
		},
		&corev1.Service{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "abandon-on-uninstall",
				Namespace: k8s.CNRMSystemNamespace,
			},
		},
	}

	for _, obj := range resources {
		if err := controllers.DeleteObject(ctx, r.client, obj); err != nil {
			return err
		}
	}
	return nil
}