This is an automated email from the ASF dual-hosted git repository. nferraro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 99f812954b8ec4c682034c69209f86c4fe9b5542 Author: lburgazzoli <lburgazz...@gmail.com> AuthorDate: Thu Sep 13 23:51:17 2018 +0200 Support for configmap and secrets #67 --- pkg/apis/camel/v1alpha1/types.go | 34 +++--- pkg/apis/camel/v1alpha1/types_support.go | 8 +- pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go | 46 ++------ pkg/client/cmd/context_create.go | 42 ++++--- pkg/client/cmd/run.go | 41 ++++--- pkg/stub/action/integration/deploy.go | 127 ++++++++++++++++----- pkg/stub/action/integration/util.go | 54 ++++++--- pkg/util/digest/digest.go | 14 ++- runtime/examples/env.js | 9 -- .../java/org/apache/camel/k/jvm/Application.java | 69 ++++++++++- .../main/java/org/apache/camel/k/jvm/Routes.java | 3 +- 11 files changed, 281 insertions(+), 166 deletions(-) diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go index 22fefe9..fd21328 100644 --- a/pkg/apis/camel/v1alpha1/types.go +++ b/pkg/apis/camel/v1alpha1/types.go @@ -21,6 +21,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +// ConfigurationSpec -- +type ConfigurationSpec struct { + Type string `json:"type"` + Value string `json:"value"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // IntegrationList -- @@ -42,12 +48,11 @@ type Integration struct { // IntegrationSpec -- type IntegrationSpec struct { - Replicas *int32 `json:"replicas,omitempty"` - Source SourceSpec `json:"source,omitempty"` - Context string `json:"context,omitempty"` - Dependencies []string `json:"dependencies,omitempty"` - Properties []PropertySpec `json:"properties,omitempty"` - Environment []EnvironmentSpec `json:"environment,omitempty"` + Replicas *int32 `json:"replicas,omitempty"` + Source SourceSpec `json:"source,omitempty"` + Context string `json:"context,omitempty"` + Dependencies []string `json:"dependencies,omitempty"` + Configuration []ConfigurationSpec `json:"configuration,omitempty"` } // SourceSpec -- @@ -102,21 +107,8 @@ type IntegrationContext struct { // IntegrationContextSpec -- type IntegrationContextSpec struct { - Dependencies []string `json:"dependencies,omitempty"` - Properties []PropertySpec `json:"properties,omitempty"` - Environment []EnvironmentSpec `json:"environment,omitempty"` -} - -// PropertySpec -- -type PropertySpec struct { - Name string `json:"name"` - Value string `json:"value"` -} - -// EnvironmentSpec -- -type EnvironmentSpec struct { - Name string `json:"name"` - Value string `json:"value"` + Dependencies []string `json:"dependencies,omitempty"` + Configuration []ConfigurationSpec `json:"configuration,omitempty"` } // IntegrationContextStatus -- diff --git a/pkg/apis/camel/v1alpha1/types_support.go b/pkg/apis/camel/v1alpha1/types_support.go index b1cd02e..b202aa3 100644 --- a/pkg/apis/camel/v1alpha1/types_support.go +++ b/pkg/apis/camel/v1alpha1/types_support.go @@ -29,12 +29,8 @@ import ( // // ********************************** -func (spec PropertySpec) String() string { - return fmt.Sprintf("%s=%s", spec.Name, spec.Value) -} - -func (spec EnvironmentSpec) String() string { - return fmt.Sprintf("%s=%s", spec.Name, spec.Value) +func (spec ConfigurationSpec) String() string { + return fmt.Sprintf("%s=%s", spec.Type, spec.Value) } // ********************************** diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go index 83af289..ec6db14 100644 --- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go @@ -26,17 +26,17 @@ import ( ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EnvironmentSpec) DeepCopyInto(out *EnvironmentSpec) { +func (in *ConfigurationSpec) DeepCopyInto(out *ConfigurationSpec) { *out = *in return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentSpec. -func (in *EnvironmentSpec) DeepCopy() *EnvironmentSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigurationSpec. +func (in *ConfigurationSpec) DeepCopy() *ConfigurationSpec { if in == nil { return nil } - out := new(EnvironmentSpec) + out := new(ConfigurationSpec) in.DeepCopyInto(out) return out } @@ -138,14 +138,9 @@ func (in *IntegrationContextSpec) DeepCopyInto(out *IntegrationContextSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.Properties != nil { - in, out := &in.Properties, &out.Properties - *out = make([]PropertySpec, len(*in)) - copy(*out, *in) - } - if in.Environment != nil { - in, out := &in.Environment, &out.Environment - *out = make([]EnvironmentSpec, len(*in)) + if in.Configuration != nil { + in, out := &in.Configuration, &out.Configuration + *out = make([]ConfigurationSpec, len(*in)) copy(*out, *in) } return @@ -224,14 +219,9 @@ func (in *IntegrationSpec) DeepCopyInto(out *IntegrationSpec) { *out = make([]string, len(*in)) copy(*out, *in) } - if in.Properties != nil { - in, out := &in.Properties, &out.Properties - *out = make([]PropertySpec, len(*in)) - copy(*out, *in) - } - if in.Environment != nil { - in, out := &in.Environment, &out.Environment - *out = make([]EnvironmentSpec, len(*in)) + if in.Configuration != nil { + in, out := &in.Configuration, &out.Configuration + *out = make([]ConfigurationSpec, len(*in)) copy(*out, *in) } return @@ -264,22 +254,6 @@ func (in *IntegrationStatus) DeepCopy() *IntegrationStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *PropertySpec) DeepCopyInto(out *PropertySpec) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PropertySpec. -func (in *PropertySpec) DeepCopy() *PropertySpec { - if in == nil { - return nil - } - out := new(PropertySpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SourceSpec) DeepCopyInto(out *SourceSpec) { *out = *in return diff --git a/pkg/client/cmd/context_create.go b/pkg/client/cmd/context_create.go index 75b63d7..49c3950 100644 --- a/pkg/client/cmd/context_create.go +++ b/pkg/client/cmd/context_create.go @@ -21,7 +21,6 @@ import ( "errors" "fmt" "strconv" - "strings" "github.com/operator-framework/operator-sdk/pkg/sdk" @@ -46,9 +45,10 @@ func newContextCreateCmd(rootCmdOptions *RootCmdOptions) *cobra.Command { RunE: impl.run, } - cmd.Flags().StringSliceVarP(&impl.env, "env", "e", nil, "Add an environment variable") - cmd.Flags().StringSliceVarP(&impl.properties, "property", "p", nil, "Add a system property") cmd.Flags().StringSliceVarP(&impl.dependencies, "dependency", "d", nil, "Add a dependency") + cmd.Flags().StringSliceVarP(&impl.properties, "property", "p", nil, "Add a camel property") + cmd.Flags().StringSliceVar(&impl.configmaps, "configmap", nil, "Add a ConfigMap") + cmd.Flags().StringSliceVar(&impl.secrets, "secret", nil, "Add a Secret") return &cmd } @@ -56,9 +56,10 @@ func newContextCreateCmd(rootCmdOptions *RootCmdOptions) *cobra.Command { type contextCreateCommand struct { *RootCmdOptions - env []string - properties []string dependencies []string + properties []string + configmaps []string + secrets []string } func (command *contextCreateCommand) validateArgs(cmd *cobra.Command, args []string) error { @@ -75,22 +76,27 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string) erro ctx := v1alpha1.NewIntegrationContext(namespace, name) ctx.Spec = v1alpha1.IntegrationContextSpec{ - Dependencies: command.dependencies, - Environment: make([]v1alpha1.EnvironmentSpec, 0), - Properties: make([]v1alpha1.PropertySpec, 0), + Dependencies: command.dependencies, + Configuration: make([]v1alpha1.ConfigurationSpec, 0), } - for _, item := range command.env { - pair := strings.Split(item, "=") - if len(pair) == 2 { - ctx.Spec.Environment = append(ctx.Spec.Environment, v1alpha1.EnvironmentSpec{Name: pair[0], Value: pair[1]}) - } - } for _, item := range command.properties { - pair := strings.Split(item, "=") - if len(pair) == 2 { - ctx.Spec.Properties = append(ctx.Spec.Properties, v1alpha1.PropertySpec{Name: pair[0], Value: pair[1]}) - } + ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "property", + Value: item, + }) + } + for _, item := range command.configmaps { + ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "configmap", + Value: item, + }) + } + for _, item := range command.secrets { + ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "secret", + Value: item, + }) } existed := false diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go index 4af17df..c4df815 100644 --- a/pkg/client/cmd/run.go +++ b/pkg/client/cmd/run.go @@ -53,8 +53,9 @@ func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command { cmd.Flags().StringSliceVarP(&options.Dependencies, "dependency", "d", nil, "The integration dependency") cmd.Flags().BoolVarP(&options.Wait, "wait", "w", false, "Waits for the integration to be running") cmd.Flags().StringVarP(&options.IntegrationContext, "context", "x", "", "The contex used to run the integration") - cmd.Flags().StringSliceVarP(&options.Properties, "property", "p", nil, "Add a system property") - cmd.Flags().StringSliceVarP(&options.Environment, "env", "e", nil, "Add an environment variable") + cmd.Flags().StringSliceVarP(&options.Properties, "property", "p", nil, "Add a camel property") + cmd.Flags().StringSliceVar(&options.ConfigMaps, "configmap", nil, "Add a ConfigMap") + cmd.Flags().StringSliceVar(&options.Secrets, "secret", nil, "Add a Secret") return &cmd } @@ -66,7 +67,8 @@ type runCmdOptions struct { IntegrationName string Dependencies []string Properties []string - Environment []string + ConfigMaps []string + Secrets []string Wait bool } @@ -175,24 +177,29 @@ func (o *runCmdOptions) createIntegration(cmd *cobra.Command, args []string) (*v Content: code, Language: o.Language, }, - Dependencies: o.Dependencies, - Context: o.IntegrationContext, + Dependencies: o.Dependencies, + Context: o.IntegrationContext, + Configuration: make([]v1alpha1.ConfigurationSpec, 0), }, } - integration.Spec.Properties = make([]v1alpha1.PropertySpec, 0) for _, item := range o.Properties { - pair := strings.Split(item, "=") - if len(pair) == 2 { - integration.Spec.Properties = append(integration.Spec.Properties, v1alpha1.PropertySpec{Name: pair[0], Value: pair[1]}) - } - } - integration.Spec.Environment = make([]v1alpha1.EnvironmentSpec, 0) - for _, item := range o.Environment { - pair := strings.Split(item, "=") - if len(pair) == 2 { - integration.Spec.Environment = append(integration.Spec.Environment, v1alpha1.EnvironmentSpec{Name: pair[0], Value: pair[1]}) - } + integration.Spec.Configuration = append(integration.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "property", + Value: item, + }) + } + for _, item := range o.ConfigMaps { + integration.Spec.Configuration = append(integration.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "configmap", + Value: item, + }) + } + for _, item := range o.Secrets { + integration.Spec.Configuration = append(integration.Spec.Configuration, v1alpha1.ConfigurationSpec{ + Type: "secret", + Value: item, + }) } existed := false diff --git a/pkg/stub/action/integration/deploy.go b/pkg/stub/action/integration/deploy.go index 551a267..8bc4b74 100644 --- a/pkg/stub/action/integration/deploy.go +++ b/pkg/stub/action/integration/deploy.go @@ -18,6 +18,7 @@ limitations under the License. package action import ( + "fmt" "strings" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" @@ -72,7 +73,7 @@ func getConfigMapFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Int // combine properties of integration with context, integration // properties have the priority - properties := CombinePropertiesAsMap(ctx, integration) + properties := CombineConfigurationAsMap("property", ctx, integration) cm := corev1.ConfigMap{ TypeMeta: metav1.TypeMeta{ @@ -137,13 +138,14 @@ func getDeploymentFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.In // combine environment of integration with context, integration // environment has the priority - environment := CombineEnvironmentAsMap(ctx, integration) + environment := CombineConfigurationAsMap("env", ctx, integration) // set env vars needed by the runtime environment["JAVA_MAIN_CLASS"] = "org.apache.camel.k.jvm.Application" - environment["CAMEL_K_ROUTES_URI"] = "file:/etc/camel/" + sourceName + environment["CAMEL_K_ROUTES_URI"] = "file:/etc/camel/conf/" + sourceName environment["CAMEL_K_ROUTES_LANGUAGE"] = integration.Spec.Source.Language - environment["CAMEL_K_PROPERTIES"] = "file:/etc/camel/application.properties" + environment["CAMEL_K_CONF"] = "/etc/camel/conf/application.properties" + environment["CAMEL_K_CONF_D"] = "/etc/camel/conf.d" labels := map[string]string{ "camel.apache.org/integration": integration.Name, @@ -184,40 +186,105 @@ func getDeploymentFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.In Name: integration.Name, Image: integration.Status.Image, Env: EnvironmentAsEnvVarSlice(environment), - VolumeMounts: []corev1.VolumeMount{ - { - Name: "integration-volume", - MountPath: "/etc/camel", - }, - }, }, }, - Volumes: []corev1.Volume{ - { - Name: "integration-volume", - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: integration.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: "integration", - Path: sourceName, - }, { - Key: "properties", - Path: "application.properties", - }, - }, - }, - }, - }, + }, + }, + }, + } + + // + // Volumes :: Setup + // + + vols := make([]corev1.Volume, 0) + mnts := make([]corev1.VolumeMount, 0) + cnt := 0 + + // + // Volumes :: Defaults + // + + vols = append(vols, corev1.Volume{ + Name: "integration", + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: integration.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: "integration", + Path: sourceName, + }, { + Key: "properties", + Path: "application.properties", }, }, }, }, + }) + + mnts = append(mnts, corev1.VolumeMount{ + Name: "integration", + MountPath: "/etc/camel/conf", + }) + + // + // Volumes :: Additional ConfigMaps + // + + cmList := CombineConfigurationAsSlice("configmap", ctx, integration) + for _, cmName := range cmList { + cnt++ + + vols = append(vols, corev1.Volume{ + Name: "integration-cm-" + cmName, + VolumeSource: corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: cmName, + }, + }, + }, + }) + + mnts = append(mnts, corev1.VolumeMount{ + Name: "integration-cm-" + cmName, + MountPath: fmt.Sprintf("/etc/camel/conf.d/%03d_%s", cnt, cmName), + }) + } + + // + // Volumes :: Additional Secrets + // + + secretList := CombineConfigurationAsSlice("secret", ctx, integration) + for _, secretName := range secretList { + cnt++ + + vols = append(vols, corev1.Volume{ + Name: "integration-secret-" + secretName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + }, + }, + }) + + mnts = append(mnts, corev1.VolumeMount{ + Name: "integration-secret-" + secretName, + MountPath: fmt.Sprintf("/etc/camel/conf.d/%03d_%s", cnt, secretName), + }) } + // + // Volumes + // + + deployment.Spec.Template.Spec.Volumes = vols + deployment.Spec.Template.Spec.Containers[0].VolumeMounts = mnts + return &deployment, nil } diff --git a/pkg/stub/action/integration/util.go b/pkg/stub/action/integration/util.go index 96e9d1b..8021809 100644 --- a/pkg/stub/action/integration/util.go +++ b/pkg/stub/action/integration/util.go @@ -2,6 +2,7 @@ package action import ( "fmt" + "strings" "github.com/apache/camel-k/pkg/apis/camel/v1alpha1" "github.com/operator-framework/operator-sdk/pkg/sdk" @@ -47,42 +48,59 @@ func EnvironmentAsEnvVarSlice(m map[string]string) []v1.EnvVar { return env } -// CombinePropertiesAsMap -- -func CombinePropertiesAsMap(context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) map[string]string { - properties := make(map[string]string) +// CombineConfigurationAsMap -- +func CombineConfigurationAsMap(configurationType string, context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) map[string]string { + result := make(map[string]string) if context != nil { // Add context properties first so integrations can // override it - for _, p := range context.Spec.Properties { - properties[p.Name] = p.Value + for _, c := range context.Spec.Configuration { + if c.Type == configurationType { + pair := strings.Split(c.Value, "=") + if len(pair) == 2 { + result[pair[0]] = pair[1] + } + } } } if integration != nil { - for _, p := range integration.Spec.Properties { - properties[p.Name] = p.Value + for _, c := range integration.Spec.Configuration { + if c.Type == configurationType { + pair := strings.Split(c.Value, "=") + if len(pair) == 2 { + result[pair[0]] = pair[1] + } + } } } - return properties + return result } -// CombineEnvironmentAsMap -- -func CombineEnvironmentAsMap(context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) map[string]string { - environment := make(map[string]string) +// CombineConfigurationAsSlice -- +func CombineConfigurationAsSlice(configurationType string, context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) []string { + result := make(map[string]bool, 0) if context != nil { - // Add context environment first so integrations can + // Add context properties first so integrations can // override it - for _, p := range context.Spec.Environment { - environment[p.Name] = p.Value + for _, c := range context.Spec.Configuration { + if c.Type == configurationType { + result[c.Value] = true + } } } - if integration != nil { - for _, p := range integration.Spec.Environment { - environment[p.Name] = p.Value + for _, c := range integration.Spec.Configuration { + if c.Type == configurationType { + result[c.Value] = true } } - return environment + keys := make([]string, 0, len(result)) + for k := range result { + keys = append(keys, k) + } + + return keys } diff --git a/pkg/util/digest/digest.go b/pkg/util/digest/digest.go index 103a6f1..265c664 100644 --- a/pkg/util/digest/digest.go +++ b/pkg/util/digest/digest.go @@ -44,6 +44,10 @@ func ComputeForIntegration(integration *v1alpha1.Integration) string { for _, item := range integration.Spec.Dependencies { hash.Write([]byte(item)) } + // Integration configuration + for _, item := range integration.Spec.Configuration { + hash.Write([]byte(item.String())) + } // Add a letter at the beginning and use URL safe encoding return "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil)) @@ -51,18 +55,15 @@ func ComputeForIntegration(integration *v1alpha1.Integration) string { // ComputeForIntegrationContext a digest of the fields that are relevant for the deployment // Produces a digest that can be used as docker image tag -func ComputeForIntegrationContext(integration *v1alpha1.IntegrationContext) string { +func ComputeForIntegrationContext(context *v1alpha1.IntegrationContext) string { hash := sha256.New() // Operator version is relevant hash.Write([]byte(version.Version)) - for _, item := range integration.Spec.Dependencies { + for _, item := range context.Spec.Dependencies { hash.Write([]byte(item)) } - for _, item := range integration.Spec.Environment { - hash.Write([]byte(item.String())) - } - for _, item := range integration.Spec.Properties { + for _, item := range context.Spec.Configuration { hash.Write([]byte(item.String())) } @@ -70,6 +71,7 @@ func ComputeForIntegrationContext(integration *v1alpha1.IntegrationContext) stri return "v" + base64.RawURLEncoding.EncodeToString(hash.Sum(nil)) } +// Random -- func Random() string { return "v" + strconv.FormatInt(rand.Int63(), 10) } diff --git a/runtime/examples/env.js b/runtime/examples/env.js deleted file mode 100644 index 8e26f8e..0000000 --- a/runtime/examples/env.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// To run this integrations use: -// -// kamel run -e MY_MESSAGE=test-env runtime/examples/env.js -// - -from('timer:env?period=1s') - .routeId('env') - .log('{{env:MY_MESSAGE}}') \ No newline at end of file diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java index 8a394ea..1575131 100644 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Application.java @@ -16,21 +16,37 @@ */ package org.apache.camel.k.jvm; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + import org.apache.camel.builder.RouteBuilder; import org.apache.camel.main.Main; import org.apache.camel.util.ObjectHelper; +import org.apache.commons.io.FilenameUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Application { + private static final Logger LOGGER = LoggerFactory.getLogger(Application.class); public static void main(String[] args) throws Exception { final String resource = System.getenv(Routes.ENV_CAMEL_K_ROUTES_URI); final String language = System.getenv(Routes.ENV_CAMEL_K_ROUTES_LANGUAGE); - final String properties = System.getenv(Routes.ENV_CAMEL_K_PROPERTIES); if (ObjectHelper.isEmpty(resource)) { throw new IllegalStateException("No valid resource found in " + Routes.ENV_CAMEL_K_ROUTES_URI + " environment variable"); } + String locations = computePropertyPlaceholderLocations(); RoutesLoader loader = Routes.loaderFor(resource, language); RouteBuilder routes = loader.load(resource); @@ -38,14 +54,59 @@ public class Application { throw new IllegalStateException("Unable to load route from: " + resource); } + LOGGER.info("Routes : {}", resource); + LOGGER.info("Language : {}", language); + LOGGER.info("Locations : {}", locations); + Main main = new Main(); - // Load properties - if (ObjectHelper.isNotEmpty(properties)) { - main.setPropertyPlaceholderLocations(properties); + if (ObjectHelper.isNotEmpty(locations)) { + main.setPropertyPlaceholderLocations(locations); } main.addRouteBuilder(routes); main.run(); } + + // ******************************* + // + // helpers + // + // ******************************* + + private static String computePropertyPlaceholderLocations() throws IOException { + final String conf = System.getenv(Routes.ENV_CAMEL_K_CONF); + final String confd = System.getenv(Routes.ENV_CAMEL_K_CONF_D); + final List<String> locations = new ArrayList<>(); + + // Main location + if (ObjectHelper.isNotEmpty(conf)) { + locations.add("file:" + conf); + } + + // Additional locations + if (ObjectHelper.isNotEmpty(confd)) { + Path root = Paths.get(confd); + FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Objects.requireNonNull(file); + Objects.requireNonNull(attrs); + + String path = file.toFile().getAbsolutePath(); + String ext = FilenameUtils.getExtension(path); + + if (Objects.equals("properties", ext)) { + locations.add("file:" + path); + } + + return FileVisitResult.CONTINUE; + } + }; + + Files.walkFileTree(root, visitor); + } + + return String.join(",", locations); + } } diff --git a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java index 308b838..03c91e4 100644 --- a/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java +++ b/runtime/jvm/src/main/java/org/apache/camel/k/jvm/Routes.java @@ -27,7 +27,8 @@ import org.apache.commons.lang3.StringUtils; public final class Routes { public static final String ENV_CAMEL_K_ROUTES_URI = "CAMEL_K_ROUTES_URI"; public static final String ENV_CAMEL_K_ROUTES_LANGUAGE = "CAMEL_K_ROUTES_LANGUAGE"; - public static final String ENV_CAMEL_K_PROPERTIES = "CAMEL_K_PROPERTIES"; + public static final String ENV_CAMEL_K_CONF = "CAMEL_K_CONF"; + public static final String ENV_CAMEL_K_CONF_D = "CAMEL_K_CONF_D"; public static final String SCHEME_CLASSPATH = "classpath:"; public static final String SCHEME_FILE = "file:";