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


The following commit(s) were added to refs/heads/main by this push:
     new 0a22bed84 feat(trait): enable health trait by default
0a22bed84 is described below

commit 0a22bed84ccff83042f70e45e530c7057b1d9671
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Fri Apr 26 16:02:09 2024 +0200

    feat(trait): enable health trait by default
    
    Closes #5024
---
 e2e/common/cli/get_test.go                 |   4 +-
 e2e/common/misc/files/cron-fallback.yaml   |   5 ++
 e2e/common/misc/files/cron-quartz.yaml     |   5 ++
 e2e/common/misc/files/cron-timer.yaml      |   5 ++
 e2e/common/misc/files/cron-trait-yaml.yaml |   5 ++
 e2e/common/misc/files/cron-yaml.yaml       |   5 ++
 e2e/common/misc/integration_fail_test.go   |  15 ++--
 e2e/common/traits/health_test.go           |  32 +++++----
 e2e/common/traits/master_test.go           |  28 ++++----
 pkg/apis/camel/v1/trait/health.go          |   2 +-
 pkg/cmd/debug.go                           |   7 +-
 pkg/cmd/debug_test.go                      |  78 +++++++++++++++++++++
 pkg/trait/health.go                        |  10 ++-
 pkg/trait/health_test.go                   | 106 +++++++++++++++++++++++++++++
 pkg/trait/jvm.go                           |   6 +-
 pkg/trait/trait_test.go                    |   2 +-
 16 files changed, 269 insertions(+), 46 deletions(-)

diff --git a/e2e/common/cli/get_test.go b/e2e/common/cli/get_test.go
index c9b0ee351..88dbb71eb 100644
--- a/e2e/common/cli/get_test.go
+++ b/e2e/common/cli/get_test.go
@@ -46,7 +46,7 @@ func TestKamelCLIGet(t *testing.T) {
                        kitName := IntegrationKit(t, ctx, ns, "yaml")()
                        kitNamespace := IntegrationKitNamespace(t, ctx, ns, 
"yaml")()
                        regex := 
fmt.Sprintf("^NAME\tPHASE\tKIT\n\\s*yaml\tRunning\t(%s/%s|%s)", kitNamespace, 
kitName, kitName)
-                       g.Expect(GetOutputString(Kamel(t, ctx, "get", "-n", 
ns))).To(MatchRegexp(regex))
+                       g.Eventually(GetOutputString(Kamel(t, ctx, "get", "-n", 
ns))).Should(MatchRegexp(regex))
 
                        g.Expect(Kamel(t, ctx, "delete", "--all", "-n", 
ns).Execute()).To(Succeed())
                })
@@ -65,7 +65,7 @@ func TestKamelCLIGet(t *testing.T) {
                        kitNamespace2 := IntegrationKitNamespace(t, ctx, ns, 
"yaml")()
                        regex := 
fmt.Sprintf("^NAME\tPHASE\tKIT\n\\s*java\tRunning\t"+
                                "(%s/%s|%s)\n\\s*yaml\tRunning\t(%s/%s|%s)\n", 
kitNamespace1, kitName1, kitName1, kitNamespace2, kitName2, kitName2)
-                       g.Expect(GetOutputString(Kamel(t, ctx, "get", "-n", 
ns))).To(MatchRegexp(regex))
+                       g.Eventually(GetOutputString(Kamel(t, ctx, "get", "-n", 
ns))).Should(MatchRegexp(regex))
 
                        g.Expect(Kamel(t, ctx, "delete", "--all", "-n", 
ns).Execute()).To(Succeed())
                })
diff --git a/e2e/common/misc/files/cron-fallback.yaml 
b/e2e/common/misc/files/cron-fallback.yaml
index f20d0f21a..6ca1af958 100644
--- a/e2e/common/misc/files/cron-fallback.yaml
+++ b/e2e/common/misc/files/cron-fallback.yaml
@@ -25,6 +25,11 @@
           constant: "string!"
       - setBody:
           simple: "Magic${header.m}"
+      # Simulate a job workload
+      - delay:
+          expression:
+            constant: 20000
+          asyncDelayed: false
       - to:
           uri: "log:info"
           parameters:
diff --git a/e2e/common/misc/files/cron-quartz.yaml 
b/e2e/common/misc/files/cron-quartz.yaml
index 074367a3c..c80da789c 100644
--- a/e2e/common/misc/files/cron-quartz.yaml
+++ b/e2e/common/misc/files/cron-quartz.yaml
@@ -27,6 +27,11 @@
             constant: "string!"
         - setBody:
             simple: "Magic${header.m}"
+        # Simulate a job workload
+        - delay:
+            expression:
+              constant: 20000
+            asyncDelayed: false
         - to:
             uri: "log:info"
             parameters:
diff --git a/e2e/common/misc/files/cron-timer.yaml 
b/e2e/common/misc/files/cron-timer.yaml
index 4acd7a8c2..d486ef7fe 100644
--- a/e2e/common/misc/files/cron-timer.yaml
+++ b/e2e/common/misc/files/cron-timer.yaml
@@ -27,6 +27,11 @@
             constant: "string!"
         - setBody:
             simple: "Magic${header.m}"
+        # Simulate a job workload
+        - delay:
+            expression:
+              constant: 20000
+            asyncDelayed: false
         - to:
             uri: "log:info"
             parameters:
diff --git a/e2e/common/misc/files/cron-trait-yaml.yaml 
b/e2e/common/misc/files/cron-trait-yaml.yaml
index 464579ee7..1016d624f 100644
--- a/e2e/common/misc/files/cron-trait-yaml.yaml
+++ b/e2e/common/misc/files/cron-trait-yaml.yaml
@@ -26,6 +26,11 @@
           constant: "string!"
       - setBody:
           simple: "Magic${header.m}"
+      # Simulate a job workload
+      - delay:
+          expression:
+            constant: 20000
+          asyncDelayed: false
       - to:
           uri: "log:info"
           parameters:
diff --git a/e2e/common/misc/files/cron-yaml.yaml 
b/e2e/common/misc/files/cron-yaml.yaml
index 9b6735053..e238e2e02 100644
--- a/e2e/common/misc/files/cron-yaml.yaml
+++ b/e2e/common/misc/files/cron-yaml.yaml
@@ -25,6 +25,11 @@
           constant: "string!"
       - setBody:
           simple: "Magic${header.m}"
+      # Simulate a job workload
+      - delay:
+          expression:
+            constant: 20000
+          asyncDelayed: false
       - to:
           uri: "log:info"
           parameters:
diff --git a/e2e/common/misc/integration_fail_test.go 
b/e2e/common/misc/integration_fail_test.go
index cdd731be4..1236faafa 100644
--- a/e2e/common/misc/integration_fail_test.go
+++ b/e2e/common/misc/integration_fail_test.go
@@ -48,7 +48,7 @@ func TestBadRouteIntegration(t *testing.T) {
 
                t.Run("run bad java route", func(t *testing.T) {
                        name := RandomizedSuffixName("bad-route")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/BadRoute.java", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/BadRoute.java", "--name", name, "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseError))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
@@ -73,7 +73,7 @@ func TestBadRouteIntegration(t *testing.T) {
                t.Run("run missing dependency java route", func(t *testing.T) {
                        name := RandomizedSuffixName("java-route")
                        g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name,
-                               "-d", 
"mvn:com.example:nonexistent:1.0").Execute()).To(Succeed())
+                               "-d", "mvn:com.example:nonexistent:1.0", "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        // Integration in error
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(v1.IntegrationPhaseError))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionKitAvailable), 
TestTimeoutShort).Should(Equal(corev1.ConditionFalse))
@@ -106,7 +106,7 @@ func TestBadRouteIntegration(t *testing.T) {
 
                t.Run("run invalid dependency java route", func(t *testing.T) {
                        name := RandomizedSuffixName("invalid-dependency")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-d", 
"camel:non-existent").Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-d", "camel:non-existent", "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        // Integration in error with Initialization Failed 
condition
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(v1.IntegrationPhaseError))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
@@ -135,7 +135,7 @@ func TestBadRouteIntegration(t *testing.T) {
 
                t.Run("run unresolvable component java route", func(t 
*testing.T) {
                        name := RandomizedSuffixName("unresolvable-route")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Unresolvable.java", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Unresolvable.java", "--name", name, "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        // Integration in error with Initialization Failed 
condition
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseError))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
@@ -148,7 +148,7 @@ func TestBadRouteIntegration(t *testing.T) {
                        g.Consistently(IntegrationKit(t, ctx, ns, name), 
10*time.Second).Should(BeEmpty())
 
                        // Fixing the route should reconcile the Integration in 
Initialization Failed condition to Running
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
                                Should(Equal(corev1.ConditionTrue))
@@ -164,7 +164,8 @@ func TestBadRouteIntegration(t *testing.T) {
 
                t.Run("run invalid java route", func(t *testing.T) {
                        name := RandomizedSuffixName("invalid-java-route")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/InvalidJava.java", "--name", name).Execute()).To(Succeed())
+                       // Skip the health check so we can quickly read from log
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/InvalidJava.java", "--name", name, "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseError))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
@@ -177,7 +178,7 @@ func TestBadRouteIntegration(t *testing.T) {
                        g.Eventually(KitPhase(t, ctx, integrationKitNamespace, 
kitName), TestTimeoutShort).Should(Equal(v1.IntegrationKitPhaseReady))
 
                        // Fixing the route should reconcile the Integration in 
Initialization Failed condition to Running
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-t", 
"health.enabled=false").Execute()).To(Succeed())
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
                                Should(Equal(corev1.ConditionTrue))
diff --git a/e2e/common/traits/health_test.go b/e2e/common/traits/health_test.go
index 31221cff7..7a26bb9f2 100644
--- a/e2e/common/traits/health_test.go
+++ b/e2e/common/traits/health_test.go
@@ -37,7 +37,6 @@ import (
        . "github.com/onsi/gomega"
 
        corev1 "k8s.io/api/core/v1"
-       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 
        . "github.com/apache/camel-k/v2/e2e/support"
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
@@ -54,9 +53,23 @@ func TestHealthTrait(t *testing.T) {
 
                g.Eventually(SelectedPlatformPhase(t, ctx, ns, operatorID), 
TestTimeoutMedium).Should(Equal(v1.IntegrationPlatformPhaseReady))
 
+               t.Run("Disabled health trait", func(t *testing.T) {
+                       name := RandomizedSuffixName("java")
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "-t", "health.enabled=false", "--name", 
name).Execute()).To(Succeed())
+
+                       g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
+                       g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
+                       g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), TestTimeoutShort).
+                               Should(Equal(corev1.ConditionTrue))
+                       g.Eventually(IntegrationLogs(t, ctx, ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+
+                       // Clean-up
+                       g.Expect(Kamel(t, ctx, "delete", "--all", "-n", 
ns).Execute()).To(Succeed())
+               })
+
                t.Run("Readiness condition with stopped route scaled", func(t 
*testing.T) {
                        name := RandomizedSuffixName("java")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "-t", "health.enabled=true", "-t", "jolokia.enabled=true", 
"-t", "jolokia.use-ssl-client-authentication=false", "-t", 
"jolokia.protocol=http", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "-t", "jolokia.enabled=true", "-t", 
"jolokia.use-ssl-client-authentication=false", "-t", "jolokia.protocol=http", 
"--name", name).Execute()).To(Succeed())
 
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
@@ -75,16 +88,7 @@ func TestHealthTrait(t *testing.T) {
                        // Finally check the readiness condition becomes truthy 
back
                        g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady), 
TestTimeoutMedium).Should(Equal(corev1.ConditionTrue))
 
-                       // check integration schema does not contains unwanted 
default trait value.
-                       g.Eventually(UnstructuredIntegration(t, ctx, ns, 
name)).ShouldNot(BeNil())
-                       unstructuredIntegration := UnstructuredIntegration(t, 
ctx, ns, name)()
-                       healthTrait, _, _ := 
unstructured.NestedMap(unstructuredIntegration.Object, "spec", "traits", 
"health")
-                       g.Expect(healthTrait).ToNot(BeNil())
-                       g.Expect(len(healthTrait)).To(Equal(1))
-                       g.Expect(healthTrait["enabled"]).To(Equal(true))
-
                        pods := IntegrationPods(t, ctx, ns, name)()
-
                        for i, pod := range pods {
                                // Stop the Camel route
                                request := map[string]string{
@@ -155,7 +159,7 @@ func TestHealthTrait(t *testing.T) {
 
                t.Run("Readiness condition with stopped route", func(t 
*testing.T) {
                        name := RandomizedSuffixName("java")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "-t", "health.enabled=true", "-t", "jolokia.enabled=true", 
"-t", "jolokia.use-ssl-client-authentication=false", "-t", 
"jolokia.protocol=http", "--name", name).Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "-t", "jolokia.enabled=true", "-t", 
"jolokia.use-ssl-client-authentication=false", "-t", "jolokia.protocol=http", 
"--name", name).Execute()).To(Succeed())
 
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutShort).Should(Equal(v1.IntegrationPhaseRunning))
@@ -410,7 +414,7 @@ func TestHealthTrait(t *testing.T) {
                t.Run("Startup condition with never ready route", func(t 
*testing.T) {
                        name := 
RandomizedSuffixName("startup-probe-never-ready-route")
 
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/NeverReady.java", "--name", name, "-t", "health.enabled=true", "-t", 
"health.startup-probe-enabled=true", "-t", 
"health.startup-timeout=60").Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/NeverReady.java", "--name", name, "-t", 
"health.startup-probe-enabled=true", "-t", 
"health.startup-timeout=60").Execute()).To(Succeed())
 
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
@@ -467,7 +471,7 @@ func TestHealthTrait(t *testing.T) {
                t.Run("Startup condition with ready route", func(t *testing.T) {
                        name := 
RandomizedSuffixName("startup-probe-ready-route")
 
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-t", "health.enabled=true", "-t", 
"health.startup-probe-enabled=true", "-t", 
"health.startup-timeout=60").Execute()).To(Succeed())
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Java.java", "--name", name, "-t", "health.startup-probe-enabled=true", 
"-t", "health.startup-timeout=60").Execute()).To(Succeed())
 
                        g.Eventually(IntegrationPodPhase(t, ctx, ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
                        g.Eventually(IntegrationPhase(t, ctx, ns, name), 
TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
diff --git a/e2e/common/traits/master_test.go b/e2e/common/traits/master_test.go
index 96541a8cc..eb40fe039 100644
--- a/e2e/common/traits/master_test.go
+++ b/e2e/common/traits/master_test.go
@@ -24,13 +24,13 @@ package traits
 
 import (
        "context"
+       "fmt"
        "testing"
        "time"
 
        . "github.com/onsi/gomega"
 
        corev1 "k8s.io/api/core/v1"
-       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 
        . "github.com/apache/camel-k/v2/e2e/support"
        v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
@@ -56,24 +56,20 @@ func TestMasterTrait(t *testing.T) {
 
                t.Run("only one integration with master runs", func(t 
*testing.T) {
                        nameFirst := RandomizedSuffixName("first")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Master.java", "--name", nameFirst, "--label", "leader-group=same", "-t", 
"master.label-key=leader-group", "-t", "master.label-value=same", "-t", 
"owner.target-labels=leader-group").Execute()).To(Succeed())
-                       g.Eventually(IntegrationPodPhase(t, ctx, ns, 
nameFirst), TestTimeoutLong).Should(Equal(corev1.PodRunning))
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Master.java", "--name", nameFirst,
+                               "--label", "leader-group=same", "-t", 
"master.label-key=leader-group", "-t", "master.label-value=same", "-t", 
"owner.target-labels=leader-group",
+                       ).Execute()).To(Succeed())
+                       g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
nameFirst, v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
                        g.Eventually(IntegrationLogs(t, ctx, ns, nameFirst), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
-                       // Start a second integration with the same lock (it 
should not start the route)
+                       // Start a second integration with the same lock (it 
should not start the route before 15 seconds)
                        nameSecond := RandomizedSuffixName("second")
-                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Master.java", "--name", nameSecond, "--label", "leader-group=same", 
"-t", "master.label-key=leader-group", "-t", "master.label-value=same", "-t", 
"master.resource-name=first-lock", "-t", 
"owner.target-labels=leader-group").Execute()).To(Succeed())
-                       g.Eventually(IntegrationPodPhase(t, ctx, ns, 
nameSecond), TestTimeoutLong).Should(Equal(corev1.PodRunning))
+                       g.Expect(KamelRunWithID(t, ctx, operatorID, ns, 
"files/Master.java", "--name", nameSecond,
+                               "--label", "leader-group=same", "-t", 
"master.label-key=leader-group", "-t", "master.label-value=same", "-t", 
"owner.target-labels=leader-group",
+                               "-t", 
fmt.Sprintf("master.resource-name=%s-lock", nameFirst),
+                       ).Execute()).To(Succeed())
                        g.Eventually(IntegrationLogs(t, ctx, ns, nameSecond), 
TestTimeoutShort).Should(ContainSubstring("started in"))
-                       g.Eventually(IntegrationLogs(t, ctx, ns, nameSecond), 
30*time.Second).ShouldNot(ContainSubstring("Magicstring!"))
-
-                       // check integration schema does not contains unwanted 
default trait value.
-                       g.Eventually(UnstructuredIntegration(t, ctx, ns, 
nameFirst)).ShouldNot(BeNil())
-                       unstructuredIntegration := UnstructuredIntegration(t, 
ctx, ns, nameFirst)()
-                       builderTrait, _, _ := 
unstructured.NestedMap(unstructuredIntegration.Object, "spec", "traits", 
"addons", "master")
-                       g.Expect(builderTrait).ToNot(BeNil())
-                       g.Expect(len(builderTrait)).To(Equal(2))
-                       
g.Expect(builderTrait["labelKey"]).To(Equal("leader-group"))
-                       g.Expect(builderTrait["labelValue"]).To(Equal("same"))
+                       g.Eventually(IntegrationLogs(t, ctx, ns, nameSecond), 
15*time.Second).ShouldNot(ContainSubstring("Magicstring!"))
+                       g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
nameSecond, v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
                })
 
                g.Expect(Kamel(t, ctx, "delete", "--all", "-n", 
ns).Execute()).To(Succeed())
diff --git a/pkg/apis/camel/v1/trait/health.go 
b/pkg/apis/camel/v1/trait/health.go
index 587249afe..a691afadf 100644
--- a/pkg/apis/camel/v1/trait/health.go
+++ b/pkg/apis/camel/v1/trait/health.go
@@ -19,7 +19,7 @@ package trait
 
 // The health trait is responsible for configuring the health probes on the 
integration container.
 //
-// It's disabled by default.
+// NOTE: this trait is enabled by default.
 //
 // +camel-k:trait=health.
 type HealthTrait struct {
diff --git a/pkg/cmd/debug.go b/pkg/cmd/debug.go
index 997ecb218..b6c38262c 100644
--- a/pkg/cmd/debug.go
+++ b/pkg/cmd/debug.go
@@ -134,6 +134,11 @@ func (o *debugCmdOptions) run(cmd *cobra.Command, args 
[]string) error {
 }
 
 func (o *debugCmdOptions) toggleDebug(c camelv1.IntegrationsGetter, it 
*v1.Integration, active bool) (*v1.Integration, error) {
+       it = o.toggle(it, active)
+       return c.Integrations(it.Namespace).Update(o.Context, it, 
metav1.UpdateOptions{})
+}
+
+func (o *debugCmdOptions) toggle(it *v1.Integration, active bool) 
*v1.Integration {
        if it.Spec.Traits.JVM == nil {
                it.Spec.Traits.JVM = &traitv1.JVMTrait{}
        }
@@ -147,5 +152,5 @@ func (o *debugCmdOptions) toggleDebug(c 
camelv1.IntegrationsGetter, it *v1.Integ
                jvmTrait.DebugSuspend = nil
        }
 
-       return c.Integrations(it.Namespace).Update(o.Context, it, 
metav1.UpdateOptions{})
+       return it
 }
diff --git a/pkg/cmd/debug_test.go b/pkg/cmd/debug_test.go
new file mode 100644
index 000000000..67d5e23d0
--- /dev/null
+++ b/pkg/cmd/debug_test.go
@@ -0,0 +1,78 @@
+/*
+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 cmd
+
+import (
+       "testing"
+
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/v2/pkg/util/test"
+       "github.com/spf13/cobra"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+       corev1 "k8s.io/api/core/v1"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/utils/pointer"
+)
+
+const cmdDebug = "debug"
+
+// nolint: unparam
+func initializeDebugCmdOptions(t *testing.T, initObjs ...runtime.Object) 
(*cobra.Command, *debugCmdOptions) {
+       t.Helper()
+       fakeClient, err := test.NewFakeClient(initObjs...)
+       require.NoError(t, err)
+       options, rootCmd := kamelTestPreAddCommandInitWithClient(fakeClient)
+       options.Namespace = "default"
+       debugCmdOptions := addTestDebugCmd(*options, rootCmd)
+       kamelTestPostAddCommandInit(t, rootCmd, options)
+
+       return rootCmd, debugCmdOptions
+}
+
+func addTestDebugCmd(options RootCmdOptions, rootCmd *cobra.Command) 
*debugCmdOptions {
+       debugCmd, debugOptions := newCmdDebug(&options)
+       debugCmd.Args = test.ArbitraryArgs
+       rootCmd.AddCommand(debugCmd)
+       return debugOptions
+}
+
+func TestToggle(t *testing.T) {
+       defaultIntegration, defaultKit := nominalDebugIntegration("my-it-test")
+
+       _, debugCmdOptions := initializeDebugCmdOptions(t, &defaultIntegration, 
&defaultKit)
+       // toggle on
+       it := debugCmdOptions.toggle(&defaultIntegration, true)
+       assert.Equal(t, pointer.Bool(true), it.Spec.Traits.JVM.Debug)
+       // toggle off
+       it = debugCmdOptions.toggle(&defaultIntegration, false)
+       assert.Nil(t, it.Spec.Traits.JVM.Debug)
+}
+
+func nominalDebugIntegration(name string) (v1.Integration, v1.IntegrationKit) {
+       it := v1.NewIntegration("default", name)
+       it.Status.Phase = v1.IntegrationPhaseRunning
+       it.Status.Image = "my-special-image"
+       ik := v1.NewIntegrationKit("default", name+"-kit")
+       it.Status.IntegrationKit = &corev1.ObjectReference{
+               Namespace: ik.Namespace,
+               Name:      ik.Name,
+               Kind:      ik.Kind,
+       }
+       return it, *ik
+}
diff --git a/pkg/trait/health.go b/pkg/trait/health.go
index 7f764fb7b..b2bd3558a 100644
--- a/pkg/trait/health.go
+++ b/pkg/trait/health.go
@@ -60,11 +60,15 @@ func (t *healthTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
                !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && 
!e.IntegrationInRunningPhases() {
                return false, nil, nil
        }
-       if !pointer.BoolDeref(t.Enabled, false) {
-               return false, nil, nil
+
+       // The trait must be disabled if a debug operation is ongoing
+       if jt := e.Catalog.GetTrait(jvmTraitID); jt != nil {
+               if jvm, ok := jt.(*jvmTrait); ok && 
pointer.BoolDeref(jvm.Debug, false) {
+                       return false, 
NewIntegrationConditionPlatformDisabledWithMessage("Health", "debug operation 
ongoing: incompatible with health checks"), nil
+               }
        }
 
-       return true, nil, nil
+       return pointer.BoolDeref(t.Enabled, true), nil, nil
 }
 
 func (t *healthTrait) Apply(e *Environment) error {
diff --git a/pkg/trait/health_test.go b/pkg/trait/health_test.go
index 1de406671..571908f7f 100644
--- a/pkg/trait/health_test.go
+++ b/pkg/trait/health_test.go
@@ -23,6 +23,7 @@ import (
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
 
+       appsv1 "k8s.io/api/apps/v1"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/utils/pointer"
@@ -116,5 +117,110 @@ func TestHealthTrait(t *testing.T) {
        assert.Nil(t, d.Spec.Template.Spec.Containers[0].ReadinessProbe)
        assert.NotNil(t, d.Spec.Template.Spec.Containers[0].StartupProbe)
        assert.Equal(t, "/q/health/started", 
d.Spec.Template.Spec.Containers[0].StartupProbe.HTTPGet.Path)
+}
+
+func TestConfigureHealthTraitDoesSucceed(t *testing.T) {
+       ht, environment := createNominalHealthTrait(t)
+       configured, condition, err := ht.Configure(environment)
+
+       assert.True(t, configured)
+       assert.Nil(t, err)
+       assert.Nil(t, condition)
+}
+
+func TestConfigureHealthTraitDisabled(t *testing.T) {
+       enabled := false
+       ht, environment := createNominalHealthTrait(t)
+       ht.Enabled = &enabled
+       configured, condition, err := ht.Configure(environment)
+
+       assert.False(t, configured)
+       assert.Nil(t, err)
+       assert.Nil(t, condition)
+}
+
+func TestApplyHealthTraitDefault(t *testing.T) {
+       ht, environment := createNominalHealthTrait(t)
+       configured, condition, err := ht.Configure(environment)
+       assert.True(t, configured)
+       assert.Nil(t, err)
+       assert.Nil(t, condition)
+
+       err = ht.Apply(environment)
+       assert.Nil(t, err)
+       assert.Equal(t, "/q/health/ready", 
environment.GetIntegrationContainer().ReadinessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTP, 
environment.GetIntegrationContainer().ReadinessProbe.HTTPGet.Scheme)
+       assert.Equal(t, "8080", 
environment.GetIntegrationContainer().ReadinessProbe.HTTPGet.Port.String())
+}
+func TestApplyHealthTraitLivenessDefault(t *testing.T) {
+       enabled := true
+       ht, environment := createNominalHealthTrait(t)
+       ht.LivenessProbeEnabled = &enabled
+       configured, condition, err := ht.Configure(environment)
+       assert.True(t, configured)
+       assert.Nil(t, err)
+       assert.Nil(t, condition)
+
+       err = ht.Apply(environment)
+       assert.Nil(t, err)
+       assert.Equal(t, "/q/health/live", 
environment.GetIntegrationContainer().LivenessProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTP, 
environment.GetIntegrationContainer().LivenessProbe.HTTPGet.Scheme)
+       assert.Equal(t, "8080", 
environment.GetIntegrationContainer().LivenessProbe.HTTPGet.Port.String())
+}
+
+func TestApplyHealthTraitStartupDefault(t *testing.T) {
+       enabled := true
+       ht, environment := createNominalHealthTrait(t)
+       ht.StartupProbeEnabled = &enabled
+       configured, condition, err := ht.Configure(environment)
+       assert.True(t, configured)
+       assert.Nil(t, err)
+       assert.Nil(t, condition)
+
+       err = ht.Apply(environment)
+       assert.Nil(t, err)
+       assert.Equal(t, "/q/health/started", 
environment.GetIntegrationContainer().StartupProbe.HTTPGet.Path)
+       assert.Equal(t, corev1.URISchemeHTTP, 
environment.GetIntegrationContainer().StartupProbe.HTTPGet.Scheme)
+       assert.Equal(t, "8080", 
environment.GetIntegrationContainer().StartupProbe.HTTPGet.Port.String())
+}
+
+func createNominalHealthTrait(t *testing.T) (*healthTrait, *Environment) {
+       t.Helper()
+       catalog, err := camel.DefaultCatalog()
+       assert.Nil(t, err)
+       trait, _ := newHealthTrait().(*healthTrait)
+
+       environment := &Environment{
+               CamelCatalog: catalog,
+               Catalog:      NewCatalog(nil),
+               Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name:       "integration-name",
+                               Generation: 1,
+                       },
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+               Resources: kubernetes.NewCollection(),
+       }
+
+       deployment := appsv1.Deployment{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "Deployment",
+                       APIVersion: appsv1.SchemeGroupVersion.String(),
+               },
+               Spec: appsv1.DeploymentSpec{
+                       Template: corev1.PodTemplateSpec{
+                               Spec: corev1.PodSpec{
+                                       Containers: []corev1.Container{
+                                               {Name: "integration"},
+                                       },
+                               },
+                       },
+               },
+       }
+       environment.Resources.Add(&deployment)
 
+       return trait, environment
 }
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 57a59081a..06166a894 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -40,6 +40,10 @@ import (
        "github.com/apache/camel-k/v2/pkg/util/sets"
 )
 
+const (
+       jvmTraitID = "jvm"
+)
+
 type jvmTrait struct {
        BaseTrait
        traitv1.JVMTrait `property:",squash"`
@@ -47,7 +51,7 @@ type jvmTrait struct {
 
 func newJvmTrait() Trait {
        return &jvmTrait{
-               BaseTrait: NewBaseTrait("jvm", 2000),
+               BaseTrait: NewBaseTrait(jvmTraitID, 2000),
                JVMTrait: traitv1.JVMTrait{
                        DebugAddress: "*:5005",
                        PrintCommand: pointer.Bool(true),
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index db1dc7cf8..f7fc02e12 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -561,7 +561,7 @@ func TestExecutedTraitsCondition(t *testing.T) {
                v1.IntegrationConditionTraitInfo,
                corev1.ConditionTrue,
                "TraitConfiguration",
-               "Applied traits: 
camel,environment,logging,deployer,deployment,gc,container,mount,quarkus,jvm,owner",
+               "Applied traits: 
camel,environment,logging,deployer,deployment,gc,container,mount,health,quarkus,jvm,owner",
        )
        assert.Contains(t, conditions, expectedCondition)
 }

Reply via email to