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

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit e60fb567b73d19f580f0be1bc528599f69bd69b4
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Thu Oct 19 13:31:19 2023 +0200

    feat(build): add root image info
    
    * Useful to know from which image a kit hierarchy started
    * added builder.base-image property trait to override easily the base image
    
    Ref #2844
---
 config/crd/bases/camel.apache.org_builds.yaml      |  4 ++
 .../bases/camel.apache.org_integrationkits.yaml    | 13 ++++-
 .../camel.apache.org_integrationplatforms.yaml     |  6 +++
 .../crd/bases/camel.apache.org_integrations.yaml   |  3 ++
 .../bases/camel.apache.org_kameletbindings.yaml    |  3 ++
 config/crd/bases/camel.apache.org_pipes.yaml       |  3 ++
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  | 23 +++++++-
 docs/modules/traits/pages/builder.adoc             |  4 ++
 .../incremental_build_test.go                      | 61 ++++++++++++++++++++++
 helm/camel-k/crds/crd-build.yaml                   |  4 ++
 helm/camel-k/crds/crd-integration-kit.yaml         | 13 ++++-
 helm/camel-k/crds/crd-integration-platform.yaml    |  6 +++
 helm/camel-k/crds/crd-integration.yaml             |  3 ++
 helm/camel-k/crds/crd-kamelet-binding.yaml         |  3 ++
 helm/camel-k/crds/crd-pipe.yaml                    |  3 ++
 pkg/apis/camel/v1/build_types.go                   |  2 +
 pkg/apis/camel/v1/integrationkit_types.go          |  5 +-
 pkg/apis/camel/v1/trait/builder.go                 |  2 +
 pkg/builder/image.go                               | 12 +++--
 pkg/builder/jib.go                                 |  7 ++-
 pkg/builder/spectrum.go                            |  7 ++-
 .../applyconfiguration/camel/v1/buildstatus.go     |  9 ++++
 .../camel/v1/integrationkitstatus.go               |  9 ++++
 pkg/controller/integrationkit/build.go             |  1 +
 pkg/trait/builder.go                               | 14 +++--
 resources/traits.yaml                              |  3 ++
 26 files changed, 210 insertions(+), 13 deletions(-)

diff --git a/config/crd/bases/camel.apache.org_builds.yaml 
b/config/crd/bases/camel.apache.org_builds.yaml
index caacc731d..f0555f582 100644
--- a/config/crd/bases/camel.apache.org_builds.yaml
+++ b/config/crd/bases/camel.apache.org_builds.yaml
@@ -1740,6 +1740,10 @@ spec:
               phase:
                 description: describes the phase
                 type: string
+              rootImage:
+                description: root image (the first image from which the 
incremental
+                  image has started)
+                type: string
               startedAt:
                 description: the time when it started
                 format: date-time
diff --git a/config/crd/bases/camel.apache.org_integrationkits.yaml 
b/config/crd/bases/camel.apache.org_integrationkits.yaml
index d3e061b62..6d2611798 100644
--- a/config/crd/bases/camel.apache.org_integrationkits.yaml
+++ b/config/crd/bases/camel.apache.org_integrationkits.yaml
@@ -59,6 +59,10 @@ spec:
       jsonPath: .status.image
       name: Image
       type: string
+    - description: The integration kit root image
+      jsonPath: .status.rootImage
+      name: Root
+      type: string
     name: v1
     schema:
       openAPIV3Schema:
@@ -197,6 +201,9 @@ spec:
                     description: The builder trait is internally used to 
determine
                       the best strategy to build and configure IntegrationKits.
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
@@ -410,7 +417,7 @@ spec:
                   type: object
                 type: array
               baseImage:
-                description: base image used by the kit
+                description: base image used by the kit (could be another 
IntegrationKit)
                 type: string
               conditions:
                 description: a list of conditions which happened for the 
events related
@@ -495,6 +502,10 @@ spec:
               platform:
                 description: the platform for which this kit was configured
                 type: string
+              rootImage:
+                description: root image used by the kit (the first image from 
which
+                  the incremental image has started, typically a JDK/JRE base 
image)
+                type: string
               runtimeProvider:
                 description: the runtime provider for which this kit was 
configured
                 type: string
diff --git a/config/crd/bases/camel.apache.org_integrationplatforms.yaml 
b/config/crd/bases/camel.apache.org_integrationplatforms.yaml
index 011141207..63c5cb610 100644
--- a/config/crd/bases/camel.apache.org_integrationplatforms.yaml
+++ b/config/crd/bases/camel.apache.org_integrationplatforms.yaml
@@ -497,6 +497,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
@@ -2315,6 +2318,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
diff --git a/config/crd/bases/camel.apache.org_integrations.yaml 
b/config/crd/bases/camel.apache.org_integrations.yaml
index 0ea61efce..415adf376 100644
--- a/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/config/crd/bases/camel.apache.org_integrations.yaml
@@ -6417,6 +6417,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
diff --git a/config/crd/bases/camel.apache.org_kameletbindings.yaml 
b/config/crd/bases/camel.apache.org_kameletbindings.yaml
index 5e137abd8..a9c90247d 100644
--- a/config/crd/bases/camel.apache.org_kameletbindings.yaml
+++ b/config/crd/bases/camel.apache.org_kameletbindings.yaml
@@ -6699,6 +6699,9 @@ spec:
                       builder:
                         description: The configuration of Builder trait
                         properties:
+                          baseImage:
+                            description: Specify a base image
+                            type: string
                           configuration:
                             description: 'Legacy trait configuration 
parameters. Deprecated:
                               for backward compatibility.'
diff --git a/config/crd/bases/camel.apache.org_pipes.yaml 
b/config/crd/bases/camel.apache.org_pipes.yaml
index a30364531..cef7bf657 100644
--- a/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/config/crd/bases/camel.apache.org_pipes.yaml
@@ -6697,6 +6697,9 @@ spec:
                       builder:
                         description: The configuration of Builder trait
                         properties:
+                          baseImage:
+                            description: Specify a base image
+                            type: string
                           configuration:
                             description: 'Legacy trait configuration 
parameters. Deprecated:
                               for backward compatibility.'
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc 
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index ebcfe5f69..4799180e7 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -733,6 +733,13 @@ string
 
 the digest from image
 
+|`rootImage` +
+string
+|
+
+
+root image (the first image from which the incremental image has started)
+
 |`baseImage` +
 string
 |
@@ -2461,12 +2468,19 @@ ObservedGeneration is the most recent generation 
observed for this IntegrationKi
 
 phase of the kit
 
+|`rootImage` +
+string
+|
+
+
+root image used by the kit (the first image from which the incremental image 
has started, typically a JDK/JRE base image)
+
 |`baseImage` +
 string
 |
 
 
-base image used by the kit
+base image used by the kit (could be another IntegrationKit)
 
 |`image` +
 string
@@ -5797,6 +5811,13 @@ string
 
 The strategy to use, either `pod` or `routine` (default routine)
 
+|`baseImage` +
+string
+|
+
+
+Specify a base image
+
 |`incrementalImageBuild` +
 bool
 |
diff --git a/docs/modules/traits/pages/builder.adoc 
b/docs/modules/traits/pages/builder.adoc
index 5f57773e3..646b16dfb 100755
--- a/docs/modules/traits/pages/builder.adoc
+++ b/docs/modules/traits/pages/builder.adoc
@@ -40,6 +40,10 @@ The following configuration options are available:
 | string
 | The strategy to use, either `pod` or `routine` (default routine)
 
+| builder.base-image
+| string
+| Specify a base image
+
 | builder.incremental-image-build
 | bool
 | Use the incremental image build option, to reuse existing containers 
(default `true`)
diff --git a/e2e/commonwithcustominstall/incremental_build_test.go 
b/e2e/commonwithcustominstall/incremental_build_test.go
index d6e94f904..10ed57bbf 100644
--- a/e2e/commonwithcustominstall/incremental_build_test.go
+++ b/e2e/commonwithcustominstall/incremental_build_test.go
@@ -23,6 +23,7 @@ limitations under the License.
 package commonwithcustominstall
 
 import (
+       "fmt"
        "testing"
 
        . "github.com/onsi/gomega"
@@ -34,6 +35,7 @@ import (
        "github.com/apache/camel-k/v2/pkg/util/defaults"
 )
 
+/*
 func TestRunIncrementalBuildRoutine(t *testing.T) {
        WithNewTestNamespace(t, func(ns string) {
                operatorID := "camel-k-incremental-build"
@@ -48,6 +50,7 @@ func TestRunIncrementalBuildRoutine(t *testing.T) {
                Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
                integrationKitName := IntegrationKit(ns, name)()
                Eventually(Kit(ns, 
integrationKitName)().Status.BaseImage).Should(Equal(defaults.BaseImage()))
+               Eventually(Kit(ns, 
integrationKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
 
                t.Run("Reuse previous kit", func(t *testing.T) {
                        nameClone := "java-clone"
@@ -77,6 +80,7 @@ func TestRunIncrementalBuildRoutine(t *testing.T) {
                        // 
10.108.177.66/test-d7cad110-bb1d-4e79-8a0e-ebd44f6fe5d4/camel-k-kit-c8357r4k5tp6fn1idm60@sha256:d49716f0429ad8b23a1b8d20a357d64b1aa42a67c1a2a534ebd4c54cd598a18d
                        // we should be save just to check the substring is 
contained
                        Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.BaseImage).Should(ContainSubstring(integrationKitName))
+                       Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
                })
 
                Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).To(Succeed())
@@ -98,6 +102,7 @@ func TestRunIncrementalBuildPod(t *testing.T) {
                Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
                integrationKitName := IntegrationKit(ns, name)()
                Eventually(Kit(ns, 
integrationKitName)().Status.BaseImage).Should(Equal(defaults.BaseImage()))
+               Eventually(Kit(ns, 
integrationKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
                Eventually(BuilderPodsCount(ns)).Should(Equal(1))
 
                t.Run("Reuse previous kit", func(t *testing.T) {
@@ -131,6 +136,7 @@ func TestRunIncrementalBuildPod(t *testing.T) {
                        // 
10.108.177.66/test-d7cad110-bb1d-4e79-8a0e-ebd44f6fe5d4/camel-k-kit-c8357r4k5tp6fn1idm60@sha256:d49716f0429ad8b23a1b8d20a357d64b1aa42a67c1a2a534ebd4c54cd598a18d
                        // we should be save just to check the substring is 
contained
                        Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.BaseImage).Should(ContainSubstring(integrationKitName))
+                       Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
                        Eventually(BuilderPodsCount(ns)).Should(Equal(2))
                })
 
@@ -185,3 +191,58 @@ func TestRunIncrementalBuildOff(t *testing.T) {
                Expect(Kamel("delete", "--all", "-n", 
ns).Execute()).To(Succeed())
        })
 }
+*/
+func TestRunIncrementalBuildWithDifferentBaseImages(t *testing.T) {
+       WithNewTestNamespace(t, func(ns string) {
+               operatorID := "camel-k-standard-build"
+               Expect(KamelInstallWithID(operatorID, 
ns).Execute()).To(Succeed())
+
+               name := "java"
+               Expect(KamelRunWithID(operatorID, ns, "files/Java.java",
+                       "--name", name,
+               ).Execute()).To(Succeed())
+               Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
+               Eventually(IntegrationConditionStatus(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+               Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+               integrationKitName := IntegrationKit(ns, name)()
+               Eventually(Kit(ns, 
integrationKitName)().Status.BaseImage).Should(Equal(defaults.BaseImage()))
+               Eventually(Kit(ns, 
integrationKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
+
+               t.Run("Create incremental kit", func(t *testing.T) {
+                       // Another integration that should be built on top of 
the previous IntegrationKit
+                       // just add a new random dependency
+                       nameIncremental := "java-incremental"
+                       Expect(KamelRunWithID(operatorID, ns, "files/Java.java",
+                               "--name", nameIncremental,
+                               "-d", "camel:zipfile",
+                       ).Execute()).To(Succeed())
+                       Eventually(IntegrationPodPhase(ns, nameIncremental), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
+                       Eventually(IntegrationConditionStatus(ns, 
nameIncremental, v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+                       Eventually(IntegrationLogs(ns, nameIncremental), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+                       integrationIncrementalKitName := IntegrationKit(ns, 
nameIncremental)()
+                       // the container comes in a format like
+                       // 
10.108.177.66/test-d7cad110-bb1d-4e79-8a0e-ebd44f6fe5d4/camel-k-kit-c8357r4k5tp6fn1idm60@sha256:d49716f0429ad8b23a1b8d20a357d64b1aa42a67c1a2a534ebd4c54cd598a18d
+                       // we should be save just to check the substring is 
contained
+                       Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.BaseImage).Should(ContainSubstring(integrationKitName))
+                       Eventually(Kit(ns, 
integrationIncrementalKitName)().Status.RootImage).Should(Equal(defaults.BaseImage()))
+               })
+
+               t.Run("Create new hierarchy kit", func(t *testing.T) {
+                       // We should spin off a new hierarchy of builds
+                       newBaseImage := 
"eclipse-temurin:17.0.8.1_1-jdk-ubi9-minimal"
+                       name = "java-new"
+                       Expect(KamelRunWithID(operatorID, ns, "files/Java.java",
+                               "--name", name,
+                               "-d", "camel:mongodb",
+                               "-t", fmt.Sprintf("builder.base-image=%s", 
newBaseImage),
+                       ).Execute()).To(Succeed())
+                       Eventually(IntegrationPodPhase(ns, name), 
TestTimeoutLong).Should(Equal(corev1.PodRunning))
+                       Eventually(IntegrationConditionStatus(ns, name, 
v1.IntegrationConditionReady), 
TestTimeoutShort).Should(Equal(corev1.ConditionTrue))
+                       Eventually(IntegrationLogs(ns, name), 
TestTimeoutShort).Should(ContainSubstring("Magicstring!"))
+                       integrationKitName = IntegrationKit(ns, name)()
+                       Eventually(Kit(ns, 
integrationKitName)().Status.BaseImage).Should(Equal(newBaseImage))
+                       Eventually(Kit(ns, 
integrationKitName)().Status.RootImage).Should(Equal(newBaseImage))
+               })
+               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 caacc731d..f0555f582 100644
--- a/helm/camel-k/crds/crd-build.yaml
+++ b/helm/camel-k/crds/crd-build.yaml
@@ -1740,6 +1740,10 @@ spec:
               phase:
                 description: describes the phase
                 type: string
+              rootImage:
+                description: root image (the first image from which the 
incremental
+                  image has started)
+                type: string
               startedAt:
                 description: the time when it started
                 format: date-time
diff --git a/helm/camel-k/crds/crd-integration-kit.yaml 
b/helm/camel-k/crds/crd-integration-kit.yaml
index d3e061b62..6d2611798 100644
--- a/helm/camel-k/crds/crd-integration-kit.yaml
+++ b/helm/camel-k/crds/crd-integration-kit.yaml
@@ -59,6 +59,10 @@ spec:
       jsonPath: .status.image
       name: Image
       type: string
+    - description: The integration kit root image
+      jsonPath: .status.rootImage
+      name: Root
+      type: string
     name: v1
     schema:
       openAPIV3Schema:
@@ -197,6 +201,9 @@ spec:
                     description: The builder trait is internally used to 
determine
                       the best strategy to build and configure IntegrationKits.
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
@@ -410,7 +417,7 @@ spec:
                   type: object
                 type: array
               baseImage:
-                description: base image used by the kit
+                description: base image used by the kit (could be another 
IntegrationKit)
                 type: string
               conditions:
                 description: a list of conditions which happened for the 
events related
@@ -495,6 +502,10 @@ spec:
               platform:
                 description: the platform for which this kit was configured
                 type: string
+              rootImage:
+                description: root image used by the kit (the first image from 
which
+                  the incremental image has started, typically a JDK/JRE base 
image)
+                type: string
               runtimeProvider:
                 description: the runtime provider for which this kit was 
configured
                 type: string
diff --git a/helm/camel-k/crds/crd-integration-platform.yaml 
b/helm/camel-k/crds/crd-integration-platform.yaml
index 011141207..63c5cb610 100644
--- a/helm/camel-k/crds/crd-integration-platform.yaml
+++ b/helm/camel-k/crds/crd-integration-platform.yaml
@@ -497,6 +497,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
@@ -2315,6 +2318,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
diff --git a/helm/camel-k/crds/crd-integration.yaml 
b/helm/camel-k/crds/crd-integration.yaml
index 0ea61efce..415adf376 100644
--- a/helm/camel-k/crds/crd-integration.yaml
+++ b/helm/camel-k/crds/crd-integration.yaml
@@ -6417,6 +6417,9 @@ spec:
                   builder:
                     description: The configuration of Builder trait
                     properties:
+                      baseImage:
+                        description: Specify a base image
+                        type: string
                       configuration:
                         description: 'Legacy trait configuration parameters. 
Deprecated:
                           for backward compatibility.'
diff --git a/helm/camel-k/crds/crd-kamelet-binding.yaml 
b/helm/camel-k/crds/crd-kamelet-binding.yaml
index 5e137abd8..a9c90247d 100644
--- a/helm/camel-k/crds/crd-kamelet-binding.yaml
+++ b/helm/camel-k/crds/crd-kamelet-binding.yaml
@@ -6699,6 +6699,9 @@ spec:
                       builder:
                         description: The configuration of Builder trait
                         properties:
+                          baseImage:
+                            description: Specify a base image
+                            type: string
                           configuration:
                             description: 'Legacy trait configuration 
parameters. Deprecated:
                               for backward compatibility.'
diff --git a/helm/camel-k/crds/crd-pipe.yaml b/helm/camel-k/crds/crd-pipe.yaml
index a30364531..cef7bf657 100644
--- a/helm/camel-k/crds/crd-pipe.yaml
+++ b/helm/camel-k/crds/crd-pipe.yaml
@@ -6697,6 +6697,9 @@ spec:
                       builder:
                         description: The configuration of Builder trait
                         properties:
+                          baseImage:
+                            description: Specify a base image
+                            type: string
                           configuration:
                             description: 'Legacy trait configuration 
parameters. Deprecated:
                               for backward compatibility.'
diff --git a/pkg/apis/camel/v1/build_types.go b/pkg/apis/camel/v1/build_types.go
index c78a1d732..5e2a99681 100644
--- a/pkg/apis/camel/v1/build_types.go
+++ b/pkg/apis/camel/v1/build_types.go
@@ -204,6 +204,8 @@ type BuildStatus struct {
        Image string `json:"image,omitempty"`
        // the digest from image
        Digest string `json:"digest,omitempty"`
+       // root image (the first image from which the incremental image has 
started)
+       RootImage string `json:"rootImage,omitempty"`
        // the base image used for this build
        BaseImage string `json:"baseImage,omitempty"`
        // a list of artifacts contained in the build
diff --git a/pkg/apis/camel/v1/integrationkit_types.go 
b/pkg/apis/camel/v1/integrationkit_types.go
index f5b7ad1d5..2ddca5179 100644
--- a/pkg/apis/camel/v1/integrationkit_types.go
+++ b/pkg/apis/camel/v1/integrationkit_types.go
@@ -37,6 +37,7 @@ import (
 // 
+kubebuilder:printcolumn:name="Type",type=string,JSONPath=`.metadata.labels.camel\.apache\.org\/kit\.type`,description="The
 integration kit type"
 // 
+kubebuilder:printcolumn:name="Layout",type=string,JSONPath=`.metadata.labels.camel\.apache\.org\/kit\.layout`,description="The
 integration kit layout"
 // 
+kubebuilder:printcolumn:name="Image",type=string,JSONPath=`.status.image`,description="The
 integration kit image"
+// 
+kubebuilder:printcolumn:name="Root",type=string,JSONPath=`.status.rootImage`,description="The
 integration kit root image"
 
 // IntegrationKit defines a container image and additional configuration 
needed to run an `Integration`.
 // An `IntegrationKit` is a generic image generally built from the 
requirements of an `Integration`, but agnostic to it,
@@ -97,7 +98,9 @@ type IntegrationKitStatus struct {
        ObservedGeneration int64 `json:"observedGeneration,omitempty"`
        // phase of the kit
        Phase IntegrationKitPhase `json:"phase,omitempty"`
-       // base image used by the kit
+       // root image used by the kit (the first image from which the 
incremental image has started, typically a JDK/JRE base image)
+       RootImage string `json:"rootImage,omitempty"`
+       // base image used by the kit (could be another IntegrationKit)
        BaseImage string `json:"baseImage,omitempty"`
        // actual image name of the kit
        Image string `json:"image,omitempty"`
diff --git a/pkg/apis/camel/v1/trait/builder.go 
b/pkg/apis/camel/v1/trait/builder.go
index 3b32cf53b..47d2278e0 100644
--- a/pkg/apis/camel/v1/trait/builder.go
+++ b/pkg/apis/camel/v1/trait/builder.go
@@ -29,6 +29,8 @@ type BuilderTrait struct {
        Properties []string `property:"properties" json:"properties,omitempty"`
        // The strategy to use, either `pod` or `routine` (default routine)
        Strategy string `property:"strategy" json:"strategy,omitempty"`
+       // Specify a base image
+       BaseImage string `property:"base-image" json:"baseImage,omitempty"`
        // Use the incremental image build option, to reuse existing containers 
(default `true`)
        IncrementalImageBuild *bool `property:"incremental-image-build" 
json:"incrementalImageBuild,omitempty"`
        // The build order strategy to use, either `dependencies`, `fifo` or 
`sequential` (default sequential)
diff --git a/pkg/builder/image.go b/pkg/builder/image.go
index c1b2ef6c2..a3abe1757 100644
--- a/pkg/builder/image.go
+++ b/pkg/builder/image.go
@@ -131,6 +131,7 @@ func incrementalImageContext(ctx *builderContext) error {
 
                bestImage, commonLibs := findBestImage(images, ctx.Artifacts)
                if bestImage.Image != "" {
+
                        ctx.BaseImage = bestImage.Image
                        ctx.SelectedArtifacts = make([]v1.Artifact, 0)
 
@@ -203,13 +204,16 @@ func listPublishedImages(context *builderContext) 
([]v1.IntegrationKitStatus, er
        }
 
        images := make([]v1.IntegrationKitStatus, 0)
-       for _, item := range list.Items {
-               kit := item
-
+       for _, kit := range list.Items {
+               // Discard non ready kits
                if kit.Status.Phase != v1.IntegrationKitPhaseReady {
                        continue
                }
-
+               // Discard kits with a different root hierarchy
+               // context.BaseImage should still contain the root base image 
at this stage
+               if kit.Status.RootImage != context.BaseImage {
+                       continue
+               }
                images = append(images, kit.Status)
        }
        return images, nil
diff --git a/pkg/builder/jib.go b/pkg/builder/jib.go
index 75a8c26f8..264c95a08 100644
--- a/pkg/builder/jib.go
+++ b/pkg/builder/jib.go
@@ -46,8 +46,13 @@ func (t *jibTask) Do(ctx context.Context) v1.BuildStatus {
        baseImage := t.build.Status.BaseImage
        if baseImage == "" {
                baseImage = t.task.BaseImage
-               status.BaseImage = baseImage
        }
+       status.BaseImage = baseImage
+       rootImage := t.build.Status.RootImage
+       if rootImage == "" {
+               rootImage = t.task.BaseImage
+       }
+       status.RootImage = rootImage
 
        contextDir := t.task.ContextDir
        if contextDir == "" {
diff --git a/pkg/builder/spectrum.go b/pkg/builder/spectrum.go
index 2bc3b2673..c30f6f743 100644
--- a/pkg/builder/spectrum.go
+++ b/pkg/builder/spectrum.go
@@ -52,8 +52,13 @@ func (t *spectrumTask) Do(ctx context.Context) 
v1.BuildStatus {
        baseImage := t.build.Status.BaseImage
        if baseImage == "" {
                baseImage = t.task.BaseImage
-               status.BaseImage = baseImage
        }
+       status.BaseImage = baseImage
+       rootImage := t.build.Status.RootImage
+       if rootImage == "" {
+               rootImage = t.task.BaseImage
+       }
+       status.RootImage = rootImage
 
        contextDir := t.task.ContextDir
        if contextDir == "" {
diff --git a/pkg/client/camel/applyconfiguration/camel/v1/buildstatus.go 
b/pkg/client/camel/applyconfiguration/camel/v1/buildstatus.go
index 8158601fd..172865f2d 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/buildstatus.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/buildstatus.go
@@ -31,6 +31,7 @@ type BuildStatusApplyConfiguration struct {
        Phase              *v1.BuildPhase                     
`json:"phase,omitempty"`
        Image              *string                            
`json:"image,omitempty"`
        Digest             *string                            
`json:"digest,omitempty"`
+       RootImage          *string                            
`json:"rootImage,omitempty"`
        BaseImage          *string                            
`json:"baseImage,omitempty"`
        Artifacts          []ArtifactApplyConfiguration       
`json:"artifacts,omitempty"`
        Error              *string                            
`json:"error,omitempty"`
@@ -78,6 +79,14 @@ func (b *BuildStatusApplyConfiguration) WithDigest(value 
string) *BuildStatusApp
        return b
 }
 
+// WithRootImage sets the RootImage field in the declarative configuration to 
the given value
+// and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
+// If called multiple times, the RootImage field is set to the value of the 
last call.
+func (b *BuildStatusApplyConfiguration) WithRootImage(value string) 
*BuildStatusApplyConfiguration {
+       b.RootImage = &value
+       return b
+}
+
 // WithBaseImage sets the BaseImage field in the declarative configuration to 
the given value
 // and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
 // If called multiple times, the BaseImage field is set to the value of the 
last call.
diff --git 
a/pkg/client/camel/applyconfiguration/camel/v1/integrationkitstatus.go 
b/pkg/client/camel/applyconfiguration/camel/v1/integrationkitstatus.go
index 26791a21b..12650227a 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/integrationkitstatus.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/integrationkitstatus.go
@@ -28,6 +28,7 @@ import (
 type IntegrationKitStatusApplyConfiguration struct {
        ObservedGeneration *int64                                      
`json:"observedGeneration,omitempty"`
        Phase              *v1.IntegrationKitPhase                     
`json:"phase,omitempty"`
+       RootImage          *string                                     
`json:"rootImage,omitempty"`
        BaseImage          *string                                     
`json:"baseImage,omitempty"`
        Image              *string                                     
`json:"image,omitempty"`
        Digest             *string                                     
`json:"digest,omitempty"`
@@ -62,6 +63,14 @@ func (b *IntegrationKitStatusApplyConfiguration) 
WithPhase(value v1.IntegrationK
        return b
 }
 
+// WithRootImage sets the RootImage field in the declarative configuration to 
the given value
+// and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
+// If called multiple times, the RootImage field is set to the value of the 
last call.
+func (b *IntegrationKitStatusApplyConfiguration) WithRootImage(value string) 
*IntegrationKitStatusApplyConfiguration {
+       b.RootImage = &value
+       return b
+}
+
 // WithBaseImage sets the BaseImage field in the declarative configuration to 
the given value
 // and returns the receiver, so that objects can be built by chaining "With" 
function invocations.
 // If called multiple times, the BaseImage field is set to the value of the 
last call.
diff --git a/pkg/controller/integrationkit/build.go 
b/pkg/controller/integrationkit/build.go
index 202b10bdf..4880ad365 100644
--- a/pkg/controller/integrationkit/build.go
+++ b/pkg/controller/integrationkit/build.go
@@ -199,6 +199,7 @@ func (action *buildAction) handleBuildRunning(ctx 
context.Context, kit *v1.Integ
                        )
                }
 
+               kit.Status.RootImage = build.Status.RootImage
                kit.Status.BaseImage = build.Status.BaseImage
                kit.Status.Image = build.Status.Image
 
diff --git a/pkg/trait/builder.go b/pkg/trait/builder.go
index b9dc0c0a3..58d5790d5 100644
--- a/pkg/trait/builder.go
+++ b/pkg/trait/builder.go
@@ -187,7 +187,7 @@ func (t *builderTrait) Apply(e *Environment) error {
                                Configuration: *taskConfOrDefault(tasksConf, 
"spectrum"),
                        },
                        PublishTask: v1.PublishTask{
-                               BaseImage: e.Platform.Status.Build.BaseImage,
+                               BaseImage: t.getBaseImage(e),
                                Image:     getImageName(e),
                                Registry:  e.Platform.Status.Build.Registry,
                        },
@@ -200,7 +200,7 @@ func (t *builderTrait) Apply(e *Environment) error {
                                Configuration: *taskConfOrDefault(tasksConf, 
"jib"),
                        },
                        PublishTask: v1.PublishTask{
-                               BaseImage: e.Platform.Status.Build.BaseImage,
+                               BaseImage: t.getBaseImage(e),
                                Image:     getImageName(e),
                                Registry:  e.Platform.Status.Build.Registry,
                        },
@@ -330,7 +330,7 @@ func (t *builderTrait) builderTask(e *Environment, taskConf 
*v1.BuildConfigurati
                        Name:          "builder",
                        Configuration: *taskConf,
                },
-               BaseImage:    e.Platform.Status.Build.BaseImage,
+               BaseImage:    t.getBaseImage(e),
                Runtime:      e.CamelCatalog.Runtime,
                Dependencies: e.IntegrationKit.Spec.Dependencies,
                Maven:        maven,
@@ -399,6 +399,14 @@ func getImageName(e *Environment) string {
        return e.Platform.Status.Build.Registry.Address + "/" + organization + 
"/camel-k-" + e.IntegrationKit.Name + ":" + e.IntegrationKit.ResourceVersion
 }
 
+func (t *builderTrait) getBaseImage(e *Environment) string {
+       baseImage := t.BaseImage
+       if baseImage == "" {
+               baseImage = e.Platform.Status.Build.BaseImage
+       }
+       return baseImage
+}
+
 func (t *builderTrait) customTasks(tasksConf 
map[string]*v1.BuildConfiguration) ([]v1.Task, error) {
        customTasks := make([]v1.Task, len(t.Tasks))
 
diff --git a/resources/traits.yaml b/resources/traits.yaml
index 6b9357beb..dee0be418 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -244,6 +244,9 @@ traits:
   - name: strategy
     type: string
     description: The strategy to use, either `pod` or `routine` (default 
routine)
+  - name: base-image
+    type: string
+    description: Specify a base image
   - name: incremental-image-build
     type: bool
     description: Use the incremental image build option, to reuse existing 
containers

Reply via email to