in pkg/handler/warm.go [59:131]
func (w *warmResourceHandler) HandleCreate(_ int, pod *v1.Pod) (ctrl.Result, error) {
resourcePool, err := w.getResourcePool(pod.Spec.NodeName)
if err != nil {
return ctrl.Result{}, err
}
if _, present := pod.Annotations[w.resourceName]; present {
// Pod has already been allocated the resource, skip the event
return ctrl.Result{}, nil
}
log := w.log.WithValues("UID", string(pod.UID), "namespace",
pod.Namespace, "name", pod.Name)
resID, shouldReconcile, err := resourcePool.AssignResource(string(pod.UID))
if err != nil {
// Reconcile the pool before retrying or returning an error
w.reconcilePool(shouldReconcile, resourcePool)
switch err {
case pool.ErrResourceAreBeingCooledDown:
log.V(1).Info("resources are currently being cooled down, will retry")
w.APIWrapper.K8sAPI.BroadcastEvent(pod, ReasonResourceAllocationFailed,
fmt.Sprintf("Resource %s are being cooled down, will retry in %s",
w.resourceName, RequeueAfterWhenResourceCooling), v1.EventTypeWarning)
return ctrl.Result{Requeue: true, RequeueAfter: RequeueAfterWhenResourceCooling}, nil
case pool.ErrResourcesAreBeingCreated, pool.ErrWarmPoolEmpty:
log.V(1).Info("resources are currently being created or warm pool is empty, will retry")
w.APIWrapper.K8sAPI.BroadcastEvent(pod, ReasonResourceAllocationFailed,
fmt.Sprintf("Warm pool for resource %s is currently empty, will retry in %s",
w.resourceName, RequeueAfterWhenWPEmpty), v1.EventTypeWarning)
return ctrl.Result{Requeue: true, RequeueAfter: RequeueAfterWhenWPEmpty}, nil
case pool.ErrResourceAlreadyAssigned:
// The Pod may already have the request annotated, however the cache may not have
// may not reflect the change immediately.
pod, err := w.APIWrapper.PodAPI.GetPodFromAPIServer(w.ctx, pod.Namespace, pod.Name)
if err != nil {
return ctrl.Result{}, err
}
resourceID, present := pod.Annotations[w.resourceName]
if present {
log.Info("cache had stale entry, pod already has resource",
"resource from annotation", resourceID,
"resource from data store", resID)
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
case pool.ErrInsufficientCidrBlocks:
log.V(1).Info("prefix is not available in subnet, will retry")
w.APIWrapper.K8sAPI.BroadcastEvent(pod, ReasonResourceAllocationFailed,
fmt.Sprintf("Warm pool for resource %s is currently empty because the specified subnet does not have enough "+
"free cidr blocks, will retry in %s", w.resourceName, RequeueAfterWhenPrefixNotAvailable), v1.EventTypeWarning)
return ctrl.Result{Requeue: true, RequeueAfter: RequeueAfterWhenPrefixNotAvailable}, nil
default:
return ctrl.Result{}, err
}
}
err = w.APIWrapper.PodAPI.AnnotatePod(pod.Namespace, pod.Name, pod.UID, w.resourceName, resID)
if err != nil {
_, errFree := resourcePool.FreeResource(string(pod.UID), resID)
if errFree != nil {
err = fmt.Errorf("failed to annotate %v, failed to free %v", err, errFree)
}
}
w.APIWrapper.K8sAPI.BroadcastEvent(pod, ReasonResourceAllocated,
fmt.Sprintf("Allocated Resource %s: %s to the pod", w.resourceName, resID), v1.EventTypeNormal)
log.Info("successfully allocated and annotated resource", "resource id", resID)
w.reconcilePool(shouldReconcile, resourcePool)
return ctrl.Result{}, err
}