Skip to content

Commit

Permalink
feat(trait): set env as configmaps/secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
squakez committed Aug 13, 2024
1 parent e039e22 commit 6a180d7
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 39 deletions.
6 changes: 2 additions & 4 deletions addons/vault/aws/aws_secrets_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ limitations under the License.
package aws

import (
"regexp"
"strconv"

"github.com/apache/camel-k/v2/pkg/util/kubernetes"
Expand Down Expand Up @@ -105,7 +104,6 @@ func (t *awsSecretsManagerTrait) Configure(environment *trait.Environment) (bool
}

func (t *awsSecretsManagerTrait) Apply(environment *trait.Environment) error {
rex := regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
if environment.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
util.StringSliceUniqueAdd(&environment.Integration.Status.Capabilities, v1.CapabilityAwsSecretsManager)
}
Expand All @@ -114,7 +112,7 @@ func (t *awsSecretsManagerTrait) Apply(environment *trait.Environment) error {
return nil
}

hits := rex.FindAllStringSubmatch(t.AccessKey, -1)
hits := v1.PlainConfigSecretRegexp.FindAllStringSubmatch(t.AccessKey, -1)
if len(hits) >= 1 {
var res, _ = v1.DecodeValueSource(t.AccessKey, "aws-access-key", "The access Key provided is not valid")
if secretValue, err := kubernetes.ResolveValueSource(environment.Ctx, environment.Client, environment.Platform.Namespace, &res); err != nil {
Expand All @@ -125,7 +123,7 @@ func (t *awsSecretsManagerTrait) Apply(environment *trait.Environment) error {
} else {
environment.ApplicationProperties["camel.vault.aws.accessKey"] = t.AccessKey
}
hits = rex.FindAllStringSubmatch(t.SecretKey, -1)
hits = v1.PlainConfigSecretRegexp.FindAllStringSubmatch(t.SecretKey, -1)
if len(hits) >= 1 {
var res, _ = v1.DecodeValueSource(t.SecretKey, "aws-secret-key", "The secret Key provided is not valid")
if secretValue, err := kubernetes.ResolveValueSource(environment.Ctx, environment.Client, environment.Platform.Namespace, &res); err != nil {
Expand Down
9 changes: 2 additions & 7 deletions addons/vault/azure/azure_key_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ limitations under the License.
package azure

import (
"regexp"
"strconv"

"github.com/apache/camel-k/v2/pkg/util/kubernetes"
Expand Down Expand Up @@ -81,10 +80,6 @@ type Trait struct {
BlobContainerName string `property:"blob-container-name" json:"blobContainerName,omitempty"`
}

var (
azureKeyValueRex = regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
)

type azureKeyVaultTrait struct {
trait.BaseTrait
Trait `property:",squash"`
Expand Down Expand Up @@ -130,7 +125,7 @@ func (t *azureKeyVaultTrait) Apply(environment *trait.Environment) error {
return nil
}

hits := azureKeyValueRex.FindAllStringSubmatch(t.ClientSecret, -1)
hits := v1.PlainConfigSecretRegexp.FindAllStringSubmatch(t.ClientSecret, -1)
if len(hits) >= 1 {
var res, _ = v1.DecodeValueSource(t.ClientSecret, "azure-key-vault-client-secret", "The Azure Key Vault Client Secret provided is not valid")
if secretValue, err := kubernetes.ResolveValueSource(environment.Ctx, environment.Client, environment.Platform.Namespace, &res); err != nil {
Expand All @@ -141,7 +136,7 @@ func (t *azureKeyVaultTrait) Apply(environment *trait.Environment) error {
} else {
environment.ApplicationProperties["camel.vault.azure.clientSecret"] = t.ClientSecret
}
hits = azureKeyValueRex.FindAllStringSubmatch(t.BlobAccessKey, -1)
hits = v1.PlainConfigSecretRegexp.FindAllStringSubmatch(t.BlobAccessKey, -1)
if len(hits) >= 1 {
var res, _ = v1.DecodeValueSource(t.BlobAccessKey, "azure-storage-blob-access-key", "The Azure Storage Blob Access Key provided is not valid")
if secretValue, err := kubernetes.ResolveValueSource(environment.Ctx, environment.Client, environment.Platform.Namespace, &res); err != nil {
Expand Down
5 changes: 1 addition & 4 deletions addons/vault/hashicorp/hashicorp_vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ limitations under the License.
package hashicorp

import (
"regexp"

v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
"github.com/apache/camel-k/v2/pkg/trait"
Expand Down Expand Up @@ -81,7 +79,6 @@ func (t *hashicorpVaultTrait) Configure(environment *trait.Environment) (bool, *
}

func (t *hashicorpVaultTrait) Apply(environment *trait.Environment) error {
rex := regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
if environment.IntegrationInPhase(v1.IntegrationPhaseInitialization) {
util.StringSliceUniqueAdd(&environment.Integration.Status.Capabilities, v1.CapabilityHashicorpVault)
}
Expand All @@ -90,7 +87,7 @@ func (t *hashicorpVaultTrait) Apply(environment *trait.Environment) error {
return nil
}

hits := rex.FindAllStringSubmatch(t.Token, -1)
hits := v1.PlainConfigSecretRegexp.FindAllStringSubmatch(t.Token, -1)
if len(hits) >= 1 {
var res, _ = v1.DecodeValueSource(t.Token, "hashicorp-vault-token", "The Hashicorp Vault Token provided is not valid")

Expand Down
5 changes: 3 additions & 2 deletions docs/modules/ROOT/partials/apis/camel-k-crds.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6906,8 +6906,9 @@ Propagates the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap{vbar}secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
|===
Expand Down
5 changes: 3 additions & 2 deletions docs/modules/traits/pages/environment.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ The following configuration options are available:
| environment.vars
| []string
| A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap\|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.

|===

Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/camel/v1/common_types_support.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (
"github.com/imdario/mergo"
)

var PlainConfigSecretRegexp = regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)

func (in *Artifact) String() string {
return in.ID
}
Expand Down Expand Up @@ -224,8 +226,7 @@ func (bc *BuildConfiguration) IsEmpty() bool {
// DecodeValueSource returns a ValueSource object from an input that respects the format configmap|secret:resource-name[/path].
func DecodeValueSource(input string, defaultKey string, errorMessage string) (ValueSource, error) {
sub := make([]string, 0)
rex := regexp.MustCompile(`^(configmap|secret):([a-zA-Z0-9][a-zA-Z0-9-]*)(/([a-zA-Z0-9].*))?$`)
hits := rex.FindAllStringSubmatch(input, -1)
hits := PlainConfigSecretRegexp.FindAllStringSubmatch(input, -1)

for _, hit := range hits {
if len(hit) > 1 {
Expand Down
5 changes: 3 additions & 2 deletions pkg/apis/camel/v1/trait/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ type EnvironmentTrait struct {
// Propagates the `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY` environment variables (default `true`)
HTTPProxy *bool `property:"http-proxy" json:"httpProxy,omitempty"`
// A list of environment variables to be added to the integration container.
// The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
// These take precedence over the previously defined environment variables.
// The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
// and key represents the resource key to be mapped as and environment variable.
// These take precedence over any previously defined environment variables.
Vars []string `property:"vars" json:"vars,omitempty"`
}
Original file line number Diff line number Diff line change
Expand Up @@ -993,8 +993,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down Expand Up @@ -3091,8 +3092,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down Expand Up @@ -2848,8 +2849,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6884,8 +6884,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6955,8 +6955,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down
5 changes: 3 additions & 2 deletions pkg/resources/config/crd/bases/camel.apache.org_pipes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6953,8 +6953,9 @@ spec:
vars:
description: |-
A list of environment variables to be added to the integration container.
The syntax is KEY=VALUE, e.g., `MY_VAR="my value"`.
These take precedence over the previously defined environment variables.
The syntax is either VAR=VALUE or VAR=[configmap|secret]:name/key, where name represents the resource name,
and key represents the resource key to be mapped as and environment variable.
These take precedence over any previously defined environment variables.
items:
type: string
type: array
Expand Down
12 changes: 11 additions & 1 deletion pkg/trait/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"k8s.io/utils/ptr"

v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
traitv1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1/trait"
"github.com/apache/camel-k/v2/pkg/util/camel"
"github.com/apache/camel-k/v2/pkg/util/defaults"
Expand Down Expand Up @@ -102,7 +103,16 @@ func (t *environmentTrait) Apply(e *Environment) error {
if t.Vars != nil {
for _, env := range t.Vars {
k, v := property.SplitPropertyFileEntry(env)
envvar.SetVal(&e.EnvVars, k, v)
confs := v1.PlainConfigSecretRegexp.FindAllStringSubmatch(v, -1)
if len(confs) > 0 {
var res, err = v1.DecodeValueSource(v, "", "Invalid configuration "+v)
if err != nil {
return err
}
envvar.SetValFromValueSource(&e.EnvVars, k, res)
} else {
envvar.SetVal(&e.EnvVars, k, v)
}
}
}

Expand Down
40 changes: 40 additions & 0 deletions pkg/trait/environment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
package trait

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -192,6 +193,45 @@ func TestCustomEnvVars(t *testing.T) {
assert.True(t, userK2)
}

func TestValueSourceEnvVars(t *testing.T) {
c, err := camel.DefaultCatalog()
require.NoError(t, err)

env := mockEnvironment(c)
env.Integration.Spec.Traits = v1.Traits{
Environment: &traitv1.EnvironmentTrait{
Vars: []string{"MY_VAR_1=secret:my-sec/my-sec-value", "MY_VAR_2=configmap:my-cm/my-cm-value"},
},
}
env.Platform.ResyncStatusFullConfig()

conditions, err := NewEnvironmentTestCatalog().apply(&env)
require.NoError(t, err)
assert.NotEmpty(t, conditions)

userK1 := false
userK2 := false

env.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
fmt.Println(deployment.Spec.Template.Spec.Containers[0].Env)
for _, e := range deployment.Spec.Template.Spec.Containers[0].Env {
if e.Name == "MY_VAR_1" {
userK1 = e.Value == "" &&
e.ValueFrom.SecretKeyRef.Name == "my-sec" &&
e.ValueFrom.SecretKeyRef.Key == "my-sec-value"
}
if e.Name == "MY_VAR_2" {
userK2 = e.Value == "" &&
e.ValueFrom.ConfigMapKeyRef.Name == "my-cm" &&
e.ValueFrom.ConfigMapKeyRef.Key == "my-cm-value"
}
}
})

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

func NewEnvironmentTestCatalog() *Catalog {
return NewCatalog(nil)
}
Expand Down
29 changes: 28 additions & 1 deletion pkg/util/envvar/envvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ limitations under the License.

package envvar

import corev1 "k8s.io/api/core/v1"
import (
v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
corev1 "k8s.io/api/core/v1"
)

// Get --.
func Get(vars []corev1.EnvVar, name string) *corev1.EnvVar {
Expand Down Expand Up @@ -92,3 +95,27 @@ func SetValFrom(vars *[]corev1.EnvVar, name string, path string) {
})
}
}

// SetValFromValueSource --.
func SetValFromValueSource(vars *[]corev1.EnvVar, name string, vs v1.ValueSource) {
var envVarSource *corev1.EnvVarSource
if vs.SecretKeyRef != nil {
envVarSource = &corev1.EnvVarSource{
SecretKeyRef: vs.SecretKeyRef,
}
} else if vs.ConfigMapKeyRef != nil {
envVarSource = &corev1.EnvVarSource{
ConfigMapKeyRef: vs.ConfigMapKeyRef,
}
}

if envVar := Get(*vars, name); envVar != nil {
envVar.Value = ""
envVar.ValueFrom = envVarSource
} else {
*vars = append(*vars, corev1.EnvVar{
Name: name,
ValueFrom: envVarSource,
})
}
}

0 comments on commit 6a180d7

Please sign in to comment.