in pkg/controllers/node/emptiness.go [40:82]
func (r *Emptiness) Reconcile(ctx context.Context, provisioner *v1alpha5.Provisioner, n *v1.Node) (reconcile.Result, error) {
// 1. Ignore node if not applicable
if provisioner.Spec.TTLSecondsAfterEmpty == nil {
return reconcile.Result{}, nil
}
if !node.IsReady(n) {
return reconcile.Result{}, nil
}
// 2. Remove ttl if not empty
empty, err := r.isEmpty(ctx, n)
if err != nil {
return reconcile.Result{}, err
}
emptinessTimestamp, hasEmptinessTimestamp := n.Annotations[v1alpha5.EmptinessTimestampAnnotationKey]
if !empty {
if hasEmptinessTimestamp {
delete(n.Annotations, v1alpha5.EmptinessTimestampAnnotationKey)
logging.FromContext(ctx).Infof("Removed emptiness TTL from node")
}
return reconcile.Result{}, nil
}
// 3. Set TTL if not set
n.Annotations = functional.UnionStringMaps(n.Annotations)
ttl := time.Duration(ptr.Int64Value(provisioner.Spec.TTLSecondsAfterEmpty)) * time.Second
if !hasEmptinessTimestamp {
n.Annotations[v1alpha5.EmptinessTimestampAnnotationKey] = injectabletime.Now().Format(time.RFC3339)
logging.FromContext(ctx).Infof("Added TTL to empty node")
return reconcile.Result{RequeueAfter: ttl}, nil
}
// 4. Delete node if beyond TTL
emptinessTime, err := time.Parse(time.RFC3339, emptinessTimestamp)
if err != nil {
return reconcile.Result{}, fmt.Errorf("parsing emptiness timestamp, %s", emptinessTimestamp)
}
if injectabletime.Now().After(emptinessTime.Add(ttl)) {
logging.FromContext(ctx).Infof("Triggering termination after %s for empty node", ttl)
if err := r.kubeClient.Delete(ctx, n); err != nil {
return reconcile.Result{}, fmt.Errorf("deleting node, %w", err)
}
}
return reconcile.Result{}, nil
}