You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2022/01/07 13:48:25 UTC
[camel-k] 19/24: feat(trait/mount): moving volumes logic
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 2568fad4c43d047e15229106ea4934986be326ec
Author: Pasquale Congiusti <pa...@gmail.com>
AuthorDate: Tue Dec 28 15:12:00 2021 +0100
feat(trait/mount): moving volumes logic
---
docs/modules/ROOT/nav.adoc | 1 +
docs/modules/traits/pages/container.adoc | 12 ---
docs/modules/traits/pages/mount.adoc | 45 ++++++++
pkg/cmd/run.go | 4 +-
pkg/trait/container.go | 77 -------------
pkg/trait/mount.go | 177 ++++++++++++++++++++++++++++++
pkg/trait/mount_test.go | 179 +++++++++++++++++++++++++++++++
pkg/trait/trait_register.go | 3 +-
pkg/trait/trait_test.go | 2 +-
resources/traits.yaml | 39 ++++---
10 files changed, 433 insertions(+), 106 deletions(-)
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 5bc1a65..593ab84 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -67,6 +67,7 @@
** xref:traits:knative.adoc[Knative]
** xref:traits:logging.adoc[Logging]
** xref:traits:master.adoc[Master]
+** xref:traits:mount.adoc[Mount]
** xref:traits:openapi.adoc[Openapi]
** xref:traits:owner.adoc[Owner]
** xref:traits:pdb.adoc[Pdb]
diff --git a/docs/modules/traits/pages/container.adoc b/docs/modules/traits/pages/container.adoc
index 0d608e4..f5be96f 100755
--- a/docs/modules/traits/pages/container.adoc
+++ b/docs/modules/traits/pages/container.adoc
@@ -81,18 +81,6 @@ The following configuration options are available:
| PullPolicy
| The pull policy: Always\|Never\|IfNotPresent
-| container.configs
-| []string
-| A list of configuration pointing to configmap/secret. Syntax: [configmap\|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
-
-| container.resources
-| []string
-| A list of resources pointing to configmap/secret. Syntax: [configmap\|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
-
-| container.volumes
-| []string
-| A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]
-
| container.probes-enabled
| bool
| DeprecatedProbesEnabled enable/disable probes on the container (default `false`)
diff --git a/docs/modules/traits/pages/mount.adoc b/docs/modules/traits/pages/mount.adoc
new file mode 100644
index 0000000..d5e2c19
--- /dev/null
+++ b/docs/modules/traits/pages/mount.adoc
@@ -0,0 +1,45 @@
+= Mount Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The Mount trait can be used to configure volumes mounted on the Integration Pod.
+
+nolint: tagliatelle
+
+This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
+
+WARNING: The mount trait is a *platform trait*: disabling it may compromise the platform functionality.
+
+// 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 mount.[key]=[value] --trait mount.[key2]=[value2] integration.groovy
+----
+The following configuration options are available:
+
+[cols="2m,1m,5a"]
+|===
+|Property | Type | Description
+
+| mount.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common property.
+
+| mount.configs
+| []string
+| A list of configuration pointing to configmap/secret. Syntax: [configmap\|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
+
+| mount.resources
+| []string
+| A list of resources pointing to configmap/secret. Syntax: [configmap\|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
+
+| mount.volumes
+| []string
+| A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index 1c1b183..35f2c0a 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -576,12 +576,12 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
}
generatedConfigmaps := make([]*corev1.ConfigMap, 0)
- resCms, err := o.parseAndConvertToTrait(c, integration, o.Resources, resource.ParseResource, func(c *resource.Config) string { return c.String() }, "container.resources")
+ resCms, err := o.parseAndConvertToTrait(c, integration, o.Resources, resource.ParseResource, func(c *resource.Config) string { return c.String() }, "mount.resources")
if err != nil {
return nil, err
}
generatedConfigmaps = append(generatedConfigmaps, resCms...)
- confCms, err := o.parseAndConvertToTrait(c, integration, o.Configs, resource.ParseConfig, func(c *resource.Config) string { return c.String() }, "container.configs")
+ confCms, err := o.parseAndConvertToTrait(c, integration, o.Configs, resource.ParseConfig, func(c *resource.Config) string { return c.String() }, "mount.configs")
if err != nil {
return nil, err
}
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 0abf914..5fc7da8 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -20,7 +20,6 @@ package trait
import (
"fmt"
"path"
- "strings"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/batch/v1beta1"
@@ -36,7 +35,6 @@ import (
"github.com/apache/camel-k/pkg/util/defaults"
"github.com/apache/camel-k/pkg/util/envvar"
"github.com/apache/camel-k/pkg/util/kubernetes"
- utilResource "github.com/apache/camel-k/pkg/util/resource"
)
const (
@@ -83,12 +81,6 @@ type containerTrait struct {
Image string `property:"image" json:"image,omitempty"`
// The pull policy: Always|Never|IfNotPresent
ImagePullPolicy corev1.PullPolicy `property:"image-pull-policy" json:"imagePullPolicy,omitempty"`
- // A list of configuration pointing to configmap/secret. Syntax: [configmap|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
- Configs []string `property:"configs" json:"configs,omitempty"`
- // A list of resources pointing to configmap/secret. Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
- Resources []string `property:"resources" json:"resources,omitempty"`
- // A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]
- Volumes []string `property:"volumes" json:"volumes,omitempty"`
// DeprecatedProbesEnabled enable/disable probes on the container (default `false`)
// Deprecated: replaced by the health trait.
@@ -168,23 +160,6 @@ func (t *containerTrait) Configure(e *Environment) (bool, error) {
return false, fmt.Errorf("unsupported pull policy %s", t.ImagePullPolicy)
}
- // Validate resources and pvcs
- for _, c := range t.Configs {
- if !strings.HasPrefix(c, "configmap:") && !strings.HasPrefix(c, "secret:") {
- return false, fmt.Errorf("unsupported config %s, must be a configmap or secret resource", c)
- }
- }
- for _, r := range t.Resources {
- if !strings.HasPrefix(r, "configmap:") && !strings.HasPrefix(r, "secret:") {
- return false, fmt.Errorf("unsupported resource %s, must be a configmap or secret resource", r)
- }
- }
- for _, r := range t.Volumes {
- if !strings.HasPrefix(r, "pvc:") {
- return false, fmt.Errorf("unsupported volume %s, must be a pvc", r)
- }
- }
-
return true, nil
}
@@ -287,7 +262,6 @@ func (t *containerTrait) configureContainer(e *Environment) error {
}
t.configureCapabilities(e)
- var volumes *[]corev1.Volume
var containers *[]corev1.Container
visited := false
@@ -297,7 +271,6 @@ func (t *containerTrait) configureContainer(e *Environment) error {
envvar.SetVar(&container.Env, envVar)
}
- volumes = &deployment.Spec.Template.Spec.Volumes
containers = &deployment.Spec.Template.Spec.Containers
visited = true
return nil
@@ -322,7 +295,6 @@ func (t *containerTrait) configureContainer(e *Environment) error {
}
}
- volumes = &service.Spec.ConfigurationSpec.Template.Spec.Volumes
containers = &service.Spec.ConfigurationSpec.Template.Spec.Containers
visited = true
return nil
@@ -336,7 +308,6 @@ func (t *containerTrait) configureContainer(e *Environment) error {
envvar.SetVar(&container.Env, envVar)
}
- volumes = &cron.Spec.JobTemplate.Spec.Template.Spec.Volumes
containers = &cron.Spec.JobTemplate.Spec.Template.Spec.Containers
visited = true
return nil
@@ -345,60 +316,12 @@ func (t *containerTrait) configureContainer(e *Environment) error {
}
if visited {
- // Volumes declared in the Integration resources
- e.configureVolumesAndMounts(volumes, &container.VolumeMounts)
- // Volumes declared in the trait config/resource options
- err := t.configureVolumesAndMounts(volumes, &container.VolumeMounts)
- if err != nil {
- return err
- }
*containers = append(*containers, container)
}
return nil
}
-func (t *containerTrait) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount) error {
- for _, c := range t.Configs {
- if conf, parseErr := utilResource.ParseConfig(c); parseErr == nil {
- t.mountResource(vols, mnts, conf)
- } else {
- return parseErr
- }
- }
- for _, r := range t.Resources {
- if res, parseErr := utilResource.ParseResource(r); parseErr == nil {
- t.mountResource(vols, mnts, res)
- } else {
- return parseErr
- }
- }
- for _, v := range t.Volumes {
- if vol, parseErr := utilResource.ParseVolume(v); parseErr == nil {
- t.mountResource(vols, mnts, vol)
- } else {
- return parseErr
- }
- }
-
- return nil
-}
-
-func (t *containerTrait) mountResource(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount, conf *utilResource.Config) {
- refName := kubernetes.SanitizeLabel(conf.Name())
- vol := getVolume(refName, string(conf.StorageType()), conf.Name(), conf.Key(), conf.Key())
- mntPath := getMountPoint(conf.Name(), conf.DestinationPath(), string(conf.StorageType()), string(conf.ContentType()))
- readOnly := true
- if conf.StorageType() == utilResource.StorageTypePVC {
- readOnly = false
- }
- // No need to specify a subpath, as we mount the entire configmap/secret
- mnt := getMount(refName, mntPath, "", readOnly)
-
- *vols = append(*vols, *vol)
- *mnts = append(*mnts, *mnt)
-}
-
func (t *containerTrait) configureService(e *Environment, container *corev1.Container) {
service := e.Resources.GetServiceForIntegration(e.Integration)
if service == nil {
diff --git a/pkg/trait/mount.go b/pkg/trait/mount.go
new file mode 100644
index 0000000..18114bb
--- /dev/null
+++ b/pkg/trait/mount.go
@@ -0,0 +1,177 @@
+/*
+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"
+ "k8s.io/api/batch/v1beta1"
+ corev1 "k8s.io/api/core/v1"
+
+ serving "knative.dev/serving/pkg/apis/serving/v1"
+
+ v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+ "github.com/apache/camel-k/pkg/util/kubernetes"
+ utilResource "github.com/apache/camel-k/pkg/util/resource"
+)
+
+// The Mount trait can be used to configure volumes mounted on the Integration Pod.
+//
+// +camel-k:trait=mount
+// nolint: tagliatelle
+type mountTrait struct {
+ BaseTrait `property:",squash"`
+ // A list of configuration pointing to configmap/secret. Syntax: [configmap|secret]:name[key], where name represents the resource name and key optionally represents the resource key to be filtered
+ Configs []string `property:"configs" json:"configs,omitempty"`
+ // A list of resources pointing to configmap/secret. Syntax: [configmap|secret]:name[/key][@path], where name represents the resource name, key optionally represents the resource key to be filtered and path represents the destination path
+ Resources []string `property:"resources" json:"resources,omitempty"`
+ // A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]
+ Volumes []string `property:"volumes" json:"volumes,omitempty"`
+}
+
+func newMountTrait() Trait {
+ return &mountTrait{
+ // Must follow immediately the container trait
+ BaseTrait: NewBaseTrait("mount", 1610),
+ }
+}
+
+func (t *mountTrait) Configure(e *Environment) (bool, error) {
+ if IsFalse(t.Enabled) {
+ return false, nil
+ }
+
+ if !e.IntegrationInPhase(v1.IntegrationPhaseInitialization) && !e.IntegrationInRunningPhases() {
+ return false, nil
+ }
+
+ // Validate resources and pvcs
+ for _, c := range t.Configs {
+ if !strings.HasPrefix(c, "configmap:") && !strings.HasPrefix(c, "secret:") {
+ return false, fmt.Errorf("unsupported config %s, must be a configmap or secret resource", c)
+ }
+ }
+ for _, r := range t.Resources {
+ if !strings.HasPrefix(r, "configmap:") && !strings.HasPrefix(r, "secret:") {
+ return false, fmt.Errorf("unsupported resource %s, must be a configmap or secret resource", r)
+ }
+ }
+
+ return true, nil
+}
+
+func (t *mountTrait) Apply(e *Environment) error {
+ if e.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
+ return nil
+ }
+
+ container := e.GetIntegrationContainer()
+ if container == nil {
+ return fmt.Errorf("unable to find integration container: %s", e.Integration.Name)
+ }
+
+ var volumes *[]corev1.Volume
+ visited := false
+
+ // Deployment
+ if err := e.Resources.VisitDeploymentE(func(deployment *appsv1.Deployment) error {
+ volumes = &deployment.Spec.Template.Spec.Volumes
+ visited = true
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ // Knative Service
+ if err := e.Resources.VisitKnativeServiceE(func(service *serving.Service) error {
+ volumes = &service.Spec.ConfigurationSpec.Template.Spec.Volumes
+ visited = true
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ // CronJob
+ if err := e.Resources.VisitCronJobE(func(cron *v1beta1.CronJob) error {
+ volumes = &cron.Spec.JobTemplate.Spec.Template.Spec.Volumes
+ visited = true
+ return nil
+ }); err != nil {
+ return err
+ }
+
+ if visited {
+ // Volumes declared in the Integration resources
+ e.configureVolumesAndMounts(volumes, &container.VolumeMounts)
+ // Volumes declared in the trait config/resource options
+ err := t.configureVolumesAndMounts(volumes, &container.VolumeMounts)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (t *mountTrait) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount) error {
+ for _, c := range t.Configs {
+ if conf, parseErr := utilResource.ParseConfig(c); parseErr == nil {
+ t.mountResource(vols, mnts, conf)
+ } else {
+ return parseErr
+ }
+ }
+ for _, r := range t.Resources {
+ if res, parseErr := utilResource.ParseResource(r); parseErr == nil {
+ t.mountResource(vols, mnts, res)
+ } else {
+ return parseErr
+ }
+ }
+ for _, v := range t.Volumes {
+ if vol, parseErr := utilResource.ParseVolume(v); parseErr == nil {
+ t.mountResource(vols, mnts, vol)
+ } else {
+ return parseErr
+ }
+ }
+
+ return nil
+}
+
+func (t *mountTrait) mountResource(vols *[]corev1.Volume, mnts *[]corev1.VolumeMount, conf *utilResource.Config) {
+ refName := kubernetes.SanitizeLabel(conf.Name())
+ vol := getVolume(refName, string(conf.StorageType()), conf.Name(), conf.Key(), conf.Key())
+ mntPath := getMountPoint(conf.Name(), conf.DestinationPath(), string(conf.StorageType()), string(conf.ContentType()))
+ readOnly := true
+ if conf.StorageType() == utilResource.StorageTypePVC {
+ readOnly = false
+ }
+ // No need to specify a subpath, as we mount the entire configmap/secret
+ mnt := getMount(refName, mntPath, "", readOnly)
+
+ *vols = append(*vols, *vol)
+ *mnts = append(*mnts, *mnt)
+}
+
+// IsPlatformTrait overrides base class method.
+func (t *mountTrait) IsPlatformTrait() bool {
+ return true
+}
diff --git a/pkg/trait/mount_test.go b/pkg/trait/mount_test.go
new file mode 100644
index 0000000..eee4bc0
--- /dev/null
+++ b/pkg/trait/mount_test.go
@@ -0,0 +1,179 @@
+/*
+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"
+
+ "github.com/stretchr/testify/assert"
+
+ appsv1 "k8s.io/api/apps/v1"
+ corev1 "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
+ "github.com/apache/camel-k/pkg/util/camel"
+ "github.com/apache/camel-k/pkg/util/gzip"
+ "github.com/apache/camel-k/pkg/util/kubernetes"
+ "github.com/apache/camel-k/pkg/util/test"
+)
+
+func TestMountVolumesEmpty(t *testing.T) {
+ traitCatalog := NewCatalog(nil)
+
+ environment := getNominalEnv(t, traitCatalog)
+ environment.Integration.Spec.Traits = map[string]v1.TraitSpec{}
+ environment.Platform.ResyncStatusFullConfig()
+
+ err := traitCatalog.apply(environment)
+
+ assert.Nil(t, err)
+ 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.Containers[0].VolumeMounts, 2)
+ assert.Len(t, spec.Volumes, 2)
+}
+
+func TestMountVolumesIntegrationPhaseDeploying(t *testing.T) {
+ traitCatalog := NewCatalog(nil)
+
+ environment := getNominalEnv(t, traitCatalog)
+ environment.Platform.ResyncStatusFullConfig()
+
+ err := traitCatalog.apply(environment)
+
+ assert.Nil(t, err)
+ 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.Containers[0].VolumeMounts, 5)
+ assert.Len(t, spec.Volumes, 5)
+
+ assert.Condition(t, func() bool {
+ for _, v := range spec.Containers[0].VolumeMounts {
+ if v.Name == "my-pvc" {
+ return true
+ }
+ }
+ return false
+ })
+ assert.Condition(t, func() bool {
+ for _, v := range spec.Containers[0].VolumeMounts {
+ if v.Name == "my-cm" {
+ return true
+ }
+ }
+ return false
+ })
+ assert.Condition(t, func() bool {
+ for _, v := range spec.Volumes {
+ if v.Name == "my-secret" {
+ return true
+ }
+ }
+ return false
+ })
+}
+
+func TestMountVolumesIntegrationPhaseInitialization(t *testing.T) {
+ traitCatalog := NewCatalog(nil)
+
+ environment := getNominalEnv(t, traitCatalog)
+ environment.Integration.Status.Phase = v1.IntegrationPhaseInitialization
+ environment.Platform.ResyncStatusFullConfig()
+
+ err := traitCatalog.apply(environment)
+
+ assert.Nil(t, err)
+ 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.Nil(t, s)
+}
+
+func getNominalEnv(t *testing.T, traitCatalog *Catalog) *Environment {
+ t.Helper()
+ catalog, _ := camel.DefaultCatalog()
+ compressedRoute, _ := gzip.CompressBase64([]byte(`from("undertow:test").log("hello")`))
+
+ return &Environment{
+ CamelCatalog: catalog,
+ Catalog: traitCatalog,
+ Integration: &v1.Integration{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "hello",
+ Namespace: "default",
+ },
+ Status: v1.IntegrationStatus{
+ Phase: v1.IntegrationPhaseDeploying,
+ },
+ Spec: v1.IntegrationSpec{
+ Sources: []v1.SourceSpec{
+ {
+ DataSpec: v1.DataSpec{
+ Name: "routes.js",
+ Content: string(compressedRoute),
+ Compression: true,
+ },
+ Language: v1.LanguageJavaScript,
+ },
+ },
+ Traits: map[string]v1.TraitSpec{
+ "mount": test.TraitSpecFromMap(t, map[string]interface{}{
+ "configs": []string{"configmap:my-cm"},
+ "resources": []string{"secret:my-secret"},
+ "volumes": []string{"my-pvc:/over/the/rainbow"},
+ }),
+ },
+ },
+ },
+ IntegrationKit: &v1.IntegrationKit{
+ Status: v1.IntegrationKitStatus{
+ Phase: v1.IntegrationKitPhaseReady,
+ },
+ },
+ Platform: &v1.IntegrationPlatform{
+ Spec: v1.IntegrationPlatformSpec{
+ Cluster: v1.IntegrationPlatformClusterOpenShift,
+ Build: v1.IntegrationPlatformBuildSpec{
+ PublishStrategy: v1.IntegrationPlatformBuildPublishStrategyS2I,
+ Registry: v1.RegistrySpec{Address: "registry"},
+ },
+ },
+ },
+ EnvVars: make([]corev1.EnvVar, 0),
+ ExecutedTraits: make([]Trait, 0),
+ Resources: kubernetes.NewCollection(),
+ }
+}
diff --git a/pkg/trait/trait_register.go b/pkg/trait/trait_register.go
index 68d2997..4f2a6d1 100644
--- a/pkg/trait/trait_register.go
+++ b/pkg/trait/trait_register.go
@@ -32,6 +32,7 @@ func init() {
AddToTraits(newErrorHandlerTrait)
AddToTraits(newGarbageCollectorTrait)
AddToTraits(newHealthTrait)
+ AddToTraits(newInitTrait)
AddToTraits(newIngressTrait)
AddToTraits(newIstioTrait)
AddToTraits(newJolokiaTrait)
@@ -40,7 +41,7 @@ func init() {
AddToTraits(newKnativeTrait)
AddToTraits(newKnativeServiceTrait)
AddToTraits(newLoggingTraitTrait)
- AddToTraits(newInitTrait)
+ AddToTraits(newMountTrait)
AddToTraits(newOpenAPITrait)
AddToTraits(newOwnerTrait)
AddToTraits(newPdbTrait)
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index bef6932..0bc1f41 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -495,7 +495,7 @@ func TestOnlySomeTraitsInfluenceBuild(t *testing.T) {
func TestOnlySomeTraitsArePlatform(t *testing.T) {
c := NewTraitTestCatalog()
platformTraits := []string{
- "builder", "camel", "jvm", "runtime", "container", "dependencies", "deployer",
+ "builder", "camel", "jvm", "runtime", "container", "mount", "dependencies", "deployer",
"deployment", "environment", "error-handler", "kamelets", "openapi", "owner", "platform", "quarkus",
}
diff --git a/resources/traits.yaml b/resources/traits.yaml
index d3ec499..2b66ec4 100755
--- a/resources/traits.yaml
+++ b/resources/traits.yaml
@@ -132,19 +132,6 @@ traits:
- name: image-pull-policy
type: PullPolicy
description: 'The pull policy: Always|Never|IfNotPresent'
- - name: configs
- type: '[]string'
- description: 'A list of configuration pointing to configmap/secret. Syntax: [configmap|secret]:name[key],
- where name represents the resource name and key optionally represents the resource
- key to be filtered'
- - name: resources
- type: '[]string'
- description: 'A list of resources pointing to configmap/secret. Syntax: [configmap|secret]:name[/key][@path],
- where name represents the resource name, key optionally represents the resource
- key to be filtered and path represents the destination path'
- - name: volumes
- type: '[]string'
- description: 'A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]'
- name: probes-enabled
type: bool
description: 'DeprecatedProbesEnabled enable/disable probes on the container (default
@@ -765,6 +752,32 @@ traits:
type: string
description: Label value that will be used to identify all pods contending the
lock. Defaults to the integration name.
+- name: mount
+ platform: true
+ profiles:
+ - Kubernetes
+ - Knative
+ - OpenShift
+ description: 'The Mount trait can be used to configure volumes mounted on the Integration
+ Pod. nolint: tagliatelle'
+ properties:
+ - name: enabled
+ type: bool
+ description: Can be used to enable or disable a trait. All traits share this common
+ property.
+ - name: configs
+ type: '[]string'
+ description: 'A list of configuration pointing to configmap/secret. Syntax: [configmap|secret]:name[key],
+ where name represents the resource name and key optionally represents the resource
+ key to be filtered'
+ - name: resources
+ type: '[]string'
+ description: 'A list of resources pointing to configmap/secret. Syntax: [configmap|secret]:name[/key][@path],
+ where name represents the resource name, key optionally represents the resource
+ key to be filtered and path represents the destination path'
+ - name: volumes
+ type: '[]string'
+ description: 'A list of Persistent Volume Claims to be mounted. Syntax: [pvcname:/container/path]'
- name: openapi
platform: true
profiles: