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
}