From b6478cf7ee6ee1f3a1057a960b9ad42bfb0edd30 Mon Sep 17 00:00:00 2001 From: qingliu Date: Thu, 15 Feb 2024 13:59:11 +0800 Subject: [PATCH] feat: support for variable interpolation in workspace.* (in PipelineRun and TaskRun) fix #7667 --- docs/variables.md | 66 ++++-- .../pipelinerun/pipelinerun_test.go | 66 ++++-- pkg/reconciler/pipelinerun/resources/apply.go | 59 +---- pkg/reconciler/taskrun/resources/apply.go | 30 +-- pkg/workspace/apply.go | 85 +++++++ pkg/workspace/apply_test.go | 207 ++++++++++++++++++ 6 files changed, 392 insertions(+), 121 deletions(-) diff --git a/docs/variables.md b/docs/variables.md index 49b7a68be3d..c7ef1c84662 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -85,22 +85,22 @@ For instructions on using variable substitutions see the relevant section of [th | `Task` | `spec.steps[].script` | | `Task` | `spec.steps[].onError` | | `Task` | `spec.steps[].env.value` | -| `Task` | `spec.steps[].env.valuefrom.secretkeyref.name` | -| `Task` | `spec.steps[].env.valuefrom.secretkeyref.key` | -| `Task` | `spec.steps[].env.valuefrom.configmapkeyref.name` | -| `Task` | `spec.steps[].env.valuefrom.configmapkeyref.key` | -| `Task` | `spec.steps[].volumemounts.name` | -| `Task` | `spec.steps[].volumemounts.mountpath` | -| `Task` | `spec.steps[].volumemounts.subpath` | +| `Task` | `spec.steps[].env.valueFrom.secretKeyRef.name` | +| `Task` | `spec.steps[].env.valueFrom.secretKeyRef.key` | +| `Task` | `spec.steps[].env.valueFrom.configMapKeyRef.name` | +| `Task` | `spec.steps[].env.valueFrom.configMapKeyRef.key` | +| `Task` | `spec.steps[].volumeMounts.name` | +| `Task` | `spec.steps[].volumeMounts.mountPath` | +| `Task` | `spec.steps[].volumeMounts.subPath` | | `Task` | `spec.volumes[].name` | -| `Task` | `spec.volumes[].configmap.name` | -| `Task` | `spec.volumes[].configmap.items[].key` | -| `Task` | `spec.volumes[].configmap.items[].path` | -| `Task` | `spec.volumes[].secret.secretname` | +| `Task` | `spec.volumes[].configMap.name` | +| `Task` | `spec.volumes[].configMap.items[].key` | +| `Task` | `spec.volumes[].configMap.items[].path` | +| `Task` | `spec.volumes[].secret.secretName` | | `Task` | `spec.volumes[].secret.items[].key` | | `Task` | `spec.volumes[].secret.items[].path` | -| `Task` | `spec.volumes[].persistentvolumeclaim.claimname` | -| `Task` | `spec.volumes[].projected.sources.configmap.name` | +| `Task` | `spec.volumes[].persistentVolumeClaim.claimName` | +| `Task` | `spec.volumes[].projected.sources.configMap.name` | | `Task` | `spec.volumes[].projected.sources.secret.name` | | `Task` | `spec.volumes[].projected.sources.serviceaccounttoken.audience` | | `Task` | `spec.volumes[].csi.nodepublishsecretref.name` | @@ -109,22 +109,31 @@ For instructions on using variable substitutions see the relevant section of [th | `Task` | `spec.sidecars[].image` | | `Task` | `spec.sidecars[].imagePullPolicy` | | `Task` | `spec.sidecars[].env.value` | -| `Task` | `spec.sidecars[].env.valuefrom.secretkeyref.name` | -| `Task` | `spec.sidecars[].env.valuefrom.secretkeyref.key` | -| `Task` | `spec.sidecars[].env.valuefrom.configmapkeyref.name` | -| `Task` | `spec.sidecars[].env.valuefrom.configmapkeyref.key` | -| `Task` | `spec.sidecars[].volumemounts.name` | -| `Task` | `spec.sidecars[].volumemounts.mountpath` | -| `Task` | `spec.sidecars[].volumemounts.subpath` | +| `Task` | `spec.sidecars[].env.valueFrom.secretKeyRef.name` | +| `Task` | `spec.sidecars[].env.valueFrom.secretKeyRef.key` | +| `Task` | `spec.sidecars[].env.valueFrom.configMapKeyRef.name` | +| `Task` | `spec.sidecars[].env.valueFrom.configMapKeyRef.key` | +| `Task` | `spec.sidecars[].volumeMounts.name` | +| `Task` | `spec.sidecars[].volumeMounts.mountPath` | +| `Task` | `spec.sidecars[].volumeMounts.subpath` | | `Task` | `spec.sidecars[].command` | | `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.name` | +| `TaskRun` | `spec.workspaces[].configMap.items[].key` | +| `TaskRun` | `spec.workspaces[].configMap.items[].path` | | `TaskRun` | `spec.workspaces[].secret.secretName` | -| `TaskRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `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.name` | +| `PipelineRun` | `spec.workspaces[].configMap.items[].key` | +| `PipelineRun` | `spec.workspaces[].configMap.items[].path` | | `PipelineRun` | `spec.workspaces[].secret.secretName` | -| `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `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..b44d4b1ce3e 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, ` @@ -5967,7 +5967,7 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - secret: + secret: secretName: $(tasks.a-task.results.aResult) `)}, expectedTr: mustParseTaskRunWithObjectMeta(t, @@ -5997,7 +5997,7 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - projected: + projected: sources: - configMap: name: $(tasks.a-task.results.aResult) @@ -6012,10 +6012,10 @@ spec: kind: Task workspaces: - name: s1 - projected: + projected: sources: - configMap: - name: aResultValue + name: aResultValue `), }, { @@ -6031,7 +6031,7 @@ spec: serviceAccountName: test-sa-0 workspaces: - name: ws-1 - projected: + projected: sources: - secret: name: $(tasks.a-task.results.aResult) @@ -6046,10 +6046,50 @@ spec: kind: Task workspaces: - name: s1 - projected: + projected: + sources: + - secret: + name: aResultValue +`), + }, + { + name: "projected.sources.secret.items success", + prs: []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` +metadata: + name: test-pipeline-run-different-service-accs + 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-different-service-accs-b-task", "foo", + "test-pipeline-run-different-service-accs", "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: name + items: + - key: aResultValue + path: aResultValue `), }, { @@ -6079,7 +6119,7 @@ spec: workspaces: - name: s1 csi: - driver: aResultValue + driver: aResultValue `), }, { @@ -6110,7 +6150,7 @@ spec: workspaces: - name: s1 csi: - nodePublishSecretRef: + nodePublishSecretRef: name: aResultValue `), }, 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)) + } + }) + } +}