You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2023/10/25 13:33:57 UTC

[camel-k] branch main updated (a9b0e336e -> b1a94dfa0)

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

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


    from a9b0e336e fix(ci): Fix golang version file setup in coverage workflow
     new 27e07a2fd feat(runtime): enable source less integrations
     new b1a94dfa0 doc(runtimes): kamel --image instructions

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 addons/telemetry/telemetry.go                      |  2 +-
 docs/modules/ROOT/nav.adoc                         |  1 +
 .../modules/ROOT/pages/running/camel-runtimes.adoc | 22 +++++++
 e2e/common/{misc => runtimes}/default.go           |  2 +-
 e2e/common/runtimes/runtimes_test.go               | 73 ++++++++++++++++++++++
 .../incremental_build_test.go                      |  3 +-
 pkg/apis/camel/v1/trait/jvm.go                     |  6 +-
 pkg/cmd/run.go                                     | 29 ++++++---
 pkg/cmd/run_test.go                                | 32 ++++++++--
 pkg/trait/builder.go                               |  8 +--
 pkg/trait/builder_test.go                          |  8 +--
 pkg/trait/container.go                             |  6 ++
 pkg/trait/container_probes_test.go                 |  4 +-
 pkg/trait/cron_test.go                             |  4 +-
 pkg/trait/gc_test.go                               |  2 +-
 pkg/trait/jvm.go                                   | 14 +++--
 pkg/trait/quarkus.go                               |  2 +-
 pkg/trait/route_test.go                            |  2 +-
 pkg/trait/service.go                               |  2 +-
 pkg/trait/service_test.go                          | 10 +--
 pkg/trait/trait_catalog.go                         |  2 +-
 pkg/trait/trait_condition_types.go                 | 20 +++---
 pkg/util/kubernetes/sanitize_test.go               |  2 +
 script/Makefile                                    |  1 +
 24 files changed, 202 insertions(+), 55 deletions(-)
 create mode 100644 docs/modules/ROOT/pages/running/camel-runtimes.adoc
 copy e2e/common/{misc => runtimes}/default.go (98%)
 create mode 100644 e2e/common/runtimes/runtimes_test.go


[camel-k] 02/02: doc(runtimes): kamel --image instructions

Posted by pc...@apache.org.
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 b1a94dfa0181600296c660a724eef23d0e073d70
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Wed Oct 18 16:12:11 2023 +0200

    doc(runtimes): kamel --image instructions
---
 addons/telemetry/telemetry.go                      |  2 +-
 docs/modules/ROOT/nav.adoc                         |  1 +
 .../modules/ROOT/pages/running/camel-runtimes.adoc | 22 ++++++++++++++++++++++
 e2e/common/runtimes/runtimes_test.go               |  3 +++
 .../incremental_build_test.go                      |  3 +--
 pkg/apis/camel/v1/trait/jvm.go                     |  6 +++++-
 pkg/cmd/run.go                                     |  1 -
 pkg/cmd/run_test.go                                |  2 --
 pkg/trait/builder.go                               |  8 ++++----
 pkg/trait/builder_test.go                          |  8 ++++----
 pkg/trait/container.go                             |  6 ++++++
 pkg/trait/container_probes_test.go                 |  4 ++--
 pkg/trait/cron_test.go                             |  4 ++--
 pkg/trait/gc_test.go                               |  2 +-
 pkg/trait/jvm.go                                   | 14 ++++++++++----
 pkg/trait/quarkus.go                               |  2 +-
 pkg/trait/route_test.go                            |  2 +-
 pkg/trait/service.go                               |  2 +-
 pkg/trait/service_test.go                          | 10 +++++-----
 pkg/trait/trait_catalog.go                         |  2 +-
 pkg/trait/trait_condition_types.go                 | 20 ++++++++++----------
 21 files changed, 81 insertions(+), 43 deletions(-)

diff --git a/addons/telemetry/telemetry.go b/addons/telemetry/telemetry.go
index 2d830d991..a3975bd04 100644
--- a/addons/telemetry/telemetry.go
+++ b/addons/telemetry/telemetry.go
@@ -105,7 +105,7 @@ func (t *telemetryTrait) Configure(e *trait.Environment) (bool, *trait.TraitCond
 					condition = trait.NewIntegrationCondition(
 						v1.IntegrationConditionTraitInfo,
 						corev1.ConditionTrue,
-						"Tracing endpoint",
+						"TracingEndpoint",
 						endpoint,
 					)
 					t.Endpoint = endpoint
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index d665b6609..f13dbd7ef 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -19,6 +19,7 @@
 ** xref:running/dev-mode.adoc[Developer mode]
 ** xref:running/dry-run.adoc[Dry run]
 ** xref:running/runtime-version.adoc[Camel version]
+** xref:running/camel-runtimes.adoc[Camel runtimes]
 ** xref:running/quarkus-native.adoc[Quarkus Native]
 ** xref:running/run-from-github.adoc[Run from GitHub]
 ** xref:running/promoting.adoc[Promote an Integration]
diff --git a/docs/modules/ROOT/pages/running/camel-runtimes.adoc b/docs/modules/ROOT/pages/running/camel-runtimes.adoc
new file mode 100644
index 000000000..393e69e0d
--- /dev/null
+++ b/docs/modules/ROOT/pages/running/camel-runtimes.adoc
@@ -0,0 +1,22 @@
+= Camel Runtimes
+
+Camel K can run any runtime available in Apache Camel. However, this is possible only when the Camel application was previously built and packaged into a container image. Also, if you run through this option, some of the features offered by the operator may not be available. For example, you won't be able to discover Camel capabilities because the source is not available to the operator but embedded in the container image.
+
+This option is quite interesting if in general you're building your applications externally, ie, via a CICD technology, and you want to delegate the operator only the "operational" part, taking care on your own of the building and publishing part.
+
+NOTE: you may loose more features, such as incremental image and container kit reusability.
+
+[[build-and-run]]
+== Build externally, run via Operator
+
+Let's see a very simple example in action.
+
+You can have your own Camel application or just create a basic one for the purpose via Camel JBang (`camel init test.yaml`). Once your development is over, you can test locally via `camel run test.yaml` and export in the runtime of your choice via `camel export test.yaml --runtime ...`.
+
+The step above is a very quick way to create a basic Camel application in any of the available runtime. Let's imagine we've done this for Camel Main or we have already a Camel application as a Maven project. As the build part is something we want to take care on our own, we create a pipeline to build, containerize and push the container to a registry (see as a reference https://github.com/tektoncd/catalog/blob/main/task/kamel-run/0.1/samples/run-external-build.yaml[Camel K Tekton example]).
+
+At this stage we do have a container image with our Camel application. We can use the `kamel` CLI to run our Camel application via `kamel run --image docker.io/my-org/my-app:1.0.0` tuning, if it's the case, with any of the trait or configuration required.
+
+NOTE: Jvm trait won't be available when running an application built externally.
+
+If all is good, in a few seconds (there is no build involved) you should have your application up and running and you can monitor and operate with Camel K as usual.
diff --git a/e2e/common/runtimes/runtimes_test.go b/e2e/common/runtimes/runtimes_test.go
index d95c6820c..f9556232b 100644
--- a/e2e/common/runtimes/runtimes_test.go
+++ b/e2e/common/runtimes/runtimes_test.go
@@ -44,6 +44,7 @@ func TestSourceLessIntegrations(t *testing.T) {
 		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-main:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
 		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
 		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Apache Camel (Main)"))
 	})
@@ -53,6 +54,7 @@ func TestSourceLessIntegrations(t *testing.T) {
 		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-sb:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
 		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
 		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Spring Boot"))
 	})
@@ -62,6 +64,7 @@ func TestSourceLessIntegrations(t *testing.T) {
 		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-quarkus:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
 		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
 		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationCondition(ns, itName, v1.IntegrationConditionTraitInfo)().Message).Should(Equal("explicitly disabled by the platform: container image was not built via Camel K operator"))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
 		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("powered by Quarkus"))
 	})
diff --git a/e2e/commonwithcustominstall/incremental_build_test.go b/e2e/commonwithcustominstall/incremental_build_test.go
index 10ed57bbf..c53d9da92 100644
--- a/e2e/commonwithcustominstall/incremental_build_test.go
+++ b/e2e/commonwithcustominstall/incremental_build_test.go
@@ -35,7 +35,6 @@ import (
 	"github.com/apache/camel-k/v2/pkg/util/defaults"
 )
 
-/*
 func TestRunIncrementalBuildRoutine(t *testing.T) {
 	WithNewTestNamespace(t, func(ns string) {
 		operatorID := "camel-k-incremental-build"
@@ -191,7 +190,7 @@ func TestRunIncrementalBuildOff(t *testing.T) {
 		Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
 	})
 }
-*/
+
 func TestRunIncrementalBuildWithDifferentBaseImages(t *testing.T) {
 	WithNewTestNamespace(t, func(ns string) {
 		operatorID := "camel-k-standard-build"
diff --git a/pkg/apis/camel/v1/trait/jvm.go b/pkg/apis/camel/v1/trait/jvm.go
index 70bb3b7de..2a08fcf0b 100644
--- a/pkg/apis/camel/v1/trait/jvm.go
+++ b/pkg/apis/camel/v1/trait/jvm.go
@@ -17,7 +17,11 @@ limitations under the License.
 
 package trait
 
-// The JVM trait is used to configure the JVM that runs the integration.
+// The JVM trait is used to configure the JVM that runs the Integration. This trait can be configured only for Integration and related IntegrationKits
+// (bound to a container image) built by Camel K operator. If the system detects the usage of a different container image (ie, built externally), then, the
+// trait is disabled by the platform.
+//
+// NOTE: the platform will skip the trait configuration for those container image matching `camel-k-kit-` name.
 //
 // +camel-k:trait=jvm.
 type JVMTrait struct {
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index ea8ba4710..8aee2b6de 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -547,7 +547,6 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
 	} else {
 		// Source-less Integration as the user provided a container image built externally
 		o.Traits = append(o.Traits, fmt.Sprintf("container.image=%s", o.ContainerImage))
-		o.Traits = append(o.Traits, "jvm.enabled=false")
 	}
 
 	if err := resolvePodTemplate(context.Background(), cmd, o.PodTemplate, &integration.Spec); err != nil {
diff --git a/pkg/cmd/run_test.go b/pkg/cmd/run_test.go
index 6ca17a838..43eb732f9 100644
--- a/pkg/cmd/run_test.go
+++ b/pkg/cmd/run_test.go
@@ -840,8 +840,6 @@ spec:
   traits:
     container:
       image: docker.io/my-org/my-app:1.0.0
-    jvm:
-      enabled: false
     mount:
       configs:
       - configmap:my-cm
diff --git a/pkg/trait/builder.go b/pkg/trait/builder.go
index 64b3144cc..9f03b66aa 100644
--- a/pkg/trait/builder.go
+++ b/pkg/trait/builder.go
@@ -126,7 +126,7 @@ func (t *builderTrait) adaptDeprecatedFields() *TraitCondition {
 		m := "The limit-memory parameter is deprecated and may be removed in future releases. Make sure to use tasks-limit-memory parameter instead."
 		t.L.Info(m)
 		if condition == nil {
-			condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, "")
+			condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, "")
 		}
 		condition = newOrAppend(condition, m)
 		t.TasksLimitMemory = append(t.TasksLimitMemory, fmt.Sprintf("builder:%s", t.LimitMemory))
@@ -135,11 +135,11 @@ func (t *builderTrait) adaptDeprecatedFields() *TraitCondition {
 	return condition
 }
 
-func newOrAppend(condition *TraitCondition, reason string) *TraitCondition {
+func newOrAppend(condition *TraitCondition, message string) *TraitCondition {
 	if condition == nil {
-		condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, reason)
+		condition = NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message)
 	} else {
-		condition.reason += "; " + reason
+		condition.message += "; " + message
 	}
 
 	return condition
diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go
index 21c7829d4..401f40759 100644
--- a/pkg/trait/builder_test.go
+++ b/pkg/trait/builder_test.go
@@ -429,10 +429,10 @@ func TestBuilderDeprecatedParams(t *testing.T) {
 	assert.Nil(t, err)
 	assert.True(t, active)
 	assert.NotNil(t, condition)
-	assert.Contains(t, condition.reason, "The request-cpu parameter is deprecated and may be removed in future releases")
-	assert.Contains(t, condition.reason, "The limit-cpu parameter is deprecated and may be removed in future releases")
-	assert.Contains(t, condition.reason, "The request-memory parameter is deprecated and may be removed in future releases")
-	assert.Contains(t, condition.reason, "The limit-memory parameter is deprecated and may be removed in future releases")
+	assert.Contains(t, condition.message, "The request-cpu parameter is deprecated and may be removed in future releases")
+	assert.Contains(t, condition.message, "The limit-cpu parameter is deprecated and may be removed in future releases")
+	assert.Contains(t, condition.message, "The request-memory parameter is deprecated and may be removed in future releases")
+	assert.Contains(t, condition.message, "The limit-memory parameter is deprecated and may be removed in future releases")
 	assert.Len(t, builderTrait.TasksLimitCPU, 1)
 	assert.Len(t, builderTrait.TasksRequestCPU, 1)
 	assert.Len(t, builderTrait.TasksLimitMemory, 1)
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 6f6bb462c..44e13e09e 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -21,6 +21,7 @@ import (
 	"errors"
 	"fmt"
 	"path/filepath"
+	"strings"
 
 	appsv1 "k8s.io/api/apps/v1"
 	batchv1 "k8s.io/api/batch/v1"
@@ -347,3 +348,8 @@ func (t *containerTrait) configureSecurityContext(e *Environment, container *cor
 		}
 	}
 }
+
+// It's a user provided image if it does not match the naming convention used by Camel K Integration Kits.
+func (t *containerTrait) hasUserProvidedImage() bool {
+	return t.Image != "" && !strings.Contains(t.Image, "camel-k-kit-")
+}
diff --git a/pkg/trait/container_probes_test.go b/pkg/trait/container_probes_test.go
index 772dfd46c..edc6b5bfb 100644
--- a/pkg/trait/container_probes_test.go
+++ b/pkg/trait/container_probes_test.go
@@ -186,13 +186,13 @@ func TestProbesOnKnativeService(t *testing.T) {
 	serviceOverrideCondition := NewIntegrationCondition(
 		v1.IntegrationConditionTraitInfo,
 		corev1.ConditionTrue,
-		"service trait configuration",
+		"serviceTraitConfiguration",
 		"explicitly disabled by the platform: knative-service trait has priority over this trait",
 	)
 	ctrlStrategyCondition := NewIntegrationCondition(
 		v1.IntegrationConditionDeploymentAvailable,
 		corev1.ConditionFalse,
-		"deployment trait configuration",
+		"deploymentTraitConfiguration",
 		"controller strategy: knative-service",
 	)
 
diff --git a/pkg/trait/cron_test.go b/pkg/trait/cron_test.go
index 78964e527..5b6492848 100644
--- a/pkg/trait/cron_test.go
+++ b/pkg/trait/cron_test.go
@@ -443,7 +443,7 @@ func TestCronWithActiveDeadline(t *testing.T) {
 	expectedCondition := NewIntegrationCondition(
 		v1.IntegrationConditionDeploymentAvailable,
 		corev1.ConditionFalse,
-		"deployment trait configuration",
+		"deploymentTraitConfiguration",
 		"controller strategy: cron-job",
 	)
 	conditions, err := tc.apply(&environment)
@@ -532,7 +532,7 @@ func TestCronWithBackoffLimit(t *testing.T) {
 	expectedCondition := NewIntegrationCondition(
 		v1.IntegrationConditionDeploymentAvailable,
 		corev1.ConditionFalse,
-		"deployment trait configuration",
+		"deploymentTraitConfiguration",
 		"controller strategy: cron-job",
 	)
 	conditions, err := tc.apply(&environment)
diff --git a/pkg/trait/gc_test.go b/pkg/trait/gc_test.go
index 463af2f5a..2987f02b3 100644
--- a/pkg/trait/gc_test.go
+++ b/pkg/trait/gc_test.go
@@ -45,7 +45,7 @@ func TestConfigureDisabledGCTraitDoesNotSucceed(t *testing.T) {
 	expectedCondition := NewIntegrationCondition(
 		v1.IntegrationConditionTraitInfo,
 		corev1.ConditionTrue,
-		"Trait configuration",
+		"TraitConfiguration",
 		"explicitly disabled by the user",
 	)
 	configured, condition, err := gcTrait.Configure(environment)
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 9223cfef6..ffcf2ccd9 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -63,10 +63,16 @@ func (t *jvmTrait) Configure(e *Environment) (bool, *TraitCondition, error) {
 		return false, nil, nil
 	}
 
-	if trait := e.Catalog.GetTrait(quarkusTraitID); trait != nil {
-		// The JVM trait must be disabled in case the current IntegrationKit corresponds to a native build
-		if quarkus, ok := trait.(*quarkusTrait); ok && quarkus.isNativeIntegration(e) {
-			return false, newIntegrationConditionPlatformDisabledWithReason("Quarkus native build"), nil
+	// The JVM trait must be disabled in case the current IntegrationKit corresponds to a native build
+	if qt := e.Catalog.GetTrait(quarkusTraitID); qt != nil {
+		if quarkus, ok := qt.(*quarkusTrait); ok && quarkus.isNativeIntegration(e) {
+			return false, newIntegrationConditionPlatformDisabledWithMessage("quarkus native build"), nil
+		}
+	}
+	// The JVM trait must be disabled if it's a user based build (for which we do not control the way to handle JVM parameters)
+	if ct := e.Catalog.GetTrait(containerTraitID); ct != nil {
+		if ct, ok := ct.(*containerTrait); ok && ct.hasUserProvidedImage() {
+			return false, newIntegrationConditionPlatformDisabledWithMessage("container image was not built via Camel K operator"), nil
 		}
 	}
 
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
index 3127c679f..8f5cbfa3f 100644
--- a/pkg/trait/quarkus.go
+++ b/pkg/trait/quarkus.go
@@ -162,7 +162,7 @@ func (t *quarkusTrait) adaptDeprecatedFields() *TraitCondition {
 				t.Modes = append(t.Modes, traitv1.JvmQuarkusMode)
 			}
 		}
-		return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, message)
+		return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, message)
 	}
 
 	return nil
diff --git a/pkg/trait/route_test.go b/pkg/trait/route_test.go
index a4ecdc2dd..145054f1a 100644
--- a/pkg/trait/route_test.go
+++ b/pkg/trait/route_test.go
@@ -236,7 +236,7 @@ func TestRoute_Disabled(t *testing.T) {
 	expectedCondition := NewIntegrationCondition(
 		v1.IntegrationConditionExposureAvailable,
 		corev1.ConditionFalse,
-		"route trait configuration",
+		"routeTraitConfiguration",
 		"explicitly disabled",
 	)
 	traitsCatalog := environment.Catalog
diff --git a/pkg/trait/service.go b/pkg/trait/service.go
index 8f431f036..1bcb499e5 100644
--- a/pkg/trait/service.go
+++ b/pkg/trait/service.go
@@ -61,7 +61,7 @@ func (t *serviceTrait) Configure(e *Environment) (bool, *TraitCondition, error)
 	if e.GetTrait(knativeServiceTraitID) != nil {
 		knativeServiceTrait, _ := e.GetTrait(knativeServiceTraitID).(*knativeServiceTrait)
 		if pointer.BoolDeref(knativeServiceTrait.Enabled, true) {
-			return false, newIntegrationConditionPlatformDisabledWithReason("knative-service trait has priority over this trait"), nil
+			return false, newIntegrationConditionPlatformDisabledWithMessage("knative-service trait has priority over this trait"), nil
 		}
 	}
 
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index cbb856856..debe27434 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -494,13 +494,13 @@ func TestServiceWithKnativeServiceEnabled(t *testing.T) {
 	deploymentCondition := NewIntegrationCondition(
 		v1.IntegrationConditionDeploymentAvailable,
 		corev1.ConditionFalse,
-		"deployment trait configuration",
+		"deploymentTraitConfiguration",
 		"controller strategy: knative-service",
 	)
 	serviceCondition := NewIntegrationCondition(
 		v1.IntegrationConditionTraitInfo,
 		corev1.ConditionTrue,
-		"service trait configuration",
+		"serviceTraitConfiguration",
 		"explicitly disabled by the platform: knative-service trait has priority over this trait",
 	)
 	conditions, err := traitCatalog.apply(&environment)
@@ -572,13 +572,13 @@ func TestServicesWithKnativeProfile(t *testing.T) {
 	deploymentCondition := NewIntegrationCondition(
 		v1.IntegrationConditionDeploymentAvailable,
 		corev1.ConditionFalse,
-		"deployment trait configuration",
+		"deploymentTraitConfiguration",
 		"controller strategy: knative-service",
 	)
 	serviceCondition := NewIntegrationCondition(
 		v1.IntegrationConditionTraitInfo,
 		corev1.ConditionTrue,
-		"service trait configuration",
+		"serviceTraitConfiguration",
 		"explicitly disabled by the platform: knative-service trait has priority over this trait",
 	)
 	conditions, err := traitCatalog.apply(&environment)
@@ -658,7 +658,7 @@ func TestServiceWithKnativeServiceDisabledInIntegrationPlatform(t *testing.T) {
 	expectedCondition := NewIntegrationCondition(
 		v1.IntegrationConditionKnativeServiceAvailable,
 		corev1.ConditionFalse,
-		"knative-service trait configuration",
+		"knative-serviceTraitConfiguration",
 		"explicitly disabled",
 	)
 	conditions, err := traitCatalog.apply(&environment)
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index dc1160709..3169f563c 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -103,7 +103,7 @@ func (c *Catalog) apply(environment *Environment) ([]*TraitCondition, error) {
 		applicable = true
 		enabled, condition, err := trait.Configure(environment)
 		if condition != nil {
-			condition.message = fmt.Sprintf("%s trait configuration", trait.ID())
+			condition.reason = fmt.Sprintf("%sTraitConfiguration", trait.ID())
 			traitsConditions = append(traitsConditions, condition)
 		}
 		if err != nil {
diff --git a/pkg/trait/trait_condition_types.go b/pkg/trait/trait_condition_types.go
index 6acf12dcf..c027bf5ec 100644
--- a/pkg/trait/trait_condition_types.go
+++ b/pkg/trait/trait_condition_types.go
@@ -26,9 +26,9 @@ import (
 )
 
 const (
-	traitConfigurationMessage = "Trait configuration"
-	userDisabledMessage       = "explicitly disabled by the user"
-	platformDisabledMessage   = "explicitly disabled by the platform"
+	traitConfigurationReason = "TraitConfiguration"
+	userDisabledMessage      = "explicitly disabled by the user"
+	platformDisabledMessage  = "explicitly disabled by the platform"
 )
 
 // TraitCondition is used to get all information/warning about a trait configuration.
@@ -41,27 +41,27 @@ type TraitCondition struct {
 	reason                      string
 }
 
-func NewIntegrationCondition(ict v1.IntegrationConditionType, cs corev1.ConditionStatus, message, reason string) *TraitCondition {
+func NewIntegrationCondition(ict v1.IntegrationConditionType, cs corev1.ConditionStatus, reason, message string) *TraitCondition {
 	return &TraitCondition{
 		integrationConditionType: ict,
 		conditionStatus:          cs,
-		message:                  message,
 		reason:                   reason,
+		message:                  message,
 	}
 }
 
 func NewIntegrationConditionUserDisabled() *TraitCondition {
-	return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, userDisabledMessage)
+	return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, userDisabledMessage)
 }
 
-func newIntegrationConditionPlatformDisabledWithReason(reason string) *TraitCondition {
-	return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationMessage, fmt.Sprintf("%s: %s", platformDisabledMessage, reason))
+func newIntegrationConditionPlatformDisabledWithMessage(message string) *TraitCondition {
+	return NewIntegrationCondition(v1.IntegrationConditionTraitInfo, corev1.ConditionTrue, traitConfigurationReason, fmt.Sprintf("%s: %s", platformDisabledMessage, message))
 }
 
 func (tc *TraitCondition) integrationCondition() (v1.IntegrationConditionType, corev1.ConditionStatus, string, string) {
-	return tc.integrationConditionType, tc.conditionStatus, tc.message, tc.reason
+	return tc.integrationConditionType, tc.conditionStatus, tc.reason, tc.message
 }
 
 func (tc *TraitCondition) integrationKitCondition() (v1.IntegrationKitConditionType, corev1.ConditionStatus, string, string) {
-	return tc.integrationKitConditionType, tc.conditionStatus, tc.message, tc.reason
+	return tc.integrationKitConditionType, tc.conditionStatus, tc.reason, tc.message
 }


[camel-k] 01/02: feat(runtime): enable source less integrations

Posted by pc...@apache.org.
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 27e07a2fdde207099c2f7ce96b8ca0265aa07a27
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Oct 17 17:28:22 2023 +0200

    feat(runtime): enable source less integrations
    
    Closes #3295
---
 e2e/common/runtimes/default.go       | 26 ++++++++++++++
 e2e/common/runtimes/runtimes_test.go | 70 ++++++++++++++++++++++++++++++++++++
 pkg/cmd/run.go                       | 30 +++++++++++-----
 pkg/cmd/run_test.go                  | 34 ++++++++++++++----
 pkg/util/kubernetes/sanitize_test.go |  2 ++
 script/Makefile                      |  1 +
 6 files changed, 149 insertions(+), 14 deletions(-)

diff --git a/e2e/common/runtimes/default.go b/e2e/common/runtimes/default.go
new file mode 100644
index 000000000..1cc41c3f9
--- /dev/null
+++ b/e2e/common/runtimes/default.go
@@ -0,0 +1,26 @@
+//go:build integration
+// +build integration
+
+/*
+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 runtimes
+
+import "github.com/apache/camel-k/v2/e2e/support"
+
+var ns = support.GetEnvOrDefault("CAMEL_K_TEST_NAMESPACE", support.GetCIProcessID())
+var operatorID = support.GetEnvOrDefault("CAMEL_K_OPERATOR_ID", support.GetCIProcessID())
diff --git a/e2e/common/runtimes/runtimes_test.go b/e2e/common/runtimes/runtimes_test.go
new file mode 100644
index 000000000..d95c6820c
--- /dev/null
+++ b/e2e/common/runtimes/runtimes_test.go
@@ -0,0 +1,70 @@
+//go:build integration
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 runtimes
+
+import (
+	"testing"
+
+	. "github.com/onsi/gomega"
+
+	corev1 "k8s.io/api/core/v1"
+
+	. "github.com/apache/camel-k/v2/e2e/support"
+	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestSourceLessIntegrations(t *testing.T) {
+	RegisterTestingT(t)
+	var cmData = make(map[string]string)
+	cmData["my-file.txt"] = "Hello World!"
+	CreatePlainTextConfigmap(ns, "my-cm-sourceless", cmData)
+
+	t.Run("Camel Main", func(t *testing.T) {
+		itName := "my-camel-main-v1"
+		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-main:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Apache Camel (Main)"))
+	})
+
+	t.Run("Camel Spring Boot", func(t *testing.T) {
+		itName := "my-camel-sb-v1"
+		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-sb:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("Spring Boot"))
+	})
+
+	t.Run("Camel Quarkus", func(t *testing.T) {
+		itName := "my-camel-quarkus-v1"
+		Expect(KamelRunWithID(operatorID, ns, "--image", "docker.io/squakez/my-camel-quarkus:1.0.0", "--resource", "configmap:my-cm-sourceless@/tmp/app/data").Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, itName), TestTimeoutShort).Should(Equal(corev1.PodRunning))
+		Eventually(IntegrationConditionStatus(ns, itName, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring(cmData["my-file.txt"]))
+		Eventually(IntegrationLogs(ns, itName), TestTimeoutShort).Should(ContainSubstring("powered by Quarkus"))
+	})
+
+	Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+}
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index f117f8138..ea8ba4710 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -98,6 +98,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions)
 	}
 
 	cmd.Flags().String("name", "", "The integration name")
+	cmd.Flags().String("image", "", "An image built externally (ie, via CICD). Enabling it will skip the Integration build phase.")
 	cmd.Flags().StringArrayP("connect", "c", nil, "A Service that the integration should bind to, specified as [[apigroup/]version:]kind:[namespace/]name")
 	cmd.Flags().StringArrayP("dependency", "d", nil, usageDependency)
 	cmd.Flags().BoolP("wait", "w", false, "Wait for the integration to be running")
@@ -145,6 +146,7 @@ type runCmdOptions struct {
 	Save            bool     `mapstructure:"save" yaml:",omitempty" kamel:"omitsave"`
 	IntegrationKit  string   `mapstructure:"kit" yaml:",omitempty"`
 	IntegrationName string   `mapstructure:"name" yaml:",omitempty"`
+	ContainerImage  string   `mapstructure:"image" yaml:",omitempty"`
 	Profile         string   `mapstructure:"profile" yaml:",omitempty"`
 	OperatorID      string   `mapstructure:"operator-id" yaml:",omitempty"`
 	OutputFormat    string   `mapstructure:"output" yaml:",omitempty"`
@@ -236,10 +238,6 @@ func (o *runCmdOptions) decode(cmd *cobra.Command, args []string) error {
 }
 
 func (o *runCmdOptions) validateArgs(cmd *cobra.Command, args []string) error {
-	if len(args) < 1 {
-		return errors.New("run expects at least 1 argument, received 0")
-	}
-
 	if _, err := source.Resolve(context.Background(), args, false, cmd); err != nil {
 		return fmt.Errorf("one of the provided sources is not reachable: %w", err)
 	}
@@ -324,6 +322,11 @@ func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error {
 		}
 	}
 
+	// We need to make this check at this point, in order to have sources filled during decoding
+	if len(args) < 1 && o.ContainerImage == "" {
+		return errors.New("run command expects either an Integration source or the container image (via --image argument)")
+	}
+
 	integration, err := o.createOrUpdateIntegration(cmd, c, args)
 	if err != nil {
 		return err
@@ -536,8 +539,15 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
 		return nil, err
 	}
 
-	if err := o.resolveSources(cmd, sources, integration); err != nil {
-		return nil, err
+	if o.ContainerImage == "" {
+		// Resolve resources
+		if err := o.resolveSources(cmd, sources, integration); err != nil {
+			return nil, err
+		}
+	} else {
+		// Source-less Integration as the user provided a container image built externally
+		o.Traits = append(o.Traits, fmt.Sprintf("container.image=%s", o.ContainerImage))
+		o.Traits = append(o.Traits, "jvm.enabled=false")
 	}
 
 	if err := resolvePodTemplate(context.Background(), cmd, o.PodTemplate, &integration.Spec); err != nil {
@@ -868,11 +878,15 @@ func (o *runCmdOptions) getPlatform(cmd *cobra.Command, c client.Client, it *v1.
 
 func (o *runCmdOptions) GetIntegrationName(sources []string) string {
 	name := ""
-	if o.IntegrationName != "" {
+	switch {
+	case o.IntegrationName != "":
 		name = o.IntegrationName
 		name = kubernetes.SanitizeName(name)
-	} else if len(sources) == 1 {
+	case len(sources) == 1:
 		name = kubernetes.SanitizeName(sources[0])
+	case o.ContainerImage != "":
+		// source-less execution
+		name = kubernetes.SanitizeName(strings.ReplaceAll(o.ContainerImage, ":", "-v"))
 	}
 	return name
 }
diff --git a/pkg/cmd/run_test.go b/pkg/cmd/run_test.go
index becac009b..6ca17a838 100644
--- a/pkg/cmd/run_test.go
+++ b/pkg/cmd/run_test.go
@@ -511,13 +511,9 @@ func TestRunBuildPropertyFlag(t *testing.T) {
 
 func TestRunValidateArgs(t *testing.T) {
 	runCmdOptions, rootCmd, _ := initializeRunCmdOptions(t)
-	args := []string{}
-	err := runCmdOptions.validateArgs(rootCmd, args)
-	assert.NotNil(t, err)
-	assert.Equal(t, "run expects at least 1 argument, received 0", err.Error())
 
-	args = []string{"run_test.go"}
-	err = runCmdOptions.validateArgs(rootCmd, args)
+	args := []string{"run_test.go"}
+	err := runCmdOptions.validateArgs(rootCmd, args)
 	assert.Nil(t, err)
 
 	args = []string{"missing_file"}
@@ -826,3 +822,29 @@ func TestRunOutputWithoutKubernetesCluster(t *testing.T) {
 	_, err = test.ExecuteCommand(rootCmd, cmdRun, "-o", "yaml", integrationSource)
 	require.NoError(t, err)
 }
+
+func TestSourceLessIntegration(t *testing.T) {
+	runCmdOptions, runCmd, _ := initializeRunCmdOptionsWithOutput(t)
+	output, err := test.ExecuteCommand(runCmd, cmdRun, "--image", "docker.io/my-org/my-app:1.0.0", "-o", "yaml", "-t", "mount.configs=configmap:my-cm")
+	assert.Equal(t, "yaml", runCmdOptions.OutputFormat)
+
+	assert.Nil(t, err)
+	assert.Equal(t, `apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  annotations:
+    camel.apache.org/operator.id: camel-k
+  creationTimestamp: null
+  name: my-app-v1
+spec:
+  traits:
+    container:
+      image: docker.io/my-org/my-app:1.0.0
+    jvm:
+      enabled: false
+    mount:
+      configs:
+      - configmap:my-cm
+status: {}
+`, output)
+}
diff --git a/pkg/util/kubernetes/sanitize_test.go b/pkg/util/kubernetes/sanitize_test.go
index 31b422e20..93bcac937 100644
--- a/pkg/util/kubernetes/sanitize_test.go
+++ b/pkg/util/kubernetes/sanitize_test.go
@@ -36,6 +36,8 @@ func TestSanitizeName(t *testing.T) {
 		{"input": "-foo-bar-", "expect": "foo-bar"},
 		{"input": "1foo-bar2", "expect": "1foo-bar2"},
 		{"input": "foo-bar-1", "expect": "foo-bar-1"},
+		{"input": "docker.io/squakez/my-camel-sb:1.0.0", "expect": "my-camel-sb1"},
+		{"input": "docker.io/squakez/my-camel-sb:2.0.0", "expect": "my-camel-sb2"},
 	}
 
 	for _, c := range cases {
diff --git a/script/Makefile b/script/Makefile
index ac59c1692..786ced9ca 100644
--- a/script/Makefile
+++ b/script/Makefile
@@ -260,6 +260,7 @@ test-common: do-build
 	go test -timeout 30m -v ./e2e/common/config -tags=integration $(TEST_INTEGRATION_COMMON_LANG_RUN) $(GOTESTFMT) || FAILED=1; \
 	go test -timeout 30m -v ./e2e/common/misc -tags=integration $(TEST_INTEGRATION_COMMON_LANG_RUN) $(GOTESTFMT) || FAILED=1; \
 	go test -timeout 60m -v ./e2e/common/traits -tags=integration $(TEST_INTEGRATION_COMMON_LANG_RUN) $(GOTESTFMT) || FAILED=1; \
+	go test -timeout 20m -v ./e2e/common/runtimes -tags=integration $(TEST_INTEGRATION_COMMON_LANG_RUN) $(GOTESTFMT) || FAILED=1; \
 	go test -timeout 10m -v ./e2e/common/support/teardown_test.go -tags=integration $(TEST_INTEGRATION_COMMON_LANG_RUN) $(GOTESTFMT) || FAILED=1; \
 	exit $${FAILED}