You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2025/12/15 08:05:17 UTC

(camel-k) 01/03: feat(ctrl): dry build - support Pipe BuildComplete phase

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

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

commit 4d7fd196cc494e48d23182d4799fe8b569051eb1
Author: Pranjul Kalsi <pr...@gmail.com>
AuthorDate: Sat Dec 13 00:40:43 2025 +0530

    feat(ctrl): dry build - support Pipe BuildComplete phase
---
 e2e/common/cli/deploy_test.go       | 21 ++++++++++++++++++
 pkg/apis/camel/v1/pipe_types.go     |  2 ++
 pkg/controller/pipe/monitor.go      | 13 ++++++++++-
 pkg/controller/pipe/monitor_test.go | 44 +++++++++++++++++++++++++++++++++++++
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/e2e/common/cli/deploy_test.go b/e2e/common/cli/deploy_test.go
index 88f407fcf..4f7a907b5 100644
--- a/e2e/common/cli/deploy_test.go
+++ b/e2e/common/cli/deploy_test.go
@@ -68,3 +68,24 @@ func TestBuildDontRun(t *testing.T) {
 		})
 	})
 }
+
+func TestPipeBuildDontRun(t *testing.T) {
+	t.Parallel()
+	WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
+		name := RandomizedSuffixName("pipe-deploy")
+		t.Run("build and dont run pipe", func(t *testing.T) {
+			g.Expect(KamelBind(t, ctx, ns, "timer-source?message=HelloPipe", "log-sink",
+				"--name", name,
+				"--annotation", "camel.apache.org/dont-run-after-build=true",
+			).Execute()).To(Succeed())
+			g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseBuildComplete))
+			g.Eventually(PipePhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.PipePhaseBuildComplete))
+			g.Consistently(IntegrationPhase(t, ctx, ns, name), 10*time.Second).Should(Equal(v1.IntegrationPhaseBuildComplete))
+			g.Consistently(PipePhase(t, ctx, ns, name), 10*time.Second).Should(Equal(v1.PipePhaseBuildComplete))
+			g.Eventually(Deployment(t, ctx, ns, name)).Should(BeNil())
+			// Pipe condition should indicate build is complete
+			g.Eventually(PipeCondition(t, ctx, ns, name, v1.PipeConditionReady), TestTimeoutShort).Should(
+				WithTransform(PipeConditionReason, Equal("BuildComplete")))
+		})
+	})
+}
diff --git a/pkg/apis/camel/v1/pipe_types.go b/pkg/apis/camel/v1/pipe_types.go
index a61eca0ce..ccdb7ff19 100644
--- a/pkg/apis/camel/v1/pipe_types.go
+++ b/pkg/apis/camel/v1/pipe_types.go
@@ -159,6 +159,8 @@ const (
 	PipePhaseError PipePhase = "Error"
 	// PipePhaseReady --.
 	PipePhaseReady PipePhase = "Ready"
+	// PipePhaseBuildComplete --.
+	PipePhaseBuildComplete PipePhase = "Build Complete"
 )
 
 // +kubebuilder:object:root=true
diff --git a/pkg/controller/pipe/monitor.go b/pkg/controller/pipe/monitor.go
index 8d16d4aa7..f75e5af7d 100644
--- a/pkg/controller/pipe/monitor.go
+++ b/pkg/controller/pipe/monitor.go
@@ -48,7 +48,8 @@ func (action *monitorAction) Name() string {
 func (action *monitorAction) CanHandle(pipe *v1.Pipe) bool {
 	return pipe.Status.Phase == v1.PipePhaseCreating ||
 		pipe.Status.Phase == v1.PipePhaseError ||
-		pipe.Status.Phase == v1.PipePhaseReady
+		pipe.Status.Phase == v1.PipePhaseReady ||
+		pipe.Status.Phase == v1.PipePhaseBuildComplete
 }
 
 func (action *monitorAction) Handle(ctx context.Context, pipe *v1.Pipe) (*v1.Pipe, error) {
@@ -128,6 +129,16 @@ func (action *monitorAction) Handle(ctx context.Context, pipe *v1.Pipe) (*v1.Pip
 		target.Status.Phase = v1.PipePhaseError
 		setPipeReadyCondition(target, &it)
 
+	case v1.IntegrationPhaseBuildComplete:
+		target.Status.Phase = v1.PipePhaseBuildComplete
+		c := v1.PipeCondition{
+			Type:    v1.PipeConditionReady,
+			Status:  corev1.ConditionFalse,
+			Reason:  "BuildComplete",
+			Message: fmt.Sprintf("Integration %q build completed successfully", it.GetName()),
+		}
+		target.Status.SetConditions(c)
+
 	default:
 		target.Status.Phase = v1.PipePhaseCreating
 
diff --git a/pkg/controller/pipe/monitor_test.go b/pkg/controller/pipe/monitor_test.go
index 543a918f9..ba2269b2b 100644
--- a/pkg/controller/pipe/monitor_test.go
+++ b/pkg/controller/pipe/monitor_test.go
@@ -376,3 +376,47 @@ func TestPipeIntegrationPipeTraitAnnotations(t *testing.T) {
 	assert.Equal(t, corev1.ConditionFalse, handledPipe.Status.GetCondition(v1.PipeConditionReady).Status)
 	assert.Equal(t, "Integration \"my-pipe\" is in \"Creating\" phase", handledPipe.Status.GetCondition(v1.PipeConditionReady).Message)
 }
+
+func TestPipeIntegrationBuildComplete(t *testing.T) {
+	pipe := &v1.Pipe{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.PipeKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-pipe",
+		},
+		Spec: v1.PipeSpec{
+			Source: v1.Endpoint{
+				URI: ptr.To("timer:tick"),
+			},
+			Sink: v1.Endpoint{
+				URI: ptr.To("log:info"),
+			},
+		},
+		Status: v1.PipeStatus{
+			Phase: v1.PipePhaseCreating,
+		},
+	}
+
+	c, err := internal.NewFakeClient(pipe)
+	require.NoError(t, err)
+	it, err := CreateIntegrationFor(context.TODO(), c, pipe)
+	require.NoError(t, err)
+	it.Status.Phase = v1.IntegrationPhaseBuildComplete
+	c, err = internal.NewFakeClient(pipe, it)
+	require.NoError(t, err)
+
+	a := NewMonitorAction()
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor", a.Name())
+	assert.True(t, a.CanHandle(pipe))
+	handledPipe, err := a.Handle(context.TODO(), pipe)
+	require.NoError(t, err)
+	assert.Equal(t, v1.PipePhaseBuildComplete, handledPipe.Status.Phase)
+	assert.Equal(t, corev1.ConditionFalse, handledPipe.Status.GetCondition(v1.PipeConditionReady).Status)
+	assert.Equal(t, "BuildComplete", handledPipe.Status.GetCondition(v1.PipeConditionReady).Reason)
+	assert.Equal(t, "Integration \"my-pipe\" build completed successfully", handledPipe.Status.GetCondition(v1.PipeConditionReady).Message)
+}