Skip to content

Commit

Permalink
fix(trait): run old native process for runtime pre 3.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Oct 3, 2023
1 parent 51ede6e commit 890b71c
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 31 deletions.
5 changes: 3 additions & 2 deletions e2e/common/traits/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func TestBuilderTrait(t *testing.T) {
integrationKitNamespace := IntegrationKitNamespace(ns, name)()
builderKitName := fmt.Sprintf("camel-k-%s-builder", integrationKitName)
Eventually(BuilderPod(integrationKitNamespace, builderKitName), TestTimeoutShort).ShouldNot(BeNil())
Eventually(len(BuilderPod(integrationKitNamespace, builderKitName)().Spec.InitContainers), TestTimeoutShort).Should(Equal(3))
Eventually(len(BuilderPod(integrationKitNamespace, builderKitName)().Spec.InitContainers), TestTimeoutShort).Should(Equal(4))
Eventually(BuilderPod(integrationKitNamespace, builderKitName)().Spec.InitContainers[0].Name, TestTimeoutShort).Should(Equal("builder"))
Eventually(BuilderPod(integrationKitNamespace, builderKitName)().Spec.InitContainers[1].Name, TestTimeoutShort).Should(Equal("custom1"))
Eventually(BuilderPod(integrationKitNamespace, builderKitName)().Spec.InitContainers[2].Name, TestTimeoutShort).Should(Equal("custom2"))
Expand Down Expand Up @@ -249,9 +249,10 @@ func TestBuilderTrait(t *testing.T) {
integrationKitName := IntegrationKit(ns, name)()
builderKitName := fmt.Sprintf("camel-k-%s-builder", integrationKitName)
Eventually(BuilderPod(ns, builderKitName), TestTimeoutShort).ShouldNot(BeNil())
Eventually(len(BuilderPod(ns, builderKitName)().Spec.InitContainers), TestTimeoutShort).Should(Equal(2))
Eventually(len(BuilderPod(ns, builderKitName)().Spec.InitContainers), TestTimeoutShort).Should(Equal(3))
Eventually(BuilderPod(ns, builderKitName)().Spec.InitContainers[0].Name, TestTimeoutShort).Should(Equal("builder"))
Eventually(BuilderPod(ns, builderKitName)().Spec.InitContainers[1].Name, TestTimeoutShort).Should(Equal("custom1"))
Eventually(BuilderPod(ns, builderKitName)().Spec.InitContainers[2].Name, TestTimeoutShort).Should(Equal("package"))

// Check containers conditions
Eventually(Build(ns, integrationKitName), TestTimeoutShort).ShouldNot(BeNil())
Expand Down
6 changes: 2 additions & 4 deletions e2e/commonwithcustominstall/catalog_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,7 @@ func TestCamelCatalogBuilder(t *testing.T) {

Eventually(CamelCatalog(ns, compatibleCatalogName)).ShouldNot(BeNil())
Eventually(CamelCatalogPhase(ns, compatibleCatalogName)).Should(Equal(v1.CamelCatalogPhaseReady))
Eventually(CamelCatalogCondition(ns, compatibleCatalogName, v1.CamelCatalogConditionReady)().Message).Should(
Or(Equal("Container image successfully built"), Equal("Container image exists on registry")),
)
Eventually(CamelCatalogCondition(ns, compatibleCatalogName, v1.CamelCatalogConditionReady)().Message).Should(Equal("Container image tool found in catalog"))
Eventually(IntegrationPodPhase(ns, name), TestTimeoutMedium).Should(Equal(corev1.PodRunning))
Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutMedium).
Should(Equal(corev1.ConditionTrue))
Expand All @@ -121,7 +119,7 @@ func TestCamelCatalogBuilder(t *testing.T) {
Eventually(CamelCatalog(ns, compatibleCatalogName)).ShouldNot(BeNil())
Eventually(CamelCatalogPhase(ns, compatibleCatalogName)).Should(Equal(v1.CamelCatalogPhaseReady))
Eventually(CamelCatalogCondition(ns, compatibleCatalogName, v1.CamelCatalogConditionReady)().Message).Should(
Equal("Container image exists on registry"),
Equal("Container image tool found in catalog"),
)

Eventually(IntegrationKit(ns, name)).ShouldNot(Equal(""))
Expand Down
12 changes: 6 additions & 6 deletions e2e/native/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestNativeIntegrations(t *testing.T) {
name := "unsupported-js"
Expect(KamelRunWithID(operatorID, ns, "files/JavaScript.js", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=6.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:6.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPhase(ns, name)).Should(Equal(v1.IntegrationPhaseError))
Expand All @@ -61,7 +61,7 @@ func TestNativeIntegrations(t *testing.T) {
name := "xml-native"
Expect(KamelRunWithID(operatorID, ns, "files/Xml.xml", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=6.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:6.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPodPhase(ns, name), TestTimeoutVeryLong).Should(Equal(corev1.PodRunning))
Expand All @@ -76,14 +76,14 @@ func TestNativeIntegrations(t *testing.T) {
Expect(Kamel("delete", name, "-n", ns).Execute()).To(Succeed())
})

t.Run("automatic rollout deployment from fast-jar to native kit", func(t *testing.T) {
t.Run("automatic rollout deployment from jvm to native kit", func(t *testing.T) {
// Let's make sure we start from a clean state
Expect(DeleteKits(ns)).To(Succeed())
name := "yaml-native"
Expect(KamelRunWithID(operatorID, ns, "files/yaml.yaml", "--name", name,
"-t", "quarkus.mode=fast-jar",
"-t", "quarkus.mode=jvm",
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=6.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:6.5Gi",
).Execute()).To(Succeed())

// Check that two Kits are created with distinct layout
Expand All @@ -107,7 +107,7 @@ func TestNativeIntegrations(t *testing.T) {
Eventually(IntegrationConditionStatus(ns, name, v1.IntegrationConditionReady), TestTimeoutShort).
Should(Equal(corev1.ConditionTrue))

Eventually(IntegrationLogs(ns, name), TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
Eventually(IntegrationLogs(ns, name), TestTimeoutMedium).Should(ContainSubstring("Magicstring!"))

// ====================================
// !!! THE MOST TIME-CONSUMING PART !!!
Expand Down
12 changes: 5 additions & 7 deletions e2e/native/native_with_sources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ package native

import (
"testing"
"time"

. "github.com/onsi/gomega"

. "github.com/apache/camel-k/v2/e2e/support"
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestNativeHighMemoryIntegrations(t *testing.T) {
Expand All @@ -47,7 +45,7 @@ func TestNativeHighMemoryIntegrations(t *testing.T) {
name := "java-native"
Expect(KamelRunWithID(operatorID, ns, "files/Java.java", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=9.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:9.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPodPhase(ns, name), TestTimeoutVeryLong).Should(Equal(corev1.PodRunning))
Expand All @@ -61,7 +59,7 @@ func TestNativeHighMemoryIntegrations(t *testing.T) {
name := "java-native-clone"
Expect(KamelRunWithID(operatorID, ns, "files/Java.java", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=9.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:9.5Gi",
).Execute()).To(Succeed())

// This one should run quickly as it suppose to reuse an IntegrationKit
Expand All @@ -78,7 +76,7 @@ func TestNativeHighMemoryIntegrations(t *testing.T) {
name := "java-native-2"
Expect(KamelRunWithID(operatorID, ns, "files/Java2.java", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=9.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:9.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPodPhase(ns, name), TestTimeoutVeryLong).Should(Equal(corev1.PodRunning))
Expand All @@ -98,7 +96,7 @@ func TestNativeHighMemoryIntegrations(t *testing.T) {
name := "groovy-native"
Expect(KamelRunWithID(operatorID, ns, "files/Groovy.groovy", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=9.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:9.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPodPhase(ns, name), TestTimeoutVeryLong).Should(Equal(corev1.PodRunning))
Expand All @@ -117,7 +115,7 @@ func TestNativeHighMemoryIntegrations(t *testing.T) {
name := "kotlin-native"
Expect(KamelRunWithID(operatorID, ns, "files/Kotlin.kts", "--name", name,
"-t", "quarkus.mode=native",
"-t", "builder.tasks-limit-memory=quarkus-native:=9.5Gi",
"-t", "builder.tasks-limit-memory=quarkus-native:9.5Gi",
).Execute()).To(Succeed())

Eventually(IntegrationPodPhase(ns, name), TestTimeoutVeryLong).Should(Equal(corev1.PodRunning))
Expand Down
2 changes: 1 addition & 1 deletion pkg/builder/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func nativeImageContext(ctx *builderContext) error {
ctx.Artifacts = []v1.Artifact{
{
ID: runner,
Location: filepath.Join(ctx.Path, "maven", "target", "native-sources", runner),
Location: QuarkusRuntimeSupport(ctx.Catalog.GetCamelQuarkusVersion()).TargetDirectory(ctx.Path, runner),
Target: runner,
},
}
Expand Down
91 changes: 91 additions & 0 deletions pkg/builder/runtime_support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
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 builder

import "path/filepath"

// QuarkusRuntimeNativeAdapter is used to get the proper Quarkus native configuration which may be different
// in Camel Quarkus version. It is known that before Camel Quarkus 3.5 there was no support to native-source,
// and using this interface will adapt the configuration to build natively according the previous configuration.
type QuarkusRuntimeNativeAdapter interface {
// The commands used to build a native application
BuildCommands() string
// The directory where to execute the command
Directory() string
// The directory where to expect the native compiled artifact
TargetDirectory(ctxPath, runner string) string
// The parameter to use for the maven project
NativeMavenProperty() string
}

// NativeSourcesAdapter used for Camel Quarkus runtime >= 3.5.0.
type NativeSourcesAdapter struct {
}

// BuildCommands -- .
func (n *NativeSourcesAdapter) BuildCommands() string {
return "cd " + n.Directory() + " && echo NativeImage version is $(native-image --version) && echo GraalVM expected version is $(cat graalvm.version) && echo WARN: Make sure they are compatible, otherwise the native compilation may results in error && native-image $(cat native-image.args)"
}

// Directory -- .
func (n *NativeSourcesAdapter) Directory() string {
return filepath.Join("maven", "target", "native-sources")
}

// TargetDirectory -- .
func (n *NativeSourcesAdapter) TargetDirectory(ctxPath, runner string) string {
return filepath.Join(ctxPath, "maven", "target", "native-sources", runner)
}

// NativeMavenProperty -- .
func (n *NativeSourcesAdapter) NativeMavenProperty() string {
return "native-sources"
}

// NativeAdapter used for Camel Quarkus runtime < 3.5.0.
type NativeAdapter struct {
}

// BuildCommands -- .
func (n *NativeAdapter) BuildCommands() string {
return "cd " + n.Directory() + " && ./mvnw package -Dquarkus.package.type=native --global-settings settings.xml"
}

// Directory -- .
func (n *NativeAdapter) Directory() string {
return "maven"
}

// TargetDirectory -- .
func (n *NativeAdapter) TargetDirectory(ctxPath, runner string) string {
return filepath.Join(ctxPath, "maven", "target", runner)
}

// NativeMavenProperty -- .
func (n *NativeAdapter) NativeMavenProperty() string {
// Empty on purpose. The parameter will be provided later by the command (see BuildCommands()).
return ""
}

// QuarkusRuntimeSupport is used to get the proper native configuration based on the Camel Quarkus version.
func QuarkusRuntimeSupport(version string) QuarkusRuntimeNativeAdapter {
if version < "3.5.0" {
return &NativeAdapter{}
}
return &NativeSourcesAdapter{}
}
10 changes: 5 additions & 5 deletions pkg/trait/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package trait

import (
"fmt"
"path/filepath"
"regexp"
"sort"
"strings"
Expand Down Expand Up @@ -79,8 +78,9 @@ func (t *builderTrait) Configure(e *Environment) (bool, error) {
return false, err
}
if ok && pointer.BoolDeref(quarkus.Enabled, true) && (isNativeIntegration || isNativeKit) {
nativeArgsCd := filepath.Join("maven", "target", "native-sources")
command := "cd " + nativeArgsCd + " && echo NativeImage version is $(native-image --version) && echo GraalVM expected version is $(cat graalvm.version) && echo WARN: Make sure they are compatible, otherwise the native compilation may results in error && native-image $(cat native-image.args)"
// TODO expect maven repository in local repo (need to change builder pod accordingly!)
command := builder.QuarkusRuntimeSupport(e.CamelCatalog.GetCamelQuarkusVersion()).BuildCommands()

// it should be performed as the last custom task
t.Tasks = append(t.Tasks, fmt.Sprintf(`quarkus-native;%s;/bin/bash -c "%s"`, e.CamelCatalog.GetQuarkusToolingImage(), command))
// Force the build to run in a separate Pod and strictly sequential
Expand Down Expand Up @@ -494,8 +494,8 @@ func (t *builderTrait) parseTasksConf() (map[string]*v1.BuildConfiguration, erro
// if however we have a command which is not quoted, then we leave it the way it is.
func splitContainerCommand(command string) []string {
if !strings.Contains(command, "\"") {
// No quotes, just return
return []string{command}
// No quotes, then, splits all commands found
return strings.Split(command, " ")
}
matches := commandsRegexp.FindAllString(command, -1)
removeQuotes := make([]string, 0, len(matches))
Expand Down
9 changes: 6 additions & 3 deletions pkg/trait/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ func TestBuilderCustomTasks(t *testing.T) {
assert.Equal(t, "ls", tasks[0].Custom.ContainerCommands[0])
assert.Equal(t, "test", tasks[1].Custom.Name)
assert.Equal(t, "alpine", tasks[1].Custom.ContainerImage)
assert.Equal(t, "mvn test", tasks[1].Custom.ContainerCommands[0])
assert.Equal(t, "mvn", tasks[1].Custom.ContainerCommands[0])
assert.Equal(t, "test", tasks[1].Custom.ContainerCommands[1])

}

func TestBuilderCustomTasksFailure(t *testing.T) {
Expand Down Expand Up @@ -399,8 +401,9 @@ func TestUserTaskSingleCommand(t *testing.T) {
command := `cat /path/to/a/resource`
podCommands := splitContainerCommand(command)

assert.Len(t, podCommands, 1)
assert.Equal(t, "cat /path/to/a/resource", podCommands[0])
assert.Len(t, podCommands, 2)
assert.Equal(t, "cat", podCommands[0])
assert.Equal(t, "/path/to/a/resource", podCommands[1])
}

func TestUserTaskMultiCommands(t *testing.T) {
Expand Down
9 changes: 6 additions & 3 deletions pkg/trait/quarkus.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,13 @@ func (t *quarkusTrait) applyWhenBuildSubmitted(e *Environment) error {
return err
}

// The LoadCamelQuarkusCatalog is required to have catalog information available by the builder
packageSteps = append(packageSteps, builder.Quarkus.LoadCamelQuarkusCatalog)

if native {
buildTask.Maven.Properties["quarkus.package.type"] = string(nativeSourcesPackageType)
if nativePackagetType := builder.QuarkusRuntimeSupport(e.CamelCatalog.GetCamelQuarkusVersion()).NativeMavenProperty(); nativePackagetType != "" {
buildTask.Maven.Properties["quarkus.package.type"] = nativePackagetType
}
if len(e.IntegrationKit.Spec.Sources) > 0 {
buildTask.Sources = e.IntegrationKit.Spec.Sources
buildSteps = append(buildSteps, builder.Quarkus.PrepareProjectWithSources)
Expand All @@ -354,8 +359,6 @@ func (t *quarkusTrait) applyWhenBuildSubmitted(e *Environment) error {
// Default, if nothing is specified
buildTask.Maven.Properties["quarkus.package.type"] = string(fastJarPackageType)
packageSteps = append(packageSteps, builder.Quarkus.ComputeQuarkusDependencies)
// The LoadCamelQuarkusCatalog is required to have catalog information available by the builder
packageSteps = append(packageSteps, builder.Quarkus.LoadCamelQuarkusCatalog)
packageSteps = append(packageSteps, builder.Image.IncrementalImageContext)
// Create the dockerfile, regardless it's later used or not by the publish strategy
packageSteps = append(packageSteps, builder.Image.JvmDockerfile)
Expand Down

0 comments on commit 890b71c

Please sign in to comment.