This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit a53c5bfb65e46bde848a48cee2448a5b3497a605
Author: Antonin Stefanutti <[email protected]>
AuthorDate: Wed Aug 18 16:28:23 2021 +0200

    feat(native): Enable builds to run concurrently
---
 pkg/controller/build/schedule.go       | 35 +++++++++++++++++++++++++++++-----
 pkg/controller/integrationkit/build.go |  4 +++-
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/pkg/controller/build/schedule.go b/pkg/controller/build/schedule.go
index da060c1..c49b904 100644
--- a/pkg/controller/build/schedule.go
+++ b/pkg/controller/build/schedule.go
@@ -23,6 +23,8 @@ import (
        "time"
 
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/labels"
+       "k8s.io/apimachinery/pkg/selection"
 
        ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
@@ -58,10 +60,29 @@ func (action *scheduleAction) Handle(ctx context.Context, 
build *v1.Build) (*v1.
        action.lock.Lock()
        defer action.lock.Unlock()
 
+       layout := build.Labels[v1.IntegrationKitLayoutLabel]
+
+       // Native builds can be run in parallel, as incremental images is not 
applicable.
+       if layout == v1.IntegrationKitLayoutNative {
+               // Reset the Build status, and transition it to pending phase.
+               // This must be done in the critical section, rather than 
delegated to the controller.
+               return nil, action.toPendingPhase(ctx, build)
+       }
+
+       // We assume incremental images is only applicable across images whose 
layout is identical
+       withCompatibleLayout, err := 
labels.NewRequirement(v1.IntegrationKitLayoutLabel, selection.Equals, 
[]string{layout})
+       if err != nil {
+               return nil, err
+       }
+
        builds := &v1.BuildList{}
        // We use the non-caching client as informers cache is not invalidated 
nor updated
        // atomically by write operations
-       err := action.reader.List(ctx, builds, 
ctrl.InNamespace(build.Namespace))
+       err = action.reader.List(ctx, builds,
+               ctrl.InNamespace(build.Namespace),
+               ctrl.MatchingLabelsSelector{
+                       Selector: 
labels.NewSelector().Add(*withCompatibleLayout),
+               })
        if err != nil {
                return nil, err
        }
@@ -69,7 +90,7 @@ func (action *scheduleAction) Handle(ctx context.Context, 
build *v1.Build) (*v1.
        // Emulate a serialized working queue to only allow one build to run at 
a given time.
        // This is currently necessary for the incremental build to work as 
expected.
        // We may want to explicitly manage build priority as opposed to 
relying on
-       // the reconcile loop to handle the queuing
+       // the reconciliation loop to handle the queuing.
        for _, b := range builds.Items {
                if b.Status.Phase == v1.BuildPhasePending || b.Status.Phase == 
v1.BuildPhaseRunning {
                        // Let's requeue the build in case one is already 
running
@@ -79,7 +100,11 @@ func (action *scheduleAction) Handle(ctx context.Context, 
build *v1.Build) (*v1.
 
        // Reset the Build status, and transition it to pending phase.
        // This must be done in the critical section, rather than delegated to 
the controller.
-       err = action.patchBuildStatus(ctx, build, func(b *v1.Build) {
+       return nil, action.toPendingPhase(ctx, build)
+}
+
+func (action *scheduleAction) toPendingPhase(ctx context.Context, build 
*v1.Build) error {
+       err := action.patchBuildStatus(ctx, build, func(b *v1.Build) {
                now := metav1.Now()
                b.Status = v1.BuildStatus{
                        Phase:      v1.BuildPhasePending,
@@ -90,13 +115,13 @@ func (action *scheduleAction) Handle(ctx context.Context, 
build *v1.Build) (*v1.
                }
        })
        if err != nil {
-               return nil, err
+               return err
        }
 
        // Report the duration the Build has been waiting in the build queue
        
queueDuration.Observe(time.Now().Sub(getBuildQueuingTime(build)).Seconds())
 
-       return nil, nil
+       return nil
 }
 
 func (action *scheduleAction) patchBuildStatus(ctx context.Context, build 
*v1.Build, mutate func(b *v1.Build)) error {
diff --git a/pkg/controller/integrationkit/build.go 
b/pkg/controller/integrationkit/build.go
index 599022f..62b6820 100644
--- a/pkg/controller/integrationkit/build.go
+++ b/pkg/controller/integrationkit/build.go
@@ -82,6 +82,8 @@ func (action *buildAction) handleBuildSubmitted(ctx 
context.Context, kit *v1.Int
                        return nil, errors.New("undefined camel catalog")
                }
 
+               labels := kubernetes.FilterCamelCreatorLabels(kit.Labels)
+               labels[v1.IntegrationKitLayoutLabel] = 
kit.Labels[v1.IntegrationKitLayoutLabel]
                build = &v1.Build{
                        TypeMeta: metav1.TypeMeta{
                                APIVersion: v1.SchemeGroupVersion.String(),
@@ -90,7 +92,7 @@ func (action *buildAction) handleBuildSubmitted(ctx 
context.Context, kit *v1.Int
                        ObjectMeta: metav1.ObjectMeta{
                                Namespace: kit.Namespace,
                                Name:      kit.Name,
-                               Labels:    
kubernetes.FilterCamelCreatorLabels(kit.Labels),
+                               Labels:    labels,
                        },
                        Spec: v1.BuildSpec{
                                Tasks:   env.BuildTasks,

Reply via email to