[GitHub] lburgazzoli closed pull request #66: Support for properties and env var

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[GitHub] lburgazzoli closed pull request #66: Support for properties and env var

GitBox
lburgazzoli closed pull request #66: Support for properties and env var
URL: https://github.com/apache/camel-k/pull/66
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 72da35a..22fefe9 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,50 @@ 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"`
+ Environment  []EnvironmentSpec `json:"environment,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 +92,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 +100,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..83af289 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -224,6 +224,16 @@ 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))
+ 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..4af17df 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,24 @@ 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")
 
  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
+ Environment        []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 +83,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 +97,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 +135,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 +162,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 +180,21 @@ 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]})
+ }
+ }
+ 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]})
+ }
+ }
+
  existed := false
  err = sdk.Create(&integration)
  if err != nil && k8serrors.IsAlreadyExists(err) {
@@ -200,7 +220,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..551a267 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -29,26 +29,31 @@ 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 {
- if err := createOrUpdateConfigMap(integration); err != nil {
+func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
+ ctx, err := LookupContextForIntegration(integration)
+ if err != nil {
  return err
  }
- if err := createOrUpdateDeployment(integration); err != nil {
+ if err = createOrUpdateConfigMap(ctx, integration); err != nil {
+ return err
+ }
+ if err = createOrUpdateDeployment(ctx, integration); err != nil {
  return err
  }
 
@@ -61,11 +66,15 @@ func (a *DeployAction) Handle(integration *v1alpha1.Integration) error {
 //
 // **********************************
 
-func getConfigMapFor(integration *v1alpha1.Integration) *corev1.ConfigMap {
+func getConfigMapFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) (*corev1.ConfigMap, error) {
  controller := true
  blockOwnerDeletion := true
 
- return &corev1.ConfigMap{
+ // 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 +100,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)
+func createOrUpdateConfigMap(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) error {
+ cm, err := getConfigMapFor(ctx, 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,10 +130,20 @@ func createOrUpdateConfigMap(integration *v1alpha1.Integration) error {
 //
 // **********************************
 
-func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment {
+func getDeploymentFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) (*appsv1.Deployment, error) {
  controller := true
  blockOwnerDeletion := true
- integrationName := strings.TrimPrefix(integration.Spec.Source.Name, "/")
+ sourceName := strings.TrimPrefix(integration.Spec.Source.Name, "/")
+
+ // combine environment of integration with context, integration
+ // environment has the priority
+ environment := CombineEnvironmentAsMap(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_LANGUAGE"] = integration.Spec.Source.Language
+ environment["CAMEL_K_PROPERTIES"] = "file:/etc/camel/application.properties"
 
  labels := map[string]string{
  "camel.apache.org/integration": integration.Name,
@@ -158,31 +183,18 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment {
  {
  Name:  integration.Name,
  Image: integration.Status.Image,
+ Env:   EnvironmentAsEnvVarSlice(environment),
  VolumeMounts: []corev1.VolumeMount{
  {
- Name:      "integration",
+ Name:      "integration-volume",
  MountPath: "/etc/camel",
  },
  },
- Env: []corev1.EnvVar{
- {
- Name:  "JAVA_MAIN_CLASS",
- Value: "org.apache.camel.k.jvm.Application",
- },
- {
- Name:  "CAMEL_K_ROUTES_URI",
- Value: "file:/etc/camel/" + integrationName,
- },
- {
- Name:  "CAMEL_K_ROUTES_LANGUAGE",
- Value: integration.Spec.Source.Language,
- },
- },
  },
  },
  Volumes: []corev1.Volume{
  {
- Name: "integration",
+ Name: "integration-volume",
  VolumeSource: corev1.VolumeSource{
  ConfigMap: &corev1.ConfigMapVolumeSource{
  LocalObjectReference: corev1.LocalObjectReference{
@@ -191,7 +203,10 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment {
  Items: []corev1.KeyToPath{
  {
  Key:  "integration",
- Path: integrationName,
+ Path: sourceName,
+ }, {
+ Key:  "properties",
+ Path: "application.properties",
  },
  },
  },
@@ -203,13 +218,16 @@ func getDeploymentFor(integration *v1alpha1.Integration) *appsv1.Deployment {
  },
  }
 
- return &deployment
+ return &deployment, nil
 }
 
-func createOrUpdateDeployment(integration *v1alpha1.Integration) error {
- deployment := getDeploymentFor(integration)
+func createOrUpdateDeployment(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) error {
+ deployment, err := getDeploymentFor(ctx, 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..96e9d1b
--- /dev/null
+++ b/pkg/stub/action/integration/util.go
@@ -0,0 +1,88 @@
+package action
+
+import (
+ "fmt"
+
+ "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+ "github.com/operator-framework/operator-sdk/pkg/sdk"
+ "k8s.io/api/core/v1"
+
+ "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
+}
+
+// EnvironmentAsEnvVarSlice --
+func EnvironmentAsEnvVarSlice(m map[string]string) []v1.EnvVar {
+ env := make([]v1.EnvVar, 0, len(m))
+
+ for k, v := range m {
+ env = append(env, v1.EnvVar{Name: k, Value: v})
+ }
+
+ return env
+}
+
+// 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
+}
+
+// CombineEnvironmentAsMap --
+func CombineEnvironmentAsMap(context *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) map[string]string {
+ environment := make(map[string]string)
+ if context != nil {
+ // Add context environment first so integrations can
+ // override it
+ for _, p := range context.Spec.Environment {
+ environment[p.Name] = p.Value
+ }
+ }
+
+ if integration != nil {
+ for _, p := range integration.Spec.Environment {
+ environment[p.Name] = p.Value
+ }
+ }
+
+ return environment
+}
diff --git a/pkg/util/maven/types.go b/pkg/util/maven/types.go
index 30a80de..5b1158e 100644
--- a/pkg/util/maven/types.go
+++ b/pkg/util/maven/types.go
@@ -25,7 +25,7 @@ type ProjectDefinition struct {
  Project     Project
  JavaSources map[string]string
  Resources   map[string]string
- Env         map[string]string
+ Env         map[string]string // TODO: should we deprecate it ? env are set on deployment
 }
 
 type Project struct {
diff --git a/runtime/examples/env.js b/runtime/examples/env.js
new file mode 100644
index 0000000..8e26f8e
--- /dev/null
+++ b/runtime/examples/env.js
@@ -0,0 +1,9 @@
+//
+// 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/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 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 static void main(String[] args) throws Exception {
         }
 
         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 @@
 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:";
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[hidden email]


With regards,
Apache Git Services