Skip to content

Commit 668080b

Browse files
committed
feat(traits): JVM agents
Closes #6123
1 parent 9958726 commit 668080b

20 files changed

+623
-104
lines changed

docs/modules/ROOT/partials/apis/camel-k-crds.adoc

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7469,19 +7469,12 @@ The InitContainersTrait trait can be used to configure `init containers` or `sid
74697469
|Field
74707470
|Description
74717471
7472-
|`PlatformBaseTrait` +
7473-
*xref:#_camel_apache_org_v1_trait_PlatformBaseTrait[PlatformBaseTrait]*
7474-
|(Members of `PlatformBaseTrait` are embedded into this type.)
7475-
7476-
7477-
7472+
|`Trait` +
7473+
*xref:#_camel_apache_org_v1_trait_Trait[Trait]*
7474+
|(Members of `Trait` are embedded into this type.)
74787475
7479-
|`auto` +
7480-
bool
7481-
|
74827476
74837477
7484-
To automatically enable the trait
74857478
74867479
|`initTasks` +
74877480
[]string
@@ -7614,6 +7607,13 @@ string
76147607
76157608
The Jar dependency which will run the application. Leave it empty for managed Integrations.
76167609
7610+
|`agents` +
7611+
[]string
7612+
|
7613+
7614+
7615+
A list of JVM agents to download and execute with format `<agent-name>;<agent-url>[;<jvm-agent-options>]`.
7616+
76177617
76187618
|===
76197619
@@ -8383,7 +8383,6 @@ Only one of `max-unavailable` and `min-available` can be specified.
83838383
* <<#_camel_apache_org_v1_trait_DeploymentTrait, DeploymentTrait>>
83848384
* <<#_camel_apache_org_v1_trait_EnvironmentTrait, EnvironmentTrait>>
83858385
* <<#_camel_apache_org_v1_trait_ErrorHandlerTrait, ErrorHandlerTrait>>
8386-
* <<#_camel_apache_org_v1_trait_InitContainersTrait, InitContainersTrait>>
83878386
* <<#_camel_apache_org_v1_trait_MountTrait, MountTrait>>
83888387
* <<#_camel_apache_org_v1_trait_OpenAPITrait, OpenAPITrait>>
83898388
* <<#_camel_apache_org_v1_trait_PlatformTrait, PlatformTrait>>
@@ -9174,6 +9173,7 @@ The list of taints to tolerate, in the form `Key[=Value]:Effect[:Seconds]`
91749173
* <<#_camel_apache_org_v1_trait_GCTrait, GCTrait>>
91759174
* <<#_camel_apache_org_v1_trait_HealthTrait, HealthTrait>>
91769175
* <<#_camel_apache_org_v1_trait_IngressTrait, IngressTrait>>
9176+
* <<#_camel_apache_org_v1_trait_InitContainersTrait, InitContainersTrait>>
91779177
* <<#_camel_apache_org_v1_trait_IstioTrait, IstioTrait>>
91789178
* <<#_camel_apache_org_v1_trait_JVMTrait, JVMTrait>>
91799179
* <<#_camel_apache_org_v1_trait_JolokiaTrait, JolokiaTrait>>

docs/modules/traits/pages/init-containers.adoc

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ The InitContainersTrait trait can be used to configure `init containers` or `sid
88

99
This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
1010

11-
NOTE: The init-containers trait is a *platform trait* and cannot be disabled by the user.
12-
1311
// End of autogenerated code - DO NOT EDIT! (description)
1412
// Start of autogenerated code - DO NOT EDIT! (configuration)
1513
== Configuration
@@ -27,11 +25,7 @@ The following configuration options are available:
2725

2826
| init-containers.enabled
2927
| bool
30-
| Deprecated: no longer in use.
31-
32-
| init-containers.auto
33-
| bool
34-
| To automatically enable the trait
28+
| Can be used to enable or disable a trait. All traits share this common property.
3529

3630
| init-containers.init-tasks
3731
| []string
@@ -58,7 +52,7 @@ Create an Integration which read some value initialized by an init container. Th
5852
# by the initContainer
5953
uri: file:/tmp
6054
parameters:
61-
fileName: init
55+
include: ^(init).*
6256
steps:
6357
- log:
6458
message: "${body}"
@@ -70,7 +64,39 @@ When creating the Integration, then, it should include an init container taking
7064

7165
[source,console]
7266
----
73-
kamel run route.yaml -t mount.empty-dirs=common:/tmp -t init-containers.tasks="init;alpine;/bin/sh -c \"echo hello >> /tmp/init\""
67+
kamel run route.yaml -t mount.empty-dirs=common:/tmp -t init-containers.init-tasks="init;alpine;/bin/sh -c \"echo hello >> /tmp/init\""
7468
----
7569

7670
As the file is shared between the containers you will need to provide a shared volume (an `EmtpyDir` in this case).
71+
72+
== An example sidecar container
73+
74+
Create an Integration which generate some values on a folder shared by the main Integration. This process is done by a `sidecar` container. The route takes care to read the files without knowing the process generating.
75+
76+
[source,yaml]
77+
.route.yaml
78+
----
79+
- route:
80+
from:
81+
# Read a file that should have been initialized
82+
# by the initContainer
83+
uri: file:/tmp
84+
parameters:
85+
include: ^(sidecar).*
86+
steps:
87+
- log:
88+
message: "${body}"
89+
----
90+
91+
The route is agnostic how this file is generated.
92+
93+
When creating the Integration, then, it should include the sidecar container:
94+
95+
[source,console]
96+
----
97+
kamel run route.yaml -t mount.empty-dirs=common:/tmp -t init-containers.init-tasks="init;alpine;/bin/sh -c \"echo hello >> /tmp/init\""
98+
99+
kamel run route.yaml -t mount.empty-dirs=common:/tmp -t init-containers.sidecar-tasks="sidecar;alpine;/bin/sh -c \"for i in $(seq 1 10); do echo helloSidecar$i > /tmp/sidecar_$i.txt; sleep 1; done\""
100+
----
101+
102+
As the file is shared between the containers you will need to provide a shared volume (an `EmtpyDir` in this case). Mind that the sidecar container can be any other process embedded into a docker container: in this simple case we're creating a simple script to generate some content.

docs/modules/traits/pages/jvm.adoc

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ Deprecated: no longer in use.
5858
| string
5959
| The Jar dependency which will run the application. Leave it empty for managed Integrations.
6060

61+
| jvm.agents
62+
| []string
63+
| A list of JVM agents to download and execute with format `<agent-name>;<agent-url>[;<jvm-agent-options>]`.
64+
6165
|===
6266

6367
// End of autogenerated code - DO NOT EDIT! (configuration)
@@ -73,9 +77,20 @@ $ kamel run --image docker.io/squakez/my-camel-sb:1.0.0 -t jvm.jar=/deployments/
7377

7478
The above command would allow the execution of the JVM trait given that the user specify the path to the jar to execute.
7579

76-
== Other examples
80+
== Jolokia agent configuration
81+
82+
You can use the `jvm.agents` configuration to run any given agent. Additionally you can use the other traits to expose any service provided by your agent. Take, as an example, the Jolokia JVM agent:
83+
84+
[source,console]
85+
$ kamel run test.yaml -t jvm.agents=jolokia;https://repo1.maven.org/maven2/org/jolokia/jolokia-agent-jvm/2.3.0/jolokia-agent-jvm-2.3.0-javaagent.jar;host=* -t container.ports=jolokia;8778 -t service.ports=jolokia;8778;8778 -d camel:management
86+
87+
The Jolokia endpoint will be exposed to port `8778` on the Service created for this Integration.
88+
89+
== JVM classpath
90+
91+
You can use `jvm.classpath` configuration with dependencies available externally (ie, via `mount.resources` trait):
7792

78-
* Include an additional classpath to the `Integration`:
79-
+
8093
[source,console]
81-
$ kamel run -t jvm.classpath=/path/to/my-dependency.jar:/path/to/another-dependency.jar ...
94+
kubectl create configmap my-dep --from-file=sample-1.0.jar
95+
...
96+
$ kamel run --resource configmap:my-dep -t jvm.classpath=/etc/camel/resources/my-dep/sample-1.0.jar MyApp.java

e2e/common/traits/health_test.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ func TestHealthTrait(t *testing.T) {
4848
name := RandomizedSuffixName("java")
4949
g.Expect(KamelRun(t, ctx, ns, "files/Java.java",
5050
"-t", "health.enabled=true",
51-
"-t", "jolokia.enabled=true", "-t", "jolokia.use-ssl-client-authentication=false",
52-
"-t", "jolokia.protocol=http",
51+
"-t", "jvm.agents=jolokia;https://repo1.maven.org/maven2/org/jolokia/jolokia-agent-jvm/2.3.0/jolokia-agent-jvm-2.3.0-javaagent.jar;host=*",
52+
"-t", "container.ports=jolokia;8778",
53+
"-d", "camel:management",
5354
"--name", name).Execute()).To(Succeed())
5455

5556
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))
@@ -145,8 +146,9 @@ func TestHealthTrait(t *testing.T) {
145146
name := RandomizedSuffixName("java")
146147
g.Expect(KamelRun(t, ctx, ns, "files/Java.java",
147148
"-t", "health.enabled=true",
148-
"-t", "jolokia.enabled=true", "-t", "jolokia.use-ssl-client-authentication=false",
149-
"-t", "jolokia.protocol=http",
149+
"-t", "jvm.agents=jolokia;https://repo1.maven.org/maven2/org/jolokia/jolokia-agent-jvm/2.3.0/jolokia-agent-jvm-2.3.0-javaagent.jar;host=*",
150+
"-t", "container.ports=jolokia;8778",
151+
"-d", "camel:management",
150152
"--name", name).Execute()).To(Succeed())
151153

152154
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))
@@ -230,7 +232,7 @@ func TestHealthTrait(t *testing.T) {
230232
g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutShort).Should(Equal(v1.IntegrationPhaseError))
231233
})
232234

233-
t.Run("Readiness condition with stopped binding", func(t *testing.T) {
235+
t.Run("Readiness condition with stopped pipe", func(t *testing.T) {
234236
name := RandomizedSuffixName("stopped-binding")
235237
source := RandomizedSuffixName("my-health-timer-source")
236238
sink := RandomizedSuffixName("my-health-log-sink")
@@ -405,7 +407,9 @@ func TestHealthTrait(t *testing.T) {
405407

406408
g.Expect(KamelRun(t, ctx, ns, "files/NeverReady.java", "--name", name,
407409
"-t", "health.enabled=true",
408-
"-t", "health.startup-probe-enabled=true", "-t", "health.startup-timeout=60").Execute()).To(Succeed())
410+
"-t", "health.startup-probe-enabled=true",
411+
"-t", "health.startup-timeout=60",
412+
).Execute()).To(Succeed())
409413

410414
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
411415
g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
@@ -455,7 +459,9 @@ func TestHealthTrait(t *testing.T) {
455459

456460
g.Expect(KamelRun(t, ctx, ns, "files/Java.java", "--name", name,
457461
"-t", "health.enabled=true",
458-
"-t", "health.startup-probe-enabled=true", "-t", "health.startup-timeout=60").Execute()).To(Succeed())
462+
"-t", "health.startup-probe-enabled=true",
463+
"-t", "health.startup-timeout=60",
464+
).Execute()).To(Succeed())
459465

460466
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
461467
g.Eventually(IntegrationPhase(t, ctx, ns, name), TestTimeoutMedium).Should(Equal(v1.IntegrationPhaseRunning))
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//go:build integration
2+
// +build integration
3+
4+
// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
5+
6+
/*
7+
Licensed to the Apache Software Foundation (ASF) under one or more
8+
contributor license agreements. See the NOTICE file distributed with
9+
this work for additional information regarding copyright ownership.
10+
The ASF licenses this file to You under the Apache License, Version 2.0
11+
(the "License"); you may not use this file except in compliance with
12+
the License. You may obtain a copy of the License at
13+
14+
http://www.apache.org/licenses/LICENSE-2.0
15+
16+
Unless required by applicable law or agreed to in writing, software
17+
distributed under the License is distributed on an "AS IS" BASIS,
18+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19+
See the License for the specific language governing permissions and
20+
limitations under the License.
21+
*/
22+
23+
package common
24+
25+
import (
26+
"context"
27+
"fmt"
28+
"testing"
29+
"time"
30+
31+
. "github.com/onsi/gomega"
32+
33+
corev1 "k8s.io/api/core/v1"
34+
35+
. "github.com/apache/camel-k/v2/e2e/support"
36+
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
37+
)
38+
39+
func TestJvmAgentJolokiaTrait(t *testing.T) {
40+
t.Parallel()
41+
WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
42+
t.Run("Run Java with Jolokia Agent", func(t *testing.T) {
43+
name := RandomizedSuffixName("jolokia")
44+
g.Expect(KamelRun(t, ctx, ns, "files/Java.java", "--name", name,
45+
"-t", "jvm.agents=jolokia;https://repo1.maven.org/maven2/org/jolokia/jolokia-agent-jvm/2.3.0/jolokia-agent-jvm-2.3.0-javaagent.jar;host=*",
46+
"-t", "container.ports=jolokia;8778",
47+
"-d", "camel:management",
48+
).Execute()).To(Succeed())
49+
g.Eventually(IntegrationPodPhase(t, ctx, ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning))
50+
g.Eventually(IntegrationConditionStatus(t, ctx, ns, name, v1.IntegrationConditionReady), TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
51+
g.Eventually(IntegrationLogs(t, ctx, ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
52+
53+
pod := IntegrationPod(t, ctx, ns, name)
54+
response, err := TestClient(t).CoreV1().RESTClient().Get().
55+
AbsPath(fmt.Sprintf("/api/v1/namespaces/%s/pods/%s/proxy/jolokia/", ns, pod().Name)).
56+
Timeout(30 * time.Second).
57+
DoRaw(ctx)
58+
g.Expect(err).To(BeNil())
59+
g.Expect(response).To(ContainSubstring(`"status":200`))
60+
})
61+
})
62+
}

0 commit comments

Comments
 (0)