Skip to content

Commit

Permalink
feat: support for variable interpolation in workspace.* (in PipelineR…
Browse files Browse the repository at this point in the history
…un and TaskRun)

fix #7667

Support for variable interpolation in:

* spec.workspaces[].configMap.items[].*
* spec.workspaces[].secret.items[].*
* spec.workspaces[].projected.sources[].configMap.items[].*
* spec.workspaces[].projected.sources[].secret.items[].*
  • Loading branch information
l-qing committed Feb 22, 2024
1 parent 203c490 commit 325e973
Show file tree
Hide file tree
Showing 6 changed files with 368 additions and 97 deletions.
18 changes: 18 additions & 0 deletions docs/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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` |
Expand All @@ -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` |
66 changes: 53 additions & 13 deletions pkg/reconciler/pipelinerun/pipelinerun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4891,18 +4891,18 @@ 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
value: "v3"
taskRef:
name: ref-task
- name: c-task-matrixed
matrix:
matrix:
params:
- name: ref-p1
value: [v1, v2]
Expand Down Expand Up @@ -4981,7 +4981,7 @@ spec:
steps:
- name: s1
image: alpine
script: |
script: |
echo $(params.version)
`)}
prs := []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, `
Expand Down Expand Up @@ -5967,7 +5967,7 @@ spec:
serviceAccountName: test-sa-0
workspaces:
- name: ws-1
secret:
secret:
secretName: $(tasks.a-task.results.aResult)
`)},
expectedTr: mustParseTaskRunWithObjectMeta(t,
Expand Down Expand Up @@ -5997,7 +5997,7 @@ spec:
serviceAccountName: test-sa-0
workspaces:
- name: ws-1
projected:
projected:
sources:
- configMap:
name: $(tasks.a-task.results.aResult)
Expand All @@ -6012,10 +6012,10 @@ spec:
kind: Task
workspaces:
- name: s1
projected:
projected:
sources:
- configMap:
name: aResultValue
name: aResultValue
`),
},
{
Expand All @@ -6031,7 +6031,7 @@ spec:
serviceAccountName: test-sa-0
workspaces:
- name: ws-1
projected:
projected:
sources:
- secret:
name: $(tasks.a-task.results.aResult)
Expand All @@ -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
`),
},
{
Expand Down Expand Up @@ -6079,7 +6119,7 @@ spec:
workspaces:
- name: s1
csi:
driver: aResultValue
driver: aResultValue
`),
},
{
Expand Down Expand Up @@ -6110,7 +6150,7 @@ spec:
workspaces:
- name: s1
csi:
nodePublishSecretRef:
nodePublishSecretRef:
name: aResultValue
`),
},
Expand Down
59 changes: 3 additions & 56 deletions pkg/reconciler/pipelinerun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
30 changes: 2 additions & 28 deletions pkg/reconciler/taskrun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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
}

Expand Down
85 changes: 85 additions & 0 deletions pkg/workspace/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Loading

0 comments on commit 325e973

Please sign in to comment.