func()

in pkg/controller/build/build_controller.go [108:237]


func (r *reconcileBuild) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
	rlog := Log.WithValues("request-namespace", request.Namespace, "request-name", request.Name)
	rlog.Debug("Reconciling Build")

	// Make sure the operator is allowed to act on namespace
	if ok, err := platform.IsOperatorAllowedOnNamespace(ctx, r.client, request.Namespace); err != nil {
		return reconcile.Result{}, err
	} else if !ok {
		rlog.Info("Ignoring request because namespace is locked")
		return reconcile.Result{}, nil
	}

	// Fetch the Build instance
	var instance v1.Build

	if err := r.client.Get(ctx, request.NamespacedName, &instance); err != nil {
		if k8serrors.IsNotFound(err) {
			// Request object not found, could have been deleted after reconcile request.
			// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
			// Return and don't requeue
			return reconcile.Result{}, nil
		}
		// Error reading the object - requeue the request.
		return reconcile.Result{}, err
	}

	// Only process resources assigned to the operator
	if !platform.IsOperatorHandlerConsideringLock(ctx, r.client, request.Namespace, &instance) {
		rlog.Info("Ignoring request because resource is not assigned to current operator")
		return reconcile.Result{}, nil
	}

	target := instance.DeepCopy()
	targetLog := rlog.ForBuild(target)

	var actions []Action
	ip, err := platform.GetOrFindForResource(ctx, r.client, &instance, true)
	if err != nil {
		rlog.Error(err, "Could not find a platform bound to this Build")
		return reconcile.Result{}, err
	}
	buildMonitor := Monitor{
		maxRunningBuilds:   ip.Status.Build.MaxRunningBuilds,
		buildOrderStrategy: ip.Status.Build.BuildConfiguration.OrderStrategy,
	}

	switch instance.BuilderConfiguration().Strategy {
	case v1.BuildStrategyPod:
		actions = []Action{
			newInitializePodAction(r.reader),
			newScheduleAction(r.reader, buildMonitor),
			newMonitorPodAction(r.reader),
			newErrorRecoveryAction(),
			newErrorAction(),
		}
	case v1.BuildStrategyRoutine:
		actions = []Action{
			newInitializeRoutineAction(),
			newScheduleAction(r.reader, buildMonitor),
			newMonitorRoutineAction(),
			newErrorRecoveryAction(),
			newErrorAction(),
		}
	}

	for _, a := range actions {
		a.InjectClient(r.client)
		a.InjectLogger(targetLog)
		a.InjectRecorder(r.recorder)

		if a.CanHandle(target) {
			targetLog.Debugf("Invoking action %s", a.Name())

			newTarget, err := a.Handle(ctx, target)
			if err != nil {
				camelevent.NotifyBuildError(ctx, r.client, r.recorder, &instance, newTarget, err)
				return reconcile.Result{}, err
			}

			if newTarget != nil {
				if err := r.update(ctx, &instance, newTarget); err != nil {
					camelevent.NotifyBuildError(ctx, r.client, r.recorder, &instance, newTarget, err)
					return reconcile.Result{}, err
				}

				if newTarget.Status.Phase != instance.Status.Phase {
					targetLog.Info(
						"State transition",
						"phase-from", instance.Status.Phase,
						"phase-to", newTarget.Status.Phase,
					)

					if newTarget.Status.Phase == v1.BuildPhaseError || newTarget.Status.Phase == v1.BuildPhaseFailed {
						reason := string(newTarget.Status.Phase)

						if newTarget.Status.Failure != nil {
							reason = newTarget.Status.Failure.Reason
						}

						targetLog.Info(
							"Build error",
							"reason", reason,
							"error-message", newTarget.Status.Error)
					}
				}

				target = newTarget
			}

			// handle one action at time so the resource
			// is always at its latest state
			camelevent.NotifyBuildUpdated(ctx, r.client, r.recorder, &instance, newTarget)

			break
		}
	}

	if target.Status.Phase == v1.BuildPhaseScheduling || target.Status.Phase == v1.BuildPhaseFailed {
		// Requeue scheduling (resp. failed) build so that it re-enters the build (resp. recovery) working queue
		return reconcile.Result{RequeueAfter: 5 * time.Second}, nil
	}

	if target.BuilderConfiguration().Strategy == v1.BuildStrategyPod &&
		(target.Status.Phase == v1.BuildPhasePending || target.Status.Phase == v1.BuildPhaseRunning) {
		// Requeue running Build to poll Pod and signal timeout
		return reconcile.Result{RequeueAfter: 1 * time.Second}, nil
	}

	return reconcile.Result{}, nil
}