Skip to content

Commit

Permalink
feat(trait): environment variables
Browse files Browse the repository at this point in the history
Moved the logic to process environment variable to trait. It will simplify setting via annotations

Closes apache#2512
  • Loading branch information
squakez committed Sep 24, 2021
1 parent bb86ac5 commit f4743d6
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 103 deletions.
4 changes: 4 additions & 0 deletions docs/modules/traits/pages/environment.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ The following configuration options are available:
| bool
| Enables injection of `NAMESPACE` and `POD_NAME` environment variables (default `true`)

| environment.vars
| []string
| A list of variables to be created on the Pod. Must have KEY=VALUE syntax (ie, MY_VAR="my value").

|===

// End of autogenerated code - DO NOT EDIT! (configuration)
5 changes: 3 additions & 2 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ In this section you will find the most basic examples. Useful to start learning
| Type | Description | Link |
|---|---|---|
| Languages | Simple integrations developed in various supported languages | [see examples](./languages/)|
| Basic | Simple integrations with basic configuration | [see examples](./basic/)|
| Cron | How to create a `cront` integration | [see examples](./cron/)|
| User Config | Explore how to include a `property`, `secret`, `configmap` or file `resource` in your integration | [see examples](./user-config/)|
| Processor | Show how to include `Processor`s logic | [see examples](./processor/)|
Expand All @@ -20,7 +21,6 @@ In this section you will find the most basic examples. Useful to start learning

In this section you can find a few examples of certain [`Camel` components](https://camel.apache.org/components/latest/index.html). This is a limited number of the wide variety of components supported by Apache Camel. You can also find useful examples [in this repository](https://github.com/apache/camel-k-examples).


| Type | Description | Link |
|---|---|---|
| AMQP | Component usage | [see examples](./amqp/)|
Expand Down Expand Up @@ -50,4 +50,5 @@ Traits configuration will be very helpful to fine tune your `Integration`. Here

| Type | Description | Link |
|---|---|---|
| JVM | How to use `JVM` trait| [see examples](./traits/jvm/)|
| Container | How to customize with `container` trait| [see examples](./traits/container/)|
| JVM | How to use `jvm` trait| [see examples](./traits/jvm/)|
31 changes: 31 additions & 0 deletions examples/basic/Env.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// To run this integrations use:
//
// kamel run --env MY_ENV_VAR="hello world" Env.java --dev
//

import org.apache.camel.builder.RouteBuilder;

public class Env extends RouteBuilder {
@Override
public void configure() throws Exception {
from("timer:tick")
.log("${env:MY_ENV_VAR}");
}
}
3 changes: 3 additions & 0 deletions examples/basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Camel K basic examples

Find useful examples about how to run an integration in Camel K.
31 changes: 31 additions & 0 deletions examples/kamelets/kameletbindings/env-var-writer.kamelet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ---------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ---------------------------------------------------------------------------

apiVersion: camel.apache.org/v1alpha1
kind: Kamelet
metadata:
name: env-var-writer
spec:
definition:
title: "Log some env vars"
flow:
from:
uri: kamelet:source
steps:
- set-body:
simple: "${env:MY_ENV_VAR1} / ${env:MY_ENV_VAR2}"
- to: "log:bar"
22 changes: 14 additions & 8 deletions examples/kamelets/kameletbindings/kb-env-vars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@
# limitations under the License.
# ---------------------------------------------------------------------------

# Apply kamelet used in this binding
# kubectl apply -f env-var-writer.kamelet.yaml
#
# Apply kamelet binding
# kubect apply -f kb-env-vars.yaml
#
apiVersion: camel.apache.org/v1alpha1
kind: KameletBinding
metadata:
name: timer-to-log
namespace: default
annotations:
trait.camel.apache.org/environment.vars: "[\"MY_ENV_VAR1 = value1\", \"MY_ENV_VAR2 = value2\"]"
spec:
integration:
configuration:
- type: env
value: X=hello world!
sink:
uri: log:bar
source:
uri: timer:foo
uri: timer:foo
sink:
ref:
kind: Kamelet
apiVersion: camel.apache.org/v1alpha1
name: env-var-writer
2 changes: 1 addition & 1 deletion pkg/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ func (o *runCmdOptions) createOrUpdateIntegration(cmd *cobra.Command, c client.C
integration.Spec.AddConfiguration("volume", item)
}
for _, item := range o.EnvVars {
integration.Spec.AddConfiguration("env", item)
o.Traits = append(o.Traits, fmt.Sprintf("environment.vars=%s", item))
}

if err := o.configureTraits(integration, o.Traits, catalog); err != nil {
Expand Down
10 changes: 10 additions & 0 deletions pkg/trait/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package trait
import (
"github.com/apache/camel-k/pkg/util/defaults"
"github.com/apache/camel-k/pkg/util/envvar"
"github.com/apache/camel-k/pkg/util/property"
)

// The environment trait is used internally to inject standard environment variables in the integration container,
Expand All @@ -30,6 +31,8 @@ type environmentTrait struct {
BaseTrait `property:",squash"`
// Enables injection of `NAMESPACE` and `POD_NAME` environment variables (default `true`)
ContainerMeta *bool `property:"container-meta" json:"containerMeta,omitempty"`
// A list of variables to be created on the Pod. Must have KEY=VALUE syntax (ie, MY_VAR="my value").
Vars []string `property:"vars" json:"vars,omitempty"`
}

const (
Expand Down Expand Up @@ -78,6 +81,13 @@ func (t *environmentTrait) Apply(e *Environment) error {
envvar.SetValFrom(&e.EnvVars, envVarPodName, "metadata.name")
}

if t.Vars != nil {
for _, env := range t.Vars {
k, v := property.SplitPropertyFileEntry(env)
envvar.SetVal(&e.EnvVars, k, v)
}
}

return nil
}

Expand Down
169 changes: 77 additions & 92 deletions pkg/trait/environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,7 @@ func TestDefaultEnvironment(t *testing.T) {
catalog, err := camel.DefaultCatalog()
assert.Nil(t, err)

env := Environment{
CamelCatalog: catalog,
Catalog: NewCatalog(nil),
Integration: &v1.Integration{
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseDeploying,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileOpenShift,
},
},
IntegrationKit: &v1.IntegrationKit{
Status: v1.IntegrationKitStatus{
Phase: v1.IntegrationKitPhaseReady,
},
},
Platform: &v1.IntegrationPlatform{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
},
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
}
env := mockEnvironment(catalog)
env.Platform.ResyncStatusFullConfig()

err = NewEnvironmentTestCatalog().apply(&env)
Expand Down Expand Up @@ -107,38 +80,11 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) {
c, err := camel.DefaultCatalog()
assert.Nil(t, err)

env := Environment{
CamelCatalog: c,
Catalog: NewCatalog(nil),
Integration: &v1.Integration{
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseDeploying,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileOpenShift,
Traits: map[string]v1.TraitSpec{
"environment": test.TraitSpecFromMap(t, map[string]interface{}{
"containerMeta": true,
}),
},
},
},
IntegrationKit: &v1.IntegrationKit{
Status: v1.IntegrationKitStatus{
Phase: v1.IntegrationKitPhaseReady,
},
},
Platform: &v1.IntegrationPlatform{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
},
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
env := mockEnvironment(c)
env.Integration.Spec.Traits = map[string]v1.TraitSpec{
"environment": test.TraitSpecFromMap(t, map[string]interface{}{
"containerMeta": true,
}),
}
env.Platform.ResyncStatusFullConfig()

Expand Down Expand Up @@ -173,39 +119,13 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) {
c, err := camel.DefaultCatalog()
assert.Nil(t, err)

env := Environment{
CamelCatalog: c,
Catalog: NewCatalog(nil),
Integration: &v1.Integration{
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseDeploying,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileOpenShift,
Traits: map[string]v1.TraitSpec{
"environment": test.TraitSpecFromMap(t, map[string]interface{}{
"containerMeta": false,
}),
},
},
},
IntegrationKit: &v1.IntegrationKit{
Status: v1.IntegrationKitStatus{
Phase: v1.IntegrationKitPhaseReady,
},
},
Platform: &v1.IntegrationPlatform{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
},
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
env := mockEnvironment(c)
env.Integration.Spec.Traits = map[string]v1.TraitSpec{
"environment": test.TraitSpecFromMap(t, map[string]interface{}{
"containerMeta": false,
}),
}

env.Platform.ResyncStatusFullConfig()

err = NewEnvironmentTestCatalog().apply(&env)
Expand Down Expand Up @@ -235,6 +155,71 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) {
assert.True(t, ck)
}

func TestCustomEnvVars(t *testing.T) {
c, err := camel.DefaultCatalog()
assert.Nil(t, err)

env := mockEnvironment(c)
env.Integration.Spec.Traits = map[string]v1.TraitSpec{
"environment": test.TraitSpecFromMap(t, map[string]interface{}{
"vars": []string{"key1=val1", "key2 = val2"},
}),
}
env.Platform.ResyncStatusFullConfig()

err = NewEnvironmentTestCatalog().apply(&env)

assert.Nil(t, err)

userK1 := false
userK2 := false

env.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
for _, e := range deployment.Spec.Template.Spec.Containers[0].Env {
if e.Name == "key1" {
userK1 = e.Value == "val1"
}
if e.Name == "key2" {
userK2 = e.Value == "val2"
}
}
})

assert.True(t, userK1)
assert.True(t, userK2)
}

func NewEnvironmentTestCatalog() *Catalog {
return NewCatalog(nil)
}

func mockEnvironment(catalog *camel.RuntimeCatalog) Environment {
return Environment{
CamelCatalog: catalog,
Catalog: NewCatalog(nil),
Integration: &v1.Integration{
Status: v1.IntegrationStatus{
Phase: v1.IntegrationPhaseDeploying,
},
Spec: v1.IntegrationSpec{
Profile: v1.TraitProfileOpenShift,
},
},
IntegrationKit: &v1.IntegrationKit{
Status: v1.IntegrationKitStatus{
Phase: v1.IntegrationKitPhaseReady,
},
},
Platform: &v1.IntegrationPlatform{
ObjectMeta: metav1.ObjectMeta{
Namespace: "ns",
},
Spec: v1.IntegrationPlatformSpec{
Cluster: v1.IntegrationPlatformClusterOpenShift,
},
},
EnvVars: make([]corev1.EnvVar, 0),
ExecutedTraits: make([]Trait, 0),
Resources: kubernetes.NewCollection(),
}
}
4 changes: 4 additions & 0 deletions resources/traits.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ traits:
type: bool
description: Enables injection of `NAMESPACE` and `POD_NAME` environment variables
(default `true`)
- name: vars
type: '[]string'
description: A list of variables to be created on the Pod. Must have KEY=VALUE
syntax (ie, MY_VAR="my value").
- name: error-handler
platform: true
profiles:
Expand Down

0 comments on commit f4743d6

Please sign in to comment.