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 515c7629b3b39d724b00d7217bd6c6bd5682b647
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Wed Aug 28 15:19:12 2024 +0200

    feat(api): Kit-less Integration
    
    Closes #2365
---
 addons/telemetry/telemetry.go                     |   4 -
 pkg/apis/camel/v1/integration_types_support.go    |   5 +
 pkg/apis/camel/v1/integrationkit_types.go         |   1 +
 pkg/apis/camel/v1/integrationkit_types_support.go |   1 +
 pkg/builder/image.go                              |   7 +-
 pkg/builder/image_test.go                         |  13 +-
 pkg/controller/integration/build_kit_test.go      | 358 ++++++++++++++++++++++
 pkg/controller/integration/initialize.go          |   5 +
 pkg/controller/integration/kits.go                |  16 +-
 pkg/controller/integration/monitor.go             |  77 ++---
 pkg/controller/integrationkit/monitor.go          |  13 +-
 pkg/trait/camel.go                                |  28 +-
 pkg/trait/camel_test.go                           |  26 +-
 pkg/trait/container.go                            |  39 +--
 pkg/trait/container_test.go                       |  20 +-
 pkg/trait/cron.go                                 |   3 -
 pkg/trait/jvm.go                                  |  55 ++--
 pkg/trait/jvm_test.go                             |  31 +-
 pkg/trait/quarkus.go                              |   7 +-
 pkg/trait/trait_types_test.go                     |  29 +-
 pkg/util/camel/camel_runtime.go                   |   4 +-
 pkg/util/kubernetes/camel.go                      |   3 +
 22 files changed, 550 insertions(+), 195 deletions(-)

diff --git a/addons/telemetry/telemetry.go b/addons/telemetry/telemetry.go
index 07908c13f..5fae67232 100644
--- a/addons/telemetry/telemetry.go
+++ b/addons/telemetry/telemetry.go
@@ -177,10 +177,6 @@ func (t *telemetryTrait) setCatalogConfiguration(e 
*trait.Environment) {
 
 // Deprecated: to be removed in future release in favor of func 
setCatalogConfiguration().
 func (t *telemetryTrait) setRuntimeProviderProperties(e *trait.Environment) {
-       if e.CamelCatalog == nil {
-               return
-       }
-
        provider := e.CamelCatalog.CamelCatalogSpec.Runtime.Provider
        properties := telemetryProperties[provider]
        if appPropEnabled := properties[propEnabled]; appPropEnabled != "" {
diff --git a/pkg/apis/camel/v1/integration_types_support.go 
b/pkg/apis/camel/v1/integration_types_support.go
index ca0de0626..dec40102f 100644
--- a/pkg/apis/camel/v1/integration_types_support.go
+++ b/pkg/apis/camel/v1/integration_types_support.go
@@ -88,6 +88,11 @@ func (in *Integration) UserDefinedSources() []SourceSpec {
        return sources
 }
 
+// IsManagedBuild returns true when the Integration requires to be built by 
the operator.
+func (in *Integration) IsManagedBuild() bool {
+       return in.Spec.Traits.Container == nil || 
in.Spec.Traits.Container.Image == ""
+}
+
 func (in *IntegrationSpec) AddSource(name string, content string, language 
Language) {
        in.Sources = append(in.Sources, NewSourceSpec(name, content, language))
 }
diff --git a/pkg/apis/camel/v1/integrationkit_types.go 
b/pkg/apis/camel/v1/integrationkit_types.go
index 3d2d70331..84f3b1fc8 100644
--- a/pkg/apis/camel/v1/integrationkit_types.go
+++ b/pkg/apis/camel/v1/integrationkit_types.go
@@ -155,6 +155,7 @@ const (
        IntegrationKitTypeUser = "user"
        // IntegrationKitTypeExternal identifies a Kit created by any third 
party.
        IntegrationKitTypeExternal = "external"
+       // Deprecated: synthetic Integration Kits are replaced by non managed 
build Integrations.
        // IntegrationKitTypeSynthetic identifies a synthetic Kit (generated 
for any container image for which the operator cannot make any assumption).
        IntegrationKitTypeSynthetic = "synthetic"
 
diff --git a/pkg/apis/camel/v1/integrationkit_types_support.go 
b/pkg/apis/camel/v1/integrationkit_types_support.go
index b6b70624d..ed8595c3d 100644
--- a/pkg/apis/camel/v1/integrationkit_types_support.go
+++ b/pkg/apis/camel/v1/integrationkit_types_support.go
@@ -110,6 +110,7 @@ func (in *IntegrationKit) IsExternal() bool {
        return in.Labels[IntegrationKitTypeLabel] == IntegrationKitTypeExternal
 }
 
+// Deprecated: synthetic Integration Kits are replaced by syntentic 
Integrations.
 // IsSynthetic returns true for synthetic IntegrationKits.
 func (in *IntegrationKit) IsSynthetic() bool {
        return in.Labels[IntegrationKitTypeLabel] == IntegrationKitTypeSynthetic
diff --git a/pkg/builder/image.go b/pkg/builder/image.go
index af79056ae..deaf0eaf3 100644
--- a/pkg/builder/image.go
+++ b/pkg/builder/image.go
@@ -24,6 +24,7 @@ import (
        "strings"
 
        "github.com/apache/camel-k/v2/pkg/util/io"
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
        "github.com/apache/camel-k/v2/pkg/util/log"
 
        "k8s.io/apimachinery/pkg/labels"
@@ -193,9 +194,9 @@ func listPublishedImages(context *builderContext) 
([]v1.IntegrationKitStatus, er
        options := []ctrl.ListOption{
                ctrl.InNamespace(context.Namespace),
                ctrl.MatchingLabels{
-                       v1.IntegrationKitTypeLabel:          
v1.IntegrationKitTypePlatform,
-                       "camel.apache.org/runtime.version":  
context.Catalog.Runtime.Version,
-                       "camel.apache.org/runtime.provider": 
string(context.Catalog.Runtime.Provider),
+                       v1.IntegrationKitTypeLabel:           
v1.IntegrationKitTypePlatform,
+                       kubernetes.CamelLabelRuntimeVersion:  
context.Catalog.Runtime.Version,
+                       kubernetes.CamelLabelRuntimeProvider: 
string(context.Catalog.Runtime.Provider),
                },
                ctrl.MatchingLabelsSelector{
                        Selector: 
labels.NewSelector().Add(*excludeNativeImages),
diff --git a/pkg/builder/image_test.go b/pkg/builder/image_test.go
index 0014c48dc..51c3b786c 100644
--- a/pkg/builder/image_test.go
+++ b/pkg/builder/image_test.go
@@ -28,6 +28,7 @@ import (
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
        "github.com/apache/camel-k/v2/pkg/util/camel"
        "github.com/apache/camel-k/v2/pkg/util/cancellable"
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
        "github.com/apache/camel-k/v2/pkg/util/test"
 )
 
@@ -45,9 +46,9 @@ func TestListPublishedImages(t *testing.T) {
                                Namespace: "ns",
                                Name:      "my-kit-1",
                                Labels: map[string]string{
-                                       v1.IntegrationKitTypeLabel:          
v1.IntegrationKitTypePlatform,
-                                       "camel.apache.org/runtime.version":  
catalog.Runtime.Version,
-                                       "camel.apache.org/runtime.provider": 
string(catalog.Runtime.Provider),
+                                       v1.IntegrationKitTypeLabel:           
v1.IntegrationKitTypePlatform,
+                                       kubernetes.CamelLabelRuntimeVersion:  
catalog.Runtime.Version,
+                                       kubernetes.CamelLabelRuntimeProvider: 
string(catalog.Runtime.Provider),
                                },
                        },
                        Status: v1.IntegrationKitStatus{
@@ -66,9 +67,9 @@ func TestListPublishedImages(t *testing.T) {
                                Namespace: "ns",
                                Name:      "my-kit-2",
                                Labels: map[string]string{
-                                       v1.IntegrationKitTypeLabel:          
v1.IntegrationKitTypePlatform,
-                                       "camel.apache.org/runtime.version":  
catalog.Runtime.Version,
-                                       "camel.apache.org/runtime.provider": 
string(catalog.Runtime.Provider),
+                                       v1.IntegrationKitTypeLabel:           
v1.IntegrationKitTypePlatform,
+                                       kubernetes.CamelLabelRuntimeVersion:  
catalog.Runtime.Version,
+                                       kubernetes.CamelLabelRuntimeProvider: 
string(catalog.Runtime.Provider),
                                },
                        },
                        Status: v1.IntegrationKitStatus{
diff --git a/pkg/controller/integration/build_kit_test.go 
b/pkg/controller/integration/build_kit_test.go
new file mode 100644
index 000000000..1278a6423
--- /dev/null
+++ b/pkg/controller/integration/build_kit_test.go
@@ -0,0 +1,358 @@
+/*
+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"
+
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/v2/pkg/util/defaults"
+       "github.com/apache/camel-k/v2/pkg/util/digest"
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
+       "github.com/apache/camel-k/v2/pkg/util/log"
+       "github.com/apache/camel-k/v2/pkg/util/test"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/types"
+)
+
+func TestCamelBuildKitDigestChanged(t *testing.T) {
+       it := &v1.Integration{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-it",
+               },
+               Status: v1.IntegrationStatus{
+                       Phase:  v1.IntegrationPhaseBuildingKit,
+                       Digest: "NonMatchingDigest",
+               },
+       }
+       c, err := test.NewFakeClient(it)
+       require.NoError(t, err)
+
+       a := buildKitAction{}
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "build-kit", a.Name())
+       assert.True(t, a.CanHandle(it))
+       handledIt, err := a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       assert.Equal(t, v1.IntegrationPhaseInitialization, 
handledIt.Status.Phase)
+       // Ready condition
+       assert.Nil(t, 
handledIt.Status.GetCondition(v1.IntegrationConditionReady))
+       assert.NotEqual(t, "NonMatchingDigest", handledIt.Status.Digest)
+}
+
+func TestCamelBuildKitKitSetOnIntegration(t *testing.T) {
+       ik := &v1.IntegrationKit{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKitKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-ik",
+                       Labels: map[string]string{
+                               v1.IntegrationKitTypeLabel: 
v1.IntegrationKitTypePlatform,
+                       },
+               },
+               Status: v1.IntegrationKitStatus{
+                       Phase: v1.IntegrationKitPhaseBuildRunning,
+               },
+       }
+       it := &v1.Integration{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-it",
+               },
+               Status: v1.IntegrationStatus{
+                       Phase: v1.IntegrationPhaseBuildingKit,
+                       IntegrationKit: &corev1.ObjectReference{
+                               APIVersion: ik.APIVersion,
+                               Kind:       ik.Kind,
+                               Namespace:  ik.Namespace,
+                               Name:       ik.Name,
+                       },
+               },
+       }
+       hash, err := digest.ComputeForIntegration(it, nil, nil)
+       require.NoError(t, err)
+       it.Status.Digest = hash
+       c, err := test.NewFakeClient(it, ik)
+       require.NoError(t, err)
+
+       a := buildKitAction{}
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "build-kit", a.Name())
+       assert.True(t, a.CanHandle(it))
+       handledIt, err := a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       // If the kit is under construction, we expect the Integration to be nil
+       assert.Nil(t, handledIt)
+
+       // Move IntegrationKit phase to ready status
+       it.Status.Phase = v1.IntegrationPhaseBuildingKit
+       ik.Status.Phase = v1.IntegrationKitPhaseReady
+       c, err = test.NewFakeClient(it, ik)
+       require.NoError(t, err)
+       a.InjectClient(c)
+       handledIt, err = a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       assert.Equal(t, v1.IntegrationPhaseDeploying, handledIt.Status.Phase)
+
+       // Move IntegrationKit phase to ready status
+       it.Status.Phase = v1.IntegrationPhaseBuildingKit
+       ik.Status.Phase = v1.IntegrationKitPhaseError
+       c, err = test.NewFakeClient(it, ik)
+       require.NoError(t, err)
+       a.InjectClient(c)
+       handledIt, err = a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase)
+
+       // Remove IntegrationKit
+       it.Status.Phase = v1.IntegrationPhaseBuildingKit
+       c, err = test.NewFakeClient(it)
+       require.NoError(t, err)
+       a.InjectClient(c)
+       handledIt, err = a.Handle(context.TODO(), it)
+       require.Error(t, err)
+       assert.Nil(t, handledIt)
+}
+
+func TestCamelBuildKitKitLookupExistingKit(t *testing.T) {
+       catalog := &v1.CamelCatalog{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.CamelCatalogKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "camel-k-catalog",
+               },
+               Spec: v1.CamelCatalogSpec{
+                       Runtime: v1.RuntimeSpec{
+                               Provider: v1.RuntimeProviderQuarkus,
+                               Version:  defaults.DefaultRuntimeVersion,
+                       },
+               },
+       }
+       ip := &v1.IntegrationPlatform{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationPlatformKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "camel-k",
+               },
+               Status: v1.IntegrationPlatformStatus{
+                       IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+                               Build: v1.IntegrationPlatformBuildSpec{
+                                       RuntimeVersion: 
defaults.DefaultRuntimeVersion,
+                               },
+                       },
+                       Phase: v1.IntegrationPlatformPhaseReady,
+               },
+       }
+       ik := &v1.IntegrationKit{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKitKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-ik",
+                       Labels: map[string]string{
+                               v1.IntegrationKitTypeLabel:           
v1.IntegrationKitTypePlatform,
+                               kubernetes.CamelLabelRuntimeVersion:  
defaults.DefaultRuntimeVersion,
+                               kubernetes.CamelLabelRuntimeProvider: 
string(v1.RuntimeProviderQuarkus),
+                       },
+               },
+               Status: v1.IntegrationKitStatus{
+                       Phase:           v1.IntegrationKitPhaseBuildRunning,
+                       RuntimeVersion:  defaults.DefaultRuntimeVersion,
+                       RuntimeProvider: v1.RuntimeProviderQuarkus,
+               },
+       }
+       it := &v1.Integration{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-it",
+               },
+               Status: v1.IntegrationStatus{
+                       Phase:           v1.IntegrationPhaseBuildingKit,
+                       RuntimeVersion:  defaults.DefaultRuntimeVersion,
+                       RuntimeProvider: v1.RuntimeProviderQuarkus,
+               },
+       }
+       hash, err := digest.ComputeForIntegration(it, nil, nil)
+       require.NoError(t, err)
+       it.Status.Digest = hash
+       c, err := test.NewFakeClient(it, ik, ip, catalog)
+       require.NoError(t, err)
+
+       a := buildKitAction{}
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "build-kit", a.Name())
+       assert.True(t, a.CanHandle(it))
+       handledIt, err := a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       // Found a matching kit (building)
+       assert.Equal(t, v1.IntegrationPhaseBuildingKit, handledIt.Status.Phase)
+       assert.Equal(t, ik.Name, it.Status.IntegrationKit.Name)
+       assert.Equal(t, ik.Namespace, it.Status.IntegrationKit.Namespace)
+       // Found a matching kit (ready)
+       it.Status.Phase = v1.IntegrationPhaseBuildingKit
+       ik.Status.Phase = v1.IntegrationKitPhaseReady
+       c, err = test.NewFakeClient(it, ik, ip, catalog)
+       require.NoError(t, err)
+       a.InjectClient(c)
+       handledIt, err = a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       assert.NotNil(t, handledIt)
+       assert.Equal(t, v1.IntegrationPhaseDeploying, handledIt.Status.Phase)
+       assert.Equal(t, ik.Name, it.Status.IntegrationKit.Name)
+       assert.Equal(t, ik.Namespace, it.Status.IntegrationKit.Namespace)
+       // Found a matching kit (error)
+       it.Status.Phase = v1.IntegrationPhaseBuildingKit
+       ik.Status.Phase = v1.IntegrationKitPhaseError
+       c, err = test.NewFakeClient(it, ik, ip, catalog)
+       require.NoError(t, err)
+       a.InjectClient(c)
+       handledIt, err = a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       assert.NotNil(t, handledIt)
+       assert.Equal(t, v1.IntegrationPhaseError, handledIt.Status.Phase)
+       assert.Equal(t, ik.Name, it.Status.IntegrationKit.Name)
+       assert.Equal(t, ik.Namespace, it.Status.IntegrationKit.Namespace)
+}
+
+func TestCamelBuildKitKitLookupNoMatchingKits(t *testing.T) {
+       catalog := &v1.CamelCatalog{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.CamelCatalogKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "camel-k-catalog",
+               },
+               Spec: v1.CamelCatalogSpec{
+                       Runtime: v1.RuntimeSpec{
+                               Provider: v1.RuntimeProviderQuarkus,
+                               Version:  defaults.DefaultRuntimeVersion,
+                       },
+               },
+       }
+       ip := &v1.IntegrationPlatform{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationPlatformKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "camel-k",
+               },
+               Status: v1.IntegrationPlatformStatus{
+                       IntegrationPlatformSpec: v1.IntegrationPlatformSpec{
+                               Build: v1.IntegrationPlatformBuildSpec{
+                                       RuntimeVersion: 
defaults.DefaultRuntimeVersion,
+                               },
+                       },
+                       Phase: v1.IntegrationPlatformPhaseReady,
+               },
+       }
+       ik := &v1.IntegrationKit{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKitKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-ik",
+                       Labels: map[string]string{
+                               v1.IntegrationKitTypeLabel:           
v1.IntegrationKitTypePlatform,
+                               kubernetes.CamelLabelRuntimeVersion:  
defaults.DefaultRuntimeVersion,
+                               kubernetes.CamelLabelRuntimeProvider: 
string(v1.RuntimeProviderQuarkus),
+                       },
+               },
+               Status: v1.IntegrationKitStatus{
+                       Phase:           v1.IntegrationKitPhaseBuildRunning,
+                       RuntimeVersion:  "1.2.3",
+                       RuntimeProvider: v1.RuntimeProviderQuarkus,
+               },
+       }
+       it := &v1.Integration{
+               TypeMeta: metav1.TypeMeta{
+                       APIVersion: v1.SchemeGroupVersion.String(),
+                       Kind:       v1.IntegrationKind,
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Namespace: "ns",
+                       Name:      "my-it",
+               },
+               Status: v1.IntegrationStatus{
+                       Phase:           v1.IntegrationPhaseBuildingKit,
+                       RuntimeVersion:  defaults.DefaultRuntimeVersion,
+                       RuntimeProvider: v1.RuntimeProviderQuarkus,
+               },
+       }
+       hash, err := digest.ComputeForIntegration(it, nil, nil)
+       require.NoError(t, err)
+       it.Status.Digest = hash
+       c, err := test.NewFakeClient(it, ik, ip, catalog)
+       require.NoError(t, err)
+
+       a := buildKitAction{}
+       a.InjectLogger(log.Log)
+       a.InjectClient(c)
+       assert.Equal(t, "build-kit", a.Name())
+       assert.True(t, a.CanHandle(it))
+       handledIt, err := a.Handle(context.TODO(), it)
+       require.NoError(t, err)
+       // No matching kit found
+       assert.Equal(t, v1.IntegrationPhaseBuildingKit, handledIt.Status.Phase)
+       assert.NotEqual(t, ik.Name, it.Status.IntegrationKit.Name)
+       newKit := v1.NewIntegrationKit(it.Status.IntegrationKit.Namespace, 
it.Status.IntegrationKit.Name)
+       err = c.Get(context.TODO(), types.NamespacedName{Namespace: 
newKit.Namespace, Name: newKit.Name}, newKit)
+       assert.NoError(t, err)
+       assert.Equal(t, it.Status.RuntimeVersion, 
newKit.Labels[kubernetes.CamelLabelRuntimeVersion])
+       assert.Equal(t, string(it.Status.RuntimeProvider), 
newKit.Labels[kubernetes.CamelLabelRuntimeProvider])
+       assert.Equal(t, v1.IntegrationKind, 
newKit.Labels[kubernetes.CamelCreatorLabelKind])
+       assert.Equal(t, it.Name, 
newKit.Labels[kubernetes.CamelCreatorLabelName])
+       assert.Equal(t, it.Namespace, 
newKit.Labels[kubernetes.CamelCreatorLabelNamespace])
+       assert.Equal(t, v1.IntegrationKitPhase(""), newKit.Status.Phase)
+}
diff --git a/pkg/controller/integration/initialize.go 
b/pkg/controller/integration/initialize.go
index 3f40fac9b..b0ec6e74d 100644
--- a/pkg/controller/integration/initialize.go
+++ b/pkg/controller/integration/initialize.go
@@ -65,6 +65,11 @@ func (action *initializeAction) Handle(ctx context.Context, 
integration *v1.Inte
                return integration, err
        }
 
+       if integration.Status.Image != "" {
+               integration.Status.Phase = v1.IntegrationPhaseDeploying
+               return integration, nil
+       }
+
        if integration.Status.IntegrationKit == nil {
                ikt, err := action.lookupIntegrationKit(ctx, integration)
                if err != nil {
diff --git a/pkg/controller/integration/kits.go 
b/pkg/controller/integration/kits.go
index 9832139fa..341f795e3 100644
--- a/pkg/controller/integration/kits.go
+++ b/pkg/controller/integration/kits.go
@@ -32,6 +32,7 @@ import (
        "github.com/apache/camel-k/v2/pkg/trait"
        "github.com/apache/camel-k/v2/pkg/util"
        "github.com/apache/camel-k/v2/pkg/util/defaults"
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
        "github.com/apache/camel-k/v2/pkg/util/log"
 )
 
@@ -52,8 +53,8 @@ func lookupKitsForIntegration(ctx context.Context, c 
client.Client, integration
        listOptions := []ctrl.ListOption{
                ctrl.InNamespace(integration.GetIntegrationKitNamespace(pl)),
                ctrl.MatchingLabels{
-                       "camel.apache.org/runtime.version":  
integration.Status.RuntimeVersion,
-                       "camel.apache.org/runtime.provider": 
string(integration.Status.RuntimeProvider),
+                       kubernetes.CamelLabelRuntimeVersion:  
integration.Status.RuntimeVersion,
+                       kubernetes.CamelLabelRuntimeProvider: 
string(integration.Status.RuntimeProvider),
                },
                ctrl.MatchingLabelsSelector{
                        Selector: labels.NewSelector().Add(*kitTypes),
@@ -150,10 +151,6 @@ func integrationMatches(ctx context.Context, c 
client.Client, integration *v1.In
 }
 
 func statusMatches(integration *v1.Integration, kit *v1.IntegrationKit, ilog 
*log.Logger) bool {
-       if kit.Status.Version != integration.Status.Version {
-               ilog.Debug("Integration and integration-kit versions do not 
match", "integration", integration.Name, "integration-kit", kit.Name, 
"namespace", integration.Namespace)
-               return false
-       }
        if kit.Status.RuntimeProvider != integration.Status.RuntimeProvider {
                ilog.Debug("Integration and integration-kit runtime providers 
do not match", "integration", integration.Name, "integration-kit", kit.Name, 
"namespace", integration.Namespace)
                return false
@@ -164,6 +161,7 @@ func statusMatches(integration *v1.Integration, kit 
*v1.IntegrationKit, ilog *lo
        }
        if len(integration.Status.Dependencies) != len(kit.Spec.Dependencies) {
                ilog.Debug("Integration and integration-kit have different 
number of dependencies", "integration", integration.Name, "integration-kit", 
kit.Name, "namespace", integration.Namespace)
+               return false
        }
 
        return true
@@ -171,12 +169,12 @@ func statusMatches(integration *v1.Integration, kit 
*v1.IntegrationKit, ilog *lo
 
 // kitMatches returns whether the kit matches with the existing target kit.
 func kitMatches(c client.Client, kit *v1.IntegrationKit, target 
*v1.IntegrationKit) (bool, error) {
-       version := kit.Status.Version
+       version := kit.Status.RuntimeVersion
        if version == "" {
                // Defaults with the version that is going to be set during the 
kit initialization
-               version = defaults.Version
+               version = defaults.DefaultRuntimeVersion
        }
-       if version != target.Status.Version {
+       if version != target.Status.RuntimeVersion {
                return false, nil
        }
        if len(kit.Spec.Dependencies) != len(target.Spec.Dependencies) {
diff --git a/pkg/controller/integration/monitor.go 
b/pkg/controller/integration/monitor.go
index 6342269b0..f82e8a13e 100644
--- a/pkg/controller/integration/monitor.go
+++ b/pkg/controller/integration/monitor.go
@@ -73,22 +73,26 @@ func (action *monitorAction) Handle(ctx context.Context, 
integration *v1.Integra
                return action.checkDigestAndRebuild(ctx, integration, nil)
        }
 
-       // At this stage the Integration must have a Kit
-       if integration.Status.IntegrationKit == nil {
-               return nil, fmt.Errorf("no kit set on integration %s", 
integration.Name)
+       var kit *v1.IntegrationKit
+       var err error
+       if integration.Status.IntegrationKit == nil && integration.Status.Image 
== "" {
+               return nil, fmt.Errorf("no kit nor container image set on 
integration %s", integration.Name)
        }
 
-       kit, err := kubernetes.GetIntegrationKit(ctx, action.client,
-               integration.Status.IntegrationKit.Name, 
integration.Status.IntegrationKit.Namespace)
-       if err != nil {
-               return nil, fmt.Errorf("unable to find integration kit %s/%s: 
%w",
-                       integration.Status.IntegrationKit.Namespace, 
integration.Status.IntegrationKit.Name, err)
-       }
+       if integration.Status.IntegrationKit != nil {
+               // Managed Integration
+               kit, err = kubernetes.GetIntegrationKit(ctx, action.client,
+                       integration.Status.IntegrationKit.Name, 
integration.Status.IntegrationKit.Namespace)
+               if err != nil {
+                       return nil, fmt.Errorf("unable to find integration kit 
%s/%s: %w",
+                               integration.Status.IntegrationKit.Namespace, 
integration.Status.IntegrationKit.Name, err)
+               }
 
-       // If integration is in error and its kit is also in error then 
integration does not change
-       if isInIntegrationKitFailed(integration.Status) &&
-               kit.Status.Phase == v1.IntegrationKitPhaseError {
-               return nil, nil
+               // If integration is in error and its kit is also in error then 
integration does not change
+               if isInIntegrationKitFailed(integration.Status) &&
+                       kit.Status.Phase == v1.IntegrationKitPhaseError {
+                       return nil, nil
+               }
        }
 
        // Check if the Integration requires a rebuild
@@ -98,31 +102,32 @@ func (action *monitorAction) Handle(ctx context.Context, 
integration *v1.Integra
                return changed, nil
        }
 
-       // Check if an IntegrationKit with higher priority is ready
-       priority, ok := kit.Labels[v1.IntegrationKitPriorityLabel]
-       if !ok {
-               priority = "0"
-       }
-       withHigherPriority, err := 
labels.NewRequirement(v1.IntegrationKitPriorityLabel,
-               selection.GreaterThan, []string{priority})
-       if err != nil {
-               return nil, err
-       }
+       if kit != nil {
+               // Check if an IntegrationKit with higher priority is ready
+               priority, ok := kit.Labels[v1.IntegrationKitPriorityLabel]
+               if !ok {
+                       priority = "0"
+               }
+               withHigherPriority, err := 
labels.NewRequirement(v1.IntegrationKitPriorityLabel,
+                       selection.GreaterThan, []string{priority})
+               if err != nil {
+                       return nil, err
+               }
 
-       kits, err := lookupKitsForIntegration(ctx, action.client, integration, 
ctrl.MatchingLabelsSelector{
-               Selector: labels.NewSelector().Add(*withHigherPriority),
-       })
-       if err != nil {
-               return nil, err
-       }
-       priorityReadyKit, err := findHighestPriorityReadyKit(kits)
-       if err != nil {
-               return nil, err
-       }
-       if priorityReadyKit != nil {
-               integration.SetIntegrationKit(priorityReadyKit)
+               kits, err := lookupKitsForIntegration(ctx, action.client, 
integration, ctrl.MatchingLabelsSelector{
+                       Selector: labels.NewSelector().Add(*withHigherPriority),
+               })
+               if err != nil {
+                       return nil, err
+               }
+               priorityReadyKit, err := findHighestPriorityReadyKit(kits)
+               if err != nil {
+                       return nil, err
+               }
+               if priorityReadyKit != nil {
+                       integration.SetIntegrationKit(priorityReadyKit)
+               }
        }
-
        // Run traits that are enabled for the phase
        environment, err := trait.Apply(ctx, action.client, integration, kit)
        if err != nil {
diff --git a/pkg/controller/integrationkit/monitor.go 
b/pkg/controller/integrationkit/monitor.go
index 7a71d9a76..a574bb944 100644
--- a/pkg/controller/integrationkit/monitor.go
+++ b/pkg/controller/integrationkit/monitor.go
@@ -46,7 +46,18 @@ func (action *monitorAction) CanHandle(kit 
*v1.IntegrationKit) bool {
 func (action *monitorAction) Handle(ctx context.Context, kit 
*v1.IntegrationKit) (*v1.IntegrationKit, error) {
        if kit.IsExternal() || kit.IsSynthetic() {
                // do nothing, it's not a managed kit
-               return nil, nil
+               // if it's a syntetic Kit add a condition to warn this is a
+               // deprecated feature which may be removed soon.
+               if kit.IsSynthetic() {
+                       kit.Status.SetCondition(
+                               
v1.IntegrationKitConditionType("SyntheticKitDeprecated"),
+                               corev1.ConditionTrue,
+                               "DeprecationNotice",
+                               "Synthetic IntegrationKit feature is deprecated 
and will be removed soon.",
+                       )
+                       action.L.Infof("WARN: Synthetic IntegrationKit feature 
is deprecated and will be removed soon.")
+               }
+               return kit, nil
        }
        hash, err := digest.ComputeForIntegrationKit(kit)
        if err != nil {
diff --git a/pkg/trait/camel.go b/pkg/trait/camel.go
index 093d81767..0d585a3e6 100644
--- a/pkg/trait/camel.go
+++ b/pkg/trait/camel.go
@@ -78,7 +78,7 @@ func (t *camelTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
        }
 
        var cond *TraitCondition
-       if e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic() {
+       if (e.Integration != nil && !e.Integration.IsManagedBuild()) || 
(e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic()) {
                // We set a condition to warn the user the catalog used to run 
the Integration
                // may differ from the runtime version which we don't control
                cond = NewIntegrationCondition(
@@ -97,6 +97,9 @@ func (t *camelTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
 }
 
 func (t *camelTrait) Apply(e *Environment) error {
+       // This is an important action to do as most of the traits
+       // expects a CamelCatalog to be loaded regardless it's a managed or
+       // non managed build Integration
        if e.CamelCatalog == nil {
                if err := t.loadOrCreateCatalog(e, t.RuntimeVersion); err != 
nil {
                        return err
@@ -104,31 +107,28 @@ func (t *camelTrait) Apply(e *Environment) error {
        }
 
        if e.Integration != nil {
-               e.Integration.Status.RuntimeVersion = 
e.CamelCatalog.Runtime.Version
-               e.Integration.Status.RuntimeProvider = 
e.CamelCatalog.Runtime.Provider
+               if e.Integration.IsManagedBuild() {
+                       // If it's not managed we don't know which is the 
runtime running
+                       e.Integration.Status.RuntimeVersion = 
e.CamelCatalog.Runtime.Version
+                       e.Integration.Status.RuntimeProvider = 
e.CamelCatalog.Runtime.Provider
+               }
                e.Integration.Status.Catalog = &v1.Catalog{
                        Version:  e.CamelCatalog.Runtime.Version,
                        Provider: e.CamelCatalog.Runtime.Provider,
                }
        }
        if e.IntegrationKit != nil {
-               e.IntegrationKit.Status.RuntimeVersion = 
e.CamelCatalog.Runtime.Version
-               e.IntegrationKit.Status.RuntimeProvider = 
e.CamelCatalog.Runtime.Provider
+               if !e.IntegrationKit.IsSynthetic() {
+                       e.IntegrationKit.Status.RuntimeVersion = 
e.CamelCatalog.Runtime.Version
+                       e.IntegrationKit.Status.RuntimeProvider = 
e.CamelCatalog.Runtime.Provider
+               }
                e.IntegrationKit.Status.Catalog = &v1.Catalog{
                        Version:  e.CamelCatalog.Runtime.Version,
                        Provider: e.CamelCatalog.Runtime.Provider,
                }
        }
 
-       if e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic() {
-               // Synthetic Integration Kit
-               e.Integration.Status.RuntimeVersion = ""
-               e.Integration.Status.RuntimeProvider = ""
-               e.IntegrationKit.Status.RuntimeVersion = ""
-               e.IntegrationKit.Status.RuntimeProvider = ""
-       }
-
-       if e.IntegrationKitInPhase(v1.IntegrationKitPhaseReady) && 
e.IntegrationInRunningPhases() {
+       if e.IntegrationInRunningPhases() {
                // Get all resources
                maps := t.computeConfigMaps(e)
                e.Resources.AddAll(maps)
diff --git a/pkg/trait/camel_test.go b/pkg/trait/camel_test.go
index 531e725e3..0513ebe9c 100644
--- a/pkg/trait/camel_test.go
+++ b/pkg/trait/camel_test.go
@@ -69,9 +69,11 @@ func TestApplyCamelTraitSucceeds(t *testing.T) {
        assert.False(t, exactVersionRegexp.MatchString("wroong"))
 }
 
-func TestApplyCamelTraitExternalKit(t *testing.T) {
+func TestApplyCamelTraitNonManagedBuild(t *testing.T) {
        trait, environment := createNominalCamelTest(false)
-       environment.IntegrationKit.Labels[v1.IntegrationKitTypeLabel] = 
v1.IntegrationKitTypeSynthetic
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
 
        configured, condition, err := trait.Configure(environment)
        require.NoError(t, err)
@@ -91,11 +93,8 @@ func TestApplyCamelTraitExternalKit(t *testing.T) {
        require.NoError(t, err)
        assert.Equal(t, "", environment.Integration.Status.RuntimeVersion)
        assert.Equal(t, v1.RuntimeProvider(""), 
environment.Integration.Status.RuntimeProvider)
-       assert.Equal(t, "", environment.IntegrationKit.Status.RuntimeVersion)
-       assert.Equal(t, v1.RuntimeProvider(""), 
environment.Integration.Status.RuntimeProvider)
        expectedCatalog := &v1.Catalog{Version: "0.0.1", Provider: 
v1.RuntimeProviderQuarkus}
        assert.Equal(t, expectedCatalog, environment.Integration.Status.Catalog)
-       assert.Equal(t, expectedCatalog, 
environment.IntegrationKit.Status.Catalog)
 }
 
 func TestApplyCamelTraitWithoutEnvironmentCatalogAndUnmatchableVersionFails(t 
*testing.T) {
@@ -176,8 +175,7 @@ func createNominalCamelTest(withSources bool) (*camelTrait, 
*Environment) {
                                Sources: sources,
                        },
                        Status: v1.IntegrationStatus{
-                               RuntimeVersion: "0.0.1",
-                               Phase:          v1.IntegrationPhaseDeploying,
+                               Phase: v1.IntegrationPhaseDeploying,
                        },
                },
                IntegrationKit: &v1.IntegrationKit{
@@ -195,6 +193,14 @@ func createNominalCamelTest(withSources bool) 
(*camelTrait, *Environment) {
                        ObjectMeta: metav1.ObjectMeta{
                                Namespace: "namespace",
                        },
+                       Status: v1.IntegrationPlatformStatus{
+                               IntegrationPlatformSpec: 
v1.IntegrationPlatformSpec{
+                                       Build: v1.IntegrationPlatformBuildSpec{
+                                               RuntimeProvider: 
v1.RuntimeProviderQuarkus,
+                                               RuntimeVersion:  "0.0.1",
+                                       },
+                               },
+                       },
                },
                Resources:             kubernetes.NewCollection(),
                ApplicationProperties: make(map[string]string),
@@ -224,10 +230,12 @@ func TestApplyCamelTraitWithProperties(t *testing.T) {
        }, userPropertiesCm.Data)
 }
 
-func TestApplyCamelTraitSyntheticKitWithProperties(t *testing.T) {
+func TestApplyCamelTraitNonManagedBuildWithProperties(t *testing.T) {
        trait, environment := createNominalCamelTest(false)
        trait.Properties = []string{"a=b", "c=d"}
-       environment.IntegrationKit.Labels[v1.IntegrationKitTypeLabel] = 
v1.IntegrationKitTypeSynthetic
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
 
        configured, condition, err := trait.Configure(environment)
        require.NoError(t, err)
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 4b4c05944..80c116991 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -33,7 +33,6 @@ import (
        traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
        "github.com/apache/camel-k/v2/pkg/util"
        "github.com/apache/camel-k/v2/pkg/util/camel"
-       "github.com/apache/camel-k/v2/pkg/util/defaults"
        "github.com/apache/camel-k/v2/pkg/util/digest"
        "github.com/apache/camel-k/v2/pkg/util/envvar"
        "github.com/apache/camel-k/v2/pkg/util/kubernetes"
@@ -129,43 +128,7 @@ func (t *containerTrait) configureImageIntegrationKit(e 
*Environment) error {
                        e.Integration.Spec.IntegrationKit)
        }
 
-       kitName := fmt.Sprintf("kit-%s", e.Integration.Name)
-       kit := v1.NewIntegrationKit(e.Integration.Namespace, kitName)
-       kit.Spec.Image = t.Image
-
-       // Add some information for post-processing, this may need to be 
refactored
-       // to a proper data structure
-       kit.Labels = map[string]string{
-               v1.IntegrationKitTypeLabel:            
v1.IntegrationKitTypeSynthetic,
-               kubernetes.CamelCreatorLabelKind:      v1.IntegrationKind,
-               kubernetes.CamelCreatorLabelName:      e.Integration.Name,
-               kubernetes.CamelCreatorLabelNamespace: e.Integration.Namespace,
-               kubernetes.CamelCreatorLabelVersion:   
e.Integration.ResourceVersion,
-       }
-
-       if v, ok := e.Integration.Annotations[v1.PlatformSelectorAnnotation]; 
ok {
-               v1.SetAnnotation(&kit.ObjectMeta, 
v1.PlatformSelectorAnnotation, v)
-       }
-
-       if v, ok := e.Integration.Annotations[v1.IntegrationProfileAnnotation]; 
ok {
-               v1.SetAnnotation(&kit.ObjectMeta, 
v1.IntegrationProfileAnnotation, v)
-
-               if v, ok := 
e.Integration.Annotations[v1.IntegrationProfileNamespaceAnnotation]; ok {
-                       v1.SetAnnotation(&kit.ObjectMeta, 
v1.IntegrationProfileNamespaceAnnotation, v)
-               } else {
-                       // set integration profile namespace to the integration 
namespace.
-                       // this is because the kit may live in another 
namespace and needs to resolve the integration profile from the integration 
namespace.
-                       v1.SetAnnotation(&kit.ObjectMeta, 
v1.IntegrationProfileNamespaceAnnotation, e.Integration.Namespace)
-               }
-       }
-
-       operatorID := defaults.OperatorID()
-       if operatorID != "" {
-               kit.SetOperatorID(operatorID)
-       }
-
-       e.Resources.Add(kit)
-       e.Integration.SetIntegrationKit(kit)
+       e.Integration.Status.Image = t.Image
 
        return nil
 }
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index 604b25d9d..80a60efcf 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -32,8 +32,6 @@ import (
        "k8s.io/apimachinery/pkg/types"
        "k8s.io/utils/ptr"
 
-       ctrl "sigs.k8s.io/controller-runtime/pkg/client"
-
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
        traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
        "github.com/apache/camel-k/v2/pkg/util/camel"
@@ -315,20 +313,8 @@ func TestContainerWithCustomImage(t *testing.T) {
        assert.NotEmpty(t, environment.ExecutedTraits)
        assert.NotNil(t, environment.GetTrait("deployer"))
        assert.NotNil(t, environment.GetTrait("container"))
-       assert.Equal(t, "kit-"+ServiceTestName, 
environment.Integration.Status.IntegrationKit.Name)
-
-       ikt := v1.IntegrationKit{}
-       key := ctrl.ObjectKey{
-               Namespace: "ns",
-               Name:      "kit-" + ServiceTestName,
-       }
-
-       err = client.Get(context.TODO(), key, &ikt)
-       require.NoError(t, err)
-       assert.Equal(t, environment.Integration.ObjectMeta.UID, 
ikt.ObjectMeta.OwnerReferences[0].UID)
-
-       trait := environment.Integration.Spec.Traits.Container
-       assert.Equal(t, trait.Image, ikt.Spec.Image)
+       assert.Nil(t, environment.Integration.Status.IntegrationKit)
+       assert.Equal(t, environment.Integration.Spec.Traits.Container.Image, 
environment.Integration.Status.Image)
 }
 
 func TestContainerWithCustomImageAndIntegrationKit(t *testing.T) {
@@ -386,7 +372,7 @@ func TestContainerWithCustomImageAndIntegrationKit(t 
*testing.T) {
 
        conditions, err := traitCatalog.apply(&environment)
        require.Error(t, err)
-       assert.Empty(t, conditions)
+       assert.NotEmpty(t, conditions)
        assert.Contains(t, err.Error(), "unsupported configuration: a container 
image has been set in conjunction with an IntegrationKit")
 }
 
diff --git a/pkg/trait/cron.go b/pkg/trait/cron.go
index b86216041..7fbb35d9e 100644
--- a/pkg/trait/cron.go
+++ b/pkg/trait/cron.go
@@ -321,9 +321,6 @@ func (c *cronInfo) withSchedule(schedule string) *cronInfo {
 }
 
 func (t *cronTrait) getGlobalCron(e *Environment) (*cronInfo, error) {
-       if e.CamelCatalog == nil {
-               return nil, nil
-       }
        fromURIs, err := t.getSourcesFromURIs(e)
        if err != nil {
                return nil, err
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 3b43191ba..a123f00da 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -28,7 +28,6 @@ import (
        "k8s.io/apimachinery/pkg/api/resource"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/utils/ptr"
-
        ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
@@ -81,7 +80,8 @@ func (t *jvmTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
                }
        }
 
-       if e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic() && t.Jar 
== "" {
+       if ((e.Integration != nil && !e.Integration.IsManagedBuild()) || 
(e.IntegrationKit != nil && e.IntegrationKit.IsSynthetic())) &&
+               t.Jar == "" {
                // We skip this trait since we cannot make any assumption on 
the container Java tooling running
                // for the synthetic IntegrationKit
                return false, 
NewIntegrationConditionPlatformDisabledWithMessage(
@@ -94,25 +94,6 @@ func (t *jvmTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
 }
 
 func (t *jvmTrait) Apply(e *Environment) error {
-       kit := e.IntegrationKit
-
-       if kit == nil && e.Integration.Status.IntegrationKit != nil {
-               name := e.Integration.Status.IntegrationKit.Name
-               ns := e.Integration.GetIntegrationKitNamespace(e.Platform)
-               k := v1.NewIntegrationKit(ns, name)
-               if err := t.Client.Get(e.Ctx, ctrl.ObjectKeyFromObject(k), k); 
err != nil {
-                       return fmt.Errorf("unable to find integration kit 
%s/%s: %w", ns, name, err)
-               }
-               kit = k
-       }
-
-       if kit == nil {
-               if e.Integration.Status.IntegrationKit != nil {
-                       return fmt.Errorf("unable to find integration kit 
%s/%s", e.Integration.GetIntegrationKitNamespace(e.Platform), 
e.Integration.Status.IntegrationKit.Name)
-               }
-               return fmt.Errorf("unable to find integration kit for 
integration %s", e.Integration.Name)
-       }
-
        container := e.GetIntegrationContainer()
        if container == nil {
                return fmt.Errorf("unable to find a container for %s 
Integration", e.Integration.Name)
@@ -169,8 +150,9 @@ func (t *jvmTrait) Apply(e *Environment) error {
                args = append(args, "-cp", strings.Join(classpathItems, ":"))
                args = append(args, "-jar", t.Jar)
        } else {
-               if e.CamelCatalog == nil {
-                       return fmt.Errorf("cannot execute trait: missing Camel 
catalog")
+               kit, err := t.getIntegrationKit(e)
+               if err != nil {
+                       return err
                }
                kitDepsDirs := kit.Status.GetDependenciesPaths()
                if len(kitDepsDirs) == 0 {
@@ -186,6 +168,33 @@ func (t *jvmTrait) Apply(e *Environment) error {
        return nil
 }
 
+func (t *jvmTrait) getIntegrationKit(e *Environment) (*v1.IntegrationKit, 
error) {
+       kit := e.IntegrationKit
+
+       if kit == nil && e.Integration.Status.IntegrationKit != nil {
+               name := e.Integration.Status.IntegrationKit.Name
+               ns := e.Integration.GetIntegrationKitNamespace(e.Platform)
+               k := v1.NewIntegrationKit(ns, name)
+               if err := t.Client.Get(e.Ctx, ctrl.ObjectKeyFromObject(k), k); 
err != nil {
+                       return nil, fmt.Errorf("unable to find integration kit 
%s/%s: %w", ns, name, err)
+               }
+               kit = k
+       }
+
+       if kit == nil {
+               if e.Integration.Status.IntegrationKit != nil {
+                       return nil, fmt.Errorf(
+                               "unable to find integration kit %s/%s",
+                               
e.Integration.GetIntegrationKitNamespace(e.Platform),
+                               e.Integration.Status.IntegrationKit.Name,
+                       )
+               }
+               return nil, fmt.Errorf("unable to find integration kit for 
integration %s", e.Integration.Name)
+       }
+
+       return kit, nil
+}
+
 func (t *jvmTrait) enableDebug(e *Environment) string {
        suspend := "n"
        if ptr.Deref(t.DebugSuspend, false) {
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index fab68efc2..dff67c63e 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -20,10 +20,10 @@ package trait
 import (
        "fmt"
        "path/filepath"
-       "strings"
        "testing"
 
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
        "github.com/apache/camel-k/v2/pkg/util/camel"
        "github.com/apache/camel-k/v2/pkg/util/kubernetes"
        "github.com/apache/camel-k/v2/pkg/util/test"
@@ -92,7 +92,9 @@ func TestConfigureJvmTraitInWrongJvmDisabled(t *testing.T) {
 
 func TestConfigureJvmTraitExecutableSourcelessContainer(t *testing.T) {
        trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypePlatform)
-       environment.IntegrationKit.Labels[v1.IntegrationKitTypeLabel] = 
v1.IntegrationKitTypeSynthetic
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
 
        configured, condition, err := trait.Configure(environment)
        require.NoError(t, err)
@@ -105,7 +107,9 @@ func TestConfigureJvmTraitExecutableSourcelessContainer(t 
*testing.T) {
 
 func TestConfigureJvmTraitExecutableSourcelessContainerWithJar(t *testing.T) {
        trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypePlatform)
-       environment.IntegrationKit.Labels[v1.IntegrationKitTypeLabel] = 
v1.IntegrationKitTypeSynthetic
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
        trait.Jar = "my-path/to/my-app.jar"
 
        d := appsv1.Deployment{
@@ -140,7 +144,9 @@ func 
TestConfigureJvmTraitExecutableSourcelessContainerWithJar(t *testing.T) {
 
 func TestConfigureJvmTraitExecutableSourcelessContainerWithJarAndOptions(t 
*testing.T) {
        trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypePlatform)
-       environment.IntegrationKit.Labels[v1.IntegrationKitTypeLabel] = 
v1.IntegrationKitTypeSynthetic
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
        trait.Jar = "my-path/to/my-app.jar"
        // Add some additional JVM configurations
        trait.Classpath = "deps/a.jar:deps/b.jar"
@@ -254,8 +260,10 @@ func TestConfigureJvmTraitWithJarAndConfigs(t *testing.T) {
 }
 
 func TestConfigureJvmTraitInWrongIntegrationKitPhaseExternal(t *testing.T) {
-       trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypeSynthetic)
-
+       trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypePlatform)
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
        expectedCondition := NewIntegrationCondition(
                "JVM",
                v1.IntegrationConditionTraitInfo,
@@ -494,12 +502,13 @@ func 
TestApplyJvmTraitWithClasspathAndExistingContainerCPArg(t *testing.T) {
 
 func TestApplyJvmTraitKitMissing(t *testing.T) {
        trait, environment := 
createNominalJvmTest(v1.IntegrationKitTypePlatform)
-       environment.IntegrationKit = nil
-
+       environment.Integration.Spec.Traits.Container = &traitv1.ContainerTrait{
+               Image: "my-image",
+       }
        err := trait.Apply(environment)
 
        require.Error(t, err)
-       assert.True(t, strings.HasPrefix(err.Error(), "unable to find 
integration kit"))
+       assert.Equal(t, "unable to find a container for my-it Integration", 
err.Error())
 }
 
 func TestApplyJvmTraitContainerResourceArgs(t *testing.T) {
@@ -592,6 +601,10 @@ func createNominalJvmTest(kitType string) (*jvmTrait, 
*Environment) {
                Catalog:      NewCatalog(nil),
                CamelCatalog: catalog,
                Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Namespace: "kit-namespace",
+                               Name:      "my-it",
+                       },
                        Status: v1.IntegrationStatus{
                                Phase: v1.IntegrationPhaseDeploying,
                        },
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
index b161ee6fb..748edaac5 100644
--- a/pkg/trait/quarkus.go
+++ b/pkg/trait/quarkus.go
@@ -248,8 +248,8 @@ func (t *quarkusTrait) newIntegrationKit(e *Environment, 
packageType quarkusPack
 
        kit.Labels = map[string]string{
                v1.IntegrationKitTypeLabel:            
v1.IntegrationKitTypePlatform,
-               "camel.apache.org/runtime.version":    
integration.Status.RuntimeVersion,
-               "camel.apache.org/runtime.provider":   
string(integration.Status.RuntimeProvider),
+               kubernetes.CamelLabelRuntimeVersion:   
integration.Status.RuntimeVersion,
+               kubernetes.CamelLabelRuntimeProvider:  
string(integration.Status.RuntimeProvider),
                v1.IntegrationKitLayoutLabel:          string(packageType),
                v1.IntegrationKitPriorityLabel:        kitPriority[packageType],
                kubernetes.CamelCreatorLabelKind:      v1.IntegrationKind,
@@ -447,7 +447,8 @@ func (t *quarkusTrait) applyWhenKitReady(e *Environment) 
error {
 
 func (t *quarkusTrait) isNativeIntegration(e *Environment) bool {
        // The current IntegrationKit determines the Integration runtime type
-       return e.IntegrationKit.Labels[v1.IntegrationKitLayoutLabel] == 
v1.IntegrationKitLayoutNativeSources
+       return e.IntegrationKit != nil &&
+               e.IntegrationKit.Labels[v1.IntegrationKitLayoutLabel] == 
v1.IntegrationKitLayoutNativeSources
 }
 
 // Indicates whether the given source code is embedded into the final binary.
diff --git a/pkg/trait/trait_types_test.go b/pkg/trait/trait_types_test.go
index 50146584f..8f945397f 100644
--- a/pkg/trait/trait_types_test.go
+++ b/pkg/trait/trait_types_test.go
@@ -183,21 +183,19 @@ func TestDetermineControllerStrategyAutoKnative(t 
*testing.T) {
 }
 
 func TestDetermineControllerStrategySyntheticKitDefault(t *testing.T) {
-       e := createSyntethicKitTestEnvironment(t, v1.TraitProfileKnative)
+       e := createNonManagedBuildTestEnvironment(t, v1.TraitProfileKnative)
        strategy, err := e.DetermineControllerStrategy()
        require.NoError(t, err)
        assert.Equal(t, DefaultControllerStrategy, strategy)
 }
 
 func TestDetermineControllerStrategySyntheticKitForceKnative(t *testing.T) {
-       e := createSyntethicKitTestEnvironment(t, v1.TraitProfileKnative)
-       e.Integration.Spec.Traits = v1.Traits{
-               KnativeService: &trait.KnativeServiceTrait{
-                       Trait: trait.Trait{
-                               Enabled: ptr.To(true),
-                       },
-                       Auto: ptr.To(false),
+       e := createNonManagedBuildTestEnvironment(t, v1.TraitProfileKnative)
+       e.Integration.Spec.Traits.KnativeService = &trait.KnativeServiceTrait{
+               Trait: trait.Trait{
+                       Enabled: ptr.To(true),
                },
+               Auto: ptr.To(false),
        }
        e.Platform.ResyncStatusFullConfig()
        _, err := e.Catalog.apply(e)
@@ -278,7 +276,7 @@ func createTestEnvironment(t *testing.T, profile 
v1.TraitProfile) *Environment {
        return environment
 }
 
-func createSyntethicKitTestEnvironment(t *testing.T, profile v1.TraitProfile) 
*Environment {
+func createNonManagedBuildTestEnvironment(t *testing.T, profile 
v1.TraitProfile) *Environment {
        t.Helper()
        client, _ := test.NewFakeClient()
        traitCatalog := NewCatalog(nil)
@@ -301,17 +299,12 @@ func createSyntethicKitTestEnvironment(t *testing.T, 
profile v1.TraitProfile) *E
                        },
                        Spec: v1.IntegrationSpec{
                                Profile: profile,
-                       },
-               },
-               IntegrationKit: &v1.IntegrationKit{
-                       ObjectMeta: metav1.ObjectMeta{
-                               Labels: map[string]string{
-                                       v1.IntegrationKitTypeLabel: 
v1.IntegrationKitTypeSynthetic,
+                               Traits: v1.Traits{
+                                       Container: &trait.ContainerTrait{
+                                               Image: "my-container-image",
+                                       },
                                },
                        },
-                       Status: v1.IntegrationKitStatus{
-                               Phase: v1.IntegrationKitPhaseReady,
-                       },
                },
                Platform: &v1.IntegrationPlatform{
                        Spec: v1.IntegrationPlatformSpec{
diff --git a/pkg/util/camel/camel_runtime.go b/pkg/util/camel/camel_runtime.go
index 412875783..063a30a22 100644
--- a/pkg/util/camel/camel_runtime.go
+++ b/pkg/util/camel/camel_runtime.go
@@ -47,8 +47,8 @@ func CreateCatalog(ctx context.Context, client client.Client, 
namespace string,
        cx := v1.NewCamelCatalogWithSpecs(namespace, catalogName, 
catalog.CamelCatalogSpec)
        cx.Labels = make(map[string]string)
        cx.Labels["app"] = "camel-k"
-       cx.Labels["camel.apache.org/runtime.version"] = runtime.Version
-       cx.Labels["camel.apache.org/runtime.provider"] = 
string(runtime.Provider)
+       cx.Labels[kubernetes.CamelLabelRuntimeVersion] = runtime.Version
+       cx.Labels[kubernetes.CamelLabelRuntimeProvider] = 
string(runtime.Provider)
        cx.Labels["camel.apache.org/catalog.generated"] = "true"
 
        if err := client.Create(ctx, &cx); err != nil {
diff --git a/pkg/util/kubernetes/camel.go b/pkg/util/kubernetes/camel.go
index c7bf020a1..c2df72262 100644
--- a/pkg/util/kubernetes/camel.go
+++ b/pkg/util/kubernetes/camel.go
@@ -40,6 +40,9 @@ const (
        CamelClonedLabelName      = CamelClonedLabelPrefix + ".name"
        CamelClonedLabelNamespace = CamelClonedLabelPrefix + ".namespace"
        CamelClonedLabelVersion   = CamelClonedLabelPrefix + ".version"
+
+       CamelLabelRuntimeVersion  = "camel.apache.org/runtime.version"
+       CamelLabelRuntimeProvider = "camel.apache.org/runtime.provider"
 )
 
 // FilterCamelCreatorLabels is used to inherit the creator information among 
resources.

Reply via email to