camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nferr...@apache.org
Subject [camel-k] 01/03: Support for properties #62
Date Fri, 14 Sep 2018 07:27:43 GMT
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 3676bb5175a33b094a216d3b9bb8ddb8135f5129
Author: lburgazzoli <lburgazzoli@gmail.com>
AuthorDate: Thu Sep 13 16:07:28 2018 +0200

    Support for properties #62
---
 pkg/apis/camel/v1alpha1/types.go                   | 43 ++++++++++++----
 pkg/apis/camel/v1alpha1/types_support.go           |  2 +
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  5 ++
 pkg/client/cmd/context_create.go                   |  2 +-
 pkg/client/cmd/run.go                              | 43 ++++++++++------
 pkg/stub/action/integration/build.go               | 35 +++++++------
 pkg/stub/action/integration/deploy.go              | 58 ++++++++++++++++------
 pkg/stub/action/integration/util.go                | 56 +++++++++++++++++++++
 runtime/examples/props.js                          |  9 ++++
 .../java/org/apache/camel/k/jvm/Application.java   |  7 +++
 .../main/java/org/apache/camel/k/jvm/Routes.java   |  1 +
 11 files changed, 199 insertions(+), 62 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 72da35a..e59a3e6 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -23,6 +23,7 @@ import (
 
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
+// IntegrationList --
 type IntegrationList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata"`
@@ -31,6 +32,7 @@ type IntegrationList struct {
 
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
+// Integration --
 type Integration struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata"`
@@ -38,36 +40,49 @@ type Integration struct {
 	Status            IntegrationStatus `json:"status,omitempty"`
 }
 
+// IntegrationSpec --
 type IntegrationSpec struct {
-	Replicas     *int32     `json:"replicas,omitempty"`
-	Source       SourceSpec `json:"source,omitempty"`
-	Context      string     `json:"context,omitempty"`
-	Dependencies []string   `json:"dependencies,omitempty"`
+	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"`
 }
 
+// SourceSpec --
 type SourceSpec struct {
 	Name     string `json:"name,omitempty"`
 	Content  string `json:"content,omitempty"`
 	Language string `json:"language,omitempty"`
 }
 
+// IntegrationStatus --
 type IntegrationStatus struct {
 	Phase  IntegrationPhase `json:"phase,omitempty"`
 	Digest string           `json:"digest,omitempty"`
 	Image  string           `json:"image,omitempty"`
 }
 
+// IntegrationPhase --
 type IntegrationPhase string
 
 const (
-	IntegrationPhaseBuilding  IntegrationPhase = "Building"
+	// IntegrationKind --
+	IntegrationKind string = "Integration"
+
+	// IntegrationPhaseBuilding --
+	IntegrationPhaseBuilding IntegrationPhase = "Building"
+	// IntegrationPhaseDeploying --
 	IntegrationPhaseDeploying IntegrationPhase = "Deploying"
-	IntegrationPhaseRunning   IntegrationPhase = "Running"
-	IntegrationPhaseError     IntegrationPhase = "Error"
+	// IntegrationPhaseRunning --
+	IntegrationPhaseRunning IntegrationPhase = "Running"
+	// IntegrationPhaseError --
+	IntegrationPhaseError IntegrationPhase = "Error"
 )
 
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
+// IntegrationContextList --
 type IntegrationContextList struct {
 	metav1.TypeMeta `json:",inline"`
 	metav1.ListMeta `json:"metadata"`
@@ -76,6 +91,7 @@ type IntegrationContextList struct {
 
 // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
 
+// IntegrationContext --
 type IntegrationContext struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata"`
@@ -83,28 +99,33 @@ type IntegrationContext struct {
 	Status            IntegrationContextStatus `json:"status,omitempty"`
 }
 
+// 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
-	Value string
+	Name  string `json:"name"`
+	Value string `json:"value"`
 }
 
+// EnvironmentSpec --
 type EnvironmentSpec struct {
-	Name  string
-	Value string
+	Name  string `json:"name"`
+	Value string `json:"value"`
 }
 
+// IntegrationContextStatus --
 type IntegrationContextStatus struct {
 	Phase  IntegrationContextPhase `json:"phase,omitempty"`
 	Image  string                  `json:"image,omitempty"`
 	Digest string                  `json:"digest,omitempty"`
 }
 
+// IntegrationContextPhase --
 type IntegrationContextPhase string
 
 const (
diff --git a/pkg/apis/camel/v1alpha1/types_support.go b/pkg/apis/camel/v1alpha1/types_support.go
index fe93a18..b1cd02e 100644
--- a/pkg/apis/camel/v1alpha1/types_support.go
+++ b/pkg/apis/camel/v1alpha1/types_support.go
@@ -43,6 +43,7 @@ func (spec EnvironmentSpec) String() string {
 //
 // **********************************
 
+// NewIntegrationContext --
 func NewIntegrationContext(namespace string, name string) IntegrationContext {
 	return IntegrationContext{
 		TypeMeta: metav1.TypeMeta{
@@ -56,6 +57,7 @@ func NewIntegrationContext(namespace string, name string) IntegrationContext
{
 	}
 }
 
+// NewIntegrationContextList --
 func NewIntegrationContextList() IntegrationContextList {
 	return IntegrationContextList{
 		TypeMeta: metav1.TypeMeta{
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 826918a..1da7ad7 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -224,6 +224,11 @@ 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)
+	}
 	return
 }
 
diff --git a/pkg/client/cmd/context_create.go b/pkg/client/cmd/context_create.go
index de2c1a5..75b63d7 100644
--- a/pkg/client/cmd/context_create.go
+++ b/pkg/client/cmd/context_create.go
@@ -89,7 +89,7 @@ func (command *contextCreateCommand) run(cmd *cobra.Command, args []string)
erro
 	for _, item := range command.properties {
 		pair := strings.Split(item, "=")
 		if len(pair) == 2 {
-			ctx.Spec.Environment = append(ctx.Spec.Environment, v1alpha1.EnvironmentSpec{Name: pair[0],
Value: pair[1]})
+			ctx.Spec.Properties = append(ctx.Spec.Properties, v1alpha1.PropertySpec{Name: pair[0],
Value: pair[1]})
 		}
 	}
 
diff --git a/pkg/client/cmd/run.go b/pkg/client/cmd/run.go
index 312f49b..ff66631 100644
--- a/pkg/client/cmd/run.go
+++ b/pkg/client/cmd/run.go
@@ -34,17 +34,9 @@ import (
 	"k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-type RunCmdOptions struct {
-	*RootCmdOptions
-	IntegrationContext string
-	Language           string
-	IntegrationName    string
-	Dependencies       []string
-	Wait               bool
-}
-
+// NewCmdRun --
 func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
-	options := RunCmdOptions{
+	options := runCmdOptions{
 		RootCmdOptions: rootCmdOptions,
 	}
 
@@ -61,11 +53,22 @@ 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")
 
 	return &cmd
 }
 
-func (*RunCmdOptions) validateArgs(cmd *cobra.Command, args []string) error {
+type runCmdOptions struct {
+	*RootCmdOptions
+	IntegrationContext string
+	Language           string
+	IntegrationName    string
+	Dependencies       []string
+	Properties         []string
+	Wait               bool
+}
+
+func (*runCmdOptions) validateArgs(cmd *cobra.Command, args []string) error {
 	if len(args) != 1 {
 		return errors.New("accepts 1 arg, received " + strconv.Itoa(len(args)))
 	}
@@ -78,7 +81,7 @@ func (*RunCmdOptions) validateArgs(cmd *cobra.Command, args []string) error
{
 	return nil
 }
 
-func (o *RunCmdOptions) run(cmd *cobra.Command, args []string) error {
+func (o *runCmdOptions) run(cmd *cobra.Command, args []string) error {
 	integration, err := o.createIntegration(cmd, args)
 	if err != nil {
 		return err
@@ -92,7 +95,7 @@ func (o *RunCmdOptions) run(cmd *cobra.Command, args []string) error {
 	return nil
 }
 
-func (o *RunCmdOptions) waitForIntegrationReady(integration *v1alpha1.Integration) error
{
+func (o *runCmdOptions) waitForIntegrationReady(integration *v1alpha1.Integration) error
{
 	// Block this goroutine until the integration is in a final status
 	changes, err := watch.WatchStateChanges(o.Context, integration)
 	if err != nil {
@@ -130,7 +133,7 @@ watcher:
 	return nil
 }
 
-func (o *RunCmdOptions) createIntegration(cmd *cobra.Command, args []string) (*v1alpha1.Integration,
error) {
+func (o *runCmdOptions) createIntegration(cmd *cobra.Command, args []string) (*v1alpha1.Integration,
error) {
 	code, err := o.loadCode(args[0])
 	if err != nil {
 		return nil, err
@@ -157,7 +160,7 @@ func (o *RunCmdOptions) createIntegration(cmd *cobra.Command, args []string)
(*v
 
 	integration := v1alpha1.Integration{
 		TypeMeta: v1.TypeMeta{
-			Kind:       "Integration",
+			Kind:       v1alpha1.IntegrationKind,
 			APIVersion: v1alpha1.SchemeGroupVersion.String(),
 		},
 		ObjectMeta: v1.ObjectMeta{
@@ -175,6 +178,14 @@ func (o *RunCmdOptions) createIntegration(cmd *cobra.Command, args []string)
(*v
 		},
 	}
 
+	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]})
+		}
+	}
+
 	existed := false
 	err = sdk.Create(&integration)
 	if err != nil && k8serrors.IsAlreadyExists(err) {
@@ -200,7 +211,7 @@ func (o *RunCmdOptions) createIntegration(cmd *cobra.Command, args []string)
(*v
 	return &integration, nil
 }
 
-func (*RunCmdOptions) loadCode(fileName string) (string, error) {
+func (*runCmdOptions) loadCode(fileName string) (string, error) {
 	content, err := ioutil.ReadFile(fileName)
 	if err != nil {
 		return "", err
diff --git a/pkg/stub/action/integration/build.go b/pkg/stub/action/integration/build.go
index f98930e..ba24358 100644
--- a/pkg/stub/action/integration/build.go
+++ b/pkg/stub/action/integration/build.go
@@ -24,38 +24,37 @@ import (
 	"github.com/apache/camel-k/pkg/build"
 	"github.com/apache/camel-k/pkg/build/api"
 	"github.com/operator-framework/operator-sdk/pkg/sdk"
-	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
 
-type BuildAction struct {
-	buildManager *build.Manager
-}
-
+// NewBuildAction create an action that handles integration build
 func NewBuildAction(ctx context.Context, namespace string) IntegrationAction {
-	return &BuildAction{
+	return &buildAction{
 		buildManager: build.NewManager(ctx, namespace),
 	}
 }
 
-func (b *BuildAction) Name() string {
+type buildAction struct {
+	buildManager *build.Manager
+}
+
+func (action *buildAction) Name() string {
 	return "build"
 }
 
-func (b *BuildAction) CanHandle(integration *v1alpha1.Integration) bool {
+func (action *buildAction) CanHandle(integration *v1alpha1.Integration) bool {
 	return integration.Status.Phase == v1alpha1.IntegrationPhaseBuilding
 }
 
-func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
-	if integration.Spec.Context != "" {
-		name := integration.Spec.Context
-		ctx := v1alpha1.NewIntegrationContext(integration.Namespace, name)
+func (action *buildAction) Handle(integration *v1alpha1.Integration) error {
+	ctx, err := LookupContextForIntegration(integration)
+	if err != nil {
+		//TODO: we may need to add a wait strategy, i.e give up after some time
+		return err
+	}
 
-		if err := sdk.Get(&ctx); err != nil {
-			//TODO: we may need to add a wait strategy, i.e give up after some time
-			return errors.Wrapf(err, "unable to find integration context %s, %s", ctx.Name, err)
-		}
 
+	if ctx != nil {
 		if ctx.Status.Phase == v1alpha1.IntegrationContextPhaseReady {
 			target := integration.DeepCopy()
 			target.Status.Image = ctx.Status.Image
@@ -70,9 +69,9 @@ func (b *BuildAction) Handle(integration *v1alpha1.Integration) error {
 		Name:      integration.Name,
 		Qualifier: integration.Status.Digest,
 	}
-	buildResult := b.buildManager.Get(buildIdentifier)
+	buildResult := action.buildManager.Get(buildIdentifier)
 	if buildResult.Status == api.BuildStatusNotRequested {
-		b.buildManager.Start(api.BuildSource{
+		action.buildManager.Start(api.BuildSource{
 			Identifier: buildIdentifier,
 			Code: api.Code{
 				Name:     integration.Spec.Source.Name,
diff --git a/pkg/stub/action/integration/deploy.go b/pkg/stub/action/integration/deploy.go
index 3403928..9acd9d8 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -29,22 +29,23 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-type DeployAction struct {
+// NewDeployAction create an action that handles integration deploy
+func NewDeployAction() IntegrationAction {
+	return &deployAction{}
 }
 
-func NewDeployAction() IntegrationAction {
-	return &DeployAction{}
+type deployAction struct {
 }
 
-func (b *DeployAction) Name() string {
+func (action *deployAction) Name() string {
 	return "deploy"
 }
 
-func (a *DeployAction) CanHandle(integration *v1alpha1.Integration) bool {
+func (action *deployAction) CanHandle(integration *v1alpha1.Integration) bool {
 	return integration.Status.Phase == v1alpha1.IntegrationPhaseDeploying
 }
 
-func (a *DeployAction) Handle(integration *v1alpha1.Integration) error {
+func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
 	if err := createOrUpdateConfigMap(integration); err != nil {
 		return err
 	}
@@ -61,11 +62,20 @@ func (a *DeployAction) Handle(integration *v1alpha1.Integration) error
{
 //
 // **********************************
 
-func getConfigMapFor(integration *v1alpha1.Integration) *corev1.ConfigMap {
+func getConfigMapFor(integration *v1alpha1.Integration) (*corev1.ConfigMap, error) {
 	controller := true
 	blockOwnerDeletion := true
 
-	return &corev1.ConfigMap{
+	ctx, err := LookupContextForIntegration(integration)
+	if err != nil {
+		return nil, err
+	}
+
+	// combine properties of integration with context, integration
+	// properties have the priority
+	properties := CombinePropertiesAsMap(ctx, integration)
+
+	cm := corev1.ConfigMap{
 		TypeMeta: metav1.TypeMeta{
 			Kind:       "ConfigMap",
 			APIVersion: "v1",
@@ -91,14 +101,20 @@ func getConfigMapFor(integration *v1alpha1.Integration) *corev1.ConfigMap
{
 		},
 		Data: map[string]string{
 			"integration": integration.Spec.Source.Content,
+			"properties":  PropertiesString(properties),
 		},
 	}
+
+	return &cm, nil
 }
 
 func createOrUpdateConfigMap(integration *v1alpha1.Integration) error {
-	cm := getConfigMapFor(integration)
+	cm, err := getConfigMapFor(integration)
+	if err != nil {
+		return err
+	}
 
-	err := sdk.Create(cm)
+	err = sdk.Create(cm)
 	if err != nil && k8serrors.IsAlreadyExists(err) {
 		err = sdk.Update(cm)
 	}
@@ -115,7 +131,7 @@ func createOrUpdateConfigMap(integration *v1alpha1.Integration) error
{
 //
 // **********************************
 
-func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment {
+func getDeploymentFor(integration *v1alpha1.Integration) (*appsv1.Deployment, error) {
 	controller := true
 	blockOwnerDeletion := true
 	integrationName := strings.TrimPrefix(integration.Spec.Source.Name, "/")
@@ -160,7 +176,7 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment
{
 							Image: integration.Status.Image,
 							VolumeMounts: []corev1.VolumeMount{
 								{
-									Name:      "integration",
+									Name:      "integration-volume",
 									MountPath: "/etc/camel",
 								},
 							},
@@ -177,12 +193,16 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment
{
 									Name:  "CAMEL_K_ROUTES_LANGUAGE",
 									Value: integration.Spec.Source.Language,
 								},
+								{
+									Name:  "CAMEL_K_PROPERTIES",
+									Value: "file:/etc/camel/application.properties",
+								},
 							},
 						},
 					},
 					Volumes: []corev1.Volume{
 						{
-							Name: "integration",
+							Name: "integration-volume",
 							VolumeSource: corev1.VolumeSource{
 								ConfigMap: &corev1.ConfigMapVolumeSource{
 									LocalObjectReference: corev1.LocalObjectReference{
@@ -192,6 +212,9 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment
{
 										{
 											Key:  "integration",
 											Path: integrationName,
+										}, {
+											Key:  "properties",
+											Path: "application.properties",
 										},
 									},
 								},
@@ -203,13 +226,16 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment
{
 		},
 	}
 
-	return &deployment
+	return &deployment, nil
 }
 
 func createOrUpdateDeployment(integration *v1alpha1.Integration) error {
-	deployment := getDeploymentFor(integration)
+	deployment, err := getDeploymentFor(integration)
+	if err != nil {
+		return err
+	}
 
-	err := sdk.Create(deployment)
+	err = sdk.Create(deployment)
 	if err != nil && k8serrors.IsAlreadyExists(err) {
 		err = sdk.Update(deployment)
 	}
diff --git a/pkg/stub/action/integration/util.go b/pkg/stub/action/integration/util.go
new file mode 100644
index 0000000..339a996
--- /dev/null
+++ b/pkg/stub/action/integration/util.go
@@ -0,0 +1,56 @@
+package action
+
+import (
+	"fmt"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/operator-framework/operator-sdk/pkg/sdk"
+
+	"github.com/pkg/errors"
+)
+
+// LookupContextForIntegration --
+func LookupContextForIntegration(integration *v1alpha1.Integration) (*v1alpha1.IntegrationContext,
error) {
+	if integration.Spec.Context != "" {
+		name := integration.Spec.Context
+		ctx := v1alpha1.NewIntegrationContext(integration.Namespace, name)
+
+		if err := sdk.Get(&ctx); err != nil {
+			return nil, errors.Wrapf(err, "unable to find integration context %s, %s", ctx.Name, err)
+		}
+
+		return &ctx, nil
+	}
+
+	return nil, nil
+}
+
+// PropertiesString --
+func PropertiesString(m map[string]string) string {
+	properties := ""
+	for k, v := range m {
+		properties += fmt.Sprintf("%s=%s\n", k, v)
+	}
+
+	return properties
+}
+
+// CombinePropertiesAsMap --
+func CombinePropertiesAsMap(context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration)
map[string]string {
+	properties := 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
+		}
+	}
+
+	if integration != nil {
+		for _, p := range integration.Spec.Properties {
+			properties[p.Name] = p.Value
+		}
+	}
+
+	return properties
+}
diff --git a/runtime/examples/props.js b/runtime/examples/props.js
new file mode 100644
index 0000000..a89b6ae
--- /dev/null
+++ b/runtime/examples/props.js
@@ -0,0 +1,9 @@
+//
+// To run this integrations use:
+//
+//     kamel run -p my.message=test-props runtime/examples/props.js
+//
+
+from('timer:props?period=1s')
+    .routeId('props')
+    .log('{{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 bec284f..8a394ea 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
@@ -25,6 +25,7 @@ public class Application {
     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");
@@ -38,6 +39,12 @@ public class Application {
         }
 
         Main main = new Main();
+
+        // Load properties
+        if (ObjectHelper.isNotEmpty(properties)) {
+            main.setPropertyPlaceholderLocations(properties);
+        }
+
         main.addRouteBuilder(routes);
         main.run();
     }
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 b2c87d4..308b838 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,6 +27,7 @@ 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 SCHEME_CLASSPATH = "classpath:";
     public static final String SCHEME_FILE = "file:";
 


Mime
View raw message