This is an automated email from the ASF dual-hosted git repository. astefanutti pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 1f958527c5b1db1ed27b99e93c857a3d16f8716d Author: Pasquale Congiusti <[email protected]> AuthorDate: Wed Jun 2 15:24:59 2021 +0200 feat(cmd/run): resource @path support Adding the possibility to specify the destination path for any resource Ref #2003 --- pkg/apis/camel/v1/common_types.go | 8 ++++-- pkg/apis/camel/v1/integration_types_support.go | 11 ++++---- pkg/cmd/run.go | 2 +- pkg/cmd/run_help.go | 35 ++++++++++++++++++------ pkg/cmd/run_help_test.go | 6 ++++ pkg/cmd/run_test.go | 8 +++--- pkg/trait/trait_types.go | 38 +++++++++++++++++--------- pkg/trait/util.go | 1 + 8 files changed, 74 insertions(+), 35 deletions(-) diff --git a/pkg/apis/camel/v1/common_types.go b/pkg/apis/camel/v1/common_types.go index 6b2cda8..42a23fa 100644 --- a/pkg/apis/camel/v1/common_types.go +++ b/pkg/apis/camel/v1/common_types.go @@ -26,9 +26,10 @@ const TraitAnnotationPrefix = "trait.camel.apache.org/" // ConfigurationSpec -- type ConfigurationSpec struct { - Type string `json:"type"` - Value string `json:"value"` - ResourceType string `json:"resourceType,omitempty"` + Type string `json:"type"` + Value string `json:"value"` + ResourceType string `json:"resourceType,omitempty"` + ResourceMountPoint string `json:"resourceMountPoint,omitempty"` } // Artifact -- @@ -232,6 +233,7 @@ const ( // DataSpec -- type DataSpec struct { Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` Content string `json:"content,omitempty"` RawContent []byte `json:"rawContent,omitempty"` ContentRef string `json:"contentRef,omitempty"` diff --git a/pkg/apis/camel/v1/integration_types_support.go b/pkg/apis/camel/v1/integration_types_support.go index acf3bd6..8c2d3e5 100644 --- a/pkg/apis/camel/v1/integration_types_support.go +++ b/pkg/apis/camel/v1/integration_types_support.go @@ -109,12 +109,13 @@ func (in *IntegrationSpec) AddConfiguration(confType string, confValue string) { }) } -// AddConfigurationAsResourceType will set a configuration specified with a resource type -func (in *IntegrationSpec) AddConfigurationAsResourceType(confType string, confValue string, resourceType string) { +// AddConfigurationAsResource will set a configuration specified with a resource type +func (in *IntegrationSpec) AddConfigurationAsResource(confType string, confValue string, resourceType string, resourceMountPoint string) { in.Configuration = append(in.Configuration, ConfigurationSpec{ - Type: confType, - Value: confValue, - ResourceType: resourceType, + Type: confType, + Value: confValue, + ResourceType: resourceType, + ResourceMountPoint: resourceMountPoint, }) } diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index ad0485d..6e4c373 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -82,7 +82,7 @@ func newCmdRun(rootCmdOptions *RootCmdOptions) (*cobra.Command, *runCmdOptions) cmd.Flags().StringArrayP("property", "p", nil, "Add a runtime property or properties file (syntax: [my-key=my-value|file:/path/to/my-conf.properties])") cmd.Flags().StringArray("build-property", nil, "Add a build time property or properties file (syntax: [my-key=my-value|file:/path/to/my-conf.properties])") cmd.Flags().StringArray("config", nil, "Add a runtime configuration from a Configmap, a Secret or a file (syntax: [configmap|secret|file]:name)") - cmd.Flags().StringArray("resource", nil, "Add a runtime resource from a Configmap, a Secret or a file (syntax: [configmap|secret|file]:name)") + cmd.Flags().StringArray("resource", nil, "Add a runtime resource from a Configmap, a Secret or a file (syntax: [configmap|secret|file]:name[@path])") cmd.Flags().StringArray("configmap", nil, "[Deprecated] Add a ConfigMap") cmd.Flags().StringArray("secret", nil, "[Deprecated] Add a Secret") cmd.Flags().StringArray("maven-repository", nil, "Add a maven repository") diff --git a/pkg/cmd/run_help.go b/pkg/cmd/run_help.go index ca36a91..12264c2 100644 --- a/pkg/cmd/run_help.go +++ b/pkg/cmd/run_help.go @@ -31,8 +31,14 @@ import ( // RunConfigOption represents a config option type RunConfigOption struct { - ConfigType configOptionType - Value string + ConfigType configOptionType + Value string + destinationPath string +} + +// DestinationPath is the location where the resource will be stored on destination +func (runConfigOption *RunConfigOption) DestinationPath() string { + return runConfigOption.destinationPath } type configOptionType string @@ -46,13 +52,23 @@ const ( ConfigOptionTypeFile configOptionType = "file" ) -var validConfigRegexp = regexp.MustCompile(`^(configmap|secret|file)\:([\w\.\-\_\:\/]+)$`) +var validConfigRegexp = regexp.MustCompile(`^(configmap|secret|file)\:([\w\.\-\_\:\/@]+)$`) func newRunConfigOption(configType configOptionType, value string) *RunConfigOption { + optionValue, maybeDestinationPath := parseFileValue(value) return &RunConfigOption{ - ConfigType: configType, - Value: value, + ConfigType: configType, + Value: optionValue, + destinationPath: maybeDestinationPath, + } +} + +func parseFileValue(value string) (string, string) { + split := strings.SplitN(value, "@", 2) + if len(split) == 2 { + return split[0], split[1] } + return value, "" } // ParseResourceOption will parse and return a runConfigOption @@ -107,14 +123,14 @@ func applyOption(config *RunConfigOption, integrationSpec *v1.IntegrationSpec, } else if resourceType != v1.ResourceTypeData && cm.BinaryData != nil { return fmt.Errorf("you cannot provide a binary config, use a text file instead") } - integrationSpec.AddConfigurationAsResourceType(string(config.ConfigType), config.Value, string(resourceType)) + integrationSpec.AddConfigurationAsResource(string(config.ConfigType), config.Value, string(resourceType), config.DestinationPath()) case ConfigOptionTypeSecret: secret := kubernetes.LookupSecret(context.Background(), c, namespace, config.Value) 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.Value, namespace) } - integrationSpec.AddConfigurationAsResourceType(string(config.ConfigType), config.Value, string(resourceType)) + integrationSpec.AddConfigurationAsResource(string(config.ConfigType), config.Value, string(resourceType), config.DestinationPath()) case ConfigOptionTypeFile: // Don't allow a binary non compressed resource rawData, contentType, err := loadRawContent(config.Value) @@ -124,7 +140,7 @@ func applyOption(config *RunConfigOption, integrationSpec *v1.IntegrationSpec, 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") } - resourceSpec, err := binaryOrTextResource(path.Base(config.Value), rawData, contentType, enableCompression, resourceType) + resourceSpec, err := binaryOrTextResource(path.Base(config.Value), rawData, contentType, enableCompression, resourceType, config.DestinationPath()) if err != nil { return err } @@ -147,10 +163,11 @@ func ApplyResourceOption(config *RunConfigOption, integrationSpec *v1.Integratio return applyOption(config, integrationSpec, c, namespace, enableCompression, v1.ResourceTypeData) } -func binaryOrTextResource(fileName string, data []byte, contentType string, base64Compression bool, resourceType v1.ResourceType) (v1.ResourceSpec, error) { +func binaryOrTextResource(fileName string, data []byte, contentType string, base64Compression bool, resourceType v1.ResourceType, destinationPath string) (v1.ResourceSpec, error) { resourceSpec := v1.ResourceSpec{ DataSpec: v1.DataSpec{ Name: fileName, + Path: destinationPath, ContentKey: fileName, ContentType: contentType, Compression: false, diff --git a/pkg/cmd/run_help_test.go b/pkg/cmd/run_help_test.go index 39d67f0..5eab301 100644 --- a/pkg/cmd/run_help_test.go +++ b/pkg/cmd/run_help_test.go @@ -28,6 +28,7 @@ func TestParseConfigOption(t *testing.T) { validSecret := "secret:my-secret" validFile := "file:/tmp/my-file.txt" notValid := "someprotocol:wrong" + validLocation := "file:my-file.txt@/tmp/another-name.xml" configmap, err := ParseConfigOption(validConfigMap) assert.Nil(t, err) @@ -43,4 +44,9 @@ func TestParseConfigOption(t *testing.T) { assert.Equal(t, "/tmp/my-file.txt", file.Value) _, err = ParseConfigOption(notValid) assert.NotNil(t, err) + location, err := ParseConfigOption(validLocation) + assert.Nil(t, err) + assert.Equal(t, ConfigOptionTypeFile, location.ConfigType) + assert.Equal(t, "my-file.txt", location.Value) + assert.Equal(t, "/tmp/another-name.xml", location.DestinationPath()) } diff --git a/pkg/cmd/run_test.go b/pkg/cmd/run_test.go index 7d1f8cd..bae4c9d 100644 --- a/pkg/cmd/run_test.go +++ b/pkg/cmd/run_test.go @@ -487,7 +487,7 @@ func TestRunWithSavedValues(t *testing.T) { }*/ func TestRunBinaryResource(t *testing.T) { - binaryResourceSpec, err := binaryOrTextResource("file.ext", []byte{1, 2, 3, 4}, "application/octet-stream", false, v1.ResourceTypeData) + binaryResourceSpec, err := binaryOrTextResource("file.ext", []byte{1, 2, 3, 4}, "application/octet-stream", false, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, "", binaryResourceSpec.Content) assert.NotNil(t, binaryResourceSpec.RawContent) @@ -499,7 +499,7 @@ func TestRunBinaryResource(t *testing.T) { func TestRunBinaryCompressedResource(t *testing.T) { data := []byte{1, 2, 3, 4} base64Compressed, _ := compressToString(data) - binaryResourceSpec, err := binaryOrTextResource("file.ext", data, "application/octet-stream", true, v1.ResourceTypeData) + binaryResourceSpec, err := binaryOrTextResource("file.ext", data, "application/octet-stream", true, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, base64Compressed, binaryResourceSpec.Content) assert.Nil(t, binaryResourceSpec.RawContent) @@ -509,7 +509,7 @@ func TestRunBinaryCompressedResource(t *testing.T) { } func TestRunTextResource(t *testing.T) { - textResourceSpec, err := binaryOrTextResource("file.ext", []byte("hello world"), "text/plain", false, v1.ResourceTypeData) + textResourceSpec, err := binaryOrTextResource("file.ext", []byte("hello world"), "text/plain", false, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, "hello world", textResourceSpec.Content) assert.Nil(t, textResourceSpec.RawContent) @@ -521,7 +521,7 @@ func TestRunTextResource(t *testing.T) { func TestRunTextCompressedResource(t *testing.T) { data := []byte("hello horld") base64Compressed, _ := compressToString(data) - textResourceSpec, err := binaryOrTextResource("file.ext", []byte("hello horld"), "text/plain", true, v1.ResourceTypeData) + textResourceSpec, err := binaryOrTextResource("file.ext", []byte("hello horld"), "text/plain", true, v1.ResourceTypeData, "") assert.Nil(t, err) assert.Equal(t, base64Compressed, textResourceSpec.Content) assert.Nil(t, textResourceSpec.RawContent) diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go index 2786f25..9049fe0 100644 --- a/pkg/trait/trait_types.go +++ b/pkg/trait/trait_types.go @@ -613,8 +613,7 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c refName := fmt.Sprintf("i-resource-%03d", i) resName := strings.TrimPrefix(r.Name, "/") cmKey := "content" - resourceMountPoint := getResourceMountPoint(r.Type) - resPath := path.Join(resourceMountPoint, resName) + resPath := getResourcePath(resName, r.Path, r.Type) if r.ContentRef != "" { cmName = r.ContentRef @@ -711,7 +710,7 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c *mnts = append(*mnts, corev1.VolumeMount{ Name: refName, - MountPath: path.Join(getConfigmapMountPoint(configmaps["resourceType"]), strings.ToLower(configmaps["value"])), + MountPath: getConfigmapMountPoint(configmaps["value"], configmaps["resourceMountPoint"], configmaps["resourceType"]), ReadOnly: true, }) } @@ -751,7 +750,7 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c *mnts = append(*mnts, corev1.VolumeMount{ Name: refName, - MountPath: path.Join(getSecretMountPoint(secret["resourceType"]), strings.ToLower(secret["value"])), + MountPath: getSecretMountPoint(secret["value"], secret["resourceMountPoint"], secret["resourceType"]), ReadOnly: true, }) } @@ -786,31 +785,44 @@ func (e *Environment) configureVolumesAndMounts(vols *[]corev1.Volume, mnts *[]c } } -func getResourceMountPoint(resourceType v1.ResourceType) string { +func getResourcePath(resourceName string, maybePath string, resourceType v1.ResourceType) string { + // If the path is specified, we'll return it + if maybePath != "" { + return maybePath + } + // otherwise return a default path, according to the resource type switch resourceType { case v1.ResourceTypeData: - return dataResourcesMountPath + return path.Join(dataResourcesMountPath, resourceName) } // Default, config type - return configResourcesMountPath + return path.Join(configResourcesMountPath, resourceName) } -func getConfigmapMountPoint(resourceType string) string { +func getConfigmapMountPoint(resourceName string, maybeMountPoint string, resourceType string) string { + // If the mount point is specified, we'll return it + if maybeMountPoint != "" { + return maybeMountPoint + } switch resourceType { case "data": - return dataConfigmapsMountPath + return path.Join(dataConfigmapsMountPath, resourceName) } // Default, config type - return configConfigmapsMountPath + return path.Join(configConfigmapsMountPath, resourceName) } -func getSecretMountPoint(resourceType string) string { +func getSecretMountPoint(resourceName string, maybeMountPoint string, resourceType string) string { + // If the mount point is specified, we'll return it + if maybeMountPoint != "" { + return maybeMountPoint + } switch resourceType { case "data": - return dataSecretsMountPath + return path.Join(dataSecretsMountPath, resourceName) } // Default, config type - return configSecretsMountPath + return path.Join(configSecretsMountPath, resourceName) } func (e *Environment) collectConfigurationValues(configurationType string) []string { diff --git a/pkg/trait/util.go b/pkg/trait/util.go index 4a2dc5d..0f5d936 100644 --- a/pkg/trait/util.go +++ b/pkg/trait/util.go @@ -97,6 +97,7 @@ func collectConfigurations(configurationType string, configurable ...v1.Configur var item = make(map[string]string) item["value"] = entry.Value item["resourceType"] = entry.ResourceType + item["resourceMountPoint"] = entry.ResourceMountPoint result = append(result, item) } }
