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


The following commit(s) were added to refs/heads/main by this push:
     new ed390df1e feat(trait): init containers
ed390df1e is described below

commit ed390df1e57917db9f3fdec7f9a5879b00260797
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Fri Aug 15 08:42:38 2025 +0200

    feat(trait): init containers
    
    A trait which simplify setting init and sidecar containers
---
 docs/modules/ROOT/nav.adoc                         |   1 +
 docs/modules/ROOT/partials/apis/camel-k-crds.adoc  |  54 ++++
 docs/modules/traits/pages/init-containers.adoc     |  76 ++++++
 e2e/common/traits/files/init-container.yaml        |  27 ++
 e2e/common/traits/init_container_test.go           |  71 +++++
 helm/camel-k/crds/camel-k-crds.yaml                | 196 ++++++++++++++
 pkg/apis/camel/v1/common_types.go                  |   2 +
 pkg/apis/camel/v1/trait/init_containers.go         |  31 +++
 pkg/apis/camel/v1/trait/zz_generated.deepcopy.go   |  31 +++
 pkg/apis/camel/v1/zz_generated.deepcopy.go         |   5 +
 .../camel/applyconfiguration/camel/v1/traits.go    |   9 +
 .../camel.apache.org_integrationplatforms.yaml     |  56 ++++
 .../camel.apache.org_integrationprofiles.yaml      |  56 ++++
 .../crd/bases/camel.apache.org_integrations.yaml   |  56 ++++
 .../config/crd/bases/camel.apache.org_pipes.yaml   |  28 ++
 pkg/trait/init_containers.go                       | 146 +++++++++++
 pkg/trait/init_containers_test.go                  | 287 +++++++++++++++++++++
 pkg/trait/mount.go                                 |  24 +-
 pkg/trait/mount_test.go                            |  34 +++
 pkg/trait/trait_register.go                        |   1 +
 pkg/trait/trait_test.go                            |   2 +-
 21 files changed, 1188 insertions(+), 5 deletions(-)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index d7832331e..0a668f892 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -59,6 +59,7 @@
 ** xref:traits:hashicorp-vault.adoc[Hashicorp Vault]
 ** xref:traits:health.adoc[Health]
 ** xref:traits:ingress.adoc[Ingress]
+** xref:traits:init-containers.adoc[Init Containers]
 ** xref:traits:istio.adoc[Istio]
 ** xref:traits:jolokia.adoc[Jolokia]
 ** xref:traits:jvm.adoc[Jvm]
diff --git a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc 
b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
index fe77f3128..0eacd3960 100644
--- a/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
+++ b/docs/modules/ROOT/partials/apis/camel-k-crds.adoc
@@ -5980,6 +5980,13 @@ The configuration of Health trait
 
 The configuration of Ingress trait
 
+|`init-containers` +
+*xref:#_camel_apache_org_v1_trait_InitContainersTrait[InitContainersTrait]*
+|
+
+
+The configuration of Init Containers trait
+
 |`istio` +
 *xref:#_camel_apache_org_v1_trait_IstioTrait[IstioTrait]*
 |
@@ -7433,6 +7440,52 @@ string
 To configure tls secret name
 
 
+|===
+
+[#_camel_apache_org_v1_trait_InitContainersTrait]
+=== InitContainersTrait
+
+*Appears on:*
+
+* <<#_camel_apache_org_v1_Traits, Traits>>
+
+The InitContainersTrait trait can be used to configure `init containers` or 
`sidecar containers`.
+
+
+[cols="2,2a",options="header"]
+|===
+|Field
+|Description
+
+|`PlatformBaseTrait` +
+*xref:#_camel_apache_org_v1_trait_PlatformBaseTrait[PlatformBaseTrait]*
+|(Members of `PlatformBaseTrait` are embedded into this type.)
+
+
+
+
+|`auto` +
+bool
+|
+
+
+To automatically enable the trait
+
+|`initTasks` +
+[]string
+|
+
+
+A list of init tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+
+|`sideCarTasks` +
+[]string
+|
+
+
+A list of sidecar tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+
+
 |===
 
 [#_camel_apache_org_v1_trait_IstioTrait]
@@ -8318,6 +8371,7 @@ Only one of `max-unavailable` and `min-available` can be 
specified.
 * <<#_camel_apache_org_v1_trait_DeploymentTrait, DeploymentTrait>>
 * <<#_camel_apache_org_v1_trait_EnvironmentTrait, EnvironmentTrait>>
 * <<#_camel_apache_org_v1_trait_ErrorHandlerTrait, ErrorHandlerTrait>>
+* <<#_camel_apache_org_v1_trait_InitContainersTrait, InitContainersTrait>>
 * <<#_camel_apache_org_v1_trait_MountTrait, MountTrait>>
 * <<#_camel_apache_org_v1_trait_OpenAPITrait, OpenAPITrait>>
 * <<#_camel_apache_org_v1_trait_PlatformTrait, PlatformTrait>>
diff --git a/docs/modules/traits/pages/init-containers.adoc 
b/docs/modules/traits/pages/init-containers.adoc
new file mode 100644
index 000000000..8a4fb4e6b
--- /dev/null
+++ b/docs/modules/traits/pages/init-containers.adoc
@@ -0,0 +1,76 @@
+= Init Containers Trait
+
+// Start of autogenerated code - DO NOT EDIT! (badges)
+// End of autogenerated code - DO NOT EDIT! (badges)
+// Start of autogenerated code - DO NOT EDIT! (description)
+The InitContainersTrait trait can be used to configure `init containers` or 
`sidecar containers`.
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, 
OpenShift**.
+
+NOTE: The init-containers trait is a *platform trait* and cannot be disabled 
by the user.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+[source,console]
+----
+$ kamel run --trait init-containers.[key]=[value] --trait 
init-containers.[key2]=[value2] integration.yaml
+----
+The following configuration options are available:
+
+[cols="2m,1m,5a"]
+|===
+|Property | Type | Description
+
+| init-containers.enabled
+| bool
+| Deprecated: no longer in use.
+
+| init-containers.auto
+| bool
+| To automatically enable the trait
+
+| init-containers.init-tasks
+| []string
+| A list of init tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+
+| init-containers.sidecar-tasks
+| []string
+| A list of sidecar tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
+
+== An example init container
+
+Create an Integration which read some value initialized by an init container. 
The following route takes care to read a file which is expected to be 
initialized by another process.
+
+[source,yaml]
+.route.yaml
+----
+- route:
+    from:
+      # Read a file that should have been initialized
+      # by the initContainer
+      uri: file:/tmp
+      parameters:
+        fileName: init
+      steps:
+        - log:
+            message: "${body}"
+----
+
+The route is agnostic how this file is generated.
+
+When creating the Integration, then, it should include an init container 
taking care to initialize such file, for example:
+
+[source,console]
+----
+kamel run route.yaml -t mount.empty-dirs=common:/tmp -t 
init-containers.tasks="init;alpine;/bin/sh -c \"echo hello >> /tmp/init\""
+----
+
+As the file is shared between the containers you will need to provide a shared 
volume (an `EmtpyDir` in this case).
diff --git a/e2e/common/traits/files/init-container.yaml 
b/e2e/common/traits/files/init-container.yaml
new file mode 100644
index 000000000..69d4e154d
--- /dev/null
+++ b/e2e/common/traits/files/init-container.yaml
@@ -0,0 +1,27 @@
+# ---------------------------------------------------------------------------
+# 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.
+# ---------------------------------------------------------------------------
+
+- route:
+    from:
+      # Read a file that should have been initialized
+      # by the initContainer
+      uri: file:/tmp
+      parameters:
+        include: ^(init|sidecar).*
+      steps:
+        - log:
+            message: "${body}"
\ No newline at end of file
diff --git a/e2e/common/traits/init_container_test.go 
b/e2e/common/traits/init_container_test.go
new file mode 100644
index 000000000..e6f811706
--- /dev/null
+++ b/e2e/common/traits/init_container_test.go
@@ -0,0 +1,71 @@
+//go:build integration
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> 
Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+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 common
+
+import (
+       "context"
+       "testing"
+
+       . "github.com/onsi/gomega"
+
+       corev1 "k8s.io/api/core/v1"
+
+       . "github.com/apache/camel-k/v2/e2e/support"
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+)
+
+func TestInitContainerTrait(t *testing.T) {
+       t.Parallel()
+       WithNewTestNamespace(t, func(ctx context.Context, g *WithT, ns string) {
+               t.Run("Init container write a file", func(t *testing.T) {
+                       name := RandomizedSuffixName("init")
+                       g.Expect(KamelRun(t, ctx, ns,
+                               "files/init-container.yaml",
+                               "-t",
+                               "mount.empty-dirs=common:/tmp",
+                               "-t",
+                               "init-containers.init-tasks=init;alpine;/bin/sh 
-c \"echo helloInit >> /tmp/init\"",
+                               "--name",
+                               name).Execute()).To(Succeed())
+                       g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady)).
+                               Should(Equal(corev1.ConditionTrue))
+                       g.Eventually(IntegrationPodPhase(t, ctx, ns, 
name)).Should(Equal(corev1.PodRunning))
+                       g.Eventually(IntegrationLogs(t, ctx, ns, 
name)).Should(ContainSubstring("helloInit"))
+               })
+               t.Run("Sidecar container write a file", func(t *testing.T) {
+                       name := RandomizedSuffixName("sidecar")
+                       g.Expect(KamelRun(t, ctx, ns,
+                               "files/init-container.yaml",
+                               "-t",
+                               "mount.empty-dirs=common:/tmp",
+                               "-t",
+                               
"init-containers.sidecar-tasks=sidecar;alpine;/bin/sh -c \"for i in $(seq 1 
10); do echo helloSidecar$i > /tmp/sidecar_$i.txt; sleep 1; done\"",
+                               "--name",
+                               name).Execute()).To(Succeed())
+                       g.Eventually(IntegrationConditionStatus(t, ctx, ns, 
name, v1.IntegrationConditionReady)).
+                               Should(Equal(corev1.ConditionTrue))
+                       g.Eventually(IntegrationPodPhase(t, ctx, ns, 
name)).Should(Equal(corev1.PodRunning))
+                       g.Eventually(IntegrationLogs(t, ctx, ns, 
name)).Should(ContainSubstring("helloSidecar10"))
+               })
+       })
+}
diff --git a/helm/camel-k/crds/camel-k-crds.yaml 
b/helm/camel-k/crds/camel-k-crds.yaml
index 9f9abcc1e..42433fd38 100644
--- a/helm/camel-k/crds/camel-k-crds.yaml
+++ b/helm/camel-k/crds/camel-k-crds.yaml
@@ -4490,6 +4490,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -6694,6 +6722,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -8800,6 +8856,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -10883,6 +10967,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -19404,6 +19516,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -21430,6 +21570,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -31309,6 +31477,34 @@ spec:
                             description: To configure tls secret name
                             type: string
                         type: object
+                      init-containers:
+                        description: The configuration of Init Containers trait
+                        properties:
+                          auto:
+                            description: To automatically enable the trait
+                            type: boolean
+                          configuration:
+                            description: |-
+                              Legacy trait configuration parameters.
+                              Deprecated: for backward compatibility.
+                            type: object
+                            x-kubernetes-preserve-unknown-fields: true
+                          enabled:
+                            description: 'Deprecated: no longer in use.'
+                            type: boolean
+                          initTasks:
+                            description: A list of init tasks to be executed 
with
+                              format 
`<name>;<container-image>;<container-command>`.
+                            items:
+                              type: string
+                            type: array
+                          sideCarTasks:
+                            description: A list of sidecar tasks to be 
executed with
+                              format 
`<name>;<container-image>;<container-command>`.
+                            items:
+                              type: string
+                            type: array
+                        type: object
                       istio:
                         description: The configuration of Istio trait
                         properties:
diff --git a/pkg/apis/camel/v1/common_types.go 
b/pkg/apis/camel/v1/common_types.go
index 71d4bba36..dd06d6337 100644
--- a/pkg/apis/camel/v1/common_types.go
+++ b/pkg/apis/camel/v1/common_types.go
@@ -207,6 +207,8 @@ type Traits struct {
        Health *trait.HealthTrait `property:"health" json:"health,omitempty"`
        // The configuration of Ingress trait
        Ingress *trait.IngressTrait `property:"ingress" 
json:"ingress,omitempty"`
+       // The configuration of Init Containers trait
+       InitContainers *trait.InitContainersTrait `property:"init-containers" 
json:"init-containers,omitempty"`
        // The configuration of Istio trait
        Istio *trait.IstioTrait `property:"istio" json:"istio,omitempty"`
        // The configuration of Jolokia trait
diff --git a/pkg/apis/camel/v1/trait/init_containers.go 
b/pkg/apis/camel/v1/trait/init_containers.go
new file mode 100644
index 000000000..af8c98afd
--- /dev/null
+++ b/pkg/apis/camel/v1/trait/init_containers.go
@@ -0,0 +1,31 @@
+/*
+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 trait
+
+// The InitContainersTrait trait can be used to configure `init containers` or 
`sidecar containers`.
+//
+// +camel-k:trait=init-containers.
+type InitContainersTrait struct {
+       PlatformBaseTrait `property:",squash" json:",inline"`
+       // To automatically enable the trait
+       Auto *bool `property:"auto" json:"auto,omitempty"`
+       // A list of init tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+       InitTasks []string `property:"init-tasks" json:"initTasks,omitempty"`
+       // A list of sidecar tasks to be executed with format 
`<name>;<container-image>;<container-command>`.
+       SidecarTasks []string `property:"sidecar-tasks" 
json:"sideCarTasks,omitempty"`
+}
diff --git a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
index 39870bd8f..85011d3c1 100644
--- a/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/trait/zz_generated.deepcopy.go
@@ -479,6 +479,37 @@ func (in *IngressTrait) DeepCopy() *IngressTrait {
        return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
+func (in *InitContainersTrait) DeepCopyInto(out *InitContainersTrait) {
+       *out = *in
+       in.PlatformBaseTrait.DeepCopyInto(&out.PlatformBaseTrait)
+       if in.Auto != nil {
+               in, out := &in.Auto, &out.Auto
+               *out = new(bool)
+               **out = **in
+       }
+       if in.InitTasks != nil {
+               in, out := &in.InitTasks, &out.InitTasks
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
+       if in.SidecarTasks != nil {
+               in, out := &in.SidecarTasks, &out.SidecarTasks
+               *out = make([]string, len(*in))
+               copy(*out, *in)
+       }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, 
creating a new InitContainersTrait.
+func (in *InitContainersTrait) DeepCopy() *InitContainersTrait {
+       if in == nil {
+               return nil
+       }
+       out := new(InitContainersTrait)
+       in.DeepCopyInto(out)
+       return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, 
writing into out. in must be non-nil.
 func (in *IstioTrait) DeepCopyInto(out *IstioTrait) {
        *out = *in
diff --git a/pkg/apis/camel/v1/zz_generated.deepcopy.go 
b/pkg/apis/camel/v1/zz_generated.deepcopy.go
index 25965dd29..c79874ce1 100644
--- a/pkg/apis/camel/v1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1/zz_generated.deepcopy.go
@@ -3228,6 +3228,11 @@ func (in *Traits) DeepCopyInto(out *Traits) {
                *out = new(trait.IngressTrait)
                (*in).DeepCopyInto(*out)
        }
+       if in.InitContainers != nil {
+               in, out := &in.InitContainers, &out.InitContainers
+               *out = new(trait.InitContainersTrait)
+               (*in).DeepCopyInto(*out)
+       }
        if in.Istio != nil {
                in, out := &in.Istio, &out.Istio
                *out = new(trait.IstioTrait)
diff --git a/pkg/client/camel/applyconfiguration/camel/v1/traits.go 
b/pkg/client/camel/applyconfiguration/camel/v1/traits.go
index b9654a9c8..7077d311d 100644
--- a/pkg/client/camel/applyconfiguration/camel/v1/traits.go
+++ b/pkg/client/camel/applyconfiguration/camel/v1/traits.go
@@ -39,6 +39,7 @@ type TraitsApplyConfiguration struct {
        GC              *trait.GCTrait                          
`json:"gc,omitempty"`
        Health          *trait.HealthTrait                      
`json:"health,omitempty"`
        Ingress         *trait.IngressTrait                     
`json:"ingress,omitempty"`
+       InitContainers  *trait.InitContainersTrait              
`json:"init-containers,omitempty"`
        Istio           *trait.IstioTrait                       
`json:"istio,omitempty"`
        Jolokia         *trait.JolokiaTrait                     
`json:"jolokia,omitempty"`
        JVM             *trait.JVMTrait                         
`json:"jvm,omitempty"`
@@ -180,6 +181,14 @@ func (b *TraitsApplyConfiguration) WithIngress(value 
trait.IngressTrait) *Traits
        return b
 }
 
+// WithInitContainers sets the InitContainers 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 InitContainers field is set to the value of 
the last call.
+func (b *TraitsApplyConfiguration) WithInitContainers(value 
trait.InitContainersTrait) *TraitsApplyConfiguration {
+       b.InitContainers = &value
+       return b
+}
+
 // WithIstio sets the Istio 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 Istio field is set to the value of the last 
call.
diff --git 
a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
index dd2a09c1d..3fa5ea073 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationplatforms.yaml
@@ -1259,6 +1259,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -3463,6 +3491,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
diff --git 
a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
index 2c10d4958..70b24286d 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrationprofiles.yaml
@@ -1127,6 +1127,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -3210,6 +3238,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
index 634f2be68..6a25e9ec8 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_integrations.yaml
@@ -7545,6 +7545,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
@@ -9571,6 +9599,34 @@ spec:
                         description: To configure tls secret name
                         type: string
                     type: object
+                  init-containers:
+                    description: The configuration of Init Containers trait
+                    properties:
+                      auto:
+                        description: To automatically enable the trait
+                        type: boolean
+                      configuration:
+                        description: |-
+                          Legacy trait configuration parameters.
+                          Deprecated: for backward compatibility.
+                        type: object
+                        x-kubernetes-preserve-unknown-fields: true
+                      enabled:
+                        description: 'Deprecated: no longer in use.'
+                        type: boolean
+                      initTasks:
+                        description: A list of init tasks to be executed with 
format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                      sideCarTasks:
+                        description: A list of sidecar tasks to be executed 
with format
+                          `<name>;<container-image>;<container-command>`.
+                        items:
+                          type: string
+                        type: array
+                    type: object
                   istio:
                     description: The configuration of Istio trait
                     properties:
diff --git a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml 
b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
index 5d421f1b1..28c65260d 100644
--- a/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
+++ b/pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
@@ -7597,6 +7597,34 @@ spec:
                             description: To configure tls secret name
                             type: string
                         type: object
+                      init-containers:
+                        description: The configuration of Init Containers trait
+                        properties:
+                          auto:
+                            description: To automatically enable the trait
+                            type: boolean
+                          configuration:
+                            description: |-
+                              Legacy trait configuration parameters.
+                              Deprecated: for backward compatibility.
+                            type: object
+                            x-kubernetes-preserve-unknown-fields: true
+                          enabled:
+                            description: 'Deprecated: no longer in use.'
+                            type: boolean
+                          initTasks:
+                            description: A list of init tasks to be executed 
with
+                              format 
`<name>;<container-image>;<container-command>`.
+                            items:
+                              type: string
+                            type: array
+                          sideCarTasks:
+                            description: A list of sidecar tasks to be 
executed with
+                              format 
`<name>;<container-image>;<container-command>`.
+                            items:
+                              type: string
+                            type: array
+                        type: object
                       istio:
                         description: The configuration of Istio trait
                         properties:
diff --git a/pkg/trait/init_containers.go b/pkg/trait/init_containers.go
new file mode 100644
index 000000000..07a38e900
--- /dev/null
+++ b/pkg/trait/init_containers.go
@@ -0,0 +1,146 @@
+/*
+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 trait
+
+import (
+       "fmt"
+       "strings"
+
+       appsv1 "k8s.io/api/apps/v1"
+       batchv1 "k8s.io/api/batch/v1"
+       corev1 "k8s.io/api/core/v1"
+
+       serving "knative.dev/serving/pkg/apis/serving/v1"
+
+       traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+       "k8s.io/utils/ptr"
+)
+
+const (
+       initContainerTraitID    = "init-containers"
+       initContainerTraitOrder = 1610
+)
+
+type containerTask struct {
+       name      string
+       image     string
+       command   string
+       isSidecar bool
+}
+
+type initContainersTrait struct {
+       BasePlatformTrait
+       traitv1.InitContainersTrait `property:",squash"`
+
+       tasks []containerTask
+}
+
+func newInitContainersTrait() Trait {
+       return &initContainersTrait{
+               BasePlatformTrait: NewBasePlatformTrait(initContainerTraitID, 
initContainerTraitOrder),
+       }
+}
+
+func (t *initContainersTrait) Configure(e *Environment) (bool, 
*TraitCondition, error) {
+       if e.Integration == nil || !e.IntegrationInRunningPhases() {
+               return false, nil, nil
+       }
+
+       return t.parseTasks()
+}
+
+func (t *initContainersTrait) Apply(e *Environment) error {
+       var initContainers *[]corev1.Container
+
+       if err := e.Resources.VisitDeploymentE(func(deployment 
*appsv1.Deployment) error {
+               // Deployment
+               initContainers = &deployment.Spec.Template.Spec.InitContainers
+               return nil
+       }); err != nil {
+               return err
+       } else if err := e.Resources.VisitKnativeServiceE(func(service 
*serving.Service) error {
+               // Knative Service
+               initContainers = 
&service.Spec.ConfigurationSpec.Template.Spec.InitContainers
+               return nil
+       }); err != nil {
+               return err
+       } else if err := e.Resources.VisitCronJobE(func(cron *batchv1.CronJob) 
error {
+               // CronJob
+               initContainers = 
&cron.Spec.JobTemplate.Spec.Template.Spec.InitContainers
+               return nil
+       }); err != nil {
+               return err
+       }
+
+       t.configureContainers(initContainers)
+
+       return nil
+}
+
+func (t *initContainersTrait) configureContainers(containers 
*[]corev1.Container) {
+       if containers == nil {
+               containers = &[]corev1.Container{}
+       }
+       for _, task := range t.tasks {
+               initCont := corev1.Container{
+                       Name:    task.name,
+                       Image:   task.image,
+                       Command: splitContainerCommand(task.command),
+               }
+               if task.isSidecar {
+                       initCont.RestartPolicy = 
ptr.To(corev1.ContainerRestartPolicyAlways)
+               }
+               *containers = append(*containers, initCont)
+       }
+}
+
+func (t *initContainersTrait) parseTasks() (bool, *TraitCondition, error) {
+       if t.InitTasks == nil && t.SidecarTasks == nil {
+               return false, nil, nil
+       }
+       t.tasks = make([]containerTask, len(t.InitTasks)+len(t.SidecarTasks))
+       i := 0
+       for _, task := range t.InitTasks {
+               split := strings.SplitN(task, ";", 3)
+               if len(split) != 3 {
+                       return false, nil, fmt.Errorf(`could not parse init 
container task "%s": format expected "name;container-image;command"`, task)
+               }
+               t.tasks[i] = containerTask{
+                       name:      split[0],
+                       image:     split[1],
+                       command:   split[2],
+                       isSidecar: false,
+               }
+               i++
+       }
+       for _, task := range t.SidecarTasks {
+               split := strings.SplitN(task, ";", 3)
+               if len(split) != 3 {
+                       return false, nil, fmt.Errorf(`could not parse sidecar 
container task "%s": format expected "name;container-image;command"`, task)
+               }
+               t.tasks[i] = containerTask{
+                       name:      split[0],
+                       image:     split[1],
+                       command:   split[2],
+                       isSidecar: true,
+               }
+               i++
+       }
+
+       return true, nil, nil
+}
diff --git a/pkg/trait/init_containers_test.go 
b/pkg/trait/init_containers_test.go
new file mode 100644
index 000000000..3cb4ed886
--- /dev/null
+++ b/pkg/trait/init_containers_test.go
@@ -0,0 +1,287 @@
+/*
+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 trait
+
+import (
+       "testing"
+
+       v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+       "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
+       "github.com/apache/camel-k/v2/pkg/util/kubernetes"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+       appsv1 "k8s.io/api/apps/v1"
+       corev1 "k8s.io/api/core/v1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/utils/ptr"
+)
+
+func TestParseInitContainerNoIntegration(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+       }
+       initCont := newInitContainersTrait()
+       configured, condition, err := initCont.Configure(&environment)
+       assert.False(t, configured, "Should not be configured, Integration is 
nil")
+       assert.Nil(t, condition, "should be nil")
+       assert.Nil(t, err, "should be nil")
+}
+
+func TestParseInitContainerShouldFail(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       initCont := initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       InitTasks: []string{
+                               "not a valid format",
+                       },
+               },
+       }
+       configured, condition, err := initCont.Configure(&environment)
+       assert.False(t, configured, "Should not be configured, there's an 
error")
+       assert.Nil(t, condition)
+       assert.NotNil(t, err)
+       assert.Equal(t, `could not parse init container task "not a valid 
format": format expected "name;container-image;command"`, err.Error())
+}
+
+func TestParseInitContainerOK(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       initCont := initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       InitTasks: []string{
+                               "agent;my-agent-image:1.2.3;echo \"hello\"",
+                               "more thing;my-image;echo \"hello\" && 
something else",
+                       },
+               },
+       }
+       configured, condition, err := initCont.Configure(&environment)
+       assert.True(t, configured)
+       assert.Nil(t, condition)
+       require.Nil(t, err)
+       require.Len(t, initCont.tasks, 2)
+       assert.Equal(t, "agent", initCont.tasks[0].name)
+       assert.Equal(t, "my-agent-image:1.2.3", initCont.tasks[0].image)
+       assert.Equal(t, "echo \"hello\"", initCont.tasks[0].command)
+       assert.Equal(t, "more thing", initCont.tasks[1].name)
+       assert.Equal(t, "my-image", initCont.tasks[1].image)
+       assert.Equal(t, "echo \"hello\" && something else", 
initCont.tasks[1].command)
+}
+
+func TestParseInitContainerDefault(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       initCont := initContainersTrait{}
+       configured, condition, err := initCont.Configure(&environment)
+       assert.False(t, configured)
+       assert.Nil(t, condition)
+       require.Nil(t, err)
+}
+
+func TestApplyInitContainerOK(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name: "my-it",
+                       },
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       environment.Resources.Add(&appsv1.Deployment{
+               ObjectMeta: metav1.ObjectMeta{
+                       Labels: map[string]string{
+                               v1.IntegrationLabel: "my-it",
+                       },
+               },
+               Spec: appsv1.DeploymentSpec{
+                       Template: corev1.PodTemplateSpec{
+                               Spec: corev1.PodSpec{},
+                       },
+               },
+       })
+       initCont := initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       InitTasks: []string{
+                               "agent;my-agent-image:1.2.3;echo hello",
+                       },
+               },
+       }
+       configured, condition, err := initCont.Configure(&environment)
+       assert.True(t, configured)
+       assert.Nil(t, condition)
+       require.Nil(t, err)
+       err = initCont.Apply(&environment)
+       require.Nil(t, err)
+       deploy := 
environment.Resources.GetDeploymentForIntegration(environment.Integration)
+       require.NotNil(t, deploy)
+
+       require.Len(t, deploy.Spec.Template.Spec.InitContainers, 1)
+       assert.Equal(t, "agent", 
deploy.Spec.Template.Spec.InitContainers[0].Name)
+       assert.Equal(t, "my-agent-image:1.2.3", 
deploy.Spec.Template.Spec.InitContainers[0].Image)
+       assert.Equal(t, []string{"echo", "hello"}, 
deploy.Spec.Template.Spec.InitContainers[0].Command)
+       assert.NotEqual(t, ptr.To(corev1.ContainerRestartPolicyAlways), 
deploy.Spec.Template.Spec.InitContainers[0].RestartPolicy)
+}
+
+func TestApplyInitContainerSidecarOK(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name: "my-it",
+                       },
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       environment.Resources.Add(&appsv1.Deployment{
+               ObjectMeta: metav1.ObjectMeta{
+                       Labels: map[string]string{
+                               v1.IntegrationLabel: "my-it",
+                       },
+               },
+               Spec: appsv1.DeploymentSpec{
+                       Template: corev1.PodTemplateSpec{
+                               Spec: corev1.PodSpec{},
+                       },
+               },
+       })
+       initCont := initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       SidecarTasks: []string{
+                               "agent;my-agent-image:1.2.3;echo hello",
+                       },
+               },
+       }
+       configured, condition, err := initCont.Configure(&environment)
+       assert.True(t, configured)
+       assert.Nil(t, condition)
+       require.Nil(t, err)
+       err = initCont.Apply(&environment)
+       require.Nil(t, err)
+       deploy := 
environment.Resources.GetDeploymentForIntegration(environment.Integration)
+       require.NotNil(t, deploy)
+
+       require.Len(t, deploy.Spec.Template.Spec.InitContainers, 1)
+       assert.Equal(t, "agent", 
deploy.Spec.Template.Spec.InitContainers[0].Name)
+       assert.Equal(t, "my-agent-image:1.2.3", 
deploy.Spec.Template.Spec.InitContainers[0].Image)
+       assert.Equal(t, []string{"echo", "hello"}, 
deploy.Spec.Template.Spec.InitContainers[0].Command)
+       assert.Equal(t, ptr.To(corev1.ContainerRestartPolicyAlways), 
deploy.Spec.Template.Spec.InitContainers[0].RestartPolicy)
+}
+
+func TestApplyInitContainerAndSidecarOK(t *testing.T) {
+       environment := Environment{
+               Resources: kubernetes.NewCollection(),
+               Integration: &v1.Integration{
+                       ObjectMeta: metav1.ObjectMeta{
+                               Name: "my-it",
+                       },
+                       Status: v1.IntegrationStatus{
+                               Phase: v1.IntegrationPhaseRunning,
+                       },
+               },
+       }
+       environment.Resources.Add(&appsv1.Deployment{
+               ObjectMeta: metav1.ObjectMeta{
+                       Labels: map[string]string{
+                               v1.IntegrationLabel: "my-it",
+                       },
+               },
+               Spec: appsv1.DeploymentSpec{
+                       Template: corev1.PodTemplateSpec{
+                               Spec: corev1.PodSpec{},
+                       },
+               },
+       })
+       initCont := initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       SidecarTasks: []string{
+                               "sidecar;my-agent-image:1.2.3;echo sidecar",
+                       },
+                       InitTasks: []string{
+                               "init;my-agent-image:3.2.1;echo init",
+                       },
+               },
+       }
+       configured, condition, err := initCont.Configure(&environment)
+       assert.True(t, configured)
+       assert.Nil(t, condition)
+       require.Nil(t, err)
+       err = initCont.Apply(&environment)
+       require.Nil(t, err)
+       deploy := 
environment.Resources.GetDeploymentForIntegration(environment.Integration)
+       require.NotNil(t, deploy)
+
+       require.Len(t, deploy.Spec.Template.Spec.InitContainers, 2)
+       assert.Contains(t, deploy.Spec.Template.Spec.InitContainers, 
corev1.Container{
+               Name:          "sidecar",
+               Image:         "my-agent-image:1.2.3",
+               Command:       []string{"echo", "sidecar"},
+               RestartPolicy: ptr.To(corev1.ContainerRestartPolicyAlways),
+       })
+       assert.Contains(t, deploy.Spec.Template.Spec.InitContainers, 
corev1.Container{
+               Name:          "init",
+               Image:         "my-agent-image:3.2.1",
+               Command:       []string{"echo", "init"},
+               RestartPolicy: nil,
+       })
+}
+
+func TestParseTasks(t *testing.T) {
+       trait := &initContainersTrait{
+               InitContainersTrait: trait.InitContainersTrait{
+                       InitTasks:    []string{"name;image;init-command"},
+                       SidecarTasks: 
[]string{"name;image;sidecar-command;done"},
+               },
+       }
+
+       trait.parseTasks()
+       assert.Contains(t, trait.tasks, containerTask{
+               name:      "name",
+               image:     "image",
+               command:   "init-command",
+               isSidecar: false,
+       })
+       assert.Contains(t, trait.tasks, containerTask{
+               name:      "name",
+               image:     "image",
+               command:   "sidecar-command;done",
+               isSidecar: true,
+       })
+}
diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go
index 65247e11e..f76cfe191 100644
--- a/pkg/trait/mount.go
+++ b/pkg/trait/mount.go
@@ -44,7 +44,7 @@ import (
 
 const (
        mountTraitID    = "mount"
-       mountTraitOrder = 1610
+       mountTraitOrder = 1620
 )
 
 type mountTrait struct {
@@ -54,7 +54,7 @@ type mountTrait struct {
 
 func newMountTrait() Trait {
        return &mountTrait{
-               // Must follow immediately the container trait
+               // Must follow immediately the container and init-containers 
trait
                BasePlatformTrait: NewBasePlatformTrait(mountTraitID, 
mountTraitOrder),
        }
 }
@@ -86,11 +86,13 @@ func (t *mountTrait) Apply(e *Environment) error {
        }
 
        var volumes *[]corev1.Volume
+       var initContainers *[]corev1.Container
        visited := false
 
        // Deployment
        if err := e.Resources.VisitDeploymentE(func(deployment 
*appsv1.Deployment) error {
                volumes = &deployment.Spec.Template.Spec.Volumes
+               initContainers = &deployment.Spec.Template.Spec.InitContainers
                visited = true
                return nil
        }); err != nil {
@@ -100,6 +102,7 @@ func (t *mountTrait) Apply(e *Environment) error {
        // Knative Service
        if err := e.Resources.VisitKnativeServiceE(func(service 
*serving.Service) error {
                volumes = &service.Spec.ConfigurationSpec.Template.Spec.Volumes
+               initContainers = 
&service.Spec.ConfigurationSpec.Template.Spec.InitContainers
                visited = true
                return nil
        }); err != nil {
@@ -109,6 +112,7 @@ func (t *mountTrait) Apply(e *Environment) error {
        // CronJob
        if err := e.Resources.VisitCronJobE(func(cron *batchv1.CronJob) error {
                volumes = &cron.Spec.JobTemplate.Spec.Template.Spec.Volumes
+               initContainers = 
&cron.Spec.JobTemplate.Spec.Template.Spec.InitContainers
                visited = true
                return nil
        }); err != nil {
@@ -119,7 +123,7 @@ func (t *mountTrait) Apply(e *Environment) error {
                // Volumes declared in the trait config/resource options
                // as this func influences the application.properties
                // must be set as the first one to execute
-               err := t.configureVolumesAndMounts(e, volumes, 
&container.VolumeMounts)
+               err := t.configureVolumesAndMounts(e, volumes, 
&container.VolumeMounts, initContainers)
                if err != nil {
                        return err
                }
@@ -138,7 +142,13 @@ func (t *mountTrait) Apply(e *Environment) error {
 }
 
 // configureVolumesAndMounts is in charge to mount volumes and mounts coming 
from the trait configuration.
-func (t *mountTrait) configureVolumesAndMounts(e *Environment, vols 
*[]corev1.Volume, mnts *[]corev1.VolumeMount) error {
+// icnts holds the InitContainers which also require to be mounted with the 
shared volumes.
+func (t *mountTrait) configureVolumesAndMounts(
+       e *Environment,
+       vols *[]corev1.Volume,
+       mnts *[]corev1.VolumeMount,
+       icnts *[]corev1.Container,
+) error {
        for _, c := range t.Configs {
                if conf, parseErr := utilResource.ParseConfig(c); parseErr == 
nil {
                        // Let Camel parse these resources as properties
@@ -162,6 +172,9 @@ func (t *mountTrait) configureVolumesAndMounts(e 
*Environment, vols *[]corev1.Vo
                }
                *vols = append(*vols, *volume)
                *mnts = append(*mnts, *volumeMount)
+               for i := range *icnts {
+                       (*icnts)[i].VolumeMounts = 
append((*icnts)[i].VolumeMounts, *volumeMount)
+               }
        }
        for _, v := range t.EmptyDirs {
                volume, volumeMount, parseErr := ParseEmptyDirVolume(v)
@@ -170,6 +183,9 @@ func (t *mountTrait) configureVolumesAndMounts(e 
*Environment, vols *[]corev1.Vo
                }
                *vols = append(*vols, *volume)
                *mnts = append(*mnts, *volumeMount)
+               for i := range *icnts {
+                       (*icnts)[i].VolumeMounts = 
append((*icnts)[i].VolumeMounts, *volumeMount)
+               }
        }
 
        return nil
diff --git a/pkg/trait/mount_test.go b/pkg/trait/mount_test.go
index d1c624056..56c477ac4 100644
--- a/pkg/trait/mount_test.go
+++ b/pkg/trait/mount_test.go
@@ -558,3 +558,37 @@ func TestConfigureVolumesAndMountsSourcesInNativeMode(t 
*testing.T) {
        m = findVVolumeMount(mnts, func(m corev1.VolumeMount) bool { return 
m.Name == v.Name })
        assert.NotNil(t, m)
 }
+
+func TestMountVolumesInitContainers(t *testing.T) {
+       traitCatalog := NewCatalog(nil)
+       environment := getNominalEnv(t, traitCatalog)
+       // We must provide some init container
+       environment.Integration.Spec.Traits.InitContainers = 
&traitv1.InitContainersTrait{
+               InitTasks: []string{"init;my-init-image:1.2.3;echo hello"},
+       }
+       environment.Platform.ResyncStatusFullConfig()
+       conditions, traits, err := traitCatalog.apply(environment)
+
+       require.NoError(t, err)
+       assert.NotEmpty(t, traits)
+       assert.NotEmpty(t, conditions)
+       assert.NotEmpty(t, environment.ExecutedTraits)
+       assert.NotNil(t, environment.GetTrait("mount"))
+
+       s := environment.Resources.GetDeployment(func(service 
*appsv1.Deployment) bool {
+               return service.Name == "hello"
+       })
+       assert.NotNil(t, s)
+       spec := s.Spec.Template.Spec
+
+       assert.Len(t, spec.InitContainers[0].VolumeMounts, 1)
+
+       assert.Condition(t, func() bool {
+               for _, v := range spec.InitContainers[0].VolumeMounts {
+                       if v.Name == "my-pvc" {
+                               return true
+                       }
+               }
+               return false
+       })
+}
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index f5944fd16..e268a6e4c 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -32,6 +32,7 @@ func init() {
        AddToTraits(newGCTrait)
        AddToTraits(newGitTrait)
        AddToTraits(newHealthTrait)
+       AddToTraits(newInitContainersTrait)
        AddToTraits(NewInitTrait)
        AddToTraits(newIngressTrait)
        AddToTraits(newIstioTrait)
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index f7b692d36..13c92a304 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -193,7 +193,7 @@ func TestOnlySomeTraitsArePlatform(t *testing.T) {
        c := NewTraitTestCatalog()
        platformTraits := []string{
                "builder", "camel", "jvm", "runtime", "container", 
"security-context", "mount", "dependencies", "deployer",
-               "deployment", "environment", "error-handler", "kamelets", 
"openapi", "owner", "platform", "quarkus",
+               "deployment", "environment", "error-handler", 
"init-containers", "kamelets", "openapi", "owner", "platform", "quarkus",
        }
 
        for _, trait := range c.AllTraits() {

Reply via email to