Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(trait): set env as configmaps/secrets #5754

Merged
merged 1 commit into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
})
}
}