From 693563627f5f030f3956f3de340bca8a97c355c0 Mon Sep 17 00:00:00 2001 From: Pasquale Congiusti Date: Wed, 28 Aug 2024 15:19:12 +0200 Subject: [PATCH] feat(api): Kit-less Integration Closes #2365 --- addons/telemetry/telemetry.go | 4 - .../camel/v1/integration_types_support.go | 5 + pkg/apis/camel/v1/integrationkit_types.go | 1 + .../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(-) create mode 100644 pkg/controller/integration/build_kit_test.go diff --git a/addons/telemetry/telemetry.go b/addons/telemetry/telemetry.go index 07908c13fc..5fae672324 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 ca0de0626f..dec40102f9 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 3d2d703319..84f3b1fc8c 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 b6b70624db..ed8595c3dd 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 af79056ae1..deaf0eaf34 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 0014c48dc6..51c3b786cc 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 0000000000..1278a6423c --- /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 3f40fac9b1..b0ec6e74dd 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 9832139fa7..341f795e3e 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 6342269b0d..f82e8a13e6 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 7a71d9a76c..a574bb9448 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 093d81767e..0d585a3e6b 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 531e725e35..0513ebe9c7 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 4b4c059443..80c116991d 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 604b25d9d3..80a60efcf4 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 b86216041f..7fbb35d9ea 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 3b43191ba2..a123f00daf 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 fab68efc23..dff67c63ed 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 b161ee6fb0..748edaac5c 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 50146584fe..8f945397f8 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 4128757838..063a30a226 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 c7bf020a19..c2df72262b 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.