From 331e9394b66e5e3a0e3564248641127ae5e88d83 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:50:32 -0500 Subject: [PATCH 01/12] feat: add ApplyParametersToWorkspaceBindings and ApplyResultsToWorkspaceBindings methods --- pkg/reconciler/taskrun/resources/apply.go | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index 40fac760cc2..6ced9253ef1 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -223,6 +223,39 @@ func ApplyWorkspaces(ctx context.Context, spec *v1.TaskSpec, declarations []v1.W return ApplyReplacements(spec, stringReplacements, map[string][]string{}, map[string]map[string]string{}) } +// ApplyParametersToWorkspaceBindings applies parameters to the WorkspaceBindings of a TaskRun. It takes a TaskSpec and a TaskRun as input and returns the modified TaskRun. +func ApplyParametersToWorkspaceBindings(ts *v1.TaskSpec, tr *v1.TaskRun) *v1.TaskRun { + tsCopy := ts.DeepCopy() + var defaults []v1.ParamSpec + if len(tsCopy.Params) > 0 { + defaults = append(defaults, tsCopy.Params...) + } + parameters, _, _ := getTaskParameters(tsCopy, tr, tsCopy.Params...) + for i, binding := range tr.Spec.Workspaces { + if tr.Spec.Workspaces[i].PersistentVolumeClaim != nil { + binding.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 { + binding.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 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) + } + } + } + } + return tr +} + // applyWorkspaceMountPath accepts a workspace path variable of the form $(workspaces.foo.path) and replaces // it in the fields of the TaskSpec. A new updated TaskSpec is returned. Steps or Sidecars in the TaskSpec // that override the mountPath will receive that mountPath in place of the variable's value. Other Steps and From 21765c1d71fa38c8a6270c7d88f60afe9723a65d Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:52:10 -0500 Subject: [PATCH 02/12] feat: add ApplyParametersToWorkspaceBindings and tests for task run --- .../taskrun/resources/apply_test.go | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) diff --git a/pkg/reconciler/taskrun/resources/apply_test.go b/pkg/reconciler/taskrun/resources/apply_test.go index 32b825be1ad..1fcf0734e5d 100644 --- a/pkg/reconciler/taskrun/resources/apply_test.go +++ b/pkg/reconciler/taskrun/resources/apply_test.go @@ -1635,3 +1635,298 @@ func TestApplyCredentialsPath(t *testing.T) { }) } } + +func TestApplyParametersToWorkspaceBindings(t *testing.T) { + tests := []struct { + name string + ts *v1.TaskSpec + tr *v1.TaskRun + want *v1.TaskRun + }{ + { + name: "pvc", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "claim-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(params.claim-name)", + }, + }, + }, + Params: v1.Params{{Name: "claim-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "claim-value", + }}}, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "claim-value", + }, + }, + }, + Params: v1.Params{{Name: "claim-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "claim-value", + }}}, + }, + }, + }, + { + name: "subPath", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "subPath-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + SubPath: "$(params.subPath-name)", + }, + }, + Params: v1.Params{{Name: "subPath-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "subPath-value", + }}}, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + SubPath: "subPath-value", + }, + }, + Params: v1.Params{{Name: "subPath-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "subPath-value", + }}}, + }, + }, + }, + { + name: "configMap", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "configMap-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.configMap-name)", + }, + }, + }, + }, + Params: v1.Params{{Name: "configMap-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "configMap-value", + }}}, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "configMap-value", + }, + }, + }, + }, + Params: v1.Params{{Name: "configMap-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "configMap-value", + }}}, + }, + }, + }, + { + name: "secret", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "secret-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "$(params.secret-name)", + }, + }, + }, + Params: v1.Params{{Name: "secret-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "secret-value", + }}}, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "secret-value", + }, + }, + }, + Params: v1.Params{{Name: "secret-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "secret-value", + }}, + }, + }, + }, + }, + { + name: "projected-sources-configMap", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "proj-configMap-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.proj-configMap-name)", + }, + }, + }, + }, + }, + }, + }, + Params: v1.Params{ + { + Name: "proj-configMap-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "proj-configMap-value", + }, + }, + }, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "proj-configMap-value", + }, + }, + }, + }, + }, + }, + }, + Params: v1.Params{ + { + Name: "proj-configMap-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "proj-configMap-value", + }, + }, + }, + }, + }, + }, + { + name: "projected-sources-secret", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "proj-secret-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.proj-secret-name)", + }, + }, + }, + }, + }, + }, + }, + Params: v1.Params{ + { + Name: "proj-secret-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "proj-secret-value", + }, + }, + }, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "proj-secret-value", + }, + }, + }, + }, + }, + }, + }, + Params: v1.Params{ + { + Name: "proj-secret-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "proj-secret-value", + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := resources.ApplyParametersToWorkspaceBindings(tt.ts, tt.tr) + if d := cmp.Diff(got, tt.want); d != "" { + t.Errorf("ApplyParametersToWorkspaceBindings() %v, diff %v", tt.name, d) + } + }) + } +} From 39654b85c471f9ac63549cbcf9c87f3616cad339 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:53:12 -0500 Subject: [PATCH 03/12] feat: add ApplyParametersToWorkspaceBindings and ApplyResultsToWorkspaceBindings tests for pipelinerun --- pkg/reconciler/pipelinerun/resources/apply.go | 80 +++ .../pipelinerun/resources/apply_test.go | 522 +++++++++++++++++- 2 files changed, 601 insertions(+), 1 deletion(-) diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index 796baf206e3..4278a7be50c 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -246,6 +246,9 @@ func ApplyTaskResults(targets PipelineRunState, resolvedResultRefs ResolvedResul pipelineTask.TaskRef.Params = pipelineTask.TaskRef.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements) } pipelineTask.DisplayName = substitution.ApplyReplacements(pipelineTask.DisplayName, stringReplacements) + for _, workspace := range pipelineTask.Workspaces { + workspace.SubPath = substitution.ApplyReplacements(workspace.SubPath, stringReplacements) + } resolvedPipelineRunTask.PipelineTask = pipelineTask } } @@ -374,6 +377,50 @@ func propagateParams(t v1.PipelineTask, stringReplacements map[string]string, ar return t } +// ApplyResultsToWorkspaceBindings applies results from TaskRuns to WorkspaceBindings in a PipelineRun. It replaces placeholders in +// various binding types with values from TaskRun results. +func ApplyResultsToWorkspaceBindings(trResults map[string][]v1.TaskRunResult, pr *v1.PipelineRun) { + stringReplacements := map[string]string{} + arrayReplacements := map[string][]string{} + for taskName, taskResults := range trResults { + for _, res := range taskResults { + switch res.Type { + case v1.ResultsTypeString: + stringReplacements[fmt.Sprintf("tasks.%s.results.%s", taskName, res.Name)] = res.Value.StringVal + case v1.ResultsTypeArray: + arrayReplacements[fmt.Sprintf("tasks.%s.results.%s", taskName, res.Name)] = res.Value.ArrayVal + case v1.ResultsTypeObject: + for k, v := range res.Value.ObjectVal { + stringReplacements[fmt.Sprintf("tasks.%s.results.%s.%s", taskName, res.Name, k)] = v + } + } + } + } + + 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].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) + } + } + } + } +} + // PropagateResults propagate the result of the completed task to the unfinished task that is not explicitly specify in the params func PropagateResults(rpt *ResolvedPipelineTask, runStates PipelineRunState) { if rpt.ResolvedTask == nil || rpt.ResolvedTask.TaskSpec == nil { @@ -548,3 +595,36 @@ func runResultValue(taskName string, resultName string, runResults map[string][] } return nil } + +// ApplyParametersToWorkspaceBindings applies parameters from PipelineSpec and PipelineRun to the WorkspaceBindings in a PipelineRun. It replaces +// placeholders in various binding types with values from provided parameters. +func ApplyParametersToWorkspaceBindings(ctx context.Context, ps *v1.PipelineSpec, pr *v1.PipelineRun) { + psCopy := ps.DeepCopy() + var defaults []v1.ParamSpec + if len(psCopy.Params) > 0 { + defaults = append(defaults, psCopy.Params...) + } + 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].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) + } + } + } + } +} diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index 29e75078dac..c7f6a4271b7 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -19,13 +19,13 @@ package resources_test import ( "context" "fmt" + "github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun/resources" "testing" "github.com/google/go-cmp/cmp" cfgtesting "github.com/tektoncd/pipeline/pkg/apis/config/testing" v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" - resources "github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun/resources" taskresources "github.com/tektoncd/pipeline/pkg/reconciler/taskrun/resources" "github.com/tektoncd/pipeline/test/diff" corev1 "k8s.io/api/core/v1" @@ -4646,3 +4646,523 @@ func TestPropagateResults(t *testing.T) { }) } } +func TestApplyParametersToWorkspaceBindings(t *testing.T) { + testCases := []struct { + name string + ps *v1.PipelineSpec + pr *v1.PipelineRun + expectedPr *v1.PipelineRun + }{ + { + name: "pvc", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "pvc-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "pvc-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "claim-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(params.pvc-name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "pvc-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "claim-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "claim-value", + }, + }, + }, + }, + }, + }, + { + name: "subpath", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "subpath-value", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "subpath-value", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "sub/path"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + EmptyDir: &corev1.EmptyDirVolumeSource{}, + SubPath: "$(params.subpath-value)", + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "subpath-value", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "sub/path"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + EmptyDir: &corev1.EmptyDirVolumeSource{}, + SubPath: "sub/path", + }, + }, + }, + }, + }, + { + name: "configmap", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "configmap-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "configmap-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "config-map-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.configmap-name)", + }, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "configmap-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "config-map-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "config-map-value", + }, + }, + }, + }, + }, + }, + }, + { + name: "secret", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "secret-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "secret-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "secret-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "$(params.secret-name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "secret-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "secret-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "secret-value", + }, + }, + }, + }, + }, + }, + { + name: "projected-secret", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "projected-secret-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "projected-secret-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "projected-secret-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.projected-secret-name)", + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "projected-secret-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "projected-secret-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "projected-secret-value", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "projected-configmap", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "projected-configmap-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "projected-configmap-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "projected-config-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(params.projected-configmap-name)", + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "projected-configmap-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "projected-config-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "projected-config-value", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + resources.ApplyParametersToWorkspaceBindings(context.TODO(), tt.ps, tt.pr) + if d := cmp.Diff(tt.expectedPr, tt.pr); d != "" { + t.Fatalf("TestApplyParametersToWorkspaceBindings() %s, got: %v", tt.name, diff.PrintWantGot(d)) + } + }) + } +} +func TestApplyResultsToWorkspaceBindings(t *testing.T) { + testCases := []struct { + name string + trResults map[string][]v1.TaskRunResult + pr *v1.PipelineRun + expectedPr *v1.PipelineRun + }{ + { + name: "pvc", + trResults: map[string][]v1.TaskRunResult{ + "task1": { + { + Name: "pvc-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "claim-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(tasks.task1.results.pvc-name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "claim-value", + }, + }, + }, + }, + }, + }, + { + name: "subPath", + trResults: map[string][]v1.TaskRunResult{ + "task2": { + { + Name: "subpath-value", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "sub/path"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + EmptyDir: &corev1.EmptyDirVolumeSource{}, + SubPath: "$(tasks.task2.results.subpath-value)", + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + EmptyDir: &corev1.EmptyDirVolumeSource{}, + SubPath: "sub/path", + }, + }, + }, + }, + }, + { + name: "configmap name", + trResults: map[string][]v1.TaskRunResult{ + "task3": { + { + Name: "configmap-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "config-map-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: "$(tasks.task3.results.configmap-name)"}, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: "config-map-value"}, + }, + }, + }, + }, + }, + }, + { + name: "secret.secretName", + trResults: map[string][]v1.TaskRunResult{ + "task4": { + { + Name: "secret-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "secret-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "$(tasks.task4.results.secret-name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Secret: &corev1.SecretVolumeSource{ + SecretName: "secret-value", + }, + }, + }, + }, + }, + }, + { + name: "projected-configmap", + trResults: map[string][]v1.TaskRunResult{ + "task5": { + { + Name: "projected-configmap-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "projected-config-map-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(tasks.task5.results.projected-configmap-name)", + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "projected-config-map-value", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "projected-secret", + trResults: map[string][]v1.TaskRunResult{ + "task6": { + { + Name: "projected-secret-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "projected-secret-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "$(tasks.task6.results.projected-secret-name)", + }, + }, + }, + }, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "projected-secret-value", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + resources.ApplyResultsToWorkspaceBindings(tc.trResults, tc.pr) + if d := cmp.Diff(tc.pr, tc.expectedPr); d != "" { + t.Fatalf("TestApplyResultsToWorkspaceBindings() %s, %v", tc.name, diff.PrintWantGot(d)) + } + }) + } +} From c3514959fab551720a597528d6114a037d834399 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:54:15 -0500 Subject: [PATCH 04/12] feat: integrate apply params to workspacebindings in taskrun --- pkg/reconciler/taskrun/taskrun.go | 1 + pkg/reconciler/taskrun/taskrun_test.go | 302 +++++++++++++++++++++++++ 2 files changed, 303 insertions(+) diff --git a/pkg/reconciler/taskrun/taskrun.go b/pkg/reconciler/taskrun/taskrun.go index b05dfcc5e50..09ca1b7a151 100644 --- a/pkg/reconciler/taskrun/taskrun.go +++ b/pkg/reconciler/taskrun/taskrun.go @@ -558,6 +558,7 @@ func (c *Reconciler) reconcile(ctx context.Context, tr *v1.TaskRun, rtr *resourc tr.Spec.Workspaces = taskRunWorkspaces } + resources.ApplyParametersToWorkspaceBindings(rtr.TaskSpec, tr) // Get the randomized volume names assigned to workspace bindings workspaceVolumes := workspace.CreateVolumes(tr.Spec.Workspaces) diff --git a/pkg/reconciler/taskrun/taskrun_test.go b/pkg/reconciler/taskrun/taskrun_test.go index c25b39c8cce..a9be6b3baa5 100644 --- a/pkg/reconciler/taskrun/taskrun_test.go +++ b/pkg/reconciler/taskrun/taskrun_test.go @@ -2932,6 +2932,308 @@ spec: } } +func TestPopulateParamsToWorkspaceBindingsClaimName(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: myClaim + value: pvc-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + persistentVolumeClaim: + claimName: $(params.myClaim) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "pvc-1" + got := "" + for _, v := range pod.Spec.Volumes { + if v.PersistentVolumeClaim != nil { + got = v.PersistentVolumeClaim.ClaimName + break + } + } + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindings errored with: %s", diff.PrintWantGot(c)) + } +} + +func TestPopulateParamsToWorkspaceBindingsSubPath(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: myClaim + value: pvc-1 + - name: mySubPath + value: sub-1 + taskSpec: + steps: + - args: + - "$(workspaces.ws-1.volume)/foo" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + persistentVolumeClaim: + claimName: $(params.myClaim) + subPath: $(params.mySubPath) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "sub-1" + got := "" + for _, container := range pod.Spec.Containers { + for _, mount := range container.VolumeMounts { + if mount.SubPath != "" { + got = mount.SubPath + break + } + } + } + + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsSubPath errored with: %s", diff.PrintWantGot(c)) + } +} + +func TestPopulateParamsToWorkspaceBindingsConfigMapName(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: myConfig + value: config-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + configMap: + name: $(params.myConfig) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "config-1" + got := "" + + for _, v := range pod.Spec.Volumes { + if v.ConfigMap != nil { + got = v.ConfigMap.Name + break + } + } + + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsConfigMapName errored with: %s", diff.PrintWantGot(c)) + } +} + +func TestPopulateParamsToWorkspaceBindingsSecretName(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: mySecret + value: secret-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + secret: + secretName: $(params.mySecret) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "secret-1" + got := "" + + for _, v := range pod.Spec.Volumes { + if v.Secret != nil { + got = v.Secret.SecretName + break + } + } + + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsSecretName errored with: %s", diff.PrintWantGot(c)) + } +} +func TestPopulateParamsToWorkspaceBindingsProjectedSources(t *testing.T) { + tests := []struct { + description string + taskRun *v1.TaskRun + want []corev1.VolumeProjection + }{ + { + description: "taskrun propagating params to workspace bindings projected secret", + taskRun: parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings-projected-secret + namespace: foo +spec: + params: + - name: mySecret + value: secret-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + projected: + sources: + - secret: + name: $(params.mySecret) +`), + want: []corev1.VolumeProjection{ + {Secret: &corev1.SecretProjection{LocalObjectReference: corev1.LocalObjectReference{Name: "secret-1"}}}, + }, + }, + { + description: "taskrun propagating params to workspace bindings projected configMap", + taskRun: parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings-projected-configMap + namespace: foo +spec: + params: + - name: myConfig + value: config-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + projected: + sources: + - configMap: + name: $(params.myConfig) +`), + want: []corev1.VolumeProjection{ + {ConfigMap: &corev1.ConfigMapProjection{LocalObjectReference: corev1.LocalObjectReference{ + Name: "config-1", + }}}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.description, func(t *testing.T) { + d := test.Data{ + TaskRuns: []*v1.TaskRun{tt.taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", tt.taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(tt.taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + list, _ := testAssets.Clients.Kube.CoreV1().Pods(tt.taskRun.Namespace).List(testAssets.Ctx, metav1.ListOptions{}) + if len(list.Items) != 1 { + t.Fatalf("the result of list query shoud only contain 1 item.") + } + + var got []corev1.VolumeProjection + + for _, v := range list.Items[0].Spec.Volumes { + if v.Projected != nil { + got = v.Projected.Sources + break + } + } + + if c := cmp.Diff(tt.want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsProjectedSources errored with: %s", diff.PrintWantGot(c)) + } + }) + } +} + func TestStepActionRef(t *testing.T) { taskRun := parse.MustParseV1TaskRun(t, ` metadata: From be212f96738951a749b79d67bab366077d59ed2b Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:55:27 -0500 Subject: [PATCH 05/12] feat: integrate apply params and results to workspacebindings in pipeline run --- pkg/reconciler/pipelinerun/pipelinerun.go | 3 + .../pipelinerun/pipelinerun_test.go | 435 ++++++++++++++++++ 2 files changed, 438 insertions(+) diff --git a/pkg/reconciler/pipelinerun/pipelinerun.go b/pkg/reconciler/pipelinerun/pipelinerun.go index 09ca54b53a5..d3b53dd0380 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/pipelinerun/pipelinerun.go @@ -531,6 +531,7 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1.PipelineRun, getPipel return controller.NewPermanentError(err) } + resources.ApplyParametersToWorkspaceBindings(ctx, pipelineSpec, pr) // Make a deep copy of the Pipeline and its Tasks before value substution. // This is used to find referenced pipeline-level params at each PipelineTask when validate param enum subset requirement originalPipeline := pipelineSpec.DeepCopy() @@ -844,6 +845,8 @@ func (c *Reconciler) runNextSchedulableTask(ctx context.Context, pr *v1.Pipeline c.setFinallyStartedTimeIfNeeded(pr, pipelineRunFacts) } + resources.ApplyResultsToWorkspaceBindings(pipelineRunFacts.State.GetTaskRunsResults(), pr) + for _, rpt := range nextRpts { if rpt.IsFinalTask(pipelineRunFacts) { c.setFinallyStartedTimeIfNeeded(pr, pipelineRunFacts) diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index 734e5335d8e..dcd3e102751 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -5238,6 +5238,183 @@ spec: } } +func TestReconcileAndPopulateParamsToWorkspaceBindings(t *testing.T) { + names.TestingSeed() + + cPipeline := simpleHelloWorldPipeline.DeepCopy() + cPipeline.Spec.Workspaces = []v1.PipelineWorkspaceDeclaration{{Name: "ws-1"}} + cPipeline.Spec.Tasks[0].Workspaces = []v1.WorkspacePipelineTaskBinding{{Name: "s1", Workspace: "ws-1"}} + + cTask := simpleHelloWorldTask.DeepCopy() + cTask.Spec.Workspaces = []v1.WorkspaceDeclaration{{Name: "s1"}} + + tests := []struct { + name string + pr *v1.PipelineRun + expected v1.WorkspaceBinding + }{ + { + name: "populate params to pipelineRun workspaceBindings - secret.secretName", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: mySecret + value: secret-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + secret: + secretName: $(params.mySecret) +`), + expected: v1.WorkspaceBinding{Secret: &corev1.SecretVolumeSource{SecretName: "secret-1"}}, + }, + { + name: "populate params to pipelineRun workspaceBindings persistentVolumeClaim.claimName", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: myClaim + value: claim-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + persistentVolumeClaim: + claimName: $(params.myClaim) +`), + expected: v1.WorkspaceBinding{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: "claim-1"}}, + }, + { + name: "populate params to pipelineRun workspaceBindings subPath", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: mySubPath + value: sub-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + subPath: $(params.mySubPath) +`), + expected: v1.WorkspaceBinding{SubPath: "sub-1"}, + }, + { + name: "populate params to pipelineRun workspaceBindings projected.sources.configMap.name", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: myConfigMapName + value: name-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + projected: + sources: + - configMap: + name: $(params.myConfigMapName) +`), + expected: v1.WorkspaceBinding{Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{{ConfigMap: &corev1.ConfigMapProjection{LocalObjectReference: corev1.LocalObjectReference{ + "name-1", + }}}}}}, + }, + { + name: "populate params to pipelineRun workspaceBindings projected.sources.secret.name", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: mySecretName + value: name-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + projected: + sources: + - secret: + name: $(params.mySecretName) +`), + expected: v1.WorkspaceBinding{Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{{Secret: &corev1.SecretProjection{LocalObjectReference: corev1.LocalObjectReference{ + "name-1", + }}}}}}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + namespace := "foo" + prName := "test-pipeline-run" + + ps := []*v1.Pipeline{cPipeline} + + prs := []*v1.PipelineRun{tt.pr} + + ts := []*v1.Task{cTask} + + d := test.Data{ + PipelineRuns: prs, + Pipelines: ps, + Tasks: ts, + } + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + + _, clients := prt.reconcileRun("foo", prName, []string{}, false) + trs, _ := clients.Pipeline.TektonV1().TaskRuns(namespace).List(context.TODO(), metav1.ListOptions{}) + + if d := cmp.Diff(tt.expected, trs.Items[0].Spec.Workspaces[0], cmpopts.IgnoreFields(v1.WorkspaceBinding{}, "Name")); d != "" { + t.Errorf("expected to see Workspace %v created. Diff %s", tt.expected, diff.PrintWantGot(d)) + } + }) + } +} + func TestReconcileWithTaskResults(t *testing.T) { names.TestingSeed() ps := []*v1.Pipeline{parse.MustParseV1Pipeline(t, ` @@ -5345,6 +5522,264 @@ spec: } } +func TestReconcileAndPopulateTaskResultsToWorkspaceBindings(t *testing.T) { + names.TestingSeed() + ps := []*v1.Pipeline{parse.MustParseV1Pipeline(t, ` +metadata: + name: test-pipeline + namespace: foo +spec: + tasks: + - name: a-task + taskRef: + name: a-task + - name: b-task + taskRef: + name: b-task + workspaces: + - name: s1 + workspace: ws-1 + workspaces: + - name: ws-1 +`)} + ts := []*v1.Task{ + parse.MustParseV1Task(t, ` +metadata: + name: a-task + namespace: foo +spec: {} +`), + parse.MustParseV1Task(t, ` +metadata: + name: b-task + namespace: foo +spec: + workspaces: + - name: s1 +`), + } + 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), + ` +spec: + serviceAccountName: test-sa + taskRef: + name: hello-world + timeout: 1h0m0s +status: + conditions: + - lastTransitionTime: null + status: "True" + type: Succeeded + results: + - name: aResult + value: aResultValue + type: string +`)} + + tests := []struct { + name string + prs []*v1.PipelineRun + expectedTr *v1.TaskRun + disableAA bool + }{ + { + name: "pcv 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 + persistentVolumeClaim: + claimName: $(tasks.a-task.results.aResult) +`)}, + 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + persistentVolumeClaim: + claimName: aResultValue +`), + }, + { + name: "subPath 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 + 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + subPath: aResultValue +`), + }, + { + name: "secret.secretName 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 + 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + secret: + secretName: aResultValue +`), + }, + { + name: "projected.sources.configMap.name 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: + - 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + projected: + sources: + - configMap: + name: aResultValue +`), + }, + { + name: "projected.sources.secret.name 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: $(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 +`), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + d := test.Data{ + PipelineRuns: tt.prs, + Pipelines: ps, + Tasks: ts, + TaskRuns: trs, + } + if tt.disableAA { + configMap := newFeatureFlagsConfigMap() + configMap.Data["disable-affinity-assistant"] = "true" + d.ConfigMaps = []*corev1.ConfigMap{configMap} + } + + prt := newPipelineRunTest(t, d) + defer prt.Cancel() + + _, clients := prt.reconcileRun("foo", "test-pipeline-run-different-service-accs", []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", + Limit: 1, + }) + + if err != nil { + t.Fatalf("Failure to list TaskRun's %s", err) + } + if len(actual.Items) != 1 { + t.Fatalf("Expected 1 TaskRuns got %d", len(actual.Items)) + } + actualTaskRun := actual.Items[0] + if d := cmp.Diff(tt.expectedTr, &actualTaskRun, ignoreResourceVersion, ignoreTypeMeta); d != "" { + t.Errorf("expected to see TaskRun %v. Diff %s", tt.expectedTr, diff.PrintWantGot(d)) + } + }) + } +} + func TestReconcileWithTaskResultsEmbeddedNoneStarted(t *testing.T) { names.TestingSeed() prs := []*v1.PipelineRun{parse.MustParseV1PipelineRun(t, ` From 5b237d86546737e983c9b35da781195a82578eb6 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:56:07 -0500 Subject: [PATCH 06/12] feat: add new fields that support paramterization in docs --- docs/variables.md | 114 +++++++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 52 deletions(-) diff --git a/docs/variables.md b/docs/variables.md index ed742d50057..edb6feeda03 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -75,55 +75,65 @@ For instructions on using variable substitutions see the relevant section of [th ## Fields that accept variable substitutions -| CRD | Field | -| --- |-----------------------------------------------------------------| -| `Task` | `spec.steps[].name` | -| `Task` | `spec.steps[].image` | -| `Task` | `spec.steps[].imagePullPolicy` | -| `Task` | `spec.steps[].command` | -| `Task` | `spec.steps[].args` | -| `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.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[].secret.items[].key` | -| `Task` | `spec.volumes[].secret.items[].path` | -| `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` | -| `Task` | `spec.volumes[].csi.volumeattributes.* ` | -| `Task` | `spec.sidecars[].name` | -| `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[].command` | -| `Task` | `spec.sidecars[].args` | -| `Task` | `spec.sidecars[].script` | -| `Task` | `spec.workspaces[].mountPath` | -| `Pipeline` | `spec.tasks[].params[].value` | -| `Pipeline` | `spec.tasks[].conditions[].params[].value` | -| `Pipeline` | `spec.results[].value` | -| `Pipeline` | `spec.tasks[].when[].input` | -| `Pipeline` | `spec.tasks[].when[].values` | -| `Pipeline` | `spec.tasks[].workspaces[].subPath` | -| `Pipeline` | `spec.tasks[].displayName` | +| CRD | Field | +|---------------|-----------------------------------------------------------------| +| `Task` | `spec.steps[].name` | +| `Task` | `spec.steps[].image` | +| `Task` | `spec.steps[].imagePullPolicy` | +| `Task` | `spec.steps[].command` | +| `Task` | `spec.steps[].args` | +| `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.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[].secret.items[].key` | +| `Task` | `spec.volumes[].secret.items[].path` | +| `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` | +| `Task` | `spec.volumes[].csi.volumeattributes.* ` | +| `Task` | `spec.sidecars[].name` | +| `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[].command` | +| `Task` | `spec.sidecars[].args` | +| `Task` | `spec.sidecars[].script` | +| `Task` | `spec.workspaces[].mountPath` | +| `TaskRun` | `spec.workspaces[].persistentVolumeClaim.claimName` | +| `TaskRun` | `spec.workspaces[].configmap.name` | +| `TaskRun` | `spec.workspaces[].secret.secretName` | +| `TaskRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `TaskRun` | `spec.workspaces[].projected.sources[].secret.name` | +| `Pipeline` | `spec.tasks[].params[].value` | +| `Pipeline` | `spec.tasks[].conditions[].params[].value` | +| `Pipeline` | `spec.results[].value` | +| `Pipeline` | `spec.tasks[].when[].input` | +| `Pipeline` | `spec.tasks[].when[].values` | +| `Pipeline` | `spec.tasks[].workspaces[].subPath` | +| `Pipeline` | `spec.tasks[].displayName` | +| `PipelineRun` | `spec.workspaces[].persistentVolumeClaim.claimName` | +| `PipelineRun` | `spec.workspaces[].configmap.name` | +| `PipelineRun` | `spec.workspaces[].secret.secretName` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.name` | +| `PipelineRun` | `spec.workspaces[].projected.sources[].secret.name` | From aa5315cec51000b835d2c22bd99821b949fd249b Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 2 Jan 2024 10:59:52 -0500 Subject: [PATCH 07/12] chore: lint --- pkg/reconciler/pipelinerun/pipelinerun_test.go | 4 ++-- pkg/reconciler/pipelinerun/resources/apply.go | 4 ---- pkg/reconciler/pipelinerun/resources/apply_test.go | 2 +- pkg/reconciler/taskrun/resources/apply.go | 4 ---- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index dcd3e102751..1f531554ebd 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -5353,7 +5353,7 @@ spec: name: $(params.myConfigMapName) `), expected: v1.WorkspaceBinding{Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{{ConfigMap: &corev1.ConfigMapProjection{LocalObjectReference: corev1.LocalObjectReference{ - "name-1", + Name: "name-1", }}}}}}, }, { @@ -5382,7 +5382,7 @@ spec: name: $(params.mySecretName) `), expected: v1.WorkspaceBinding{Projected: &corev1.ProjectedVolumeSource{Sources: []corev1.VolumeProjection{{Secret: &corev1.SecretProjection{LocalObjectReference: corev1.LocalObjectReference{ - "name-1", + Name: "name-1", }}}}}}, }, } diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index 4278a7be50c..6599abac2cc 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -600,10 +600,6 @@ func runResultValue(taskName string, resultName string, runResults map[string][] // placeholders in various binding types with values from provided parameters. func ApplyParametersToWorkspaceBindings(ctx context.Context, ps *v1.PipelineSpec, pr *v1.PipelineRun) { psCopy := ps.DeepCopy() - var defaults []v1.ParamSpec - if len(psCopy.Params) > 0 { - defaults = append(defaults, psCopy.Params...) - } parameters, _, _ := paramsFromPipelineRun(ctx, pr) for i, binding := range pr.Spec.Workspaces { if pr.Spec.Workspaces[i].PersistentVolumeClaim != nil { diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index c7f6a4271b7..af513abb285 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -19,13 +19,13 @@ package resources_test import ( "context" "fmt" - "github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun/resources" "testing" "github.com/google/go-cmp/cmp" cfgtesting "github.com/tektoncd/pipeline/pkg/apis/config/testing" v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun/resources" taskresources "github.com/tektoncd/pipeline/pkg/reconciler/taskrun/resources" "github.com/tektoncd/pipeline/test/diff" corev1 "k8s.io/api/core/v1" diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index 6ced9253ef1..9616f7ce7e7 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -226,10 +226,6 @@ func ApplyWorkspaces(ctx context.Context, spec *v1.TaskSpec, declarations []v1.W // ApplyParametersToWorkspaceBindings applies parameters to the WorkspaceBindings of a TaskRun. It takes a TaskSpec and a TaskRun as input and returns the modified TaskRun. func ApplyParametersToWorkspaceBindings(ts *v1.TaskSpec, tr *v1.TaskRun) *v1.TaskRun { tsCopy := ts.DeepCopy() - var defaults []v1.ParamSpec - if len(tsCopy.Params) > 0 { - defaults = append(defaults, tsCopy.Params...) - } parameters, _, _ := getTaskParameters(tsCopy, tr, tsCopy.Params...) for i, binding := range tr.Spec.Workspaces { if tr.Spec.Workspaces[i].PersistentVolumeClaim != nil { From 68003eb29b80123d8337c086bda7a9771269de03 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:12:04 -0500 Subject: [PATCH 08/12] chore: lint remove unused --- pkg/reconciler/pipelinerun/pipelinerun.go | 2 +- pkg/reconciler/pipelinerun/resources/apply.go | 6 +----- pkg/reconciler/pipelinerun/resources/apply_test.go | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/reconciler/pipelinerun/pipelinerun.go b/pkg/reconciler/pipelinerun/pipelinerun.go index d3b53dd0380..ee4743f1f69 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/pipelinerun/pipelinerun.go @@ -531,7 +531,7 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1.PipelineRun, getPipel return controller.NewPermanentError(err) } - resources.ApplyParametersToWorkspaceBindings(ctx, pipelineSpec, pr) + resources.ApplyParametersToWorkspaceBindings(ctx, pr) // Make a deep copy of the Pipeline and its Tasks before value substution. // This is used to find referenced pipeline-level params at each PipelineTask when validate param enum subset requirement originalPipeline := pipelineSpec.DeepCopy() diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index 6599abac2cc..e7b914a58d5 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -381,14 +381,11 @@ func propagateParams(t v1.PipelineTask, stringReplacements map[string]string, ar // various binding types with values from TaskRun results. func ApplyResultsToWorkspaceBindings(trResults map[string][]v1.TaskRunResult, pr *v1.PipelineRun) { stringReplacements := map[string]string{} - arrayReplacements := map[string][]string{} for taskName, taskResults := range trResults { for _, res := range taskResults { switch res.Type { case v1.ResultsTypeString: stringReplacements[fmt.Sprintf("tasks.%s.results.%s", taskName, res.Name)] = res.Value.StringVal - case v1.ResultsTypeArray: - arrayReplacements[fmt.Sprintf("tasks.%s.results.%s", taskName, res.Name)] = res.Value.ArrayVal case v1.ResultsTypeObject: for k, v := range res.Value.ObjectVal { stringReplacements[fmt.Sprintf("tasks.%s.results.%s.%s", taskName, res.Name, k)] = v @@ -598,8 +595,7 @@ func runResultValue(taskName string, resultName string, runResults map[string][] // ApplyParametersToWorkspaceBindings applies parameters from PipelineSpec and PipelineRun to the WorkspaceBindings in a PipelineRun. It replaces // placeholders in various binding types with values from provided parameters. -func ApplyParametersToWorkspaceBindings(ctx context.Context, ps *v1.PipelineSpec, pr *v1.PipelineRun) { - psCopy := ps.DeepCopy() +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 { diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index af513abb285..6f1a25d3adf 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -4907,7 +4907,7 @@ func TestApplyParametersToWorkspaceBindings(t *testing.T) { for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { - resources.ApplyParametersToWorkspaceBindings(context.TODO(), tt.ps, tt.pr) + resources.ApplyParametersToWorkspaceBindings(context.TODO(), tt.pr) if d := cmp.Diff(tt.expectedPr, tt.pr); d != "" { t.Fatalf("TestApplyParametersToWorkspaceBindings() %s, got: %v", tt.name, diff.PrintWantGot(d)) } From 0bc1593dd6ee6db446c3d9258aa071a15193c805 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:24:26 -0500 Subject: [PATCH 09/12] chore: lint --- pkg/reconciler/pipelinerun/resources/apply.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index e7b914a58d5..d715ee542f0 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -386,6 +386,8 @@ func ApplyResultsToWorkspaceBindings(trResults map[string][]v1.TaskRunResult, pr switch res.Type { case v1.ResultsTypeString: stringReplacements[fmt.Sprintf("tasks.%s.results.%s", taskName, res.Name)] = res.Value.StringVal + case v1.ResultsTypeArray: + continue case v1.ResultsTypeObject: for k, v := range res.Value.ObjectVal { stringReplacements[fmt.Sprintf("tasks.%s.results.%s.%s", taskName, res.Name, k)] = v From e35fb2d7fad8c2a18b39e819b271b888dac9d6fc Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:45:33 -0500 Subject: [PATCH 10/12] feature: add paramterization support for csi in pipelineRun workspaces and taskRun workspaces --- docs/variables.md | 4 + .../pipelinerun/pipelinerun_test.go | 113 ++++++++++++++++++ pkg/reconciler/pipelinerun/resources/apply.go | 12 ++ .../pipelinerun/resources/apply_test.go | 64 ++++++++++ pkg/reconciler/taskrun/resources/apply.go | 10 +- .../taskrun/resources/apply_test.go | 88 ++++++++++++++ pkg/reconciler/taskrun/taskrun_test.go | 103 ++++++++++++++++ 7 files changed, 392 insertions(+), 2 deletions(-) diff --git a/docs/variables.md b/docs/variables.md index edb6feeda03..49b7a68be3d 100644 --- a/docs/variables.md +++ b/docs/variables.md @@ -125,6 +125,8 @@ For instructions on using variable substitutions see the relevant section of [th | `TaskRun` | `spec.workspaces[].secret.secretName` | | `TaskRun` | `spec.workspaces[].projected.sources[].configMap.name` | | `TaskRun` | `spec.workspaces[].projected.sources[].secret.name` | +| `TaskRun` | `spec.workspaces[].csi.driver` | +| `TaskRun` | `spec.workspaces[].csi.nodePublishSecretRef.name` | | `Pipeline` | `spec.tasks[].params[].value` | | `Pipeline` | `spec.tasks[].conditions[].params[].value` | | `Pipeline` | `spec.results[].value` | @@ -137,3 +139,5 @@ For instructions on using variable substitutions see the relevant section of [th | `PipelineRun` | `spec.workspaces[].secret.secretName` | | `PipelineRun` | `spec.workspaces[].projected.sources[].configMap.name` | | `PipelineRun` | `spec.workspaces[].projected.sources[].secret.name` | +| `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 1f531554ebd..46ff7e51b2c 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -5385,6 +5385,57 @@ spec: Name: "name-1", }}}}}}, }, + { + name: "populate params to pipelineRun workspaceBindings csi.driver", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: myCSIDriver + value: driver-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + csi: + driver: $(params.myCSIDriver) +`), + expected: v1.WorkspaceBinding{CSI: &corev1.CSIVolumeSource{Driver: "driver-1"}}, + }, + { + name: "populate params to pipelineRun workspaceBindings csi.nodePublishSecretRef.name", + pr: parse.MustParseV1PipelineRun(t, ` +metadata: + annotations: + PipelineRunAnnotation: PipelineRunValue + name: test-pipeline-run + namespace: foo +spec: + params: + - name: myNodePublishSecretRef + value: ref-1 + pipelineRef: + name: test-pipeline + taskRunTemplate: + serviceAccountName: test-sa + taskRunSpecs: + - pipelineTaskName: hello-world-1 + workspaces: + - name: ws-1 + csi: + nodePublishSecretRef: + name: $(params.myNodePublishSecretRef) +`), + expected: v1.WorkspaceBinding{CSI: &corev1.CSIVolumeSource{NodePublishSecretRef: &corev1.LocalObjectReference{Name: "ref-1"}}}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -5739,6 +5790,68 @@ spec: sources: - secret: name: aResultValue +`), + }, + { + name: "csi.driver 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 + csi: + 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + csi: + driver: aResultValue +`), + }, + { + name: "nodePublishSecretRef.name 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 + csi: + nodePublishSecretRef: + 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), + `spec: + serviceAccountName: test-sa-0 + taskRef: + name: b-task + kind: Task + workspaces: + - name: s1 + csi: + nodePublishSecretRef: + name: aResultValue `), }, } diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index d715ee542f0..2069c8155df 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -404,6 +404,12 @@ func ApplyResultsToWorkspaceBindings(trResults map[string][]v1.TaskRunResult, pr 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) } @@ -610,6 +616,12 @@ func ApplyParametersToWorkspaceBindings(ctx context.Context, pr *v1.PipelineRun) 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 { diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index 6f1a25d3adf..91710c9d6bd 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -4903,6 +4903,70 @@ func TestApplyParametersToWorkspaceBindings(t *testing.T) { }, }, }, + { + name: "csi-driver", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "csi-driver", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "csi-driver", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "csi-driver-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{Driver: "$(params.csi-driver)"}, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "csi-driver", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "csi-driver-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{Driver: "csi-driver-value"}, + }, + }, + }, + }, + }, + { + name: "csi-nodePublishSecretRef-name", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "csi-nodePublishSecretRef-name", Type: v1.ParamTypeString}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "csi-nodePublishSecretRef-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "csi-nodePublishSecretRef-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{NodePublishSecretRef: &corev1.LocalObjectReference{Name: "$(params.csi-nodePublishSecretRef-name)"}}, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "csi-nodePublishSecretRef-name", Value: v1.ParamValue{Type: v1.ParamTypeString, StringVal: "csi-nodePublishSecretRef-value"}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{NodePublishSecretRef: &corev1.LocalObjectReference{Name: "csi-nodePublishSecretRef-value"}}, + }, + }, + }, + }, + }, } for _, tt := range testCases { diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index 9616f7ce7e7..5fa635907ae 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -229,15 +229,21 @@ func ApplyParametersToWorkspaceBindings(ts *v1.TaskSpec, tr *v1.TaskRun) *v1.Tas parameters, _, _ := getTaskParameters(tsCopy, tr, tsCopy.Params...) for i, binding := range tr.Spec.Workspaces { if tr.Spec.Workspaces[i].PersistentVolumeClaim != nil { - binding.PersistentVolumeClaim.ClaimName = substitution.ApplyReplacements(binding.PersistentVolumeClaim.ClaimName, parameters) + 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 { - binding.ConfigMap.Name = substitution.ApplyReplacements(binding.ConfigMap.Name, parameters) + 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 { diff --git a/pkg/reconciler/taskrun/resources/apply_test.go b/pkg/reconciler/taskrun/resources/apply_test.go index 1fcf0734e5d..4d6f592dd0e 100644 --- a/pkg/reconciler/taskrun/resources/apply_test.go +++ b/pkg/reconciler/taskrun/resources/apply_test.go @@ -1920,6 +1920,94 @@ func TestApplyParametersToWorkspaceBindings(t *testing.T) { }, }, }, + { + name: "csi-driver", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "csi-driver-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{Driver: "$(params.csi-driver-name)"}, + }, + }, + Params: v1.Params{ + { + Name: "csi-driver-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "csi-driver-value", + }, + }, + }, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{Driver: "csi-driver-value"}, + }, + }, + Params: v1.Params{ + { + Name: "csi-driver-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "csi-driver-value", + }, + }, + }, + }, + }, + }, + { + name: "csi-nodePublishSecretRef-name", + ts: &v1.TaskSpec{ + Params: []v1.ParamSpec{ + {Name: "csi-nodePublishSecretRef-name", Type: v1.ParamTypeString}, + }, + }, + tr: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{NodePublishSecretRef: &corev1.LocalObjectReference{ + Name: "$(params.csi-nodePublishSecretRef-name)", + }}, + }, + }, + Params: v1.Params{ + { + Name: "csi-nodePublishSecretRef-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "csi-nodePublishSecretRef-value", + }, + }, + }, + }, + }, + want: &v1.TaskRun{ + Spec: v1.TaskRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{NodePublishSecretRef: &corev1.LocalObjectReference{ + Name: "csi-nodePublishSecretRef-value", + }}, + }, + }, + Params: v1.Params{ + { + Name: "csi-nodePublishSecretRef-name", Value: v1.ParamValue{ + Type: v1.ParamTypeString, + StringVal: "csi-nodePublishSecretRef-value", + }, + }, + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/reconciler/taskrun/taskrun_test.go b/pkg/reconciler/taskrun/taskrun_test.go index a9be6b3baa5..c681f8ae04b 100644 --- a/pkg/reconciler/taskrun/taskrun_test.go +++ b/pkg/reconciler/taskrun/taskrun_test.go @@ -3133,6 +3133,109 @@ spec: t.Errorf("TestPopulateParamsToWorkspaceBindingsSecretName errored with: %s", diff.PrintWantGot(c)) } } + +func TestPopulateParamsToWorkspaceBindingsCSIDriver(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: myDriver + value: driver-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + csi: + driver: $(params.myDriver) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "driver-1" + got := "" + + for _, v := range pod.Spec.Volumes { + if v.CSI != nil { + got = v.CSI.Driver + break + } + } + + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsCSIDriver errored with: %s", diff.PrintWantGot(c)) + } +} + +func TestPopulateParamsToWorkspaceBindingsCSINodePublishSecretRefName(t *testing.T) { + taskRun := parse.MustParseV1TaskRun(t, ` +metadata: + name: test-taskrun-propagating-params-to-workspace-bindings + namespace: foo +spec: + params: + - name: myRefName + value: ref-1 + taskSpec: + steps: + - args: + - "" + command: + - echo + image: foo + name: simple-step + workspaces: + - name: ws-1 + csi: + driver: driver-1 + nodePublishSecretRef: + name: $(params.myRefName) +`) + d := test.Data{ + TaskRuns: []*v1.TaskRun{taskRun}, + } + testAssets, cancel := getTaskRunController(t, d) + defer cancel() + createServiceAccount(t, testAssets, "default", taskRun.Namespace) + c := testAssets.Controller + if err := c.Reconciler.Reconcile(testAssets.Ctx, getRunName(taskRun)); err == nil { + t.Fatalf("Could not reconcile the taskrun: %v", err) + } + + pod, _ := testAssets.Clients.Kube.CoreV1().Pods(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name+"-pod", metav1.GetOptions{}) + + want := "ref-1" + got := "" + + for _, v := range pod.Spec.Volumes { + if v.CSI != nil { + got = v.CSI.NodePublishSecretRef.Name + break + } + } + + if c := cmp.Diff(want, got); c != "" { + t.Errorf("TestPopulateParamsToWorkspaceBindingsCSINodePublishSecretRefName errored with: %s", diff.PrintWantGot(c)) + } +} + func TestPopulateParamsToWorkspaceBindingsProjectedSources(t *testing.T) { tests := []struct { description string From 9bd534d3b72304a27222592f73fa903972e66222 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:38:16 -0500 Subject: [PATCH 11/12] chore: add more tests --- pkg/reconciler/pipelinerun/resources/apply.go | 4 +- .../pipelinerun/resources/apply_test.go | 147 +++++++++++++++++- 2 files changed, 148 insertions(+), 3 deletions(-) diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index 2069c8155df..d0dae45cf79 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -246,8 +246,8 @@ func ApplyTaskResults(targets PipelineRunState, resolvedResultRefs ResolvedResul pipelineTask.TaskRef.Params = pipelineTask.TaskRef.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements) } pipelineTask.DisplayName = substitution.ApplyReplacements(pipelineTask.DisplayName, stringReplacements) - for _, workspace := range pipelineTask.Workspaces { - workspace.SubPath = substitution.ApplyReplacements(workspace.SubPath, stringReplacements) + for i, workspace := range pipelineTask.Workspaces { + pipelineTask.Workspaces[i].SubPath = substitution.ApplyReplacements(workspace.SubPath, stringReplacements) } resolvedPipelineRunTask.PipelineTask = pipelineTask } diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index 91710c9d6bd..682f36d835a 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -3204,7 +3204,33 @@ func TestApplyTaskResults_EmbeddedExpression(t *testing.T) { DisplayName: "Result value --> aResultValue", }, }}, - }} { + }, + { + name: "Test result substitution on embedded variable substitution expression - workspace.subPath", + resolvedResultRefs: resources.ResolvedResultRefs{{ + Value: *v1.NewStructuredValues("aResultValue"), + ResultReference: v1.ResultRef{ + PipelineTask: "aTask", + Result: "aResult", + }, + FromTaskRun: "aTaskRun", + }}, + targets: resources.PipelineRunState{{ + PipelineTask: &v1.PipelineTask{ + Name: "bTask", + TaskRef: &v1.TaskRef{Name: "bTask"}, + Workspaces: []v1.WorkspacePipelineTaskBinding{{Name: "ws-1", Workspace: "ws-1", SubPath: "$(tasks.aTask.results.aResult)"}}, + }, + }}, + want: resources.PipelineRunState{{ + PipelineTask: &v1.PipelineTask{ + Name: "bTask", + TaskRef: &v1.TaskRef{Name: "bTask"}, + Workspaces: []v1.WorkspacePipelineTaskBinding{{Name: "ws-1", Workspace: "ws-1", SubPath: "aResultValue"}}, + }, + }}, + }, + } { t.Run(tt.name, func(t *testing.T) { resources.ApplyTaskResults(tt.targets, tt.resolvedResultRefs) if d := cmp.Diff(tt.want, tt.targets); d != "" { @@ -4967,6 +4993,48 @@ func TestApplyParametersToWorkspaceBindings(t *testing.T) { }, }, }, + { + name: "pvc object params", + ps: &v1.PipelineSpec{ + Params: []v1.ParamSpec{ + {Name: "pvc-object", Type: v1.ParamTypeObject, Properties: map[string]v1.PropertySpec{ + "name": {Type: v1.ParamTypeString}, + }}, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "pvc-object", Value: v1.ParamValue{Type: v1.ParamTypeObject, ObjectVal: map[string]string{ + "name": "pvc-object-value", + }}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(params.pvc-object.name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Params: []v1.Param{ + {Name: "pvc-object", Value: v1.ParamValue{Type: v1.ParamTypeObject, ObjectVal: map[string]string{ + "name": "pvc-object-value", + }}}, + }, + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvc-object-value", + }, + }, + }, + }, + }, + }, } for _, tt := range testCases { @@ -5219,6 +5287,83 @@ func TestApplyResultsToWorkspaceBindings(t *testing.T) { }, }, }, + { + name: "pvc object-result", + trResults: map[string][]v1.TaskRunResult{ + "task1": { + { + Name: "pvc-object", + Type: v1.ResultsTypeObject, + Value: v1.ResultValue{Type: v1.ParamTypeObject, ObjectVal: map[string]string{ + "name": "pvc-object-value", + }}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(tasks.task1.results.pvc-object.name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvc-object-value", + }, + }, + }, + }, + }, + }, + { + name: "pvc object-result - along with array-result (no effect)", + trResults: map[string][]v1.TaskRunResult{ + "task1": { + { + Name: "pvc-object", + Type: v1.ResultsTypeObject, + Value: v1.ResultValue{Type: v1.ParamTypeObject, ObjectVal: map[string]string{ + "name": "pvc-object-value", + }}, + }, + { + Name: "pvc-array", + Type: v1.ResultsTypeArray, + Value: v1.ResultValue{Type: v1.ParamTypeArray, ArrayVal: []string{"name-1", "name-2"}}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "$(tasks.task1.results.pvc-object.name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: "pvc-object-value", + }, + }, + }, + }, + }, + }, } for _, tc := range testCases { From 5cda0c0327f1444bac3277606527914b7ef24588 Mon Sep 17 00:00:00 2001 From: ericzzzzzzz <102683393+ericzzzzzzz@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:58:15 -0500 Subject: [PATCH 12/12] chore: add more tests csi --- .../pipelinerun/resources/apply_test.go | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index 682f36d835a..c14723cc6fb 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -5287,6 +5287,76 @@ func TestApplyResultsToWorkspaceBindings(t *testing.T) { }, }, }, + { + name: "csi-driver", + trResults: map[string][]v1.TaskRunResult{ + "task6": { + { + Name: "driver-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "driver-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "$(tasks.task6.results.driver-name)", + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "driver-value", + }, + }, + }, + }, + }, + }, + { + name: "csi-NodePublishSecretRef-name", + trResults: map[string][]v1.TaskRunResult{ + "task6": { + { + Name: "ref-name", + Type: v1.ResultsTypeString, + Value: v1.ResultValue{StringVal: "ref-value"}, + }, + }, + }, + pr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "driver", + NodePublishSecretRef: &corev1.LocalObjectReference{Name: "$(tasks.task6.results.ref-name)"}, + }, + }, + }, + }, + }, + expectedPr: &v1.PipelineRun{ + Spec: v1.PipelineRunSpec{ + Workspaces: []v1.WorkspaceBinding{ + { + CSI: &corev1.CSIVolumeSource{ + Driver: "driver", + NodePublishSecretRef: &corev1.LocalObjectReference{Name: "ref-value"}, + }, + }, + }, + }, + }, + }, { name: "pvc object-result", trResults: map[string][]v1.TaskRunResult{