in pkg/ipamd/ipamd.go [2068:2122]
func (c *IPAMContext) AnnotatePod(podName string, podNamespace string, key string, newVal string, releasedIP string) error {
ctx := context.TODO()
var err error
err = retry.RetryOnConflict(retry.DefaultBackoff, func() error {
var pod *corev1.Pod
if pod, err = c.GetPod(podName, podNamespace); err != nil || pod == nil {
// if pod is nil and err is nil for any reason, this is not retriable case, returning a nil error to not-retry
if err == nil && pod == nil {
log.Warnf("get a nil pod for pod name %s and namespace %s", podName, podNamespace)
}
// since the GetPod() error has been decorated, we have to check key words
// releasedIP is not empty meaning del path
if releasedIP != "" && err != nil && strings.Contains(err.Error(), "not found") {
return nil
}
return err
}
newPod := pod.DeepCopy()
if newPod.Annotations == nil {
newPod.Annotations = make(map[string]string)
}
oldVal, ok := newPod.Annotations[key]
// On CNI ADD, always set new annotation
if newVal != "" {
// Skip patch operation if new value is the same as existing value
if ok && oldVal == newVal {
log.Infof("Patch updating not needed")
return nil
}
newPod.Annotations[key] = newVal
} else {
// On CNI DEL, set annotation to empty string if IP is the one we are releasing
if ok {
log.Debugf("Existing annotation value: %s", oldVal)
if oldVal != releasedIP {
return fmt.Errorf("Released IP %s does not match existing annotation. Not patching pod.", releasedIP)
}
newPod.Annotations[key] = ""
}
}
if err = c.k8sClient.Patch(ctx, newPod, client.MergeFrom(pod)); err != nil {
log.Errorf("Failed to annotate %s the pod with %s, error %v", key, newVal, err)
return err
}
log.Debugf("Annotates pod %s with %s: %s", podName, key, newVal)
return nil
})
return err
}