Repository: apache/camel-k
Pull request #2527 (2021-07-23 21:14:53)

Allow Probe Scheme to Be Customized
<!-- Description -->

Addresses https://github.com/apache/camel-k/issues/2513. This change allows the scheme used for the liveness and readiness probes to be overridden to HTTPS when needed. The approach taken was minimalistic.

Verified using this groovy script saved to /tmp/helloworld.groovy
```
from('timer:tick?period=3000')
  .setBody().constant('Hello world from Camel K')
  .to('log:info')
```
and an integration deployed with the following commands
```
openssl req -x509 -newkey rsa:4096 -keyout /tmp/integration-key.pem -out /tmp/integration-cert.pem -days 365 -nodes

kubectl create secret tls my-tls-secret --cert=/tmp/integration-cert.pem --key=/tmp/integration-key.pem

kamel run \
  --property quarkus.http.ssl.certificate.file=/etc/camel/conf.d/_secrets/my-tls-secret/tls.crt \
  --property quarkus.http.ssl.certificate.key-file=/etc/camel/conf.d/_secrets/my-tls-secret/tls.key \
  --config secret:my-tls-secret \
  /tmp/helloworld.groovy \
  --trait container.port=8443 \
  --trait container.probes-enabled=true \
  --trait container.liveness-scheme=HTTPS \
  --trait container.readiness-scheme=HTTPS
```

<!--
Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". 

You can (optionally) mark this PR with labels "kind/bug" or "kind/feature" to make sure
the text is added to the right section of the release notes. 
-->

**Release Note**
```release-note
Allow the scheme used for the liveness and readiness probes to be overridden
```


squakez: @Kyle-Cooley do you think you can include that simple example under [trait/container example directory](https://github.com/apache/camel-k/tree/main/examples/traits) (it has to be created)?

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e58a5207..2d6e85062 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@
 
 **Merged pull requests:**
 
+- \[test\] Remove 3rd party dependencies [\#2529](https://github.com/apache/camel-k/pull/2529) ([bouskaJ](https://github.com/bouskaJ))
 - Use https instead of http for xsd location [\#2517](https://github.com/apache/camel-k/pull/2517) ([apupier](https://github.com/apupier))
 - Add classpath kamelet loading test [\#2516](https://github.com/apache/camel-k/pull/2516) ([bouskaJ](https://github.com/bouskaJ))
 - fix\(\#2514\): Fix tar.gz changes the uid/gid of cwd [\#2515](https://github.com/apache/camel-k/pull/2515) ([christophd](https://github.com/christophd))
@@ -37,6 +38,7 @@
 - Fix \#2468: parse all YAML nodes in the tree [\#2476](https://github.com/apache/camel-k/pull/2476) ([nicolaferraro](https://github.com/nicolaferraro))
 - fix\(cli\) Duplicated trait set as modeline and kamel run parameters causes error [\#2467](https://github.com/apache/camel-k/pull/2467) ([claudio4j](https://github.com/claudio4j))
 - doc\(architecture\): trait section [\#2465](https://github.com/apache/camel-k/pull/2465) ([squakez](https://github.com/squakez))
+- test: Missing cli e2e tests implementation [\#2461](https://github.com/apache/camel-k/pull/2461) ([vsokolov00](https://github.com/vsokolov00))
 - chore: Remove Camel Sources support from Knative trait [\#2460](https://github.com/apache/camel-k/pull/2460) ([astefanutti](https://github.com/astefanutti))
 - chore: Update embedded camel-catalog-1.8.0-SNAPSHOT.yaml [\#2459](https://github.com/apache/camel-k/pull/2459) ([astefanutti](https://github.com/astefanutti))
 - chore: Remove unsupported probe-path property from container trait [\#2458](https://github.com/apache/camel-k/pull/2458) ([astefanutti](https://github.com/astefanutti))
diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index 7803458b8..e1b7d627f 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -129,6 +129,10 @@ traits:
   - name: probes-enabled
     type: bool
     description: ProbesEnabled enable/disable probes on the container (default `false`)
+  - name: liveness-scheme
+    type: string
+    description: Scheme to use when connecting. Defaults to HTTP. Applies to the liveness
+      probe.
   - name: liveness-initial-delay
     type: int32
     description: Number of seconds after the container has started before liveness
@@ -148,6 +152,10 @@ traits:
     type: int32
     description: Minimum consecutive failures for the probe to be considered failed
       after having succeeded.Applies to the liveness probe.
+  - name: readiness-scheme
+    type: string
+    description: Scheme to use when connecting. Defaults to HTTP. Applies to the readiness
+      probe.
   - name: readiness-initial-delay
     type: int32
     description: Number of seconds after the container has started before readiness
diff --git a/docs/modules/traits/pages/container.adoc b/docs/modules/traits/pages/container.adoc
index 9fdf63b55..2a4dc45b8 100755
--- a/docs/modules/traits/pages/container.adoc
+++ b/docs/modules/traits/pages/container.adoc
@@ -81,6 +81,10 @@ The following configuration options are available:
 | bool
 | ProbesEnabled enable/disable probes on the container (default `false`)
 
+| container.liveness-scheme
+| string
+| Scheme to use when connecting. Defaults to HTTP. Applies to the liveness probe.
+
 | container.liveness-initial-delay
 | int32
 | Number of seconds after the container has started before liveness probes are initiated.
@@ -103,6 +107,10 @@ Applies to the liveness probe.
 | Minimum consecutive failures for the probe to be considered failed after having succeeded.
 Applies to the liveness probe.
 
+| container.readiness-scheme
+| string
+| Scheme to use when connecting. Defaults to HTTP. Applies to the readiness probe.
+
 | container.readiness-initial-delay
 | int32
 | Number of seconds after the container has started before readiness probes are initiated.
diff --git a/examples/traits/container/HttpsHealthChecks.java b/examples/traits/container/HttpsHealthChecks.java
new file mode 100644
index 000000000..3607fc748
--- /dev/null
+++ b/examples/traits/container/HttpsHealthChecks.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+// Generate a certificate for the integration (provide at least Country Name, can use defaults for rest)
+// openssl req -x509 -newkey rsa:4096 -keyout /tmp/integration-key.pem -out /tmp/integration-cert.pem -days 365 -nodes
+
+// Create a secret containing the generated certificate
+// kubectl create secret tls my-tls-secret --cert=/tmp/integration-cert.pem --key=/tmp/integration-key.pem
+
+// Run the integration
+/*
+kamel run \
+  --property quarkus.http.ssl.certificate.file=/etc/camel/conf.d/_secrets/my-tls-secret/tls.crt \
+  --property quarkus.http.ssl.certificate.key-file=/etc/camel/conf.d/_secrets/my-tls-secret/tls.key \
+  --config secret:my-tls-secret \
+  HttpsHealthChecks.java \
+  --trait container.port=8443 \
+  --trait container.probes-enabled=true \
+  --trait container.liveness-scheme=HTTPS \
+  --trait container.readiness-scheme=HTTPS
+*/
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class HttpsHealthChecks extends RouteBuilder {
+    @Override
+    public void configure() throws Exception {
+        from("timer:tick")
+            .setBody()
+            .constant("Hello Camel K!")
+            .to("log:info");
+    }
+}
diff --git a/examples/traits/container/README.md b/examples/traits/container/README.md
new file mode 100644
index 000000000..144142a31
--- /dev/null
+++ b/examples/traits/container/README.md
@@ -0,0 +1,3 @@
+# Camel K Container Trait
+
+In this section you will find examples about fine tuning your `Integration` using **Container** `trait` capability.
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 429d10425..ecdd83336 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -81,6 +81,8 @@ type containerTrait struct {
 
 	// ProbesEnabled enable/disable probes on the container (default `false`)
 	ProbesEnabled *bool `property:"probes-enabled" json:"probesEnabled,omitempty"`
+	// Scheme to use when connecting. Defaults to HTTP. Applies to the liveness probe.
+	LivenessScheme string `property:"liveness-scheme" json:"livenessScheme,omitempty"`
 	// Number of seconds after the container has started before liveness probes are initiated.
 	LivenessInitialDelay int32 `property:"liveness-initial-delay" json:"livenessInitialDelay,omitempty"`
 	// Number of seconds after which the probe times out. Applies to the liveness probe.
@@ -93,6 +95,8 @@ type containerTrait struct {
 	// Minimum consecutive failures for the probe to be considered failed after having succeeded.
 	// Applies to the liveness probe.
 	LivenessFailureThreshold int32 `property:"liveness-failure-threshold" json:"livenessFailureThreshold,omitempty"`
+	// Scheme to use when connecting. Defaults to HTTP. Applies to the readiness probe.
+	ReadinessScheme string `property:"readiness-scheme" json:"readinessScheme,omitempty"`
 	// Number of seconds after the container has started before readiness probes are initiated.
 	ReadinessInitialDelay int32 `property:"readiness-initial-delay" json:"readinessInitialDelay,omitempty"`
 	// Number of seconds after which the probe times out. Applies to the readiness probe.
@@ -115,6 +119,8 @@ func newContainerTrait() Trait {
 		ServicePortName: defaultContainerPortName,
 		Name:            defaultContainerName,
 		ProbesEnabled:   util.BoolP(false),
+		LivenessScheme:  string(corev1.URISchemeHTTP),
+		ReadinessScheme: string(corev1.URISchemeHTTP),
 	}
 }
 
@@ -433,6 +439,7 @@ func (t *containerTrait) configureProbes(container *corev1.Container, port int,
 func (t *containerTrait) newLivenessProbe(port int, path string) *corev1.Probe {
 	action := corev1.HTTPGetAction{}
 	action.Path = path
+	action.Scheme = corev1.URIScheme(t.LivenessScheme)
 
 	if port > 0 {
 		action.Port = intstr.FromInt(port)
@@ -457,8 +464,9 @@ func (t *containerTrait) newReadinessProbe(port int, path string) *corev1.Probe
 	p := corev1.Probe{
 		Handler: corev1.Handler{
 			HTTPGet: &corev1.HTTPGetAction{
-				Port: intstr.FromInt(port),
-				Path: path,
+				Port:   intstr.FromInt(port),
+				Path:   path,
+				Scheme: corev1.URIScheme(t.ReadinessScheme),
 			},
 		},
 	}


Test patch:
diff --git a/e2e/common/cli/bind_test.go b/e2e/common/cli/bind_test.go
new file mode 100644
index 000000000..cdab11582
--- /dev/null
+++ b/e2e/common/cli/bind_test.go
@@ -0,0 +1,53 @@
+// +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 common
+
+import (
+	v1 "k8s.io/api/core/v1"
+	"testing"
+
+	. "github.com/onsi/gomega"
+
+	. "github.com/apache/camel-k/e2e/support"
+)
+
+func TestKamelCLIBind(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+		Expect(CreateTimerKamelet(ns, "test-timer-source")()).To(Succeed())
+
+		t.Run("bind timer to log", func(t *testing.T) {
+			Expect(Kamel("bind", "test-timer-source", "log:info", "-p", "source.message=helloTest", "-n", ns).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, "test-timer-source-to-log"), TestTimeoutLong).Should(Equal(v1.PodRunning))
+
+			Eventually(IntegrationLogs(ns, "test-timer-source-to-log")).Should(ContainSubstring("Body: helloTest"))
+			Expect(Kamel("bind", "test-timer-source", "log:info", "-p", "source.message=newText", "-n", ns).Execute()).To(Succeed())
+			Eventually(IntegrationLogs(ns, "test-timer-source-to-log")).Should(ContainSubstring("Body: newText"))
+
+			Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed())
+		})
+
+		t.Run("unsuccessful binding, no property", func(t *testing.T) {
+			Expect(Kamel("bind", "timer-source", "log:info", "-n", ns).Execute()).NotTo(Succeed())
+		})
+	})
+}
diff --git a/e2e/common/cli/log_test.go b/e2e/common/cli/log_test.go
new file mode 100644
index 000000000..922b83220
--- /dev/null
+++ b/e2e/common/cli/log_test.go
@@ -0,0 +1,50 @@
+// +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 common
+
+import (
+	v1 "k8s.io/api/core/v1"
+	"strings"
+	"testing"
+
+	. "github.com/onsi/gomega"
+
+	. "github.com/apache/camel-k/e2e/support"
+)
+
+func TestKamelCLILog(t *testing.T) {
+	WithNewTestNamespace(t, func(ns string) {
+		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
+
+		t.Run("check integration log", func(t *testing.T) {
+			Expect(Kamel("run", "../files/yaml.yaml", "-n", ns).Execute()).To(Succeed())
+			Eventually(IntegrationPodPhase(ns, "yaml"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+			//first line of the integration logs
+			logs := strings.Split(IntegrationLogs(ns, "yaml")(), "\n")[0]
+			podName := IntegrationPod(ns, "yaml")().Name
+
+			logsCLI := GetOutputStringAsync(Kamel("log", "yaml", "-n", ns))
+			Eventually(logsCLI).Should(ContainSubstring("Monitoring pod " + podName))
+			Eventually(logsCLI).Should(ContainSubstring(logs))
+		})
+	})
+}
diff --git a/e2e/common/files/ChuckNorrisKamelet.java b/e2e/common/files/TimerKameletIntegration.java
similarity index 86%
rename from e2e/common/files/ChuckNorrisKamelet.java
rename to e2e/common/files/TimerKameletIntegration.java
index 34103073b..c3412a929 100644
--- a/e2e/common/files/ChuckNorrisKamelet.java
+++ b/e2e/common/files/TimerKameletIntegration.java
@@ -19,11 +19,10 @@ import java.lang.Exception;
 import java.lang.Override;
 import org.apache.camel.builder.RouteBuilder;
 
-public class ChuckNorrisKamelet extends RouteBuilder {
+public class TimerKameletIntegration extends RouteBuilder {
     @Override
     public void configure() throws Exception {
-        from("kamelet:chuck-norris-source")
-            .setBody(simple("Received another joke: ${body}"))
+        from("kamelet:timer-source?message=important%20message")
             .to("log:info");
     }
 }
diff --git a/e2e/common/files/timer-source.kamelet.yaml b/e2e/common/files/timer-source.kamelet.yaml
new file mode 100644
index 000000000..3c0957284
--- /dev/null
+++ b/e2e/common/files/timer-source.kamelet.yaml
@@ -0,0 +1,69 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+apiVersion: camel.apache.org/v1alpha1
+kind: Kamelet
+metadata:
+  name: timer-source
+  annotations:
+    camel.apache.org/kamelet.support.level: "Preview"
+    camel.apache.org/catalog.version: "0.3.0"
+    camel.apache.org/kamelet.icon: data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gU3ZnIFZlY3RvciBJY29ucyA6IGh0dHA6Ly93d3cub25saW5ld2ViZm9udHMuY29tL2ljb24gLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPG1ldGFkYXRhPiBTdmcgVmVjdG9yIEljb25zIDogaHR0cDovL3d3dy5vbmxpbmV3ZWJmb250cy5jb20vaWNvbiA8L21ldGFkYXRhPg0KPGc+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsNTExLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSI+PHBhdGggZD0iTTM4ODguMSw0Nzc0Ljl2LTIzNS4xaDQxMS40aDQxNC4zbC04LjgtMzI5LjFsLTguOC0zMzJsLTExNy41LTguOGMtMjI5LjItMTQuNy02MjAtOTkuOS05MjUuNi0xOTYuOUMyMjU3LjQsMzIyMC42LDExNjcuMiwyMDY1LjgsODAyLjksNjQ5LjZjLTUxMS4zLTE5ODYuMywzODQuOS00MDAyLDIyMDYuNy00OTY1LjhjMzAyLjYtMTYxLjYsNzU4LjEtMzIwLjIsMTE1NC44LTQwNS41YzQyNi4xLTkxLjEsMTI1MS43LTkxLjEsMTY4MC43LDBjMTc2OC45LDM4MiwzMDQ0LjEsMTY1Ny4yLDM0MjYuMSwzNDI2LjFjOTEuMSw0MjYuMSw5MS4xLDEyNTQuNiwwLDE2NzcuOGMtNDIwLjIsMTk0Mi4yLTE5MzYuNCwzMzAyLjYtMzg5MC4zLDM0OTYuNmwtMTk5LjgsMjAuNnYzMjAuM3YzMjAuM2g0MTEuNGg0MTEuNHYyMzUuMVY1MDEwSDQ5NDUuOUgzODg4LjFWNDc3NC45eiBNNTc1My45LDMzNDkuOWM3NzguNy0xNjEuNiwxNDE5LjItNTA4LjMsMTk4My40LTEwNzIuNWM1NjQuMi01NjEuMiw4ODcuNC0xMTU3LjcsMTA2MC43LTE5NDIuMmM5OS45LTQzNy44LDk5LjktMTE0MywzLTE1ODAuOEM4NTYzLTIzMDYuNCw3OTY2LjUtMzE1OC41LDcwNDMuOS0zNzUyYy0zMzUtMjE0LjUtNzg3LjUtMzk2LjctMTI0OC44LTQ5OS41Yy00MzcuOC05Ny0xMTQzLTk3LTE1ODAuOCwyLjljLTc4NC41LDE3My4zLTEzODEsNDk2LjYtMTk0Mi4yLDEwNjAuN2MtNTcwLDU2Ny4xLTkwNy45LDExOTguOC0xMDc4LjQsMTk5OC4xYy03My41LDM0Ni43LTczLjUsMTEyMi40LDAsMTQ2OS4yYzE3MC40LDc5OS4yLDUwOC4zLDE0MzEsMTA3OC40LDE5OThDMjg5NSwyOTAwLjMsMzYzOC40LDMyNzMuNSw0NDkzLjQsMzM5MUM0Nzc4LjQsMzQzMi4xLDU0NzQuOCwzNDA4LjYsNTc1My45LDMzNDkuOXoiLz48cGF0aCBkPSJNNDcxMC44LDEzNzUuM1YyMDUuOUw0NTUyLjIsNjcuOGMtMzE3LjMtMjc5LjEtMzQwLjgtNjc4LjctNTUuOC05OTMuMWMyODcuOS0zMjAuMyw2OTMuNC0zMTcuMywxMDEzLjcsNS45bDE3MC40LDE3MC40aDEwNDMuMWgxMDQzLjFWLTUxNFYtMjc5SDY3MjkuNUg1NjkyLjJsLTQ5LjksMTE0LjZjLTU4LjgsMTMyLjItMjUyLjcsMzE3LjMtMzc2LjEsMzYxLjRsLTg1LjIsMjkuNHYxMTU3Ljd2MTE1Ny43aC0yMzUuMWgtMjM1LjFWMTM3NS4zeiBNNTE2Ni4zLTI5My42YzE0Ni45LTE0NCw0NC4xLTM5Ni43LTE2MS42LTM5Ni43Yy01NS44LDAtMTE3LjUsMjYuNC0xNjEuNiw3My40Yy00Nyw0NC4xLTczLjUsMTA1LjgtNzMuNSwxNjEuNnMyNi40LDExNy41LDczLjUsMTYxLjZjNDQuMSw0NywxMDUuOCw3My41LDE2MS42LDczLjVDNTA2MC41LTIyMC4yLDUxMjIuMi0yNDYuNyw1MTY2LjMtMjkzLjZ6Ii8+PC9nPjwvZz4NCjwvc3ZnPg==
+    camel.apache.org/provider: "Apache Software Foundation"
+    camel.apache.org/kamelet.group: "Timer"
+  labels:
+    camel.apache.org/kamelet.type: source
+    camel.apache.org/kamelet.verified: "true"
+spec:
+  definition:
+    title: Timer Source
+    description: Produces periodic events with a custom payload.
+    required:
+      - message
+    type: object
+    properties:
+      period:
+        title: Period
+        description: The interval between two events in milliseconds
+        type: integer
+        default: 1000
+      message:
+        title: Message
+        description: The message to generate
+        type: string
+        example: hello world
+      contentType:
+        title: Content Type
+        description: The content type of the message being generated
+        type: string
+        default: text/plain
+  dependencies:
+    - "camel:core"
+    - "camel:timer"
+    - "camel:kamelet"
+  flow:
+    from:
+      uri: timer:tick
+      parameters:
+        period: "{{period}}"
+      steps:
+        - set-body:
+            constant: "{{message}}"
+        - set-header:
+            name: "Content-Type"
+            constant: "{{contentType}}"
+        - to: kamelet:sink
diff --git a/e2e/common/kamelet_test.go b/e2e/common/kamelet_test.go
index 13dd19f95..4db8a319d 100644
--- a/e2e/common/kamelet_test.go
+++ b/e2e/common/kamelet_test.go
@@ -34,21 +34,20 @@ func TestKameletClasspathLoading(t *testing.T) {
 	WithNewTestNamespace(t, func(ns string) {
 		Expect(Kamel("install", "-n", ns).Execute()).To(Succeed())
 
-		kameletName := "chuck-norris-source"
+		kameletName := "timer-source"
 		removeKamelet(kameletName , ns)
 
 		Eventually(Kamelet(kameletName, ns)).Should(BeNil())
 
-		Expect(Kamel("run", "files/ChuckNorrisKamelet.java", "-n", ns, "-t", "kamelets.enabled=false",
-			"-d", "github:apache.camel-kamelets:camel-kamelets-catalog:main-SNAPSHOT",
+		Expect(Kamel("run", "files/TimerKameletIntegration.java", "-n", ns, "-t", "kamelets.enabled=false",
+			"--resource", "file:files/timer-source.kamelet.yaml@/kamelets/timer-source.kamelet.yaml",
+			"-p camel.component.kamelet.location=file:/kamelets",
 			"-d", "camel:yaml-dsl",
 			// kamelet dependencies
-			"-d", "camel:timer",
-			"-d", "camel:jsonpath",
-			"-d", "camel:http").Execute()).To(Succeed())
-		Eventually(IntegrationPodPhase(ns, "chuck-norris-kamelet"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
+			"-d", "camel:timer").Execute()).To(Succeed())
+		Eventually(IntegrationPodPhase(ns, "timer-kamelet-integration"), TestTimeoutMedium).Should(Equal(v1.PodRunning))
 
-		Eventually(IntegrationLogs(ns, "chuck-norris-kamelet")).Should(ContainSubstring("Received another joke:"))
+		Eventually(IntegrationLogs(ns, "timer-kamelet-integration")).Should(ContainSubstring("important message"))
 
 		// Cleanup
 		Expect(Kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
diff --git a/e2e/support/test_support.go b/e2e/support/test_support.go
index 01a4536bc..424e49232 100644
--- a/e2e/support/test_support.go
+++ b/e2e/support/test_support.go
@@ -1372,3 +1372,15 @@ func GetOutputString(command *cobra.Command) string {
 
 	return buf.String()
 }
+
+func GetOutputStringAsync(cmd *cobra.Command) func() string {
+	var buffer bytes.Buffer
+	stdout := bufio.NewWriter(&buffer)
+
+	cmd.SetOut(stdout)
+	go cmd.Execute()
+
+	return func() string {
+		return buffer.String()
+	}
+}
diff --git a/pkg/trait/container_probes_test.go b/pkg/trait/container_probes_test.go
index 57fb6fb8f..b58c7f2ac 100644
--- a/pkg/trait/container_probes_test.go
+++ b/pkg/trait/container_probes_test.go
@@ -25,6 +25,7 @@ import (
 	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	appsv1 "k8s.io/api/apps/v1"
+	corev1 "k8s.io/api/core/v1"
 
 	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
 	"github.com/apache/camel-k/pkg/util"
@@ -97,9 +98,40 @@ func TestProbesOnDeployment(t *testing.T) {
 	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
 	assert.Equal(t, int32(defaultContainerPort), target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
 	assert.Equal(t, defaultProbePath, target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
+	assert.Equal(t, corev1.URISchemeHTTP, target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Scheme)
 	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
 	assert.Equal(t, int32(defaultContainerPort), target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
 	assert.Equal(t, defaultProbePath, target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
+	assert.Equal(t, corev1.URISchemeHTTP, target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Scheme)
+	assert.Equal(t, int32(1234), target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
+}
+
+func TestProbesOnDeploymentWithCustomScheme(t *testing.T) {
+	target := appsv1.Deployment{}
+
+	env := newTestProbesEnv(t, v1.RuntimeProviderQuarkus)
+	env.Integration.Status.Phase = v1.IntegrationPhaseDeploying
+	env.Resources.Add(&target)
+
+	expose := true
+
+	ctr := newTestContainerTrait()
+	ctr.Expose = &expose
+	ctr.LivenessTimeout = 1234
+	ctr.LivenessScheme = "HTTPS"
+	ctr.ReadinessScheme = "HTTPS"
+
+	err := ctr.Apply(&env)
+	assert.Nil(t, err)
+
+	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(defaultContainerPort), target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, defaultProbePath, target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Path)
+	assert.Equal(t, corev1.URISchemeHTTPS, target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Scheme)
+	assert.Equal(t, "", target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Host)
+	assert.Equal(t, int32(defaultContainerPort), target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Port.IntVal)
+	assert.Equal(t, defaultProbePath, target.Spec.Template.Spec.Containers[0].ReadinessProbe.HTTPGet.Path)
+	assert.Equal(t, corev1.URISchemeHTTPS, target.Spec.Template.Spec.Containers[0].LivenessProbe.HTTPGet.Scheme)
 	assert.Equal(t, int32(1234), target.Spec.Template.Spec.Containers[0].LivenessProbe.TimeoutSeconds)
 }