in controllers/service_controller.go [69:206]
func (r *ServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx).WithValues("service", req.NamespacedName)
svc := &corev1.Service{}
err := r.Get(ctx, req.NamespacedName, svc)
if err != nil {
if apierrors.IsNotFound(err) {
// Object not found, return.
return r.reconcileResult(nil)
}
// Error reading the object - requeue the request.
return r.reconcileResult(err)
}
status, ok, err := getStatuses(svc.Namespace, svc.Name, svc.ObjectMeta.Annotations, r)
// Is this service using autoneg?
if !ok {
return r.reconcileResult(nil)
}
if err != nil {
r.Recorder.Event(svc, "Warning", "ConfigError", err.Error())
return r.reconcileResult(err)
}
deleting := false
// Process deletion
if !svc.ObjectMeta.DeletionTimestamp.IsZero() && (containsString(svc.ObjectMeta.Finalizers, oldAutonegFinalizer) || containsString(svc.ObjectMeta.Finalizers, autonegFinalizer)) {
logger.Info("Deleting service")
deleting = true
}
intendedStatus := AutonegStatus{
AutonegConfig: status.config,
NEGStatus: status.negStatus,
}
logger.Info("Existing status", "status", status)
if status.syncConfig != nil {
intendedStatus.AutonegSyncConfig = status.syncConfig
}
oldIntendedStatus := OldAutonegStatus{
OldAutonegConfig: status.oldConfig,
NEGStatus: status.negStatus,
}
if deleting {
intendedStatus.BackendServices = make(map[string]map[string]AutonegNEGConfig, 0)
} else if reflect.DeepEqual(status.status, intendedStatus) && !r.AlwaysReconcile {
// Equal, no reconciliation necessary
return r.reconcileResult(nil)
}
// Reconcile differences
logger.Info("Applying intended status", "status", intendedStatus)
if err = r.ReconcileBackends(status.status, intendedStatus); err != nil {
var e *errNotFound
if !(deleting && errors.As(err, &e)) {
r.Recorder.Event(svc, "Warning", "BackendError", err.Error())
return r.reconcileResult(err)
}
if deleting {
r.Recorder.Event(svc, "Warning", "BackendError while deleting", err.Error())
return r.reconcileResult(err)
}
}
// Write changes to the service object.
if deleting {
// Remove finalizer and clear status
svc.ObjectMeta.Finalizers = removeString(svc.ObjectMeta.Finalizers, oldAutonegFinalizer)
svc.ObjectMeta.Finalizers = removeString(svc.ObjectMeta.Finalizers, autonegFinalizer)
delete(svc.ObjectMeta.Annotations, autonegStatusAnnotation)
delete(svc.ObjectMeta.Annotations, oldAutonegStatusAnnotation)
} else {
// Remove old finalizer
if containsString(svc.ObjectMeta.Finalizers, oldAutonegFinalizer) {
logger.Info("Upgrading finalizer")
svc.ObjectMeta.Finalizers = removeString(svc.ObjectMeta.Finalizers, oldAutonegFinalizer)
svc.ObjectMeta.Finalizers = append(svc.ObjectMeta.Finalizers, autonegFinalizer)
} else {
// Add the finalizer annotation if it doesn't exist.
if !containsString(svc.ObjectMeta.Finalizers, autonegFinalizer) {
logger.Info("Adding finalizer")
svc.ObjectMeta.Finalizers = append(svc.ObjectMeta.Finalizers, autonegFinalizer)
}
}
// Write status to annotations
anStatus, err := json.Marshal(intendedStatus)
if err != nil {
logger.Error(err, "json marshal error")
return r.reconcileResult(err)
}
svc.ObjectMeta.Annotations[autonegStatusAnnotation] = string(anStatus)
if !status.newConfig {
oldStatus, err := json.Marshal(oldIntendedStatus)
if err != nil {
logger.Error(err, "json marshal error")
return r.reconcileResult(err)
}
svc.ObjectMeta.Annotations[oldAutonegStatusAnnotation] = string(oldStatus)
}
}
if err = r.Update(ctx, svc); err != nil {
// Do not record an event in case of routine object conflict.
if !apierrors.IsConflict(err) {
r.Recorder.Event(svc, "Warning", "BackendError", err.Error())
}
return r.reconcileResult(err)
}
for port, endpointGroups := range intendedStatus.BackendServices {
for _, endpointGroup := range endpointGroups {
if deleting {
r.Recorder.Eventf(svc, "Normal", "Delete",
"Deregistered NEGs for %q from backend service %q (port %s)",
req.NamespacedName,
endpointGroup.Name,
port)
} else {
r.Recorder.Eventf(svc, "Normal", "Sync",
"Synced NEGs for %q as backends to backend service %q (port %s)",
req.NamespacedName,
endpointGroup.Name,
port)
}
}
}
return r.reconcileResult(nil)
}