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 8ebad22fcb5ed0e7e72258807728d5c1c4d4343c
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Tue Nov 23 12:26:45 2021 +0100

    feat(cmd/run): autogenerated configmap for resource
    
    Ref #2320
---
 .../resource-file-base64-encoded-route.groovy      |   2 +-
 .../user-config/resource-file-binary-route.groovy  |   2 +-
 pkg/cmd/run.go                                     |  38 ++++---
 pkg/cmd/run_help.go                                | 124 ++++++++++++++++-----
 pkg/trait/container.go                             |   5 +-
 pkg/trait/environment.go                           |   5 +-
 pkg/trait/jvm.go                                   |   5 +-
 pkg/trait/jvm_test.go                              |  10 +-
 pkg/trait/service_binding.go                       |   3 +-
 pkg/trait/trait_test.go                            |   4 +-
 pkg/trait/trait_types.go                           |  35 ++----
 pkg/util/camel/camel_util.go                       |  12 ++
 pkg/util/kubernetes/factory.go                     |  32 ++++++
 13 files changed, 198 insertions(+), 79 deletions(-)

diff --git a/examples/user-config/resource-file-base64-encoded-route.groovy 
b/examples/user-config/resource-file-base64-encoded-route.groovy
index 281d6ad..b88244d 100644
--- a/examples/user-config/resource-file-base64-encoded-route.groovy
+++ b/examples/user-config/resource-file-base64-encoded-route.groovy
@@ -18,7 +18,7 @@
 
 //
 // To run this integrations use:
-// kamel run --resource resources-data.txt --compression=true 
resource-file-base64-encoded-route.groovy --dev
+// kamel run --resource file:resources-data.txt --compression=true 
resource-file-base64-encoded-route.groovy --dev
 //
 
 from('timer:resources-bas64')
diff --git a/examples/user-config/resource-file-binary-route.groovy 
b/examples/user-config/resource-file-binary-route.groovy
index eef04d1..7f88b9a 100644
--- a/examples/user-config/resource-file-binary-route.groovy
+++ b/examples/user-config/resource-file-binary-route.groovy
@@ -18,7 +18,7 @@
 
 //
 // To run this integrations use:
-// kamel run --resource resources-data.zip resource-file-binary-route.groovy 
-d camel-zipfile --dev
+// kamel run --resource file:resources-data.zip 
resource-file-binary-route.groovy -d camel-zipfile --dev
 //
 
 
from('file:/etc/camel/resources/?fileName=resources-data.zip&noop=true&idempotent=false')
diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go
index 153c13c..767dada 100644
--- a/pkg/cmd/run.go
+++ b/pkg/cmd/run.go
@@ -568,10 +568,26 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd 
*cobra.Command, c client.C
                return nil, err
        }
 
+       generatedConfigmaps := make([]*corev1.ConfigMap, 0)
+
        for _, resource := range o.Resources {
                if config, parseErr := ParseResourceOption(resource); parseErr 
== nil {
-                       if applyResourceOptionErr := 
ApplyResourceOption(o.Context, config, &integration.Spec, c, namespace, 
o.Compression); applyResourceOptionErr != nil {
+                       if genCm, applyResourceOptionErr := 
ApplyResourceOption(o.Context, config, integration, c, namespace, 
o.Compression); applyResourceOptionErr != nil {
                                return nil, applyResourceOptionErr
+                       } else if genCm != nil {
+                               generatedConfigmaps = 
append(generatedConfigmaps, genCm)
+                       }
+               } else {
+                       return nil, parseErr
+               }
+       }
+
+       for _, item := range o.Configs {
+               if config, parseErr := ParseConfigOption(item); parseErr == nil 
{
+                       if genCm, applyConfigOptionErr := 
ApplyConfigOption(o.Context, config, integration, c, namespace, o.Compression); 
applyConfigOptionErr != nil {
+                               return nil, applyConfigOptionErr
+                       } else if genCm != nil {
+                               generatedConfigmaps = 
append(generatedConfigmaps, genCm)
                        }
                } else {
                        return nil, parseErr
@@ -619,15 +635,6 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd 
*cobra.Command, c client.C
                o.Traits = append(o.Traits, buildPropsTraits...)
        }
 
-       for _, item := range o.Configs {
-               if config, parseErr := ParseConfigOption(item); parseErr == nil 
{
-                       if applyConfigOptionErr := ApplyConfigOption(o.Context, 
config, &integration.Spec, c, namespace, o.Compression); applyConfigOptionErr 
!= nil {
-                               return nil, applyConfigOptionErr
-                       }
-               } else {
-                       return nil, parseErr
-               }
-       }
        for _, item := range o.ConfigMaps {
                integration.Spec.AddConfiguration("configmap", item)
        }
@@ -670,18 +677,21 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd 
*cobra.Command, c client.C
 
        if existing == nil {
                err = c.Create(o.Context, integration)
+               fmt.Printf("Integration \"%s\" created\n", name)
        } else {
                err = c.Patch(o.Context, integration, 
ctrl.MergeFromWithOptions(existing, ctrl.MergeFromWithOptimisticLock{}))
+               fmt.Printf("Integration \"%s\" updated\n", name)
        }
 
        if err != nil {
                return nil, err
        }
 
-       if existing == nil {
-               fmt.Printf("Integration \"%s\" created\n", name)
-       } else {
-               fmt.Printf("Integration \"%s\" updated\n", name)
+       if generatedConfigmaps != nil {
+               err = bindGeneratedConfigmapsToIntegration(o.Context, c, 
integration, generatedConfigmaps)
+               if err != nil {
+                       return integration, err
+               }
        }
        return integration, nil
 }
diff --git a/pkg/cmd/run_help.go b/pkg/cmd/run_help.go
index 5104ac9..5ccbe14 100644
--- a/pkg/cmd/run_help.go
+++ b/pkg/cmd/run_help.go
@@ -19,15 +19,21 @@ package cmd
 
 import (
        "context"
+       "crypto/sha1"
        "fmt"
        "path"
+       "path/filepath"
        "regexp"
        "strings"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/client"
+       "github.com/apache/camel-k/pkg/util/camel"
        "github.com/apache/camel-k/pkg/util/kubernetes"
        "github.com/magiconair/properties"
+       corev1 "k8s.io/api/core/v1"
+       k8serrors "k8s.io/apimachinery/pkg/api/errors"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 var invalidPaths = []string{"/etc/camel", "/deployments/dependencies"}
@@ -181,8 +187,9 @@ func parseOption(item string) (*RunConfigOption, error) {
        return configurationOption, nil
 }
 
-func applyOption(ctx context.Context, config *RunConfigOption, integrationSpec 
*v1.IntegrationSpec,
-       c client.Client, namespace string, enableCompression bool, resourceType 
v1.ResourceType) error {
+func applyOption(ctx context.Context, config *RunConfigOption, integration 
*v1.Integration,
+       c client.Client, namespace string, enableCompression bool, resourceType 
v1.ResourceType) (*corev1.ConfigMap, error) {
+       var maybeGenCm *corev1.ConfigMap
        switch config.configType {
        case ConfigOptionTypeConfigmap:
                cm := kubernetes.LookupConfigmap(ctx, c, namespace, 
config.Name())
@@ -190,58 +197,97 @@ func applyOption(ctx context.Context, config 
*RunConfigOption, integrationSpec *
                        fmt.Printf("Warn: %s Configmap not found in %s 
namespace, make sure to provide it before the Integration can run\n",
                                config.Name(), namespace)
                } else if resourceType != v1.ResourceTypeData && cm.BinaryData 
!= nil {
-                       return fmt.Errorf("you cannot provide a binary config, 
use a text file instead")
+                       return maybeGenCm, fmt.Errorf("you cannot provide a 
binary config, use a text file instead")
                }
-               integrationSpec.AddConfigurationAsResource(config.Type(), 
config.Name(), string(resourceType), config.DestinationPath(), config.Key())
        case ConfigOptionTypeSecret:
                secret := kubernetes.LookupSecret(ctx, c, namespace, 
config.Name())
                if secret == nil {
                        fmt.Printf("Warn: %s Secret not found in %s namespace, 
make sure to provide it before the Integration can run\n",
                                config.Name(), namespace)
                }
-               
integrationSpec.AddConfigurationAsResource(string(config.configType), 
config.Name(), string(resourceType), config.DestinationPath(), config.Key())
        case ConfigOptionTypeFile:
-               // Don't allow a file size longer than 1 MiB
-               fileSize, err := fileSize(config.Name())
-               printSize := fmt.Sprintf("%.2f", float64(fileSize)/Megabyte)
-               if err != nil {
-                       return err
-               } else if fileSize > Megabyte {
-                       return fmt.Errorf("you cannot provide a file larger 
than 1 MB (it was %s MB), check configmap option or --volume instead", 
printSize)
-               }
                // Don't allow a binary non compressed resource
                rawData, contentType, err := loadRawContent(ctx, config.Name())
                if err != nil {
-                       return err
+                       return maybeGenCm, err
                }
                if resourceType != v1.ResourceTypeData && !enableCompression && 
isBinary(contentType) {
-                       return fmt.Errorf("you cannot provide a binary config, 
use a text file or check --resource flag instead")
+                       return maybeGenCm, fmt.Errorf("you cannot provide a 
binary config, use a text file or check --resource flag instead")
                }
                resourceSpec, err := 
binaryOrTextResource(path.Base(config.Name()), rawData, contentType, 
enableCompression, resourceType, config.DestinationPath())
                if err != nil {
-                       return err
+                       return maybeGenCm, err
+               }
+               maybeGenCm, err = convertFileToConfigmap(ctx, c, resourceSpec, 
config, integration.Namespace, resourceType)
+               if err != nil {
+                       return maybeGenCm, err
                }
-               integrationSpec.AddResources(resourceSpec)
        default:
                // Should never reach this
-               return fmt.Errorf("invalid option type %s", config.configType)
+               return maybeGenCm, fmt.Errorf("invalid option type %s", 
config.configType)
        }
 
-       return nil
+       integration.Spec.AddConfigurationAsResource(config.Type(), 
config.Name(), string(resourceType), config.DestinationPath(), config.Key())
+
+       return maybeGenCm, nil
 }
 
-// ApplyConfigOption will set the proper --config option behavior to the 
IntegrationSpec.
-func ApplyConfigOption(ctx context.Context, config *RunConfigOption, 
integrationSpec *v1.IntegrationSpec, c client.Client, namespace string, 
enableCompression bool) error {
+func convertFileToConfigmap(ctx context.Context, c client.Client, resourceSpec 
v1.ResourceSpec, config *RunConfigOption,
+       namespace string, resourceType v1.ResourceType) (*corev1.ConfigMap, 
error) {
+       if config.DestinationPath() == "" {
+               config.resourceKey = filepath.Base(config.Name())
+               // As we are changing the resource to a configmap type
+               // we need to declare the mount path not to use the
+               // default behavior of a configmap (which include a 
subdirectory with the configmap name)
+               if resourceType == v1.ResourceTypeData {
+                       config.destinationPath = camel.ResourcesDefaultMountPath
+               } else {
+                       config.destinationPath = camel.ConfigResourcesMountPath
+               }
+       } else {
+               config.resourceKey = filepath.Base(config.DestinationPath())
+               config.destinationPath = filepath.Dir(config.DestinationPath())
+       }
+       genCmName := fmt.Sprintf("cm-%s", 
hashFrom([]byte(resourceSpec.Content), resourceSpec.RawContent))
+       cm := kubernetes.NewConfigmap(namespace, genCmName, config.Name(), 
config.Key(), resourceSpec.Content, resourceSpec.RawContent)
+       err := c.Create(ctx, cm)
+       if err != nil {
+               if k8serrors.IsAlreadyExists(err) {
+                       // We'll reuse it, as is
+               } else {
+                       return cm, err
+               }
+       }
+       config.configType = ConfigOptionTypeConfigmap
+       config.resourceName = cm.Name
+
+       return cm, nil
+}
+
+func hashFrom(contents ...[]byte) string {
+       // SHA1 because we need to limit the lenght to less than 64 chars
+       hash := sha1.New()
+       for _, c := range contents {
+               hash.Write(c)
+       }
+
+       return fmt.Sprintf("%x", hash.Sum(nil))
+}
+
+// ApplyConfigOption will set the proper --config option behavior to the 
IntegrationSpec
+func ApplyConfigOption(ctx context.Context, config *RunConfigOption, 
integration *v1.Integration, c client.Client,
+       namespace string, enableCompression bool) (*corev1.ConfigMap, error) {
        // A config option cannot specify destination path
        if config.DestinationPath() != "" {
-               return fmt.Errorf("cannot specify a destination path for this 
option type")
+               return nil, fmt.Errorf("cannot specify a destination path for 
this option type")
        }
-       return applyOption(ctx, config, integrationSpec, c, namespace, 
enableCompression, v1.ResourceTypeConfig)
+       return applyOption(ctx, config, integration, c, namespace, 
enableCompression, v1.ResourceTypeConfig)
 }
 
-// ApplyResourceOption will set the proper --resource option behavior to the 
IntegrationSpec.
-func ApplyResourceOption(ctx context.Context, config *RunConfigOption, 
integrationSpec *v1.IntegrationSpec, c client.Client, namespace string, 
enableCompression bool) error {
-       return applyOption(ctx, config, integrationSpec, c, namespace, 
enableCompression, v1.ResourceTypeData)
+// ApplyResourceOption will set the proper --resource option behavior to the 
IntegrationSpec
+func ApplyResourceOption(ctx context.Context, config *RunConfigOption, 
integration *v1.Integration, c client.Client,
+       namespace string, enableCompression bool) (*corev1.ConfigMap, error) {
+       return applyOption(ctx, config, integration, c, namespace, 
enableCompression, v1.ResourceTypeData)
 }
 
 func binaryOrTextResource(fileName string, data []byte, contentType string, 
base64Compression bool, resourceType v1.ResourceType, destinationPath string) 
(v1.ResourceSpec, error) {
@@ -319,3 +365,29 @@ func extractProperties(value string) 
(*properties.Properties, error) {
 func keyValueProps(value string) (*properties.Properties, error) {
        return properties.Load([]byte(value), properties.UTF8)
 }
+
+func bindGeneratedConfigmapsToIntegration(ctx context.Context, c 
client.Client, i *v1.Integration, configmaps []*corev1.ConfigMap) error {
+       controller := true
+       blockOwnerDeletion := true
+       for _, cm := range configmaps {
+               cm.ObjectMeta.Labels[v1.IntegrationLabel] = i.Name
+               cm.ObjectMeta.Labels["camel.apache.org/autogenerated"] = "true"
+               // set owner references
+               cm.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
+                       {
+                               Kind:               v1.IntegrationKind,
+                               APIVersion:         
v1.SchemeGroupVersion.String(),
+                               Name:               i.Name,
+                               UID:                i.UID,
+                               Controller:         &controller,
+                               BlockOwnerDeletion: &blockOwnerDeletion,
+                       },
+               }
+               err := c.Update(ctx, cm)
+               if err != nil {
+                       return err
+               }
+       }
+
+       return nil
+}
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index d9eae9e..7e67ae7 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -31,6 +31,7 @@ import (
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/util"
+       "github.com/apache/camel-k/pkg/util/camel"
        "github.com/apache/camel-k/pkg/util/defaults"
        "github.com/apache/camel-k/pkg/util/envvar"
        "github.com/apache/camel-k/pkg/util/kubernetes"
@@ -245,8 +246,8 @@ func (t *containerTrait) configureContainer(e *Environment) 
error {
        }
 
        envvar.SetVal(&container.Env, "CAMEL_K_DIGEST", 
e.Integration.Status.Digest)
-       envvar.SetVal(&container.Env, "CAMEL_K_CONF", path.Join(basePath, 
"application.properties"))
-       envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", confDPath)
+       envvar.SetVal(&container.Env, "CAMEL_K_CONF", path.Join(camel.BasePath, 
"application.properties"))
+       envvar.SetVal(&container.Env, "CAMEL_K_CONF_D", camel.ConfDPath)
 
        e.addSourcesProperties()
 
diff --git a/pkg/trait/environment.go b/pkg/trait/environment.go
index 3f96d24..2a21580 100644
--- a/pkg/trait/environment.go
+++ b/pkg/trait/environment.go
@@ -18,6 +18,7 @@ limitations under the License.
 package trait
 
 import (
+       "github.com/apache/camel-k/pkg/util/camel"
        "github.com/apache/camel-k/pkg/util/defaults"
        "github.com/apache/camel-k/pkg/util/envvar"
        "github.com/apache/camel-k/pkg/util/property"
@@ -73,8 +74,8 @@ func (t *environmentTrait) Apply(e *Environment) error {
                envvar.SetVal(&e.EnvVars, envVarCamelKIntegration, 
e.Integration.Name)
        }
        envvar.SetVal(&e.EnvVars, envVarCamelKRuntimeVersion, e.RuntimeVersion)
-       envvar.SetVal(&e.EnvVars, envVarMountPathConfigMaps, 
configConfigmapsMountPath)
-       envvar.SetVal(&e.EnvVars, envVarMountPathSecrets, 
configSecretsMountPath)
+       envvar.SetVal(&e.EnvVars, envVarMountPathConfigMaps, 
camel.ConfigConfigmapsMountPath)
+       envvar.SetVal(&e.EnvVars, envVarMountPathSecrets, 
camel.ConfigSecretsMountPath)
 
        if IsNilOrTrue(t.ContainerMeta) {
                envvar.SetValFrom(&e.EnvVars, envVarNamespace, 
"metadata.namespace")
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index 4787ca3..994a532 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -37,6 +37,7 @@ import (
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
        "github.com/apache/camel-k/pkg/builder"
        "github.com/apache/camel-k/pkg/util"
+       "github.com/apache/camel-k/pkg/util/camel"
 )
 
 // The JVM trait is used to configure the JVM that runs the integration.
@@ -108,8 +109,8 @@ func (t *jvmTrait) Apply(e *Environment) error {
        classpath := strset.New()
 
        classpath.Add("./resources")
-       classpath.Add(configResourcesMountPath)
-       classpath.Add(resourcesDefaultMountPath)
+       classpath.Add(camel.ConfigResourcesMountPath)
+       classpath.Add(camel.ResourcesDefaultMountPath)
        if t.Classpath != "" {
                classpath.Add(strings.Split(t.Classpath, ":")...)
        }
diff --git a/pkg/trait/jvm_test.go b/pkg/trait/jvm_test.go
index 4360692..760dadf 100644
--- a/pkg/trait/jvm_test.go
+++ b/pkg/trait/jvm_test.go
@@ -102,12 +102,12 @@ func TestApplyJvmTraitWithDeploymentResource(t 
*testing.T) {
 
        assert.Nil(t, err)
 
-       cp := strset.New("./resources", configResourcesMountPath, 
resourcesDefaultMountPath, "/mount/path").List()
+       cp := strset.New("./resources", camel.ConfigResourcesMountPath, 
camel.ResourcesDefaultMountPath, "/mount/path").List()
        sort.Strings(cp)
 
        assert.Equal(t, []string{
                "-cp",
-               fmt.Sprintf("./resources:%s:%s:/mount/path", 
configResourcesMountPath, resourcesDefaultMountPath),
+               fmt.Sprintf("./resources:%s:%s:/mount/path", 
camel.ConfigResourcesMountPath, camel.ResourcesDefaultMountPath),
                "io.quarkus.bootstrap.runner.QuarkusEntryPoint",
        }, d.Spec.Template.Spec.Containers[0].Args)
 }
@@ -134,12 +134,12 @@ func TestApplyJvmTraitWithKNativeResource(t *testing.T) {
 
        assert.Nil(t, err)
 
-       cp := strset.New("./resources", configResourcesMountPath, 
resourcesDefaultMountPath, "/mount/path").List()
+       cp := strset.New("./resources", camel.ConfigResourcesMountPath, 
camel.ResourcesDefaultMountPath, "/mount/path").List()
        sort.Strings(cp)
 
        assert.Equal(t, []string{
                "-cp",
-               fmt.Sprintf("./resources:%s:%s:/mount/path", 
configResourcesMountPath, resourcesDefaultMountPath),
+               fmt.Sprintf("./resources:%s:%s:/mount/path", 
camel.ConfigResourcesMountPath, camel.ResourcesDefaultMountPath),
                "io.quarkus.bootstrap.runner.QuarkusEntryPoint",
        }, s.Spec.Template.Spec.Containers[0].Args)
 }
@@ -243,7 +243,7 @@ func TestApplyJvmTraitWithClasspath(t *testing.T) {
        assert.Nil(t, err)
        assert.Equal(t, []string{
                "-cp",
-               fmt.Sprintf("./resources:%s:%s:/mount/path:%s:%s", 
configResourcesMountPath, resourcesDefaultMountPath,
+               fmt.Sprintf("./resources:%s:%s:/mount/path:%s:%s", 
camel.ConfigResourcesMountPath, camel.ResourcesDefaultMountPath,
                        "/path/to/another/dep.jar", "/path/to/my-dep.jar"),
                "io.quarkus.bootstrap.runner.QuarkusEntryPoint",
        }, d.Spec.Template.Spec.Containers[0].Args)
diff --git a/pkg/trait/service_binding.go b/pkg/trait/service_binding.go
index 1b574f7..ab7a78a 100644
--- a/pkg/trait/service_binding.go
+++ b/pkg/trait/service_binding.go
@@ -18,6 +18,7 @@ limitations under the License.
 package trait
 
 import (
+       "github.com/apache/camel-k/pkg/util/camel"
        "github.com/apache/camel-k/pkg/util/reference"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -77,7 +78,7 @@ func (t *serviceBindingTrait) Apply(e *Environment) error {
        if secret != nil {
                e.Resources.Add(secret)
                
e.ApplicationProperties["quarkus.kubernetes-service-binding.enabled"] = "true"
-               e.ApplicationProperties["SERVICE_BINDING_ROOT"] = 
serviceBindingsMountPath
+               e.ApplicationProperties["SERVICE_BINDING_ROOT"] = 
camel.ServiceBindingsMountPath
                e.ServiceBindingSecret = secret.GetName()
        }
        return nil
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index 0f1f5d8..bef6932 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -334,7 +334,7 @@ func 
TestConfigureVolumesAndMountsTextResourcesAndProperties(t *testing.T) {
 
        m = findVVolumeMount(mnts, func(m corev1.VolumeMount) bool { return 
m.Name == "test-configmap" })
        assert.NotNil(t, m)
-       assert.Equal(t, path.Join(configConfigmapsMountPath, "test-configmap"), 
m.MountPath)
+       assert.Equal(t, path.Join(camel.ConfigConfigmapsMountPath, 
"test-configmap"), m.MountPath)
 
        v = findVolume(vols, func(v corev1.Volume) bool { return v.Name == 
"test-secret" })
        assert.NotNil(t, v)
@@ -343,7 +343,7 @@ func 
TestConfigureVolumesAndMountsTextResourcesAndProperties(t *testing.T) {
 
        m = findVVolumeMount(mnts, func(m corev1.VolumeMount) bool { return 
m.Name == "test-secret" })
        assert.NotNil(t, m)
-       assert.Equal(t, path.Join(configSecretsMountPath, "test-secret"), 
m.MountPath)
+       assert.Equal(t, path.Join(camel.ConfigSecretsMountPath, "test-secret"), 
m.MountPath)
 
        v = findVolume(vols, func(v corev1.Volume) bool { return v.Name == 
"testvolume-data" })
        assert.NotNil(t, v)
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index 1757614..bb00d49 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -48,18 +48,7 @@ const (
        False = "false"
 )
 
-var (
-       basePath                  = "/etc/camel"
-       confDPath                 = path.Join(basePath, "conf.d")
-       sourcesMountPath          = path.Join(basePath, "sources")
-       resourcesDefaultMountPath = path.Join(basePath, "resources")
-       configResourcesMountPath  = path.Join(confDPath, "_resources")
-       configConfigmapsMountPath = path.Join(confDPath, "_configmaps")
-       configSecretsMountPath    = path.Join(confDPath, "_secrets")
-       serviceBindingsMountPath  = path.Join(confDPath, "_servicebindings")
-)
-
-// Identifiable represent an identifiable type.
+// Identifiable represent an identifiable type
 type Identifiable interface {
        ID() ID
 }
@@ -403,7 +392,7 @@ func (e *Environment) addSourcesProperties() {
        }
        for i, s := range e.Integration.Sources() {
                srcName := strings.TrimPrefix(s.Name, "/")
-               src := "file:" + path.Join(sourcesMountPath, srcName)
+               src := "file:" + path.Join(camel.SourcesMountPath, srcName)
                
e.ApplicationProperties[fmt.Sprintf("camel.k.sources[%d].location", i)] = src
 
                simpleName := srcName
@@ -457,7 +446,7 @@ func (e *Environment) configureVolumesAndMounts(vols 
*[]corev1.Volume, mnts *[]c
                }
                resName := strings.TrimPrefix(s.Name, "/")
                refName := fmt.Sprintf("i-source-%03d", i)
-               resPath := path.Join(sourcesMountPath, resName)
+               resPath := path.Join(camel.SourcesMountPath, resName)
 
                *vols = append(*vols, corev1.Volume{
                        Name: refName,
@@ -538,9 +527,9 @@ func (e *Environment) configureVolumesAndMounts(vols 
*[]corev1.Volume, mnts *[]c
                        var mountPath string
                        switch propertiesType {
                        case "application":
-                               mountPath = path.Join(basePath, resName)
+                               mountPath = path.Join(camel.BasePath, resName)
                        case "user":
-                               mountPath = path.Join(confDPath, resName)
+                               mountPath = path.Join(camel.ConfDPath, resName)
                        }
 
                        if propertiesType != "" {
@@ -626,7 +615,7 @@ func (e *Environment) configureVolumesAndMounts(vols 
*[]corev1.Volume, mnts *[]c
 
                *mnts = append(*mnts, corev1.VolumeMount{
                        Name:      refName,
-                       MountPath: path.Join(serviceBindingsMountPath, 
strings.ToLower(secret)),
+                       MountPath: path.Join(camel.ServiceBindingsMountPath, 
strings.ToLower(secret)),
                })
        }
 
@@ -698,11 +687,11 @@ func getResourcePath(resourceName string, maybePath 
string, resourceType v1.Reso
        }
        // otherwise return a default path, according to the resource type
        if resourceType == v1.ResourceTypeData {
-               return path.Join(resourcesDefaultMountPath, resourceName)
+               return path.Join(camel.ResourcesDefaultMountPath, resourceName)
        }
 
        // Default, config type
-       return path.Join(configResourcesMountPath, resourceName)
+       return path.Join(camel.ConfigResourcesMountPath, resourceName)
 }
 
 func getConfigmapMountPoint(resourceName string, maybeMountPoint string, 
resourceType string) string {
@@ -711,11 +700,11 @@ func getConfigmapMountPoint(resourceName string, 
maybeMountPoint string, resourc
                return maybeMountPoint
        }
        if resourceType == "data" {
-               return path.Join(resourcesDefaultMountPath, resourceName)
+               return path.Join(camel.ResourcesDefaultMountPath, resourceName)
        }
 
        // Default, config type
-       return path.Join(configConfigmapsMountPath, resourceName)
+       return path.Join(camel.ConfigConfigmapsMountPath, resourceName)
 }
 
 func getSecretMountPoint(resourceName string, maybeMountPoint string, 
resourceType string) string {
@@ -724,11 +713,11 @@ func getSecretMountPoint(resourceName string, 
maybeMountPoint string, resourceTy
                return maybeMountPoint
        }
        if resourceType == "data" {
-               return path.Join(resourcesDefaultMountPath, resourceName)
+               return path.Join(camel.ResourcesDefaultMountPath, resourceName)
        }
 
        // Default, config type
-       return path.Join(configSecretsMountPath, resourceName)
+       return path.Join(camel.ConfigSecretsMountPath, resourceName)
 }
 
 func (e *Environment) collectConfigurationValues(configurationType string) 
[]string {
diff --git a/pkg/util/camel/camel_util.go b/pkg/util/camel/camel_util.go
index 2aee18b..f41dad2 100644
--- a/pkg/util/camel/camel_util.go
+++ b/pkg/util/camel/camel_util.go
@@ -18,6 +18,7 @@ limitations under the License.
 package camel
 
 import (
+       "path"
        "sort"
        "strings"
 
@@ -27,6 +28,17 @@ import (
        "github.com/apache/camel-k/pkg/util/log"
 )
 
+var (
+       BasePath                  = "/etc/camel"
+       ConfDPath                 = path.Join(BasePath, "conf.d")
+       SourcesMountPath          = path.Join(BasePath, "sources")
+       ResourcesDefaultMountPath = path.Join(BasePath, "resources")
+       ConfigResourcesMountPath  = path.Join(ConfDPath, "_resources")
+       ConfigConfigmapsMountPath = path.Join(ConfDPath, "_configmaps")
+       ConfigSecretsMountPath    = path.Join(ConfDPath, "_secrets")
+       ServiceBindingsMountPath  = path.Join(ConfDPath, "_servicebindings")
+)
+
 func findBestMatch(catalogs []v1.CamelCatalog, runtime v1.RuntimeSpec) 
(*RuntimeCatalog, error) {
        for _, catalog := range catalogs {
                if catalog.Spec.Runtime.Version == runtime.Version && 
catalog.Spec.Runtime.Provider == runtime.Provider {
diff --git a/pkg/util/kubernetes/factory.go b/pkg/util/kubernetes/factory.go
index c1e7aa5..6fa42ec 100644
--- a/pkg/util/kubernetes/factory.go
+++ b/pkg/util/kubernetes/factory.go
@@ -24,6 +24,7 @@ import (
 
        corev1 "k8s.io/api/core/v1"
        "k8s.io/apimachinery/pkg/api/resource"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 var (
@@ -114,3 +115,34 @@ func NewResourceRequirements(reqs []string) 
(corev1.ResourceRequirements, error)
 
        return resReq, nil
 }
+
+// NewConfigmap will create a Configmap
+func NewConfigmap(namespace, cmName, originalFilename string, generatedKey 
string,
+       textData string, binaryData []byte) *corev1.ConfigMap {
+       immutable := true
+       cm := corev1.ConfigMap{
+               TypeMeta: metav1.TypeMeta{
+                       Kind:       "ConfigMap",
+                       APIVersion: "v1",
+               },
+               ObjectMeta: metav1.ObjectMeta{
+                       Name:      cmName,
+                       Namespace: namespace,
+                       Labels: map[string]string{
+                               "camel.apache.org/original-path": 
originalFilename,
+                       },
+               },
+               Immutable: &immutable,
+       }
+       if textData != "" {
+               cm.Data = map[string]string{
+                       generatedKey: textData,
+               }
+       }
+       if binaryData != nil {
+               cm.BinaryData = map[string][]byte{
+                       generatedKey: binaryData,
+               }
+       }
+       return &cm
+}

Reply via email to