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

astefanutti 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 1215301  chore(native): Fail-fast native build for unsupported 
languages
1215301 is described below

commit 1215301982c3fd531c5d8f611eae88ab48e258f0
Author: Antonin Stefanutti <anto...@stefanutti.fr>
AuthorDate: Mon Sep 13 12:40:53 2021 +0200

    chore(native): Fail-fast native build for unsupported languages
---
 deploy/traits.yaml                      |  7 +--
 docs/modules/traits/pages/quarkus.adoc  |  8 +--
 e2e/native/Java.java                    | 28 ++++++++++
 e2e/native/native_test.go               | 96 ++++++++++++++++++---------------
 pkg/apis/camel/v1/integration_types.go  |  2 +
 pkg/controller/integration/build_kit.go | 13 ++---
 pkg/resources/resources.go              |  4 +-
 pkg/trait/quarkus.go                    | 53 +++++++++++++-----
 8 files changed, 141 insertions(+), 70 deletions(-)

diff --git a/deploy/traits.yaml b/deploy/traits.yaml
index b441c4e..855ba4a 100755
--- a/deploy/traits.yaml
+++ b/deploy/traits.yaml
@@ -810,9 +810,10 @@ 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`,
-    requires at least 4GiB of memory. Make sure enough memory is available for 
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.'
+    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.'
   properties:
   - name: enabled
     type: bool
diff --git a/docs/modules/traits/pages/quarkus.adoc 
b/docs/modules/traits/pages/quarkus.adoc
index d90ad66..78e9f72 100755
--- a/docs/modules/traits/pages/quarkus.adoc
+++ b/docs/modules/traits/pages/quarkus.adoc
@@ -5,9 +5,11 @@ 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`, 
requires at least 4GiB of memory.
-Make sure enough memory is available for 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.
+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.
 
 
 This trait is available in the following profiles: **Kubernetes, Knative, 
OpenShift**.
diff --git a/e2e/native/Java.java b/e2e/native/Java.java
new file mode 100644
index 0000000..66fef5f
--- /dev/null
+++ b/e2e/native/Java.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+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}");
+  }
+}
diff --git a/e2e/native/native_test.go b/e2e/native/native_test.go
index a1ea20b..fca7c7e 100644
--- a/e2e/native/native_test.go
+++ b/e2e/native/native_test.go
@@ -37,7 +37,7 @@ var (
        withNativeLayout  = 
KitWithLabels(map[string]string{v1.IntegrationKitLayoutLabel: 
v1.IntegrationKitLayoutNative})
 )
 
-func TestAutomaticRolloutDeploymentFromFastJarToNativeKit(t *testing.T) {
+func TestNativeIntegrations(t *testing.T) {
        WithNewTestNamespace(t, func(ns string) {
                Expect(Kamel("install", "-n", ns,
                        "--build-timeout", "15m0s",
@@ -45,47 +45,59 @@ func TestAutomaticRolloutDeploymentFromFastJarToNativeKit(t 
*testing.T) {
                ).Execute()).To(Succeed())
                Eventually(PlatformPhase(ns), 
TestTimeoutMedium).Should(Equal(v1.IntegrationPlatformPhaseReady))
 
-               name := "jvm-to-native"
-               Expect(Kamel("run", "-n", ns, "yaml.yaml", "--name", name,
-                       "-t", "quarkus.package-type=fast-jar",
-                       "-t", "quarkus.package-type=native",
-               ).Execute()).To(Succeed())
-
-               // Check that two Kits are created with distinct layout
-               Eventually(Kits(ns, withFastJarLayout)).Should(HaveLen(1))
-               Eventually(Kits(ns, withNativeLayout)).Should(HaveLen(1))
-
-               // Check the fast-jar Kit is ready
-               Eventually(Kits(ns, withFastJarLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady)),
-                       TestTimeoutMedium).Should(HaveLen(1))
-
-               fastJarKit := Kits(ns, withFastJarLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady))()[0]
-               // Check the Integration uses the fast-jar Kit
-               Eventually(IntegrationKit(ns, name), 
TestTimeoutShort).Should(Equal(fastJarKit.Name))
-               // Check the Integration Pod uses the fast-jar Kit
-               Eventually(IntegrationPodImage(ns, 
name)).Should(Equal(fastJarKit.Status.Image))
-
-               // Check the Integration is ready
-               Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
-               Eventually(IntegrationCondition(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
-
-               Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
-
-               // Check the native Kit is ready
-               Eventually(Kits(ns, withNativeLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady)),
-                       TestTimeoutLong).Should(HaveLen(1))
-
-               nativeKit := Kits(ns, withNativeLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady))()[0]
-               // Check the Integration uses the native Kit
-               Eventually(IntegrationKit(ns, name), 
TestTimeoutShort).Should(Equal(nativeKit.Name))
-               // Check the Integration Pod uses the native Kit
-               Eventually(IntegrationPodImage(ns, 
name)).Should(Equal(nativeKit.Status.Image))
-
-               // Check the Integration is still ready
-               Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
-               Eventually(IntegrationCondition(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
-
-               Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+               t.Run("unsupported integration source language", func(t 
*testing.T) {
+                       name := "unsupported-java"
+                       Expect(Kamel("run", "-n", ns, "Java.java", "--name", 
name,
+                               "-t", "quarkus.package-type=native",
+                       ).Execute()).To(Succeed())
+
+                       Eventually(IntegrationPhase(ns, 
name)).Should(Equal(v1.IntegrationPhaseError))
+                       Eventually(IntegrationCondition(ns, name, 
v1.IntegrationConditionKitAvailable)).Should(Equal(corev1.ConditionFalse))
+               })
+
+               t.Run("automatic rollout deployment from fast-jar to native 
kit", func(t *testing.T) {
+                       name := "jvm-to-native"
+                       Expect(Kamel("run", "-n", ns, "yaml.yaml", "--name", 
name,
+                               "-t", "quarkus.package-type=fast-jar",
+                               "-t", "quarkus.package-type=native",
+                       ).Execute()).To(Succeed())
+
+                       // Check that two Kits are created with distinct layout
+                       Eventually(Kits(ns, 
withFastJarLayout)).Should(HaveLen(1))
+                       Eventually(Kits(ns, 
withNativeLayout)).Should(HaveLen(1))
+
+                       // Check the fast-jar Kit is ready
+                       Eventually(Kits(ns, withFastJarLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady)),
+                               TestTimeoutMedium).Should(HaveLen(1))
+
+                       fastJarKit := Kits(ns, withFastJarLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady))()[0]
+                       // Check the Integration uses the fast-jar Kit
+                       Eventually(IntegrationKit(ns, name), 
TestTimeoutShort).Should(Equal(fastJarKit.Name))
+                       // Check the Integration Pod uses the fast-jar Kit
+                       Eventually(IntegrationPodImage(ns, 
name)).Should(Equal(fastJarKit.Status.Image))
+
+                       // Check the Integration is ready
+                       Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+                       Eventually(IntegrationCondition(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+
+                       Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+
+                       // Check the native Kit is ready
+                       Eventually(Kits(ns, withNativeLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady)),
+                               TestTimeoutLong).Should(HaveLen(1))
+
+                       nativeKit := Kits(ns, withNativeLayout, 
KitWithPhase(v1.IntegrationKitPhaseReady))()[0]
+                       // Check the Integration uses the native Kit
+                       Eventually(IntegrationKit(ns, name), 
TestTimeoutShort).Should(Equal(nativeKit.Name))
+                       // Check the Integration Pod uses the native Kit
+                       Eventually(IntegrationPodImage(ns, 
name)).Should(Equal(nativeKit.Status.Image))
+
+                       // Check the Integration is still ready
+                       Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutMedium).Should(Equal(corev1.PodRunning))
+                       Eventually(IntegrationCondition(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+
+                       Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+               })
 
                // Clean up
                Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).To(Succeed())
diff --git a/pkg/apis/camel/v1/integration_types.go 
b/pkg/apis/camel/v1/integration_types.go
index 32125c8..fe4c469 100644
--- a/pkg/apis/camel/v1/integration_types.go
+++ b/pkg/apis/camel/v1/integration_types.go
@@ -195,6 +195,8 @@ const (
        IntegrationConditionReplicaSetReadyReason string = "ReplicaSetReady"
        // IntegrationConditionReplicaSetNotReadyReason --
        IntegrationConditionReplicaSetNotReadyReason string = 
"ReplicaSetNotReady"
+       // IntegrationConditionUnsupportedLanguageReason --
+       IntegrationConditionUnsupportedLanguageReason string = 
"UnsupportedLanguage"
 
        // IntegrationConditionKameletsAvailable --
        IntegrationConditionKameletsAvailable IntegrationConditionType = 
"KameletsAvailable"
diff --git a/pkg/controller/integration/build_kit.go 
b/pkg/controller/integration/build_kit.go
index aab2ba2..17e3c85 100644
--- a/pkg/controller/integration/build_kit.go
+++ b/pkg/controller/integration/build_kit.go
@@ -116,12 +116,13 @@ kits:
                }
        }
 
-       // Set the kit name so the next handle loop, will fall through the
-       // same path as integration with a user defined kit
-       integration.SetIntegrationKit(integrationKit)
-
-       if integrationKit.Status.Phase == v1.IntegrationKitPhaseReady {
-               integration.Status.Phase = v1.IntegrationPhaseDeploying
+       if integrationKit != nil {
+               // Set the kit name so the next handle loop, will fall through 
the
+               // same path as integration with a user defined kit
+               integration.SetIntegrationKit(integrationKit)
+               if integrationKit.Status.Phase == v1.IntegrationKitPhaseReady {
+                       integration.Status.Phase = v1.IntegrationPhaseDeploying
+               }
        }
 
        return integration, nil
diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go
index d38bfdf..d053a94 100644
--- a/pkg/resources/resources.go
+++ b/pkg/resources/resources.go
@@ -467,9 +467,9 @@ var assets = func() http.FileSystem {
                "/traits.yaml": &vfsgen۰CompressedFileInfo{
                        name:             "traits.yaml",
                        modTime:          time.Time{},
-                       uncompressedSize: 42503,
+                       uncompressedSize: 42583,
 
-                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7d\x73\x1c\xb7\xd1\x20\xfe\xbf\x3e\x05\x8a\xcf\xaf\x4a\x24\x6b\x77\x28\x27\x4f\x12\xff\x78\xe7\x4b\xd1\x92\x1c\xd3\xd6\x0b\x4f\xa2\x9d\xba\xd2\xb9\xb2\xd8\x99\xde\x5d\x68\x31\xc0\x04\xc0\x90\xda\xdc\x73\xdf\xfd\x0a\xdd\x78\x9b\xd9\x25\xb9\x94\x45\x9f\x79\xf5\x24\x7f\x58\x24\x07\x40\xa3\xd1\xe8\xf7\x6e\x38\xc3\x85\xb3\xa7\x4f\xa6\x4c\xf1\x16\x4e\x19\x5f\x2c\x84\x12\x6e\xf3\x84\xb1\x4e\x72\xb7\xd0\xa6\x3d\x65\x
 [...]
+                       compressedContent: 
[]byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6b\x73\x5b\xb9\xb1\xe0\x77\xff\x0a\x94\xee\x56\x59\x52\x91\x94\x27\xb9\x49\x66\xb5\x3b\x9b\xd2\x78\x3c\x89\x66\xfc\xd0\xda\xce\x64\x6f\x79\xa7\x42\xf0\x9c\x26\x09\x0b\x04\x4e\x00\x1c\xc9\xcc\xde\xfd\xef\x5b\xe8\x6e\x3c\x0e\x49\x49\x94\xc7\x9a\x8d\x6e\xdd\xe4\xc3\x58\xd2\x01\xd0\x68\x34\xfa\xdd\x8d\xe0\xa4\x0a\xfe\xf4\xc9\x58\x18\xb9\x82\x53\x21\xe7\x73\x65\x54\x58\x3f\x11\xa2\xd3\x32\xcc\xad\x5b\x9d\x8a\xb9\x
 [...]
                },
        }
        fs["/"].(*vfsgen۰DirInfo).entries = []os.FileInfo{
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
index c4dd613..0b76021 100644
--- a/pkg/trait/quarkus.go
+++ b/pkg/trait/quarkus.go
@@ -24,6 +24,8 @@ import (
 
        "github.com/rs/xid"
 
+       corev1 "k8s.io/api/core/v1"
+
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/builder"
        "github.com/apache/camel-k/pkg/util/defaults"
@@ -48,9 +50,11 @@ var kitPriority = map[quarkusPackageType]string{
 //
 // It's enabled by default.
 //
-// NOTE: Compiling to a native executable, i.e. when using 
`package-type=native`, requires at least 4GiB of memory.
-// Make sure enough memory is available for 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.
+// 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.
 //
 // +camel-k:trait=quarkus
 type quarkusTrait struct {
@@ -92,16 +96,7 @@ func (t *quarkusTrait) Matches(trait Trait) bool {
                return false
        }
 
-       contains := func(types []quarkusPackageType, t quarkusPackageType) bool 
{
-               for _, ti := range qt.PackageTypes {
-                       if t == ti {
-                               return true
-                       }
-               }
-               return false
-       }
-
-       if len(t.PackageTypes) == 0 && len(qt.PackageTypes) != 0 && 
!contains(qt.PackageTypes, fastJarPackageType) {
+       if len(t.PackageTypes) == 0 && len(qt.PackageTypes) != 0 && 
!containsPackageType(qt.PackageTypes, fastJarPackageType) {
                return false
        }
 
@@ -110,7 +105,7 @@ types:
                if pt == fastJarPackageType && len(qt.PackageTypes) == 0 {
                        continue
                }
-               if contains(qt.PackageTypes, pt) {
+               if containsPackageType(qt.PackageTypes, pt) {
                        continue types
                }
                return false
@@ -133,6 +128,27 @@ func (t *quarkusTrait) Configure(e *Environment) (bool, 
error) {
 
 func (t *quarkusTrait) Apply(e *Environment) error {
        if e.IntegrationInPhase(v1.IntegrationPhaseBuildingKit) {
+               if containsPackageType(t.PackageTypes, nativePackageType) {
+                       // Native compilation is only supported for a subset of 
languages,
+                       // so let's check for compatibility, and fail-fast the 
Integration,
+                       // to save compute resources and user time.
+                       for _, source := range e.Integration.Sources() {
+                               if language := source.InferLanguage(); language 
!= v1.LanguageKamelet &&
+                                       language != v1.LanguageYaml &&
+                                       language != v1.LanguageXML {
+                                       
t.L.ForIntegration(e.Integration).Infof("Integration %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(
+                                               
v1.IntegrationConditionKitAvailable,
+                                               corev1.ConditionFalse,
+                                               
v1.IntegrationConditionUnsupportedLanguageReason,
+                                               fmt.Sprintf("native compilation 
for language %q is not supported", language))
+                                       // Let the calling controller handle 
the Integration update
+                                       return nil
+                               }
+                       }
+               }
+
                switch len(t.PackageTypes) {
                case 0:
                        kit := t.newIntegrationKit(e, fastJarPackageType)
@@ -293,3 +309,12 @@ func getBuilderTask(tasks []v1.Task) *v1.BuilderTask {
        }
        return nil
 }
+
+func containsPackageType(types []quarkusPackageType, t quarkusPackageType) 
bool {
+       for _, ti := range types {
+               if t == ti {
+                       return true
+               }
+       }
+       return false
+}

Reply via email to