func()

in pkg/controller/nginxingress/nginx_ingress_controller.go [95:184]


func (n *nginxIngressControllerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
	start := time.Now()
	lgr := log.FromContext(ctx, "nginxIngressController", req.NamespacedName)
	ctx = log.IntoContext(ctx, lgr)
	lgr.Info("reconciling NginxIngressController")
	defer lgr.Info("finished reconciling resource", "latencySec", time.Since(start).String())

	defer func() {
		metrics.HandleControllerReconcileMetrics(nginxIngressControllerReconcilerName, res, err)
	}()

	var nginxIngressController approutingv1alpha1.NginxIngressController
	if err := n.client.Get(ctx, req.NamespacedName, &nginxIngressController); err != nil {
		if apierrors.IsNotFound(err) { // object was deleted
			lgr.Info("NginxIngressController not found")
			return ctrl.Result{}, nil
		}

		lgr.Error(err, "unable to fetch NginxIngressController")
		return ctrl.Result{}, err
	}
	lgr = lgr.WithValues("generation", nginxIngressController.Generation)
	ctx = log.IntoContext(ctx, lgr)

	var managedRes []approutingv1alpha1.ManagedObjectReference = nil
	var controllerDeployment *appsv1.Deployment = nil
	var ingressClass *netv1.IngressClass = nil

	lockKey := nginxIngressController.Spec.ControllerNamePrefix
	collisionCountMu.LockKey(lockKey)
	defer collisionCountMu.UnlockKey(lockKey)

	lgr.Info("determining collision count")
	startingCollisionCount := nginxIngressController.Status.CollisionCount
	newCollisionCount, collisionCountErr := n.GetCollisionCount(ctx, &nginxIngressController)
	if collisionCountErr == nil && newCollisionCount != startingCollisionCount {
		nginxIngressController.Status.CollisionCount = newCollisionCount
		if err := n.client.Status().Update(ctx, &nginxIngressController); err != nil {
			lgr.Error(err, "unable to update collision count status")
			return ctrl.Result{}, fmt.Errorf("updating status: %w", err)
		}

		return ctrl.Result{Requeue: true}, nil
	}
	defer func() { // defer is before checking err so that we can update status even if there is an error
		lgr.Info("updating status")
		n.updateStatus(&nginxIngressController, controllerDeployment, ingressClass, managedRes, collisionCountErr)
		if statusErr := n.client.Status().Update(ctx, &nginxIngressController); statusErr != nil {
			if apierrors.IsConflict(statusErr) {
				lgr.Info("conflict updating status, requeuing")
				res = ctrl.Result{Requeue: true}
				err = nil
				return
			}
			if err == nil {
				lgr.Error(statusErr, "unable to update NginxIngressController status")
				err = statusErr
			}
		}
	}()
	if collisionCountErr != nil {
		if isUnreconcilableError(collisionCountErr) {
			lgr.Info("unreconcilable collision count")
			return ctrl.Result{RequeueAfter: time.Minute}, nil // requeue in case cx fixes the unreconcilable reason
		}

		lgr.Error(collisionCountErr, "unable to get determine collision count")
		return ctrl.Result{}, fmt.Errorf("determining collision count: %w", collisionCountErr)
	}

	lgr.Info("calculating managed resources")
	resources := n.ManagedResources(&nginxIngressController)
	if resources == nil {
		return ctrl.Result{}, fmt.Errorf("unable to get managed resources")
	}
	controllerDeployment = resources.Deployment
	ingressClass = resources.IngressClass

	lgr.Info("reconciling managed resources")
	managedRes, err = n.ReconcileResource(ctx, &nginxIngressController, resources)
	if err != nil {
		lgr.Error(err, "unable to reconcile resource")
		return ctrl.Result{}, fmt.Errorf("reconciling resource: %w", err)
	}
	if replicas := resources.Deployment.Spec.Replicas; replicas != nil {
		lgr.Info(fmt.Sprintf("nginx deployment targets %d replicas", *replicas), "replicas", *replicas)
	}

	return ctrl.Result{}, nil
}