This is an automated email from the ASF dual-hosted git repository. nfilotto pushed a commit to branch 3023/compile-with-sources in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit ea59a8d8f7e2996f038b6f71a5dce80706202a02 Author: Nicolas Filotto <[email protected]> AuthorDate: Wed Feb 1 13:17:45 2023 +0100 Ref #3023: Add native compilation with sources --- config/crd/bases/camel.apache.org_builds.yaml | 61 +++++++++++ .../bases/camel.apache.org_integrationkits.yaml | 57 ++++++++++ docs/modules/ROOT/partials/apis/camel-k-crds.adoc | 24 ++++- docs/modules/traits/pages/quarkus.adoc | 8 +- .../native/files/{Java.java => Groovy.groovy} | 15 +-- e2e/namespace/native/files/Java.java | 8 +- .../native/files/{Java.java => JavaScript.js} | 15 +-- .../native/files/{Java.java => JavaShell.jsh} | 15 +-- .../native/files/{Java.java => Kotlin.kts} | 17 +-- e2e/namespace/native/files/Xml.xml | 33 ++++++ e2e/namespace/native/native_test.go | 118 ++++++++++++++++++++- helm/camel-k/crds/crd-build.yaml | 61 +++++++++++ helm/camel-k/crds/crd-integration-kit.yaml | 57 ++++++++++ pkg/apis/camel/v1/build_types.go | 2 + pkg/apis/camel/v1/common_types.go | 3 + pkg/apis/camel/v1/integrationkit_types.go | 2 + pkg/apis/camel/v1/trait/quarkus.go | 8 +- pkg/apis/camel/v1/zz_generated.deepcopy.go | 14 +++ pkg/builder/quarkus.go | 53 ++++++++- .../applyconfiguration/camel/v1/buildertask.go | 14 +++ .../camel/v1/integrationkitspec.go | 14 +++ pkg/resources/resources.go | 16 +-- pkg/trait/camel.go | 2 +- pkg/trait/quarkus.go | 91 +++++++++++++++- pkg/trait/trait_test.go | 13 +-- pkg/trait/trait_types.go | 44 +++++--- pkg/util/source/inspector.go | 6 ++ resources/traits.yaml | 1 - 28 files changed, 672 insertions(+), 100 deletions(-) diff --git a/config/crd/bases/camel.apache.org_builds.yaml b/config/crd/bases/camel.apache.org_builds.yaml index 8821ffd06..4b530895f 100644 --- a/config/crd/bases/camel.apache.org_builds.yaml +++ b/config/crd/bases/camel.apache.org_builds.yaml @@ -475,6 +475,67 @@ spec: - provider - version type: object + sources: + description: the sources to add at build time + items: + description: SourceSpec defines the configuration for + one or more routes to be executed in a certain Camel + DSL language + properties: + compression: + description: if the content is compressed (base64 + encrypted) + type: boolean + content: + description: the source code (plain text) + type: string + contentKey: + description: the confimap key holding the source content + type: string + contentRef: + description: the confimap reference holding the source + content + type: string + contentType: + description: the content type (tipically text or binary) + type: string + interceptors: + description: Interceptors are optional identifiers + the org.apache.camel.k.RoutesLoader uses to pre/post + process sources + items: + type: string + type: array + language: + description: specify which is the language (Camel + DSL) used to interpret this source code + type: string + loader: + description: Loader is an optional id of the org.apache.camel.k.RoutesLoader + that will interpret this source at runtime + type: string + name: + description: the name of the specification + type: string + path: + description: the path where the file is stored + type: string + property-names: + description: List of property names defined in the + source (e.g. if type is "template") + items: + type: string + type: array + rawContent: + description: the source code (binary) + format: byte + type: string + type: + description: Type defines the kind of source described + by this object + type: string + type: object + type: array steps: description: the list of steps to execute (see pkg/builder/) items: diff --git a/config/crd/bases/camel.apache.org_integrationkits.yaml b/config/crd/bases/camel.apache.org_integrationkits.yaml index 918cd6afe..b37b152b4 100644 --- a/config/crd/bases/camel.apache.org_integrationkits.yaml +++ b/config/crd/bases/camel.apache.org_integrationkits.yaml @@ -114,6 +114,63 @@ spec: items: type: string type: array + sources: + description: the sources to add at build time + items: + description: SourceSpec defines the configuration for one or more + routes to be executed in a certain Camel DSL language + properties: + compression: + description: if the content is compressed (base64 encrypted) + type: boolean + content: + description: the source code (plain text) + type: string + contentKey: + description: the confimap key holding the source content + type: string + contentRef: + description: the confimap reference holding the source content + type: string + contentType: + description: the content type (tipically text or binary) + type: string + interceptors: + description: Interceptors are optional identifiers the org.apache.camel.k.RoutesLoader + uses to pre/post process sources + items: + type: string + type: array + language: + description: specify which is the language (Camel DSL) used + to interpret this source code + type: string + loader: + description: Loader is an optional id of the org.apache.camel.k.RoutesLoader + that will interpret this source at runtime + type: string + name: + description: the name of the specification + type: string + path: + description: the path where the file is stored + type: string + property-names: + description: List of property names defined in the source (e.g. + if type is "template") + items: + type: string + type: array + rawContent: + description: the source code (binary) + format: byte + type: string + type: + description: Type defines the kind of source described by this + object + type: string + type: object + type: array traits: description: traits that the kit will execute properties: diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc index 4b9e182a0..0454c04c4 100644 --- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc +++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc @@ -665,6 +665,13 @@ string workspace directory to use +|`sources` + +*xref:#_camel_apache_org_v1_SourceSpec[[\]SourceSpec]* +| + + +the sources to add at build time + |=== @@ -1491,6 +1498,13 @@ configuration used by the kit Maven repositories that can be used by the kit +|`sources` + +*xref:#_camel_apache_org_v1_SourceSpec[[\]SourceSpec]* +| + + +the sources to add at build time + |=== @@ -3107,6 +3121,8 @@ string *Appears on:* +* <<#_camel_apache_org_v1_BuilderTask, BuilderTask>> +* <<#_camel_apache_org_v1_IntegrationKitSpec, IntegrationKitSpec>> * <<#_camel_apache_org_v1_IntegrationSpec, IntegrationSpec>> * <<#_camel_apache_org_v1_IntegrationStatus, IntegrationStatus>> @@ -5406,11 +5422,9 @@ The Quarkus trait configures the Quarkus runtime. It's enabled by default. -NOTE: Compiling to a native executable, i.e. when using `package-type=native`, is only supported -for kamelets, as well as YAML and XML integrations. -It also requires at least 4GiB of memory, so the Pod running the native build, that is either -the operator Pod, or the build Pod (depending on the build strategy configured for the platform), -must have enough memory available. +NOTE: Compiling to a native executable, i.e. when using `package-type=native`, requires at least +4GiB of memory, so the Pod running the native build, that is either the operator Pod, or the build +Pod (depending on the build strategy configured for the platform), must have enough memory available. [cols="2,2a",options="header"] diff --git a/docs/modules/traits/pages/quarkus.adoc b/docs/modules/traits/pages/quarkus.adoc index 595572dd6..e0201cc13 100755 --- a/docs/modules/traits/pages/quarkus.adoc +++ b/docs/modules/traits/pages/quarkus.adoc @@ -5,11 +5,9 @@ The Quarkus trait configures the Quarkus runtime. It's enabled by default. -NOTE: Compiling to a native executable, i.e. when using `package-type=native`, is only supported -for kamelets, as well as YAML and XML integrations. -It also requires at least 4GiB of memory, so the Pod running the native build, that is either -the operator Pod, or the build Pod (depending on the build strategy configured for the platform), -must have enough memory available. +NOTE: Compiling to a native executable, i.e. when using `package-type=native`, requires at least +4GiB of memory, so the Pod running the native build, that is either the operator Pod, or the build +Pod (depending on the build strategy configured for the platform), must have enough memory available. This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**. diff --git a/e2e/namespace/native/files/Java.java b/e2e/namespace/native/files/Groovy.groovy similarity index 74% copy from e2e/namespace/native/files/Java.java copy to e2e/namespace/native/files/Groovy.groovy index 66fef5fe8..baeaa9c0c 100644 --- a/e2e/namespace/native/files/Java.java +++ b/e2e/namespace/native/files/Groovy.groovy @@ -15,14 +15,7 @@ * limitations under the License. */ -import org.apache.camel.builder.RouteBuilder; - -public class Java extends RouteBuilder { - @Override - public void configure() throws Exception { - from("timer:tick") - .setHeader("m").constant("string!") - .setBody().simple("Magic${header.m}") - .log("${body}"); - } -} +from('timer:tick') + .setHeader('m').constant('string!') + .setBody().simple('Magic${header.m}') + .log('Groovy ${body}') diff --git a/e2e/namespace/native/files/Java.java b/e2e/namespace/native/files/Java.java index 66fef5fe8..35ee313e9 100644 --- a/e2e/namespace/native/files/Java.java +++ b/e2e/namespace/native/files/Java.java @@ -20,9 +20,9 @@ import org.apache.camel.builder.RouteBuilder; public class Java extends RouteBuilder { @Override public void configure() throws Exception { - from("timer:tick") - .setHeader("m").constant("string!") - .setBody().simple("Magic${header.m}") - .log("${body}"); + from("timer:tick") + .setHeader("m").constant("string!") + .setBody().simple("Magic${header.m}") + .log("Java ${body}"); } } diff --git a/e2e/namespace/native/files/Java.java b/e2e/namespace/native/files/JavaScript.js similarity index 74% copy from e2e/namespace/native/files/Java.java copy to e2e/namespace/native/files/JavaScript.js index 66fef5fe8..0d3194e58 100644 --- a/e2e/namespace/native/files/Java.java +++ b/e2e/namespace/native/files/JavaScript.js @@ -15,14 +15,7 @@ * limitations under the License. */ -import org.apache.camel.builder.RouteBuilder; - -public class Java extends RouteBuilder { - @Override - public void configure() throws Exception { - from("timer:tick") - .setHeader("m").constant("string!") - .setBody().simple("Magic${header.m}") - .log("${body}"); - } -} +from('timer:tick') + .setHeader('m').constant('string!') + .setBody().simple('Magic${header.m}') + .log('JavaScript ${body}') diff --git a/e2e/namespace/native/files/Java.java b/e2e/namespace/native/files/JavaShell.jsh similarity index 74% copy from e2e/namespace/native/files/Java.java copy to e2e/namespace/native/files/JavaShell.jsh index 66fef5fe8..32f3b4ea0 100644 --- a/e2e/namespace/native/files/Java.java +++ b/e2e/namespace/native/files/JavaShell.jsh @@ -15,14 +15,7 @@ * limitations under the License. */ -import org.apache.camel.builder.RouteBuilder; - -public class Java extends RouteBuilder { - @Override - public void configure() throws Exception { - from("timer:tick") - .setHeader("m").constant("string!") - .setBody().simple("Magic${header.m}") - .log("${body}"); - } -} +builder.from("timer:tick") + .setHeader("m").constant("string!") + .setBody().simple("Magic${header.m}") + .log("JShell ${body}"); diff --git a/e2e/namespace/native/files/Java.java b/e2e/namespace/native/files/Kotlin.kts similarity index 74% copy from e2e/namespace/native/files/Java.java copy to e2e/namespace/native/files/Kotlin.kts index 66fef5fe8..743259b38 100644 --- a/e2e/namespace/native/files/Java.java +++ b/e2e/namespace/native/files/Kotlin.kts @@ -14,15 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import org.apache.camel.builder.RouteBuilder; - -public class Java extends RouteBuilder { - @Override - public void configure() throws Exception { - from("timer:tick") - .setHeader("m").constant("string!") - .setBody().simple("Magic${header.m}") - .log("${body}"); - } -} + +from("timer:tick") + .setHeader("m").constant("string!") + .setBody().simple("Magic\${header.m}") + .log("Kotlin \${body}"); diff --git a/e2e/namespace/native/files/Xml.xml b/e2e/namespace/native/files/Xml.xml new file mode 100644 index 000000000..7b55c2d62 --- /dev/null +++ b/e2e/namespace/native/files/Xml.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://camel.apache.org/schema/spring" + xsi:schemaLocation=" + http://camel.apache.org/schema/spring + https://camel.apache.org/schema/spring/camel-spring.xsd"> + + <route id="hello"> + <from uri="timer:tick"/> + <setHeader name="m"> + <constant>string!</constant> + </setHeader> + <setBody> + <simple>Magic${header.m}</simple> + </setBody> + <log message="XML ${body}"/> + </route> + +</routes> diff --git a/e2e/namespace/native/native_test.go b/e2e/namespace/native/native_test.go index 6ea8855b0..d8da8d9c3 100644 --- a/e2e/namespace/native/native_test.go +++ b/e2e/namespace/native/native_test.go @@ -38,14 +38,14 @@ func TestNativeIntegrations(t *testing.T) { operatorID := "camel-k-quarkus-native" Expect(KamelInstallWithID(operatorID, ns, "--build-timeout", "90m0s", - "--operator-resources", "limits.memory=4.5Gi", - "--maven-cli-option", "-Dquarkus.native.native-image-xmx=3g", + "--operator-resources", "limits.memory=5.5Gi", + "--maven-cli-option", "-Dquarkus.native.native-image-xmx=4g", ).Execute()).To(Succeed()) Eventually(PlatformPhase(ns), TestTimeoutMedium).Should(Equal(v1.IntegrationPlatformPhaseReady)) t.Run("unsupported integration source language", func(t *testing.T) { - name := "unsupported-java" - Expect(KamelRunWithID(operatorID, ns, "files/Java.java", "--name", name, + name := "unsupported-js" + Expect(KamelRunWithID(operatorID, ns, "files/JavaScript.js", "--name", name, "-t", "quarkus.package-type=native", ).Execute()).To(Succeed()) @@ -126,6 +126,116 @@ func TestNativeIntegrations(t *testing.T) { Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!")) }) + t.Run("java native support", func(t *testing.T) { + name := "java-native" + Expect(KamelRunWithID(operatorID, ns, "files/Java.java", "--name", name, + "-t", "quarkus.package-type=native", + ).Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + Eventually(IntegrationPod(ns, name), TestTimeoutShort). + Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("Java Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + + t.Run("xml native support", func(t *testing.T) { + name := "xml-native" + Expect(KamelRunWithID(operatorID, ns, "files/Xml.xml", "--name", name, + "-t", "quarkus.package-type=native", + ).Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + Eventually(IntegrationPod(ns, name), TestTimeoutShort). + Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("XML Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + + t.Run("groovy native support", func(t *testing.T) { + name := "groovy-native" + Expect(KamelRunWithID(operatorID, ns, "files/Groovy.groovy", "--name", name, + "-t", "quarkus.package-type=native", + ).Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + Eventually(IntegrationPod(ns, name), TestTimeoutShort). + Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("Groovy Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + + // Native support is not yet supported due to https://github.com/apache/camel-quarkus/issues/4458 + t.Run("jshell native support", func(t *testing.T) { + name := "jshell-native" + Expect(KamelRunWithID(operatorID, ns, "files/JavaShell.jsh", "--name", name). + // "-t", "quarkus.package-type=native", + Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + // Eventually(IntegrationPod(ns, name), TestTimeoutShort). + // Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("JShell Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + + // Guest languages are not yet supported on Mandrel in native mode + t.Run("js native support", func(t *testing.T) { + name := "js-native" + Expect(KamelRunWithID(operatorID, ns, "files/JavaScript.js", "--name", name). + // "-t", "quarkus.package-type=native", + Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + // Eventually(IntegrationPod(ns, name), TestTimeoutShort). + // Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("JavaScript Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + + t.Run("kotlin native support", func(t *testing.T) { + name := "kotlin-native" + Expect(KamelRunWithID(operatorID, ns, "files/Kotlin.kts", "--name", name, + "-t", "quarkus.package-type=native", + ).Execute()).To(Succeed()) + + Eventually(IntegrationPodPhase(ns, name), TestTimeoutLong).Should(Equal(corev1.PodRunning)) + Eventually(IntegrationPod(ns, name), TestTimeoutShort). + Should(WithTransform(getContainerCommand(), MatchRegexp(".*camel-k-integration-\\d+\\.\\d+\\.\\d+[-A-Za-z]*-runner.*"))) + Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort). + Should(Equal(corev1.ConditionTrue)) + + Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("Kotlin Magicstring!")) + + // Clean up + Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed()) + }) + // Clean up Expect(Kamel("delete", "--all", "-n", ns).Execute()).To(Succeed()) }) diff --git a/helm/camel-k/crds/crd-build.yaml b/helm/camel-k/crds/crd-build.yaml index 8821ffd06..4b530895f 100644 --- a/helm/camel-k/crds/crd-build.yaml +++ b/helm/camel-k/crds/crd-build.yaml @@ -475,6 +475,67 @@ spec: - provider - version type: object + sources: + description: the sources to add at build time + items: + description: SourceSpec defines the configuration for + one or more routes to be executed in a certain Camel + DSL language + properties: + compression: + description: if the content is compressed (base64 + encrypted) + type: boolean + content: + description: the source code (plain text) + type: string + contentKey: + description: the confimap key holding the source content + type: string + contentRef: + description: the confimap reference holding the source + content + type: string + contentType: + description: the content type (tipically text or binary) + type: string + interceptors: + description: Interceptors are optional identifiers + the org.apache.camel.k.RoutesLoader uses to pre/post + process sources + items: + type: string + type: array + language: + description: specify which is the language (Camel + DSL) used to interpret this source code + type: string + loader: + description: Loader is an optional id of the org.apache.camel.k.RoutesLoader + that will interpret this source at runtime + type: string + name: + description: the name of the specification + type: string + path: + description: the path where the file is stored + type: string + property-names: + description: List of property names defined in the + source (e.g. if type is "template") + items: + type: string + type: array + rawContent: + description: the source code (binary) + format: byte + type: string + type: + description: Type defines the kind of source described + by this object + type: string + type: object + type: array steps: description: the list of steps to execute (see pkg/builder/) items: diff --git a/helm/camel-k/crds/crd-integration-kit.yaml b/helm/camel-k/crds/crd-integration-kit.yaml index 918cd6afe..b37b152b4 100644 --- a/helm/camel-k/crds/crd-integration-kit.yaml +++ b/helm/camel-k/crds/crd-integration-kit.yaml @@ -114,6 +114,63 @@ spec: items: type: string type: array + sources: + description: the sources to add at build time + items: + description: SourceSpec defines the configuration for one or more + routes to be executed in a certain Camel DSL language + properties: + compression: + description: if the content is compressed (base64 encrypted) + type: boolean + content: + description: the source code (plain text) + type: string + contentKey: + description: the confimap key holding the source content + type: string + contentRef: + description: the confimap reference holding the source content + type: string + contentType: + description: the content type (tipically text or binary) + type: string + interceptors: + description: Interceptors are optional identifiers the org.apache.camel.k.RoutesLoader + uses to pre/post process sources + items: + type: string + type: array + language: + description: specify which is the language (Camel DSL) used + to interpret this source code + type: string + loader: + description: Loader is an optional id of the org.apache.camel.k.RoutesLoader + that will interpret this source at runtime + type: string + name: + description: the name of the specification + type: string + path: + description: the path where the file is stored + type: string + property-names: + description: List of property names defined in the source (e.g. + if type is "template") + items: + type: string + type: array + rawContent: + description: the source code (binary) + format: byte + type: string + type: + description: Type defines the kind of source described by this + object + type: string + type: object + type: array traits: description: traits that the kit will execute properties: diff --git a/pkg/apis/camel/v1/build_types.go b/pkg/apis/camel/v1/build_types.go index 675472984..de1101864 100644 --- a/pkg/apis/camel/v1/build_types.go +++ b/pkg/apis/camel/v1/build_types.go @@ -74,6 +74,8 @@ type BuilderTask struct { Maven MavenBuildSpec `json:"maven,omitempty"` // workspace directory to use BuildDir string `json:"buildDir,omitempty"` + // the sources to add at build time + Sources []SourceSpec `json:"sources,omitempty"` } // MavenBuildSpec defines the Maven configuration plus additional repositories to use diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go index 33eec9f89..48ebb584a 100644 --- a/pkg/apis/camel/v1/common_types.go +++ b/pkg/apis/camel/v1/common_types.go @@ -424,6 +424,8 @@ const ( LanguageYaml Language = "yaml" // LanguageKamelet used for Kamelets LanguageKamelet Language = "kamelet" + // LanguageJavaShell used for Java Shell + LanguageJavaShell Language = "jsh" ) // Languages is the list of all supported languages @@ -435,4 +437,5 @@ var Languages = []Language{ LanguageKotlin, LanguageYaml, LanguageKamelet, + LanguageJavaShell, } diff --git a/pkg/apis/camel/v1/integrationkit_types.go b/pkg/apis/camel/v1/integrationkit_types.go index a94506388..5510561a6 100644 --- a/pkg/apis/camel/v1/integrationkit_types.go +++ b/pkg/apis/camel/v1/integrationkit_types.go @@ -69,6 +69,8 @@ type IntegrationKitSpec struct { Configuration []ConfigurationSpec `json:"configuration,omitempty"` // Maven repositories that can be used by the kit Repositories []string `json:"repositories,omitempty"` + // the sources to add at build time + Sources []SourceSpec `json:"sources,omitempty"` } // IntegrationKitTraits defines traits assigned to an `IntegrationKit` diff --git a/pkg/apis/camel/v1/trait/quarkus.go b/pkg/apis/camel/v1/trait/quarkus.go index dcbd079d6..571ad6206 100644 --- a/pkg/apis/camel/v1/trait/quarkus.go +++ b/pkg/apis/camel/v1/trait/quarkus.go @@ -21,11 +21,9 @@ package trait // // It's enabled by default. // -// NOTE: Compiling to a native executable, i.e. when using `package-type=native`, is only supported -// for kamelets, as well as YAML and XML integrations. -// It also requires at least 4GiB of memory, so the Pod running the native build, that is either -// the operator Pod, or the build Pod (depending on the build strategy configured for the platform), -// must have enough memory available. +// NOTE: Compiling to a native executable, i.e. when using `package-type=native`, requires at least +// 4GiB of memory, so the Pod running the native build, that is either the operator Pod, or the build +// Pod (depending on the build strategy configured for the platform), must have enough memory available. // // +camel-k:trait=quarkus. type QuarkusTrait struct { diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go b/pkg/apis/camel/v1/zz_generated.deepcopy.go index 6d4e1d5f0..8638494ac 100644 --- a/pkg/apis/camel/v1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go @@ -235,6 +235,13 @@ func (in *BuilderTask) DeepCopyInto(out *BuilderTask) { copy(*out, *in) } in.Maven.DeepCopyInto(&out.Maven) + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]SourceSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BuilderTask. @@ -797,6 +804,13 @@ func (in *IntegrationKitSpec) DeepCopyInto(out *IntegrationKitSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.Sources != nil { + in, out := &in.Sources, &out.Sources + *out = make([]SourceSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IntegrationKitSpec. diff --git a/pkg/builder/quarkus.go b/pkg/builder/quarkus.go index 91d6bfa33..0fe32c832 100644 --- a/pkg/builder/quarkus.go +++ b/pkg/builder/quarkus.go @@ -30,7 +30,9 @@ import ( "github.com/apache/camel-k/pkg/util/camel" "github.com/apache/camel-k/pkg/util/defaults" "github.com/apache/camel-k/pkg/util/digest" + "github.com/apache/camel-k/pkg/util/kubernetes" "github.com/apache/camel-k/pkg/util/maven" + corev1 "k8s.io/api/core/v1" ) func init() { @@ -48,6 +50,7 @@ type quarkusSteps struct { GenerateQuarkusProject Step BuildQuarkusRunner Step ComputeQuarkusDependencies Step + PrepareProjectWithSources Step CommonSteps []Step } @@ -55,10 +58,58 @@ type quarkusSteps struct { var Quarkus = quarkusSteps{ LoadCamelQuarkusCatalog: NewStep(InitPhase, loadCamelQuarkusCatalog), GenerateQuarkusProject: NewStep(ProjectGenerationPhase, generateQuarkusProject), + PrepareProjectWithSources: NewStep(ProjectBuildPhase-1, prepareProjectWithSources), BuildQuarkusRunner: NewStep(ProjectBuildPhase, buildQuarkusRunner), ComputeQuarkusDependencies: NewStep(ProjectBuildPhase+1, computeQuarkusDependencies), } +func resolveBuildSources(ctx *builderContext) ([]v1.SourceSpec, error) { + resources := kubernetes.NewCollection() + return kubernetes.ResolveSources(ctx.Build.Sources, func(name string) (*corev1.ConfigMap, error) { + // the config map could be part of the resources created + // by traits + cm := resources.GetConfigMap(func(m *corev1.ConfigMap) bool { + return m.Name == name + }) + + if cm != nil { + return cm, nil + } + + return kubernetes.GetConfigMap(ctx.C, ctx.Client, name, ctx.Namespace) + }) +} + +func prepareProjectWithSources(ctx *builderContext) error { + sources, err := resolveBuildSources(ctx) + if err != nil { + return err + } + sourcesPath := filepath.Join(ctx.Path, "maven", "src", "main", "resources", "routes") + if err := os.MkdirAll(sourcesPath, os.ModePerm); err != nil { + return errors.Wrap(err, "failure while creating resource folder") + } + + sourceList := "" + for _, source := range sources { + if sourceList != "" { + sourceList += "," + } + sourceList += "classpath:routes/" + source.Name + if err := os.WriteFile(filepath.Join(sourcesPath, source.Name), []byte(source.Content), os.ModePerm); err != nil { + return errors.Wrapf(err, "failure while writing %s", source.Name) + } + } + + if sourceList != "" { + routesIncludedPattern := "camel.main.routes-include-pattern = " + sourceList + if err := os.WriteFile(filepath.Join(filepath.Dir(sourcesPath), "application.properties"), []byte(routesIncludedPattern), os.ModePerm); err != nil { + return errors.Wrapf(err, "failure while writing the configuration application.properties") + } + } + return nil +} + func loadCamelQuarkusCatalog(ctx *builderContext) error { catalog, err := camel.LoadCatalog(ctx.C, ctx.Client, ctx.Namespace, ctx.Build.Runtime) if err != nil { @@ -196,7 +247,7 @@ func BuildQuarkusRunnerCommon(ctx context.Context, mc maven.Context, project mav // may fail the build. // In the future there should be a way to provide build information from secrets, // configmap, etc. - if _, err := os.Create(filepath.Join(resourcesPath, "application.properties")); err != nil { + if _, err := os.OpenFile(filepath.Join(resourcesPath, "application.properties"), os.O_RDWR|os.O_CREATE, 0666); err != nil { return errors.Wrap(err, "failure while creating application.properties") } diff --git a/pkg/client/camel/applyconfiguration/camel/v1/buildertask.go b/pkg/client/camel/applyconfiguration/camel/v1/buildertask.go index 2cbaa72bd..ceea83625 100644 --- a/pkg/client/camel/applyconfiguration/camel/v1/buildertask.go +++ b/pkg/client/camel/applyconfiguration/camel/v1/buildertask.go @@ -29,6 +29,7 @@ type BuilderTaskApplyConfiguration struct { Steps []string `json:"steps,omitempty"` Maven *MavenBuildSpecApplyConfiguration `json:"maven,omitempty"` BuildDir *string `json:"buildDir,omitempty"` + Sources []SourceSpecApplyConfiguration `json:"sources,omitempty"` } // BuilderTaskApplyConfiguration constructs an declarative configuration of the BuilderTask type for use with @@ -96,3 +97,16 @@ func (b *BuilderTaskApplyConfiguration) WithBuildDir(value string) *BuilderTaskA b.BuildDir = &value return b } + +// WithSources adds the given value to the Sources field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Sources field. +func (b *BuilderTaskApplyConfiguration) WithSources(values ...*SourceSpecApplyConfiguration) *BuilderTaskApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSources") + } + b.Sources = append(b.Sources, *values[i]) + } + return b +} diff --git a/pkg/client/camel/applyconfiguration/camel/v1/integrationkitspec.go b/pkg/client/camel/applyconfiguration/camel/v1/integrationkitspec.go index 08d6ae153..9b408fe8d 100644 --- a/pkg/client/camel/applyconfiguration/camel/v1/integrationkitspec.go +++ b/pkg/client/camel/applyconfiguration/camel/v1/integrationkitspec.go @@ -32,6 +32,7 @@ type IntegrationKitSpecApplyConfiguration struct { Traits *IntegrationKitTraitsApplyConfiguration `json:"traits,omitempty"` Configuration []ConfigurationSpecApplyConfiguration `json:"configuration,omitempty"` Repositories []string `json:"repositories,omitempty"` + Sources []SourceSpecApplyConfiguration `json:"sources,omitempty"` } // IntegrationKitSpecApplyConfiguration constructs an declarative configuration of the IntegrationKitSpec type for use with @@ -96,3 +97,16 @@ func (b *IntegrationKitSpecApplyConfiguration) WithRepositories(values ...string } return b } + +// WithSources adds the given value to the Sources field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Sources field. +func (b *IntegrationKitSpecApplyConfiguration) WithSources(values ...*SourceSpecApplyConfiguration) *IntegrationKitSpecApplyConfiguration { + for i := range values { + if values[i] == nil { + panic("nil value passed to WithSources") + } + b.Sources = append(b.Sources, *values[i]) + } + return b +} diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go index 139e4ee49..932282e61 100644 --- a/pkg/resources/resources.go +++ b/pkg/resources/resources.go @@ -117,9 +117,9 @@ var assets = func() http.FileSystem { "/crd/bases/camel.apache.org_builds.yaml": &vfsgen۰CompressedFileInfo{ name: "camel.apache.org_builds.yaml", modTime: time.Time{}, - uncompressedSize: 35823, + uncompressedSize: 39199, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3d\x5d\x93\xdb\x36\x92\xef\xfa\x15\x5d\x99\x07\x8f\xab\xf4\x91\xaf\xcd\xe5\xe6\xea\xea\x4a\x3b\x8e\xb3\x73\x8e\x3d\x3e\x6b\xe2\x24\x6f\x03\x91\x2d\x09\x11\x09\xf0\x00\x70\x64\xed\xd5\xfd\xf7\x2b\x34\x40\x8a\x92\xf8\x01\xce\x68\xe2\xbd\x8d\xf0\x62\x0f\x05\x36\x1a\xfd\x8d\x46\x13\xb8\x80\xd1\xe9\xda\xe0\x02\x7e\xe2\x11\x0a\x8d\x31\x18\x09\x66\x85\x30\xcd\x58\xb4\x42\x98\xc9\x85\xd9\x30\x85\xf0\x5a\xe6\x22\x66\x86\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3d\x6b\x73\x23\x29\x92\xdf\xfd\x2b\x32\xc6\x1f\xda\x1d\x61\x49\x33\xb3\x8f\x9b\xf3\xc5\xc5\x85\xd6\x3d\x33\xeb\xeb\x87\xfb\x5a\x9e\xde\xdd\x6f\x46\x55\x29\x89\x55\x15\xd4\x01\x65\xb5\xf6\xe2\xfe\xfb\x05\x09\x94\x4a\x52\x3d\x28\x3f\xa6\xf7\x76\xc5\x97\x6e\x97\x20\x49\xc8\x24\x5f\x24\x70\x0e\xa3\xe7\x2b\x67\xe7\xf0\x8e\x27\x28\x34\xa6\x60\x24\x98\x15\xc2\xb4\x60\xc9\x0a\x61\x26\x17\x66\xc3\x14\xc2\x4f\xb2\x14\x29\x [...] }, "/crd/bases/camel.apache.org_camelcatalogs.yaml": &vfsgen۰CompressedFileInfo{ name: "camel.apache.org_camelcatalogs.yaml", @@ -131,9 +131,9 @@ var assets = func() http.FileSystem { "/crd/bases/camel.apache.org_integrationkits.yaml": &vfsgen۰CompressedFileInfo{ name: "camel.apache.org_integrationkits.yaml", modTime: time.Time{}, - uncompressedSize: 16165, + uncompressedSize: 18839, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x4f\x73\xdb\xb8\x92\xbf\xeb\x53\x74\x8d\x0f\x49\xaa\x24\xfa\xcd\xee\xab\x57\x5b\xde\xda\x83\x9f\x27\x99\xe7\x4a\xe2\x64\x63\x67\xde\x4e\x55\x0e\x6e\x91\x2d\x0a\x23\x12\xe0\x00\xa0\x64\xed\xd6\x7e\xf7\xad\x6e\x80\x14\x25\x91\x94\xc6\x99\xec\x29\xbc\x24\x26\x81\x46\xff\xfd\x75\x37\x00\x5d\xc0\xec\xcf\x7b\x26\x17\xf0\x4e\xa5\xa4\x1d\x65\xe0\x0d\xf8\x25\xc1\x75\x85\xe9\x92\xe0\xde\x2c\xfc\x06\x2d\xc1\x1b\x53\xeb\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x3c\x4d\x73\xdb\xb8\x92\x77\xfd\x8a\xae\xf8\x10\xbb\x4a\xa2\xdf\xec\xbe\x9a\xda\xf2\xd6\x1e\xfc\x9c\x64\x9e\x2b\x8e\x93\x8d\x9c\x79\x3b\x55\x73\x70\x8b\x6c\x49\x18\x91\x00\x1f\x00\x4a\xd6\x6e\xed\x7f\xdf\x42\x03\xa0\x28\x89\xa4\x18\x7b\xbc\xa7\xf0\x32\xb1\x08\x34\xfa\xfb\x03\xdd\x9c\x33\x98\xfc\x79\xcf\xe8\x0c\xee\x44\x4a\xd2\x50\x06\x56\x81\x5d\x12\x5c\x97\x98\x2e\x09\xa6\x6a\x6e\x37\xa8\x09\x3e\xa8\x4a\x66\x68\x [...] }, "/crd/bases/camel.apache.org_integrationplatforms.yaml": &vfsgen۰CompressedFileInfo{ name: "camel.apache.org_integrationplatforms.yaml", @@ -604,16 +604,16 @@ var assets = func() http.FileSystem { "/camel-catalog-1.17.0-SNAPSHOT.yaml": &vfsgen۰CompressedFileInfo{ name: "camel-catalog-1.17.0-SNAPSHOT.yaml", modTime: time.Time{}, - uncompressedSize: 86658, + uncompressedSize: 86428, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\xbd\x4b\x77\xdb\xb8\xb2\x36\x3c\xcf\xaf\xe0\xea\x4c\xce\x59\xdf\x16\xba\xdb\x7d\xbe\xdd\xef\xca\x3b\xb2\xe5\x38\xb1\x63\x3b\x4e\xe4\x9d\xce\xde\x93\x5e\x10\x09\x49\xb0\x48\x82\x06\x40\x59\xce\xaf\x7f\x17\x40\xf0\x2a\xa5\x78\x71\xc1\xc7\x03\x93\x22\x0a\x4f\xa1\x1e\x80\xb8\xb3\xf0\x36\x98\xe1\xfd\xbd\x79\x1b\x5c\xf3\x90\xa5\x8a\x45\x81\x16\x81\xde\xb0\xe0\x34\xa3\xe1\x86\x05\x0b\xb1\xd2\x4f\x54\xb2\xe0\x42\xe4\x69\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\xbd\x4b\x77\xdb\xb8\xb2\x36\x3c\xcf\xaf\xe0\xea\x4c\xce\x59\xdf\x16\xba\xdb\x7d\xbe\xdd\xef\xca\x3b\xb2\xe5\x38\xb1\x63\x3b\x4e\xe4\x9d\xce\xde\x93\x5e\x10\x09\x49\xb0\x48\x82\x06\x40\x59\xce\xaf\x7f\x17\x40\xf0\x2a\xa5\x78\x71\xc1\xc7\x03\x93\x22\x0a\x4f\xa1\x1e\x80\xb8\xb3\xf0\x36\x98\xe1\xfd\xbd\x79\x1b\x5c\xf3\x90\xa5\x8a\x45\x81\x16\x81\xde\xb0\xe0\x34\xa3\xe1\x86\x05\x0b\xb1\xd2\x4f\x54\xb2\xe0\x42\xe4\x69\x [...] }, "/traits.yaml": &vfsgen۰CompressedFileInfo{ name: "traits.yaml", modTime: time.Time{}, - uncompressedSize: 58334, + uncompressedSize: 58252, - compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\xfd\x73\x1c\x37\x92\x20\xfa\xbb\xfe\x0a\x04\xf7\x6d\x90\xd4\xeb\x6e\xca\x9e\xf5\xac\x97\xef\x69\xe7\x68\x59\x9e\xa1\xad\x0f\x9e\x48\x7b\x76\x42\xa7\x98\x46\x57\xa1\xbb\xa1\xae\x02\x6a\x00\x14\xc9\xf6\xed\xfd\xef\x17\xc8\x4c\x7c\x54\x75\x35\xbb\x29\x89\xbe\xe1\xcd\xee\x44\xac\x45\xb2\x90\x48\x24\x12\x89\x44\x7e\x3a\xc3\xa5\xb3\xa7\x4f\xc6\x4c\xf1\x5a\x9c\xb2\xdf\xd9\x82\x57\xe2\x09\x63\x4d\xc5\xdd\x5c\x9b\xfa\x [...] + compressedContent: []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\x1c\x37\x92\x20\xfe\xbf\x3e\x05\x82\xfb\xdb\x20\xa9\x5f\x77\x53\xf6\xac\x67\xbd\xbc\xd3\xce\xd1\xb2\x3c\x43\x5b\x0f\x9e\x48\x7b\x6e\x42\xa7\x98\x46\x57\xa1\xbb\xa1\xae\x02\x6a\x00\x14\xc9\xf6\xed\x7d\xf7\x0b\x64\x26\x1e\x55\x5d\xcd\x6e\x4a\xa2\x6f\x78\xb3\x3b\x11\x6b\x91\x2c\x24\x12\x89\x44\x22\x91\x4f\x67\xb8\x74\xf6\xf4\xc9\x98\x29\x5e\x8b\x53\xf6\x3b\x5b\xf0\x4a\x3c\x61\xac\xa9\xb8\x9b\x6b\x53\x9f\x [...] }, } fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{ diff --git a/pkg/trait/camel.go b/pkg/trait/camel.go index 26d87c589..50348255c 100644 --- a/pkg/trait/camel.go +++ b/pkg/trait/camel.go @@ -217,7 +217,7 @@ func (t *camelTrait) computeConfigMaps(e *Environment) []ctrl.Object { } for i, s := range sources { - if s.ContentRef != "" { + if s.ContentRef != "" || e.isEmbedded(s) { continue } diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go index ff3decb31..88b299e90 100644 --- a/pkg/trait/quarkus.go +++ b/pkg/trait/quarkus.go @@ -47,6 +47,57 @@ type quarkusTrait struct { BaseTrait traitv1.QuarkusTrait `property:",squash"` } +type languageSettings struct { + // indicates whether the native mode is supported + native bool + // indicates whether the sources are required at build time for native compilation + sourcesRequiredAtBuildTime bool +} + +var ( + // settings for the Java language. + javaSettings = languageSettings{true, true} + // settings for the Groovy language. + groovySettings = languageSettings{true, true} + // settings for the XML language. + xmlSettings = languageSettings{true, false} + // settings for the Kotlin language. + kotlinSettings = languageSettings{true, true} + // settings for the YAML language. + yamlSettings = languageSettings{true, false} + // settings for the Kamelet language. + kameletSettings = languageSettings{true, false} + // settings for the Java Shell language. + // Native support is not yet supported due to https://github.com/apache/camel-quarkus/issues/4458. + jshSettings = languageSettings{false /*true*/, true} + // settings for the JavaScript language. + // Guest languages are not yet supported on Mandrel in native mode. + javaScriptSettings = languageSettings{false /*true*/, false} + // settings for an unknown language. + defaultSettings = languageSettings{false, false} +) + +func getLanguageSettings(language v1.Language) languageSettings { + switch language { + case v1.LanguageJavaSource: + return javaSettings + case v1.LanguageGroovy: + return groovySettings + case v1.LanguageXML: + return xmlSettings + case v1.LanguageKotlin: + return kotlinSettings + case v1.LanguageYaml: + return yamlSettings + case v1.LanguageKamelet: + return kameletSettings + case v1.LanguageJavaShell: + return jshSettings + case v1.LanguageJavaScript: + return javaScriptSettings + } + return defaultSettings +} func newQuarkusTrait() Trait { return &quarkusTrait{ @@ -161,9 +212,7 @@ func (t *quarkusTrait) applyWhileBuildingKit(e *Environment) { func (t *quarkusTrait) validateNativeSupport(e *Environment) bool { for _, source := range e.Integration.Sources() { - if language := source.InferLanguage(); language != v1.LanguageKamelet && - language != v1.LanguageYaml && - language != v1.LanguageXML { + if language := source.InferLanguage(); !getLanguageSettings(language).native { t.L.ForIntegration(e.Integration).Infof("Integration %s/%s contains a %s source that cannot be compiled to native executable", e.Integration.Namespace, e.Integration.Name, language) e.Integration.Status.Phase = v1.IntegrationPhaseError e.Integration.Status.SetCondition( @@ -216,6 +265,9 @@ func (t *quarkusTrait) newIntegrationKit(e *Environment, packageType traitv1.Qua Traits: propagateKitTraits(e), } + if packageType == traitv1.NativePackageType { + kit.Spec.Sources = propagateSourcesRequiredAtBuildTime(e) + } return kit } @@ -265,6 +317,10 @@ func (t *quarkusTrait) applyWhenBuildSubmitted(e *Environment) error { if native { build.Maven.Properties["quarkus.package.type"] = string(traitv1.NativePackageType) + if len(e.IntegrationKit.Spec.Sources) > 0 { + build.Sources = e.IntegrationKit.Spec.Sources + steps = append(steps, builder.Quarkus.PrepareProjectWithSources) + } steps = append(steps, builder.Image.NativeImageContext) // Spectrum does not rely on Dockerfile to assemble the image if e.Platform.Status.Build.PublishStrategy != v1.IntegrationPlatformBuildPublishStrategySpectrum { @@ -319,6 +375,18 @@ func (t *quarkusTrait) isNativeIntegration(e *Environment) bool { return e.IntegrationKit.Labels[v1.IntegrationKitLayoutLabel] == v1.IntegrationKitLayoutNative } +func (t *quarkusTrait) isEmbedded(e *Environment, source v1.SourceSpec) bool { + if language := source.InferLanguage(); sourcesRequiredAtBuildTime(language) { + if e.IntegrationInRunningPhases() { + return t.isNativeIntegration(e) + } else if e.IntegrationKitInPhase(v1.IntegrationKitPhaseBuildSubmitted) { + native, _ := t.isNativeKit(e) + return native + } + } + return false +} + func containsPackageType(types []traitv1.QuarkusPackageType, t traitv1.QuarkusPackageType) bool { for _, ti := range types { if t == ti { @@ -327,3 +395,20 @@ func containsPackageType(types []traitv1.QuarkusPackageType, t traitv1.QuarkusPa } return false } + +// Indicates whether the sources expressed in the given languages are required at build time for native compilation. +func sourcesRequiredAtBuildTime(language v1.Language) bool { + settings := getLanguageSettings(language) + return settings.native && settings.sourcesRequiredAtBuildTime +} + +// Propagates the sources that are required at build time for native compilation. +func propagateSourcesRequiredAtBuildTime(e *Environment) []v1.SourceSpec { + array := make([]v1.SourceSpec, 0) + for _, source := range e.Integration.Sources() { + if language := source.InferLanguage(); sourcesRequiredAtBuildTime(language) { + array = append(array, source) + } + } + return array +} diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go index 63fcb07d0..dbc23a36e 100644 --- a/pkg/trait/trait_test.go +++ b/pkg/trait/trait_test.go @@ -267,15 +267,15 @@ func TestConfigureVolumesAndMountsSources(t *testing.T) { Sources: []v1.SourceSpec{ { DataSpec: v1.DataSpec{ - Name: "source1.java", + Name: "source1.xml", ContentRef: "my-cm1", - ContentKey: "source1.java", + ContentKey: "source1.xml", }, Type: "data", }, { DataSpec: v1.DataSpec{ - Name: "source2.java", + Name: "source2.xml", ContentRef: "my-cm2", }, Type: "data", @@ -283,6 +283,7 @@ func TestConfigureVolumesAndMountsSources(t *testing.T) { }, }, }, + Catalog: &Catalog{}, } vols := make([]corev1.Volume, 0) @@ -297,7 +298,7 @@ func TestConfigureVolumesAndMountsSources(t *testing.T) { assert.NotNil(t, v) assert.NotNil(t, v.VolumeSource.ConfigMap) assert.Len(t, v.VolumeSource.ConfigMap.Items, 1) - assert.Equal(t, "source1.java", v.VolumeSource.ConfigMap.Items[0].Key) + assert.Equal(t, "source1.xml", v.VolumeSource.ConfigMap.Items[0].Key) m := findVVolumeMount(mnts, func(m corev1.VolumeMount) bool { return m.Name == v.Name }) assert.NotNil(t, m) @@ -403,10 +404,10 @@ func createTestEnv(t *testing.T, cluster v1.IntegrationPlatformCluster, script s Sources: []v1.SourceSpec{ { DataSpec: v1.DataSpec{ - Name: "file.groovy", + Name: "file.js", Content: script, }, - Language: v1.LanguageGroovy, + Language: v1.LanguageJavaScript, }, }, }, diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index b38b9a7d8..ab03f8f7e 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -405,32 +405,36 @@ func (e *Environment) addSourcesProperties() { if e.ApplicationProperties == nil { e.ApplicationProperties = make(map[string]string) } - for i, s := range e.Integration.Sources() { + idx := 0 + for _, s := range e.Integration.Sources() { + if e.isEmbedded(s) { + continue + } srcName := strings.TrimPrefix(filepath.ToSlash(s.Name), "/") src := "file:" + path.Join(filepath.ToSlash(camel.SourcesMountPath), srcName) - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].location", i)] = src + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].location", idx)] = src simpleName := srcName if strings.Contains(srcName, ".") { simpleName = srcName[0:strings.Index(srcName, ".")] } - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].name", i)] = simpleName + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].name", idx)] = simpleName for pid, p := range s.PropertyNames { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].property-names[%d]", i, pid)] = p + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].property-names[%d]", idx, pid)] = p } if s.Type != "" { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].type", i)] = string(s.Type) + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].type", idx)] = string(s.Type) } if s.InferLanguage() != "" { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].language", i)] = string(s.InferLanguage()) + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].language", idx)] = string(s.InferLanguage()) } if s.Loader != "" { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].loader", i)] = s.Loader + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].loader", idx)] = s.Loader } if s.Compression { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compressed", i)] = "true" + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].compressed", idx)] = "true" } interceptors := make([]string, 0, len(s.Interceptors)) @@ -441,8 +445,9 @@ func (e *Environment) addSourcesProperties() { interceptors = append(interceptors, e.Interceptors...) } for intID, interceptor := range interceptors { - e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors[%d]", i, intID)] = interceptor + e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].interceptors[%d]", idx, intID)] = interceptor } + idx++ } } @@ -450,8 +455,12 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c // // Volumes :: Sources // - for i, s := range e.Integration.Sources() { - cmName := fmt.Sprintf("%s-source-%03d", e.Integration.Name, i) + idx := 0 + for _, s := range e.Integration.Sources() { + if e.isEmbedded(s) { + continue + } + cmName := fmt.Sprintf("%s-source-%03d", e.Integration.Name, idx) if s.ContentRef != "" { cmName = s.ContentRef } @@ -460,13 +469,14 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c cmKey = s.ContentKey } resName := strings.TrimPrefix(s.Name, "/") - refName := fmt.Sprintf("i-source-%03d", i) + refName := fmt.Sprintf("i-source-%03d", idx) resPath := filepath.Join(camel.SourcesMountPath, resName) vol := getVolume(refName, "configmap", cmName, cmKey, resName) mnt := getMount(refName, resPath, resName, true) *vols = append(*vols, *vol) *mnts = append(*mnts, *mnt) + idx++ } if e.Resources != nil { @@ -651,6 +661,16 @@ func (e *Environment) GetIntegrationContainerName() string { return containerName } +// Indicates whether the given source is embedded in the final binary +func (e *Environment) isEmbedded(source v1.SourceSpec) bool { + if dt := e.Catalog.GetTrait(quarkusTraitID); dt != nil { + if qt, ok := dt.(*quarkusTrait); ok { + return qt.isEmbedded(e, source) + } + } + return false +} + func (e *Environment) GetIntegrationContainer() *corev1.Container { containerName := e.GetIntegrationContainerName() return e.Resources.GetContainerByName(containerName) diff --git a/pkg/util/source/inspector.go b/pkg/util/source/inspector.go index 33fa7b2b7..7be1eaf54 100644 --- a/pkg/util/source/inspector.go +++ b/pkg/util/source/inspector.go @@ -207,6 +207,12 @@ func InspectorForLanguage(catalog *camel.RuntimeCatalog, language v1.Language) I catalog: catalog, }, } + case v1.LanguageJavaShell: + return &JavaSourceInspector{ + baseInspector: baseInspector{ + catalog: catalog, + }, + } } return &baseInspector{} } diff --git a/resources/traits.yaml b/resources/traits.yaml index a5fef3a9f..7059df2b7 100755 --- a/resources/traits.yaml +++ b/resources/traits.yaml @@ -1100,7 +1100,6 @@ traits: - OpenShift description: 'The Quarkus trait configures the Quarkus runtime. It''s enabled by default. NOTE: Compiling to a native executable, i.e. when using `package-type=native`, - is only supported for kamelets, as well as YAML and XML integrations. It also requires at least 4GiB of memory, so the Pod running the native build, that is either the operator Pod, or the build Pod (depending on the build strategy configured for the platform), must have enough memory available.'
