func()

in pkg/controller/build/build_controller.go [115:225]


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.GetForResource(ctx, r.client, &instance)
	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) {
			continue
		}

		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 {
			err := r.update(ctx, targetLog, &instance, newTarget)
			if err != nil {
				return reconcile.Result{}, err
			}

			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: requeueAfterDuration}, 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: podRequeueAfterDuration}, nil
	}

	return reconcile.Result{}, nil
}