in internal/controllers/liveness/namespace.go [53:124]
func (c *namespaceController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := logr.FromContextOrDiscard(ctx)
ns := &corev1.Namespace{}
ns.Name = req.Name
err := c.client.Get(ctx, req.NamespacedName, ns)
if client.IgnoreNotFound(err) != nil {
logger.Error(err, "failed to get namespace")
return ctrl.Result{}, err
}
const annoKey = "eno.azure.io/recreation-reason"
const annoValue = "OrphanedResources"
// Delete the recreated namespace immediately.
// Its finalizers will keep it around until we've had time to remove our finalizers.
logger = logger.WithValues("resourceNamespace", ns.Name)
if ns.Annotations != nil && ns.Annotations[annoKey] == annoValue {
if ns.DeletionTimestamp != nil {
return ctrl.Result{}, c.cleanup(ctx, req.Name)
}
err := c.client.Delete(ctx, ns)
if err != nil {
logger.Error(err, "failed to delete namespace")
return ctrl.Result{}, err
}
logger.V(0).Info("deleting recreated namespace")
return ctrl.Result{}, nil
}
if err == nil {
// Successful GETs mean the namespace still exists - nothing for us to do
return ctrl.Result{}, nil
}
// Avoid recreating the namespace when it doesn't have any orphaned resources
for i := 1; true; i++ {
var foundOrphans bool
for _, kind := range orphanableKinds {
hasOrphans, res, err := c.findOrphans(ctx, ns.Name, kind)
if err != nil {
logger.Error(err, "failed to find orphaned resources", "resourceKind", kind)
return ctrl.Result{}, err
}
if res != nil {
return *res, nil
}
if hasOrphans {
foundOrphans = true
}
}
if !foundOrphans {
return ctrl.Result{}, nil
}
if i >= c.orphanCheckIterations {
break
}
// Sleep a bit before the next check to let informers catch up.
time.Sleep(time.Second / 2)
}
// Recreate the namespace briefly so we can remove the finalizers.
// Any updates (including finalizer updates) will fail if the namespace doesn't exist.
ns.Annotations = map[string]string{annoKey: annoValue}
err = c.client.Create(ctx, ns)
if err != nil {
logger.Error(err, "failed to create namespace")
return ctrl.Result{}, err
}
logger.V(0).Info("recreated missing namespace to free orphaned resources")
return ctrl.Result{}, nil
}