[camel-k] branch master updated (3ba8d5b -> 99f8129)

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[camel-k] branch master updated (3ba8d5b -> 99f8129)

nferraro
This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git.


    from 3ba8d5b  Fix integration tests
     new 3676bb5  Support for properties #62
     new 1b89b01  Support for environment variables #65
     new 99f8129  Support for configmap and secrets #67

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 pkg/apis/camel/v1alpha1/types.go                   |  54 +++---
 pkg/apis/camel/v1alpha1/types_support.go           |  10 +-
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  40 ++---
 pkg/client/cmd/context_create.go                   |  42 +++--
 pkg/client/cmd/run.go                              |  63 +++++--
 pkg/stub/action/integration/build.go               |  35 ++--
 pkg/stub/action/integration/deploy.go              | 197 +++++++++++++++------
 pkg/stub/action/integration/util.go                | 106 +++++++++++
 pkg/util/digest/digest.go                          |  14 +-
 pkg/util/maven/types.go                            |   2 +-
 runtime/examples/props.js                          |   9 +
 .../java/org/apache/camel/k/jvm/Application.java   |  68 +++++++
 .../main/java/org/apache/camel/k/jvm/Routes.java   |   2 +
 13 files changed, 471 insertions(+), 171 deletions(-)
 create mode 100644 pkg/stub/action/integration/util.go
 create mode 100644 runtime/examples/props.js

Reply | Threaded
Open this post in threaded view
|

[camel-k] 01/03: Support for properties #62

nferraro
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 <[hidden email]>
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:";
 

Reply | Threaded
Open this post in threaded view
|

[camel-k] 02/03: Support for environment variables #65

nferraro
In reply to this post by nferraro
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 1b89b017365f76515561ecd788e91c4b2cbd320e
Author: lburgazzoli <[hidden email]>
AuthorDate: Thu Sep 13 18:25:55 2018 +0200

    Support for environment variables #65
---
 pkg/apis/camel/v1alpha1/types.go                 | 11 +++--
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go |  5 ++
 pkg/client/cmd/run.go                            |  9 ++++
 pkg/stub/action/integration/deploy.go            | 58 ++++++++++--------------
 pkg/stub/action/integration/util.go              | 32 +++++++++++++
 pkg/util/maven/types.go                          |  2 +-
 runtime/examples/env.js                          |  9 ++++
 7 files changed, 87 insertions(+), 39 deletions(-)

diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index e59a3e6..22fefe9 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -42,11 +42,12 @@ 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"`
+ 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 --
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index 1da7ad7..83af289 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -229,6 +229,11 @@ func (in *IntegrationSpec) DeepCopyInto(out *IntegrationSpec) {
  *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/run.go b/pkg/client/cmd/run.go
index ff66631..4af17df 100644
--- a/pkg/client/cmd/run.go
+++ b/pkg/client/cmd/run.go
@@ -54,6 +54,7 @@ func NewCmdRun(rootCmdOptions *RootCmdOptions) *cobra.Command {
  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
 }
@@ -65,6 +66,7 @@ type runCmdOptions struct {
  IntegrationName    string
  Dependencies       []string
  Properties         []string
+ Environment        []string
  Wait               bool
 }
 
@@ -185,6 +187,13 @@ func (o *runCmdOptions) createIntegration(cmd *cobra.Command, args []string) (*v
  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)
diff --git a/pkg/stub/action/integration/deploy.go b/pkg/stub/action/integration/deploy.go
index 9acd9d8..551a267 100644
--- a/pkg/stub/action/integration/deploy.go
+++ b/pkg/stub/action/integration/deploy.go
@@ -46,10 +46,14 @@ func (action *deployAction) CanHandle(integration *v1alpha1.Integration) bool {
 }
 
 func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
- if err := createOrUpdateConfigMap(integration); err != nil {
+ 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
  }
 
@@ -62,15 +66,10 @@ func (action *deployAction) Handle(integration *v1alpha1.Integration) error {
 //
 // **********************************
 
-func getConfigMapFor(integration *v1alpha1.Integration) (*corev1.ConfigMap, error) {
+func getConfigMapFor(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) (*corev1.ConfigMap, error) {
  controller := true
  blockOwnerDeletion := true
 
- 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)
@@ -108,8 +107,8 @@ func getConfigMapFor(integration *v1alpha1.Integration) (*corev1.ConfigMap, erro
  return &cm, nil
 }
 
-func createOrUpdateConfigMap(integration *v1alpha1.Integration) error {
- cm, err := getConfigMapFor(integration)
+func createOrUpdateConfigMap(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) error {
+ cm, err := getConfigMapFor(ctx, integration)
  if err != nil {
  return err
  }
@@ -131,10 +130,20 @@ func createOrUpdateConfigMap(integration *v1alpha1.Integration) error {
 //
 // **********************************
 
-func getDeploymentFor(integration *v1alpha1.Integration) (*appsv1.Deployment, error) {
+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,
@@ -174,30 +183,13 @@ func getDeploymentFor(integration *v1alpha1.Integration) (*appsv1.Deployment, er
  {
  Name:  integration.Name,
  Image: integration.Status.Image,
+ Env:   EnvironmentAsEnvVarSlice(environment),
  VolumeMounts: []corev1.VolumeMount{
  {
  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,
- },
- {
- Name:  "CAMEL_K_PROPERTIES",
- Value: "file:/etc/camel/application.properties",
- },
- },
  },
  },
  Volumes: []corev1.Volume{
@@ -211,7 +203,7 @@ func getDeploymentFor(integration *v1alpha1.Integration) (*appsv1.Deployment, er
  Items: []corev1.KeyToPath{
  {
  Key:  "integration",
- Path: integrationName,
+ Path: sourceName,
  }, {
  Key:  "properties",
  Path: "application.properties",
@@ -229,8 +221,8 @@ func getDeploymentFor(integration *v1alpha1.Integration) (*appsv1.Deployment, er
  return &deployment, nil
 }
 
-func createOrUpdateDeployment(integration *v1alpha1.Integration) error {
- deployment, err := getDeploymentFor(integration)
+func createOrUpdateDeployment(ctx *v1alpha1.IntegrationContext, integration *v1alpha1.Integration) error {
+ deployment, err := getDeploymentFor(ctx, integration)
  if err != nil {
  return err
  }
diff --git a/pkg/stub/action/integration/util.go b/pkg/stub/action/integration/util.go
index 339a996..96e9d1b 100644
--- a/pkg/stub/action/integration/util.go
+++ b/pkg/stub/action/integration/util.go
@@ -5,6 +5,7 @@ import (
 
  "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"
 )
@@ -35,6 +36,17 @@ func PropertiesString(m map[string]string) string {
  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)
@@ -54,3 +66,23 @@ func CombinePropertiesAsMap(context *v1alpha1.IntegrationContext, integration *v
 
  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

Reply | Threaded
Open this post in threaded view
|

[camel-k] 03/03: Support for configmap and secrets #67

nferraro
In reply to this post by nferraro
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 <[hidden email]>
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:";