diff --git a/docs/variables.md b/docs/variables.md index 8f606d6425b..df3dadd818f 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -120,11 +120,20 @@ For instructions on using variable substitutions see the relevant section of [th | `Task` | `spec.sidecars[].args` | | `Task` | `spec.sidecars[].script` | | `Task` | `spec.workspaces[].mountPath` | +| `TaskRun` | `spec.workspaces[].subPath` | | `TaskRun` | `spec.workspaces[].persistentVolumeClaim.claimName` | | `TaskRun` | `spec.workspaces[].configMap.name` | +| `TaskRun` | `spec.workspaces[].configMap.items[].key` | +| `TaskRun` | `spec.workspaces[].configMap.items[].path` | | `TaskRun` | `spec.workspaces[].secret.secretName` | +| `TaskRun` | `spec.workspaces[].secret.items[].key` | +| `TaskRun` | `spec.workspaces[].secret.items[].path` | | `TaskRun` | `spec.workspaces[].projected.sources[].secret.name` | +| `TaskRun` | `spec.workspaces[].projected.sources[].secret.items[].key` | +| `TaskRun` | `spec.workspaces[].projected.sources[].secret.items[].path` | | `TaskRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `TaskRun` | `spec.workspaces[].projected.sources[].configMap.items[].key` | +| `TaskRun` | `spec.workspaces[].projected.sources[].configMap.items[].path` | | `TaskRun` | `spec.workspaces[].csi.driver` | | `TaskRun` | `spec.workspaces[].csi.nodePublishSecretRef.name` | | `Pipeline` | `spec.tasks[].params[].value` | @@ -134,10 +143,19 @@ For instructions on using variable substitutions see the relevant section of [th | `Pipeline` | `spec.tasks[].when[].values` | | `Pipeline` | `spec.tasks[].workspaces[].subPath` | | `Pipeline` | `spec.tasks[].displayName` | +| `PipelineRun` | `spec.workspaces[].subPath` | | `PipelineRun` | `spec.workspaces[].persistentVolumeClaim.claimName` | | `PipelineRun` | `spec.workspaces[].configMap.name` | +| `PipelineRun` | `spec.workspaces[].configMap.items[].key` | +| `PipelineRun` | `spec.workspaces[].configMap.items[].path` | | `PipelineRun` | `spec.workspaces[].secret.secretName` | +| `PipelineRun` | `spec.workspaces[].secret.items[].key` | +| `PipelineRun` | `spec.workspaces[].secret.items[].path` | | `PipelineRun` | `spec.workspaces[].projected.sources[].secret.name` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].secret.items[].key` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].secret.items[].path` | | `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.items[].key` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.items[].path` | | `PipelineRun` | `spec.workspaces[].csi.driver` | | `PipelineRun` | `spec.workspaces[].csi.nodePublishSecretRef.name` | diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 837b7982607..32d0d57618f 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -4891,10 +4891,10 @@ spec: steps: - name: s1 image: alpine - script: | + script: | echo $(params.version) + $(params.tag) - name: b-task - params: + params: - name: ref-p1 value: $(params.version) - name: ref-p2 @@ -4902,7 +4902,7 @@ spec: taskRef: name: ref-task - name: c-task-matrixed - matrix: + matrix: params: - name: ref-p1 value: [v1, v2] @@ -4981,7 +4981,7 @@ spec: steps: - name: s1 image: alpine - script: | + script: | echo $(params.version) `)} prs := []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` @@ -5870,8 +5870,8 @@ spec: `), } trs := []*v1.TaskRun{mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-a-task-xxyyy", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "a-task", true), + taskRunObjectMeta("test-pipeline-run-variable-substitution-a-task-xxyyy", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "a-task", true), ` spec: serviceAccountName: test-sa @@ -5899,7 +5899,7 @@ status: name: "pcv success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -5913,8 +5913,8 @@ spec: `)}, disableAA: true, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -5930,7 +5930,7 @@ spec: name: "subPath success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -5942,8 +5942,8 @@ spec: subPath: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -5958,7 +5958,7 @@ spec: name: "secret.secretName success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -5967,12 +5967,12 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - secret: + secret: secretName: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -5988,7 +5988,7 @@ spec: name: "projected.sources.configMap.name success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -5997,14 +5997,14 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - projected: + projected: sources: - configMap: name: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -6012,17 +6012,17 @@ spec: kind: Task workspaces: - name: s1 - projected: + projected: sources: - configMap: - name: aResultValue + name: aResultValue `), }, { name: "projected.sources.secret.name success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -6031,14 +6031,51 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - projected: + projected: sources: - secret: name: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + projected: + sources: + - secret: + name: aResultValue +`), + }, + { + name: "projected.sources.secret.items success", + prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` +metadata: + name: test-pipeline-run-variable-substitution + namespace: foo +spec: + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa-0 + workspaces: + - name: ws-1 + projected: + sources: + - secret: + name: name + items: + - key: $(tasks.a-task.results.aResult) + path: $(tasks.a-task.results.aResult) +`)}, + expectedTr: mustParseTaskRunWithObjectMeta(t, + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -6046,17 +6083,20 @@ spec: kind: Task workspaces: - name: s1 - projected: + projected: sources: - secret: - name: aResultValue + name: name + items: + - key: aResultValue + path: aResultValue `), }, { name: "csi.driver success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -6069,8 +6109,8 @@ spec: driver: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -6079,14 +6119,14 @@ spec: workspaces: - name: s1 csi: - driver: aResultValue + driver: aResultValue `), }, { name: "nodePublishSecretRef.name success", prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` metadata: - name: test-pipeline-run-different-service-accs + name: test-pipeline-run-variable-substitution namespace: foo spec: pipelineRef: @@ -6100,8 +6140,8 @@ spec: name: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, - taskRunObjectMeta("test-pipeline-run-different-service-accs-b-task", "foo", - "test-pipeline-run-different-service-accs", "test-pipeline", "b-task", false), + taskRunObjectMeta("test-pipeline-run-variable-substitution-b-task", "foo", + "test-pipeline-run-variable-substitution", "test-pipeline", "b-task", false), `spec: serviceAccountName: test-sa-0 taskRef: @@ -6110,7 +6150,7 @@ spec: workspaces: - name: s1 csi: - nodePublishSecretRef: + nodePublishSecretRef: name: aResultValue `), }, @@ -6132,10 +6172,10 @@ spec: prt := newPipelineRunTest(t, d) defer prt.Cancel() - _, clients := prt.reconcileRun("foo", "test-pipeline-run-different-service-accs", []string{}, false) + _, clients := prt.reconcileRun("foo", "test-pipeline-run-variable-substitution", []string{}, false) // Check that the expected TaskRun was created actual, err := clients.Pipeline.TektonV1().TaskRuns("foo").List(prt.TestAssets.Ctx, metav1.ListOptions{ - LabelSelector: "tekton.dev/pipelineTask=b-task,tekton.dev/pipelineRun=test-pipeline-run-different-service-accs", + LabelSelector: "tekton.dev/pipelineTask=b-task,tekton.dev/pipelineRun=test-pipeline-run-variable-substitution", Limit: 1, }) diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index d0dae45cf79..e48d8e18d0a 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -26,6 +26,7 @@ import ( "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" "github.com/tektoncd/pipeline/pkg/reconciler/taskrun/resources" "github.com/tektoncd/pipeline/pkg/substitution" + "github.com/tektoncd/pipeline/pkg/workspace" ) const ( @@ -396,34 +397,7 @@ func ApplyResultsToWorkspaceBindings(trResults map[string][]v1.TaskRunResult, pr } } - for i, binding := range pr.Spec.Workspaces { - if pr.Spec.Workspaces[i].PersistentVolumeClaim != nil { - pr.Spec.Workspaces[i].PersistentVolumeClaim.ClaimName = substitution.ApplyReplacements(binding.PersistentVolumeClaim.ClaimName, stringReplacements) - } - pr.Spec.Workspaces[i].SubPath = substitution.ApplyReplacements(binding.SubPath, stringReplacements) - if pr.Spec.Workspaces[i].ConfigMap != nil { - pr.Spec.Workspaces[i].ConfigMap.Name = substitution.ApplyReplacements(binding.ConfigMap.Name, stringReplacements) - } - if pr.Spec.Workspaces[i].CSI != nil { - pr.Spec.Workspaces[i].CSI.Driver = substitution.ApplyReplacements(binding.CSI.Driver, stringReplacements) - if pr.Spec.Workspaces[i].CSI.NodePublishSecretRef != nil { - pr.Spec.Workspaces[i].CSI.NodePublishSecretRef.Name = substitution.ApplyReplacements(binding.CSI.NodePublishSecretRef.Name, stringReplacements) - } - } - if pr.Spec.Workspaces[i].Secret != nil { - pr.Spec.Workspaces[i].Secret.SecretName = substitution.ApplyReplacements(binding.Secret.SecretName, stringReplacements) - } - if pr.Spec.Workspaces[i].Projected != nil { - for j, source := range binding.Projected.Sources { - if pr.Spec.Workspaces[i].Projected.Sources[j].ConfigMap != nil { - pr.Spec.Workspaces[i].Projected.Sources[j].ConfigMap.Name = substitution.ApplyReplacements(source.ConfigMap.Name, stringReplacements) - } - if pr.Spec.Workspaces[i].Projected.Sources[j].Secret != nil { - pr.Spec.Workspaces[i].Projected.Sources[j].Secret.Name = substitution.ApplyReplacements(source.Secret.Name, stringReplacements) - } - } - } - } + pr.Spec.Workspaces = workspace.ReplaceWorkspaceBindingsVars(pr.Spec.Workspaces, stringReplacements) } // PropagateResults propagate the result of the completed task to the unfinished task that is not explicitly specify in the params @@ -605,32 +579,5 @@ func runResultValue(taskName string, resultName string, runResults map[string][] // placeholders in various binding types with values from provided parameters. func ApplyParametersToWorkspaceBindings(ctx context.Context, pr *v1.PipelineRun) { parameters, _, _ := paramsFromPipelineRun(ctx, pr) - for i, binding := range pr.Spec.Workspaces { - if pr.Spec.Workspaces[i].PersistentVolumeClaim != nil { - pr.Spec.Workspaces[i].PersistentVolumeClaim.ClaimName = substitution.ApplyReplacements(binding.PersistentVolumeClaim.ClaimName, parameters) - } - pr.Spec.Workspaces[i].SubPath = substitution.ApplyReplacements(binding.SubPath, parameters) - if pr.Spec.Workspaces[i].ConfigMap != nil { - pr.Spec.Workspaces[i].ConfigMap.Name = substitution.ApplyReplacements(binding.ConfigMap.Name, parameters) - } - if pr.Spec.Workspaces[i].Secret != nil { - pr.Spec.Workspaces[i].Secret.SecretName = substitution.ApplyReplacements(binding.Secret.SecretName, parameters) - } - if pr.Spec.Workspaces[i].CSI != nil { - pr.Spec.Workspaces[i].CSI.Driver = substitution.ApplyReplacements(binding.CSI.Driver, parameters) - if pr.Spec.Workspaces[i].CSI.NodePublishSecretRef != nil { - pr.Spec.Workspaces[i].CSI.NodePublishSecretRef.Name = substitution.ApplyReplacements(binding.CSI.NodePublishSecretRef.Name, parameters) - } - } - if pr.Spec.Workspaces[i].Projected != nil { - for j, source := range binding.Projected.Sources { - if pr.Spec.Workspaces[i].Projected.Sources[j].ConfigMap != nil { - pr.Spec.Workspaces[i].Projected.Sources[j].ConfigMap.Name = substitution.ApplyReplacements(source.ConfigMap.Name, parameters) - } - if pr.Spec.Workspaces[i].Projected.Sources[j].Secret != nil { - pr.Spec.Workspaces[i].Projected.Sources[j].Secret.Name = substitution.ApplyReplacements(source.Secret.Name, parameters) - } - } - } - } + pr.Spec.Workspaces = workspace.ReplaceWorkspaceBindingsVars(pr.Spec.Workspaces, parameters) } diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index 2283246b95e..b0d6d43b1d8 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -30,6 +30,7 @@ import ( "github.com/tektoncd/pipeline/pkg/internal/resultref" "github.com/tektoncd/pipeline/pkg/pod" "github.com/tektoncd/pipeline/pkg/substitution" + "github.com/tektoncd/pipeline/pkg/workspace" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" ) @@ -312,34 +313,7 @@ func ApplyWorkspaces(ctx context.Context, spec *v1.TaskSpec, declarations []v1.W func ApplyParametersToWorkspaceBindings(ts *v1.TaskSpec, tr *v1.TaskRun) *v1.TaskRun { tsCopy := ts.DeepCopy() parameters, _, _ := getTaskParameters(tsCopy, tr, tsCopy.Params...) - for i, binding := range tr.Spec.Workspaces { - if tr.Spec.Workspaces[i].PersistentVolumeClaim != nil { - tr.Spec.Workspaces[i].PersistentVolumeClaim.ClaimName = substitution.ApplyReplacements(binding.PersistentVolumeClaim.ClaimName, parameters) - } - tr.Spec.Workspaces[i].SubPath = substitution.ApplyReplacements(binding.SubPath, parameters) - if tr.Spec.Workspaces[i].ConfigMap != nil { - tr.Spec.Workspaces[i].ConfigMap.Name = substitution.ApplyReplacements(binding.ConfigMap.Name, parameters) - } - if tr.Spec.Workspaces[i].Secret != nil { - tr.Spec.Workspaces[i].Secret.SecretName = substitution.ApplyReplacements(binding.Secret.SecretName, parameters) - } - if tr.Spec.Workspaces[i].CSI != nil { - tr.Spec.Workspaces[i].CSI.Driver = substitution.ApplyReplacements(binding.CSI.Driver, parameters) - if tr.Spec.Workspaces[i].CSI.NodePublishSecretRef != nil { - tr.Spec.Workspaces[i].CSI.NodePublishSecretRef.Name = substitution.ApplyReplacements(binding.CSI.NodePublishSecretRef.Name, parameters) - } - } - if binding.Projected != nil { - for j, source := range binding.Projected.Sources { - if source.ConfigMap != nil { - tr.Spec.Workspaces[i].Projected.Sources[j].ConfigMap.Name = substitution.ApplyReplacements(source.ConfigMap.Name, parameters) - } - if source.Secret != nil { - tr.Spec.Workspaces[i].Projected.Sources[j].Secret.Name = substitution.ApplyReplacements(source.Secret.Name, parameters) - } - } - } - } + tr.Spec.Workspaces = workspace.ReplaceWorkspaceBindingsVars(tr.Spec.Workspaces, parameters) return tr } diff --git a/pkg/workspace/apply.go b/pkg/workspace/apply.go index 776888debee..993e0f1c9da 100644 --- a/pkg/workspace/apply.go +++ b/pkg/workspace/apply.go @@ -275,3 +275,88 @@ func FindWorkspacesUsedByTask(ts v1.TaskSpec) (sets.String, error) { } return workspacesUsedInSteps, nil } + +// ReplaceWorkspaceBindingsVars returns a new slice of WorkspaceBinding with references to parameters replaced, +// based on the mapping provided in replacements. +func ReplaceWorkspaceBindingsVars(wbs []v1.WorkspaceBinding, replacements map[string]string) []v1.WorkspaceBinding { + for i := range wbs { + replaceWorkspaceBindingVars(&wbs[i], replacements) + } + return wbs +} + +// replaceWorkspaceBindingVars returns a new WorkspaceBinding with references to parameters replaced, +// based on the mapping provided in replacements. +func replaceWorkspaceBindingVars(wb *v1.WorkspaceBinding, replacements map[string]string) *v1.WorkspaceBinding { + wb.SubPath = substitution.ApplyReplacements(wb.SubPath, replacements) + if wb.PersistentVolumeClaim != nil { + wb.PersistentVolumeClaim = applyPersistentVolumeClaimVolumeSource(wb.PersistentVolumeClaim, replacements) + } + if wb.ConfigMap != nil { + wb.ConfigMap = applyConfigMapVolumeSource(wb.ConfigMap, replacements) + } + if wb.Secret != nil { + wb.Secret = applySecretVolumeSource(wb.Secret, replacements) + } + if wb.Projected != nil { + for j, source := range wb.Projected.Sources { + if source.ConfigMap != nil { + wb.Projected.Sources[j].ConfigMap = applyConfigMapProjection(wb.Projected.Sources[j].ConfigMap, replacements) + } + if source.Secret != nil { + wb.Projected.Sources[j].Secret = applySecretProjection(wb.Projected.Sources[j].Secret, replacements) + } + } + } + if wb.CSI != nil { + wb.CSI = applyCSIVolumeSource(wb.CSI, replacements) + } + return wb +} + +func applyPersistentVolumeClaimVolumeSource(pvc *corev1.PersistentVolumeClaimVolumeSource, + replacements map[string]string) *corev1.PersistentVolumeClaimVolumeSource { + pvc.ClaimName = substitution.ApplyReplacements(pvc.ClaimName, replacements) + return pvc +} + +func applyConfigMapVolumeSource(cm *corev1.ConfigMapVolumeSource, replacements map[string]string) *corev1.ConfigMapVolumeSource { + cm.Name = substitution.ApplyReplacements(cm.Name, replacements) + cm.Items = applyKeyToPathItems(cm.Items, replacements) + return cm +} + +func applySecretVolumeSource(s *corev1.SecretVolumeSource, replacements map[string]string) *corev1.SecretVolumeSource { + s.SecretName = substitution.ApplyReplacements(s.SecretName, replacements) + s.Items = applyKeyToPathItems(s.Items, replacements) + return s +} + +func applyConfigMapProjection(cm *corev1.ConfigMapProjection, replacements map[string]string) *corev1.ConfigMapProjection { + cm.Name = substitution.ApplyReplacements(cm.Name, replacements) + cm.Items = applyKeyToPathItems(cm.Items, replacements) + return cm +} + +func applySecretProjection(s *corev1.SecretProjection, replacements map[string]string) *corev1.SecretProjection { + s.Name = substitution.ApplyReplacements(s.Name, replacements) + s.Items = applyKeyToPathItems(s.Items, replacements) + return s +} + +func applyCSIVolumeSource(csi *corev1.CSIVolumeSource, replacements map[string]string) *corev1.CSIVolumeSource { + csi.Driver = substitution.ApplyReplacements(csi.Driver, replacements) + if csi.NodePublishSecretRef != nil { + csi.NodePublishSecretRef.Name = substitution.ApplyReplacements(csi.NodePublishSecretRef.Name, replacements) + } + return csi +} + +func applyKeyToPathItems(items []corev1.KeyToPath, replacements map[string]string) []corev1.KeyToPath { + for i := range items { + item := &items[i] + item.Key = substitution.ApplyReplacements(item.Key, replacements) + item.Path = substitution.ApplyReplacements(item.Path, replacements) + } + return items +} diff --git a/pkg/workspace/apply_test.go b/pkg/workspace/apply_test.go index 7c0528d872c..8e64881ecca 100644 --- a/pkg/workspace/apply_test.go +++ b/pkg/workspace/apply_test.go @@ -1238,3 +1238,210 @@ func TestFindWorkspacesUsedByTask(t *testing.T) { }) } } + +func TestReplaceWorkspaceBindingsVars(t *testing.T) { + testCases := []struct { + name string + workspaceBindings []v1.WorkspaceBinding + replacements map[string]string + expected []v1.WorkspaceBinding + }{ + { + name: "No replacements", + replacements: nil, + workspaceBindings: []v1.WorkspaceBinding{ + {SubPath: "$(params.to-replace)"}, + }, + expected: []v1.WorkspaceBinding{ + {SubPath: "$(params.to-replace)"}, + }, + }, + { + name: "Replace SubPath", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + {SubPath: "$(params.to-replace)"}, + }, + expected: []v1.WorkspaceBinding{ + {SubPath: "replaced"}, + }, + }, + { + name: "Replace PersistentVolumeClaim", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(params.to-replace)", + }, + }, + }, + expected: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "replaced", + }, + }, + }, + }, + { + name: "Replace ConfigMap", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.to-replace)", + }, + Items: []corev1.KeyToPath{{ + Key: "$(params.to-replace)", + Path: "$(params.to-replace)", + }}, + }, + }, + }, + expected: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "replaced", + }, + Items: []corev1.KeyToPath{{ + Key: "replaced", + Path: "replaced", + }}, + }, + }, + }, + }, + { + name: "Replace Secret", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "$(params.to-replace)", + Items: []corev1.KeyToPath{{ + Key: "$(params.to-replace)", + Path: "$(params.to-replace)", + }}, + }, + }, + }, + expected: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "replaced", + Items: []corev1.KeyToPath{{ + Key: "replaced", + Path: "replaced", + }}, + }, + }, + }, + }, + { + name: "Replace Projected", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.to-replace)", + }, + Items: []corev1.KeyToPath{{ + Key: "$(params.to-replace)", + Path: "$(params.to-replace)", + }}, + }, + }, { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.to-replace)", + }, + Items: []corev1.KeyToPath{{ + Key: "$(params.to-replace)", + Path: "$(params.to-replace)", + }}, + }, + }}, + }, + }, + }, + expected: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{{ + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "replaced", + }, + Items: []corev1.KeyToPath{{ + Key: "replaced", + Path: "replaced", + }}, + }, + }, { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "replaced", + }, + Items: []corev1.KeyToPath{{ + Key: "replaced", + Path: "replaced", + }}, + }, + }}, + }, + }, + }, + }, + { + name: "Replace CSI", + replacements: map[string]string{ + "params.to-replace": "replaced", + }, + workspaceBindings: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "$(params.to-replace)", + NodePublishSecretRef: &corev1.LocalObjectReference{ + Name: "$(params.to-replace)", + }, + }, + }, + }, + expected: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "replaced", + NodePublishSecretRef: &corev1.LocalObjectReference{ + Name: "replaced", + }, + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := workspace.ReplaceWorkspaceBindingsVars(tc.workspaceBindings, tc.replacements) + if d := cmp.Diff(tc.expected, result); d != "" { + t.Errorf("Test case %q, diff: %s", tc.name, diff.PrintWantGot(d)) + } + }) + } +}