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 2024/01/09 14:21:52 UTC

(camel-k) 04/08: chore: syntethic Integration unit testing

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 ece9fb46b2d27f3f0f5273b5bdadfff09cc6a512
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Mon Dec 4 15:30:55 2023 +0100

    chore: syntethic Integration unit testing
---
 pkg/controller/integration/initialize_test.go      | 189 ++++++++
 .../integration/monitor_synthetic_test.go          | 489 +++++++++++++++++++++
 pkg/controller/synthetic/synthetic.go              |   4 +-
 pkg/controller/synthetic/synthetic_test.go         | 221 ++++++++++
 pkg/util/test/client.go                            |  15 +-
 5 files changed, 915 insertions(+), 3 deletions(-)

diff --git a/pkg/controller/integration/initialize_test.go b/pkg/controller/integration/initialize_test.go
new file mode 100644
index 000000000..2beaaa798
--- /dev/null
+++ b/pkg/controller/integration/initialize_test.go
@@ -0,0 +1,189 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"context"
+	"testing"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+
+	"github.com/apache/camel-k/v2/pkg/util/log"
+	"github.com/apache/camel-k/v2/pkg/util/test"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestCamelImportDeployment(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-deploy",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "Deployment",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseInitialization,
+		},
+	}
+	c, err := test.NewFakeClient(importedIt)
+	assert.Nil(t, err)
+
+	a := initializeAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "initialize", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "imported from my-deploy Deployment", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+	// Deployment condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionDeploymentAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Reason)
+	assert.Equal(t, "imported from my-deploy Deployment", handledIt.Status.GetCondition(v1.IntegrationConditionDeploymentAvailable).Message)
+}
+
+func TestCamelImportCronJob(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-cron",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "CronJob",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseInitialization,
+		},
+	}
+	c, err := test.NewFakeClient(importedIt)
+	assert.Nil(t, err)
+
+	a := initializeAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "initialize", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "imported from my-cron CronJob", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+	// CronJob condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionCronJobCreatedReason, handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Reason)
+	assert.Equal(t, "imported from my-cron CronJob", handledIt.Status.GetCondition(v1.IntegrationConditionCronJobAvailable).Message)
+}
+
+func TestCamelImportKnativeService(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-ksvc",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "KnativeService",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseInitialization,
+		},
+	}
+	c, err := test.NewFakeClient(importedIt)
+	assert.Nil(t, err)
+
+	a := initializeAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "initialize", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionKnativeServiceReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "imported from my-ksvc KnativeService", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+	// Knative Service condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionKnativeServiceAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Reason)
+	assert.Equal(t, "imported from my-ksvc KnativeService", handledIt.Status.GetCondition(v1.IntegrationConditionKnativeServiceAvailable).Message)
+}
+
+func TestCamelImportUnsupportedKind(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-kind",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "SomeKind",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseInitialization,
+		},
+	}
+	c, err := test.NewFakeClient(importedIt)
+	assert.Nil(t, err)
+
+	a := initializeAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "initialize", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionImportingKindAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "Unsupported SomeKind import kind", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+}
diff --git a/pkg/controller/integration/monitor_synthetic_test.go b/pkg/controller/integration/monitor_synthetic_test.go
new file mode 100644
index 000000000..c2217218a
--- /dev/null
+++ b/pkg/controller/integration/monitor_synthetic_test.go
@@ -0,0 +1,489 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"context"
+	"testing"
+
+	appsv1 "k8s.io/api/apps/v1"
+	batchv1 "k8s.io/api/batch/v1"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
+
+	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+
+	"github.com/apache/camel-k/v2/pkg/util/log"
+	"github.com/apache/camel-k/v2/pkg/util/test"
+
+	"github.com/stretchr/testify/assert"
+	"knative.dev/pkg/apis"
+	duckv1 "knative.dev/pkg/apis/duck/v1"
+)
+
+func TestMonitorSyntheticIntegrationImportingKindUnavailable(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-deploy",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "SomeKind",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseRunning,
+		},
+	}
+	c, err := test.NewFakeClient(importedIt)
+	assert.Nil(t, err)
+
+	a := monitorSyntheticAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor-synthetic", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.NotNil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase)
+	assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionImportingKindAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "cannot create a synthetic environment for SomeKind kind", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+}
+
+func TestMonitorSyntheticIntegrationCannotMonitorPods(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-deploy",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "Deployment",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseRunning,
+			Conditions: []v1.IntegrationCondition{
+				{
+					Type:   v1.IntegrationConditionDeploymentAvailable,
+					Status: corev1.ConditionTrue,
+				},
+				{
+					Type:   v1.IntegrationConditionReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	deploy := &appsv1.Deployment{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Deployment",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-deploy",
+			Annotations: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+	}
+	c, err := test.NewFakeClient(importedIt, deploy)
+	assert.Nil(t, err)
+
+	a := monitorSyntheticAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor-synthetic", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseCannotMonitor, handledIt.Status.Phase)
+	// Ready condition should be still true
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	// Check monitoring pods condition
+	assert.Equal(t, corev1.ConditionFalse, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionMonitoringPodsAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Reason)
+	assert.Equal(t, "Could not find `camel.apache.org/integration: my-imported-it` label in the Deployment/my-deploy template. Make sure to include this label in the template for Pod monitoring purposes.", handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Message)
+}
+
+func TestMonitorSyntheticIntegrationDeployment(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-deploy",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "Deployment",
+			},
+		},
+		Spec: v1.IntegrationSpec{
+			Traits: v1.Traits{
+				Container: &trait.ContainerTrait{
+					Name: "my-cnt",
+				},
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseRunning,
+			Conditions: []v1.IntegrationCondition{
+				{
+					Type:   v1.IntegrationConditionDeploymentAvailable,
+					Status: corev1.ConditionTrue,
+				},
+				{
+					Type:   v1.IntegrationConditionReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	deploy := &appsv1.Deployment{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Deployment",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-deploy",
+			Annotations: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: appsv1.DeploymentSpec{
+			Template: corev1.PodTemplateSpec{
+				ObjectMeta: metav1.ObjectMeta{
+					Labels: map[string]string{
+						v1.IntegrationLabel: "my-imported-it",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name:  "my-cnt",
+							Image: "my-img",
+						},
+					},
+				},
+			},
+		},
+	}
+	pod := &corev1.Pod{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Pod",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-pod",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: corev1.PodSpec{
+			Containers: []corev1.Container{
+				{
+					Name:  "my-cnt",
+					Image: "my-img",
+				},
+			},
+		},
+		Status: corev1.PodStatus{
+			Phase: corev1.PodRunning,
+			Conditions: []corev1.PodCondition{
+				{
+					Type:   corev1.PodReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	c, err := test.NewFakeClient(importedIt, deploy, pod)
+	assert.Nil(t, err)
+
+	a := monitorSyntheticAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor-synthetic", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	assert.Equal(t, int32(1), *handledIt.Status.Replicas)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionDeploymentReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "1/1 ready replicas", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+	// Check monitoring pods condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionMonitoringPodsAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Reason)
+}
+
+func TestMonitorSyntheticIntegrationCronJob(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-cron",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "CronJob",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseRunning,
+			Conditions: []v1.IntegrationCondition{
+				{
+					Type:   v1.IntegrationConditionCronJobAvailable,
+					Status: corev1.ConditionTrue,
+				},
+				{
+					Type:   v1.IntegrationConditionReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	cron := &batchv1.CronJob{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "CronJob",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-cron",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: batchv1.CronJobSpec{
+			JobTemplate: batchv1.JobTemplateSpec{
+				Spec: batchv1.JobSpec{
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								v1.IntegrationLabel: "my-imported-it",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "my-cnt",
+									Image: "my-img",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	pod := &corev1.Pod{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Pod",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-pod",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: corev1.PodSpec{
+			Containers: []corev1.Container{
+				{
+					Name:  "my-cnt",
+					Image: "my-img",
+				},
+			},
+		},
+		Status: corev1.PodStatus{
+			Phase: corev1.PodRunning,
+			Conditions: []corev1.PodCondition{
+				{
+					Type:   corev1.PodReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	c, err := test.NewFakeClient(importedIt, cron, pod)
+	assert.Nil(t, err)
+
+	a := monitorSyntheticAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor-synthetic", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	assert.Equal(t, int32(1), *handledIt.Status.Replicas)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionCronJobCreatedReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	assert.Equal(t, "cronjob created", handledIt.Status.GetCondition(v1.IntegrationConditionReady).Message)
+	// Check monitoring pods condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionMonitoringPodsAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Reason)
+}
+
+func TestMonitorSyntheticIntegrationKnativeService(t *testing.T) {
+	importedIt := &v1.Integration{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: v1.SchemeGroupVersion.String(),
+			Kind:       v1.IntegrationKind,
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-imported-it",
+			Annotations: map[string]string{
+				v1.IntegrationImportedNameLabel: "my-ksvc",
+				v1.IntegrationSyntheticLabel:    "true",
+				v1.IntegrationImportedKindLabel: "KnativeService",
+			},
+		},
+		Status: v1.IntegrationStatus{
+			Phase: v1.IntegrationPhaseRunning,
+			Conditions: []v1.IntegrationCondition{
+				{
+					Type:   v1.IntegrationConditionKnativeServiceAvailable,
+					Status: corev1.ConditionTrue,
+				},
+				{
+					Type:   v1.IntegrationConditionReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	ksvc := &servingv1.Service{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Service",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-ksvc",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: servingv1.ServiceSpec{
+			ConfigurationSpec: servingv1.ConfigurationSpec{
+				Template: servingv1.RevisionTemplateSpec{
+					ObjectMeta: metav1.ObjectMeta{
+						Labels: map[string]string{
+							v1.IntegrationLabel: "my-imported-it",
+						},
+					},
+					Spec: servingv1.RevisionSpec{
+						PodSpec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "my-cnt",
+									Image: "my-img",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+		Status: servingv1.ServiceStatus{
+			Status: duckv1.Status{
+				Conditions: duckv1.Conditions{
+					apis.Condition{
+						Type:   servingv1.ServiceConditionReady,
+						Status: corev1.ConditionTrue,
+					},
+				},
+			},
+		},
+	}
+	pod := &corev1.Pod{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Pod",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-pod",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: corev1.PodSpec{
+			Containers: []corev1.Container{
+				{
+					Name:  "my-cnt",
+					Image: "my-img",
+				},
+			},
+		},
+		Status: corev1.PodStatus{
+			Phase: corev1.PodRunning,
+			Conditions: []corev1.PodCondition{
+				{
+					Type:   corev1.PodReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+	c, err := test.NewFakeClient(importedIt, ksvc, pod)
+	assert.Nil(t, err)
+
+	a := monitorSyntheticAction{}
+	a.InjectLogger(log.Log)
+	a.InjectClient(c)
+	assert.Equal(t, "monitor-synthetic", a.Name())
+	assert.True(t, a.CanHandle(importedIt))
+	handledIt, err := a.Handle(context.TODO(), importedIt)
+	assert.Nil(t, err)
+	assert.Equal(t, v1.IntegrationPhaseRunning, handledIt.Status.Phase)
+	assert.Equal(t, int32(1), *handledIt.Status.Replicas)
+	// Ready condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Status)
+	assert.Equal(t, v1.IntegrationConditionKnativeServiceReadyReason, handledIt.Status.GetCondition(v1.IntegrationConditionReady).Reason)
+	// Check monitoring pods condition
+	assert.Equal(t, corev1.ConditionTrue, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Status)
+	assert.Equal(t, v1.IntegrationConditionMonitoringPodsAvailableReason, handledIt.Status.GetCondition(v1.IntegrationConditionMonitoringPodsAvailable).Reason)
+}
diff --git a/pkg/controller/synthetic/synthetic.go b/pkg/controller/synthetic/synthetic.go
index bd785d318..c5f7bbb34 100644
--- a/pkg/controller/synthetic/synthetic.go
+++ b/pkg/controller/synthetic/synthetic.go
@@ -220,7 +220,7 @@ func nonManagedCamelApplicationFactory(obj ctrl.Object) (nonManagedCamelApplicat
 	if ok {
 		return &NonManagedCamelKnativeService{ksvc: ksvc}, nil
 	}
-	return nil, fmt.Errorf("unsupported %s object kind", obj)
+	return nil, fmt.Errorf("unsupported %s object kind", obj.GetName())
 }
 
 // NonManagedCamelDeployment represents a regular Camel application built and deployed outside the operator lifecycle.
@@ -252,7 +252,7 @@ func (app *nonManagedCamelDeployment) getContainerNameFromDeployment() string {
 	for _, ct := range app.deploy.Spec.Template.Spec.Containers {
 		// set as fallback if no container is named as the deployment
 		if firstContainerName == "" {
-			firstContainerName = app.deploy.Name
+			firstContainerName = ct.Name
 		}
 		if ct.Name == app.deploy.Name {
 			return app.deploy.Name
diff --git a/pkg/controller/synthetic/synthetic_test.go b/pkg/controller/synthetic/synthetic_test.go
new file mode 100644
index 000000000..c600f6d3e
--- /dev/null
+++ b/pkg/controller/synthetic/synthetic_test.go
@@ -0,0 +1,221 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package synthetic
+
+import (
+	"testing"
+
+	appsv1 "k8s.io/api/apps/v1"
+	batchv1 "k8s.io/api/batch/v1"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
+
+	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+	"github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNonManagedUnsupported(t *testing.T) {
+	pod := &corev1.Pod{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: corev1.SchemeGroupVersion.String(),
+			Kind:       "Pod",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-pod",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: corev1.PodSpec{
+			Containers: []corev1.Container{
+				{
+					Name:  "my-cnt",
+					Image: "my-img",
+				},
+			},
+		},
+		Status: corev1.PodStatus{
+			Phase: corev1.PodRunning,
+			Conditions: []corev1.PodCondition{
+				{
+					Type:   corev1.PodReady,
+					Status: corev1.ConditionTrue,
+				},
+			},
+		},
+	}
+
+	nilAdapter, err := nonManagedCamelApplicationFactory(pod)
+	assert.NotNil(t, err)
+	assert.Equal(t, "unsupported my-pod object kind", err.Error())
+	assert.Nil(t, nilAdapter)
+}
+
+func TestNonManagedDeployment(t *testing.T) {
+	deploy := &appsv1.Deployment{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Deployment",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-deploy",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: appsv1.DeploymentSpec{
+			Template: corev1.PodTemplateSpec{
+				ObjectMeta: metav1.ObjectMeta{
+					Labels: map[string]string{
+						v1.IntegrationLabel: "my-imported-it",
+					},
+				},
+				Spec: corev1.PodSpec{
+					Containers: []corev1.Container{
+						{
+							Name:  "my-cnt",
+							Image: "my-img",
+						},
+					},
+				},
+			},
+		},
+	}
+
+	expectedIt := v1.NewIntegration("ns", "my-imported-it")
+	expectedIt.SetAnnotations(map[string]string{
+		v1.IntegrationImportedNameLabel: "my-deploy",
+		v1.IntegrationImportedKindLabel: "Deployment",
+		v1.IntegrationSyntheticLabel:    "true",
+	})
+	expectedIt.Spec = v1.IntegrationSpec{
+		Traits: v1.Traits{
+			Container: &trait.ContainerTrait{
+				Name: "my-cnt",
+			},
+		},
+	}
+
+	deploymentAdapter, err := nonManagedCamelApplicationFactory(deploy)
+	assert.Nil(t, err)
+	assert.NotNil(t, deploymentAdapter)
+	assert.Equal(t, expectedIt, *deploymentAdapter.Integration())
+}
+
+func TestNonManagedCronJob(t *testing.T) {
+	cron := &batchv1.CronJob{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: batchv1.SchemeGroupVersion.String(),
+			Kind:       "CronJob",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-cron",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: batchv1.CronJobSpec{
+			JobTemplate: batchv1.JobTemplateSpec{
+				Spec: batchv1.JobSpec{
+					Template: corev1.PodTemplateSpec{
+						ObjectMeta: metav1.ObjectMeta{
+							Labels: map[string]string{
+								v1.IntegrationLabel: "my-imported-it",
+							},
+						},
+						Spec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "my-cnt",
+									Image: "my-img",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	expectedIt := v1.NewIntegration("ns", "my-imported-it")
+	expectedIt.SetAnnotations(map[string]string{
+		v1.IntegrationImportedNameLabel: "my-cron",
+		v1.IntegrationImportedKindLabel: "CronJob",
+		v1.IntegrationSyntheticLabel:    "true",
+	})
+
+	cronJobAdapter, err := nonManagedCamelApplicationFactory(cron)
+	assert.Nil(t, err)
+	assert.NotNil(t, cronJobAdapter)
+	assert.Equal(t, expectedIt, *cronJobAdapter.Integration())
+}
+
+func TestNonManagedKnativeService(t *testing.T) {
+	ksvc := &servingv1.Service{
+		TypeMeta: metav1.TypeMeta{
+			APIVersion: appsv1.SchemeGroupVersion.String(),
+			Kind:       "Service",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: "ns",
+			Name:      "my-ksvc",
+			Labels: map[string]string{
+				v1.IntegrationLabel: "my-imported-it",
+			},
+		},
+		Spec: servingv1.ServiceSpec{
+			ConfigurationSpec: servingv1.ConfigurationSpec{
+				Template: servingv1.RevisionTemplateSpec{
+					ObjectMeta: metav1.ObjectMeta{
+						Labels: map[string]string{
+							v1.IntegrationLabel: "my-imported-it",
+						},
+					},
+					Spec: servingv1.RevisionSpec{
+						PodSpec: corev1.PodSpec{
+							Containers: []corev1.Container{
+								{
+									Name:  "my-cnt",
+									Image: "my-img",
+								},
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	expectedIt := v1.NewIntegration("ns", "my-imported-it")
+	expectedIt.SetAnnotations(map[string]string{
+		v1.IntegrationImportedNameLabel: "my-ksvc",
+		v1.IntegrationImportedKindLabel: "KnativeService",
+		v1.IntegrationSyntheticLabel:    "true",
+	})
+
+	knativeServiceAdapter, err := nonManagedCamelApplicationFactory(ksvc)
+	assert.Nil(t, err)
+	assert.NotNil(t, knativeServiceAdapter)
+	assert.Equal(t, expectedIt, *knativeServiceAdapter.Integration())
+}
diff --git a/pkg/util/test/client.go b/pkg/util/test/client.go
index fef78d2b6..9105719eb 100644
--- a/pkg/util/test/client.go
+++ b/pkg/util/test/client.go
@@ -30,6 +30,7 @@ import (
 	camelv1alpha1 "github.com/apache/camel-k/v2/pkg/client/camel/clientset/versioned/typed/camel/v1alpha1"
 	"github.com/apache/camel-k/v2/pkg/util"
 	autoscalingv1 "k8s.io/api/autoscaling/v1"
+	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -55,7 +56,19 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
 		return nil, err
 	}
 
-	c := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(initObjs...).Build()
+	c := fake.
+		NewClientBuilder().
+		WithScheme(scheme).
+		WithIndex(
+			&corev1.Pod{},
+			"status.phase",
+			func(obj controller.Object) []string {
+				pod, _ := obj.(*corev1.Pod)
+				return []string{string(pod.Status.Phase)}
+			},
+		).
+		WithRuntimeObjects(initObjs...).
+		Build()
 
 	camelClientset := fakecamelclientset.NewSimpleClientset(filterObjects(scheme, initObjs, func(gvk schema.GroupVersionKind) bool {
 		return strings.Contains(gvk.Group, "camel")