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 <[email protected]> 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:
