From 6a4ff33555dd2d7a9498009f2e018182c600c463 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Fri, 14 Jun 2019 10:43:30 +0200 Subject: [PATCH] Add support for secret and configMap valueFrom and envFrom fields in templating Currently, we support template on the environment variables key, *but* not if the environment variable comes from a `ConfigMap` or a `Secret`. The following won't work. ``` env: - name: GOPATH value: /workspace - name: GITHUB_TOKEN valueFrom: secretKeyRef: name: ${inputs.params.github-token-secret} key: bot-token ``` This fixes that and add support for using variable interpolation on `valueFrom.secretKeyRef` and `valueFrom.configMapKeyRef`. This also adds variable interpolation on `envFrom`. Signed-off-by: Vincent Demeester --- docs/tasks.md | 41 +++++++++++- .../v1alpha1/taskrun/resources/apply.go | 19 ++++++ .../v1alpha1/taskrun/resources/apply_test.go | 65 +++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/docs/tasks.md b/docs/tasks.md index 8d27dac57fa..63988679096 100644 --- a/docs/tasks.md +++ b/docs/tasks.md @@ -401,7 +401,9 @@ Use these code snippets to help you understand how to define your `Tasks`. - [Example of image building and pushing](#example-task) - [Mounting extra volumes](#using-an-extra-volume) -- [Mounting configMap as volume source](#using-kubernetes-configmap-as-volume-source) +- [Mounting configMap as volume + source](#using-kubernetes-configmap-as-volume-source) +- [Using secret as environment source](#using-secret-as-environment-source) _Tip: See the collection of simple [examples](https://github.com/tektoncd/pipeline/tree/master/examples) for @@ -516,6 +518,43 @@ spec: name: "${inputs.params.CFGNAME}" ``` +#### Using secret as environment source + +```yaml +apiVersion: tekton.dev/v1alpha1 +kind: Task +metadata: + name: goreleaser +spec: + inputs: + params: + - name: package + description: base package to build in + - name: github-token-secret + description: name of the secret holding the github-token + default: github-token + resources: + - name: source + type: git + targetPath: src/${inputs.params.package} + steps: + - name: release + image: goreleaser/goreleaser + workingdir: /workspace/src/${inputs.params.package} + command: + - goreleaser + args: + - release + env: + - name: GOPATH + value: /workspace + - name: GITHUB_TOKEN + valueFrom: + secretKeyRef: + name: ${inputs.params.github-token-secret} + key: bot-token +``` + Except as otherwise noted, the content of this page is licensed under the [Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/), and code samples are licensed under the diff --git a/pkg/reconciler/v1alpha1/taskrun/resources/apply.go b/pkg/reconciler/v1alpha1/taskrun/resources/apply.go index 3f784224a26..33c2c91a144 100644 --- a/pkg/reconciler/v1alpha1/taskrun/resources/apply.go +++ b/pkg/reconciler/v1alpha1/taskrun/resources/apply.go @@ -67,6 +67,25 @@ func ApplyReplacements(spec *v1alpha1.TaskSpec, replacements map[string]string) } for ie, e := range steps[i].Env { steps[i].Env[ie].Value = templating.ApplyReplacements(e.Value, replacements) + if steps[i].Env[ie].ValueFrom != nil { + if e.ValueFrom.SecretKeyRef != nil { + steps[i].Env[ie].ValueFrom.SecretKeyRef.LocalObjectReference.Name = templating.ApplyReplacements(e.ValueFrom.SecretKeyRef.LocalObjectReference.Name, replacements) + steps[i].Env[ie].ValueFrom.SecretKeyRef.Key = templating.ApplyReplacements(e.ValueFrom.SecretKeyRef.Key, replacements) + } + if e.ValueFrom.ConfigMapKeyRef != nil { + steps[i].Env[ie].ValueFrom.ConfigMapKeyRef.LocalObjectReference.Name = templating.ApplyReplacements(e.ValueFrom.ConfigMapKeyRef.LocalObjectReference.Name, replacements) + steps[i].Env[ie].ValueFrom.ConfigMapKeyRef.Key = templating.ApplyReplacements(e.ValueFrom.ConfigMapKeyRef.Key, replacements) + } + } + } + for ie, e := range steps[i].EnvFrom { + steps[i].EnvFrom[ie].Prefix = templating.ApplyReplacements(e.Prefix, replacements) + if e.ConfigMapRef != nil { + steps[i].EnvFrom[ie].ConfigMapRef.LocalObjectReference.Name = templating.ApplyReplacements(e.ConfigMapRef.LocalObjectReference.Name, replacements) + } + if e.SecretRef != nil { + steps[i].EnvFrom[ie].SecretRef.LocalObjectReference.Name = templating.ApplyReplacements(e.SecretRef.LocalObjectReference.Name, replacements) + } } steps[i].WorkingDir = templating.ApplyReplacements(steps[i].WorkingDir, replacements) for ic, c := range steps[i].Command { diff --git a/pkg/reconciler/v1alpha1/taskrun/resources/apply_test.go b/pkg/reconciler/v1alpha1/taskrun/resources/apply_test.go index 66f1df3fa17..fc56b082fe9 100644 --- a/pkg/reconciler/v1alpha1/taskrun/resources/apply_test.go +++ b/pkg/reconciler/v1alpha1/taskrun/resources/apply_test.go @@ -41,6 +41,44 @@ var simpleTaskSpec = &v1alpha1.TaskSpec{ }}, } +var envTaskSpec = &v1alpha1.TaskSpec{ + Steps: []corev1.Container{{ + Name: "foo", + Image: "busybox:${inputs.params.FOO}", + Env: []corev1.EnvVar{{ + Name: "foo", + Value: "value-${inputs.params.FOO}", + }, { + Name: "bar", + ValueFrom: &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: "config-${inputs.params.FOO}"}, + Key: "config-key-${inputs.params.FOO}", + }, + }, + }, { + Name: "baz", + ValueFrom: &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + LocalObjectReference: corev1.LocalObjectReference{Name: "secret-${inputs.params.FOO}"}, + Key: "secret-key-${inputs.params.FOO}", + }, + }, + }}, + EnvFrom: []corev1.EnvFromSource{{ + Prefix: "prefix-0-${inputs.params.FOO}", + ConfigMapRef: &corev1.ConfigMapEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: "config-${inputs.params.FOO}"}, + }, + }, { + Prefix: "prefix-1-${inputs.params.FOO}", + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: "secret-${inputs.params.FOO}"}, + }, + }}, + }}, +} + var volumeMountTaskSpec = &v1alpha1.TaskSpec{ Steps: []corev1.Container{{ Name: "foo", @@ -183,6 +221,33 @@ func TestApplyParameters(t *testing.T) { spec.Steps[0].VolumeMounts[0].MountPath = "path/to/world" spec.Steps[0].Image = "busybox:world" }), + }, { + name: "envs parameter", + args: args{ + ts: envTaskSpec, + tr: &v1alpha1.TaskRun{ + Spec: v1alpha1.TaskRunSpec{ + Inputs: v1alpha1.TaskRunInputs{ + Params: []v1alpha1.Param{{ + Name: "FOO", + Value: "world", + }}, + }, + }, + }, + }, + want: applyMutation(envTaskSpec, func(spec *v1alpha1.TaskSpec) { + spec.Steps[0].Env[0].Value = "value-world" + spec.Steps[0].Env[1].ValueFrom.ConfigMapKeyRef.LocalObjectReference.Name = "config-world" + spec.Steps[0].Env[1].ValueFrom.ConfigMapKeyRef.Key = "config-key-world" + spec.Steps[0].Env[2].ValueFrom.SecretKeyRef.LocalObjectReference.Name = "secret-world" + spec.Steps[0].Env[2].ValueFrom.SecretKeyRef.Key = "secret-key-world" + spec.Steps[0].EnvFrom[0].Prefix = "prefix-0-world" + spec.Steps[0].EnvFrom[0].ConfigMapRef.LocalObjectReference.Name = "config-world" + spec.Steps[0].EnvFrom[1].Prefix = "prefix-1-world" + spec.Steps[0].EnvFrom[1].SecretRef.LocalObjectReference.Name = "secret-world" + spec.Steps[0].Image = "busybox:world" + }), }, { name: "with default parameter", args: args{