Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor substituting variables in Parameter values #6657

Merged
merged 1 commit into from
May 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pkg/apis/pipeline/v1/param_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,15 @@ func (ps Params) validateDuplicateParameters() (errs *apis.FieldError) {
return errs
}

// ReplaceVariables applies string, array and object replacements to variables in Params
func (ps Params) ReplaceVariables(stringReplacements map[string]string, arrayReplacements map[string][]string, objectReplacements map[string]map[string]string) Params {
jerop marked this conversation as resolved.
Show resolved Hide resolved
params := ps.DeepCopy()
for i := range params {
params[i].Value.ApplyReplacements(stringReplacements, arrayReplacements, objectReplacements)
}
return params
}

// extractParamArrayLengths extract and return the lengths of all array params
// Example of returned value: {"a-array-params": 2,"b-array-params": 2 }
func (ps ParamSpecs) extractParamArrayLengths() map[string]int {
Expand Down
64 changes: 64 additions & 0 deletions pkg/apis/pipeline/v1/param_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,3 +500,67 @@ func TestExtractNames(t *testing.T) {
}
}
}

func TestParams_ReplaceVariables(t *testing.T) {
tests := []struct {
name string
ps v1.Params
stringReplacements map[string]string
arrayReplacements map[string][]string
objectReplacements map[string]map[string]string
want v1.Params
}{
{
name: "string replacement",
ps: v1.Params{{
Name: "foo",
Value: v1.ParamValue{StringVal: "$(params.foo)"},
}},
stringReplacements: map[string]string{
"params.foo": "bar",
},
want: v1.Params{{
Name: "foo",
Value: v1.ParamValue{StringVal: "bar"},
}},
},
{
name: "array replacement",
ps: v1.Params{{
Name: "foo",
Value: v1.ParamValue{StringVal: "$(params.foo)"},
}},
arrayReplacements: map[string][]string{
"params.foo": {"bar", "zoo"},
},
want: v1.Params{{
Name: "foo",
Value: v1.ParamValue{Type: v1.ParamTypeArray, ArrayVal: []string{"bar", "zoo"}},
}},
},
{
name: "object replacement",
ps: v1.Params{{
Name: "foo",
Value: v1.ParamValue{StringVal: "$(params.foo)"},
}},
objectReplacements: map[string]map[string]string{
"params.foo": {
"abc": "123",
},
},
want: v1.Params{{
Name: "foo",
Value: v1.ParamValue{Type: v1.ParamTypeObject, ObjectVal: map[string]string{"abc": "123"}},
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.ps.ReplaceVariables(tt.stringReplacements, tt.arrayReplacements, tt.objectReplacements)
if d := cmp.Diff(tt.want, got); d != "" {
t.Errorf(diff.PrintWantGot(d))
}
})
}
}
9 changes: 9 additions & 0 deletions pkg/apis/pipeline/v1beta1/param_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,15 @@ func (ps Params) validateDuplicateParameters() (errs *apis.FieldError) {
return errs
}

// ReplaceVariables applies string, array and object replacements to variables in Params
func (ps Params) ReplaceVariables(stringReplacements map[string]string, arrayReplacements map[string][]string, objectReplacements map[string]map[string]string) Params {
params := ps.DeepCopy()
for i := range params {
params[i].Value.ApplyReplacements(stringReplacements, arrayReplacements, objectReplacements)
}
return params
}

// extractParamArrayLengths extract and return the lengths of all array params
// Example of returned value: {"a-array-params": 2,"b-array-params": 2 }
func (ps ParamSpecs) extractParamArrayLengths() map[string]int {
Expand Down
64 changes: 64 additions & 0 deletions pkg/apis/pipeline/v1beta1/param_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -531,3 +531,67 @@ func TestExtractNames(t *testing.T) {
}
}
}

func TestParams_ReplaceVariables(t *testing.T) {
tests := []struct {
name string
ps v1beta1.Params
stringReplacements map[string]string
arrayReplacements map[string][]string
objectReplacements map[string]map[string]string
want v1beta1.Params
}{
{
name: "string replacement",
ps: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{StringVal: "$(params.foo)"},
}},
stringReplacements: map[string]string{
"params.foo": "bar",
},
want: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{StringVal: "bar"},
}},
},
{
name: "array replacement",
ps: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{StringVal: "$(params.foo)"},
}},
arrayReplacements: map[string][]string{
"params.foo": {"bar", "zoo"},
},
want: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{Type: v1beta1.ParamTypeArray, ArrayVal: []string{"bar", "zoo"}},
}},
},
{
name: "object replacement",
ps: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{StringVal: "$(params.foo)"},
}},
objectReplacements: map[string]map[string]string{
"params.foo": {
"abc": "123",
},
},
want: v1beta1.Params{{
Name: "foo",
Value: v1beta1.ParamValue{Type: v1beta1.ParamTypeObject, ObjectVal: map[string]string{"abc": "123"}},
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.ps.ReplaceVariables(tt.stringReplacements, tt.arrayReplacements, tt.objectReplacements)
if d := cmp.Diff(tt.want, got); d != "" {
t.Errorf(diff.PrintWantGot(d))
}
})
}
}
41 changes: 17 additions & 24 deletions pkg/reconciler/pipelinerun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,11 @@ func ApplyPipelineTaskContexts(pt *v1beta1.PipelineTask) *v1beta1.PipelineTask {
replacements := map[string]string{
"context.pipelineTask.retries": strconv.Itoa(pt.Retries),
}
pt.Params = replaceParamValues(pt.Params, replacements, map[string][]string{}, map[string]map[string]string{})
pt.Params = pt.Params.ReplaceVariables(replacements, map[string][]string{}, map[string]map[string]string{})
if pt.IsMatrixed() {
pt.Matrix.Params = replaceParamValues(pt.Matrix.Params, replacements, map[string][]string{}, map[string]map[string]string{})
pt.Matrix.Params = pt.Params.ReplaceVariables(replacements, map[string][]string{}, map[string]map[string]string{})
for i := range pt.Matrix.Include {
pt.Matrix.Include[i].Params = replaceParamValues(pt.Matrix.Include[i].Params, replacements, map[string][]string{}, map[string]map[string]string{})
pt.Matrix.Include[i].Params = pt.Matrix.Include[i].Params.ReplaceVariables(replacements, map[string][]string{}, map[string]map[string]string{})
}
}
return pt
Expand All @@ -174,19 +174,19 @@ func ApplyTaskResults(targets PipelineRunState, resolvedResultRefs ResolvedResul
for _, resolvedPipelineRunTask := range targets {
if resolvedPipelineRunTask.PipelineTask != nil {
pipelineTask := resolvedPipelineRunTask.PipelineTask.DeepCopy()
pipelineTask.Params = replaceParamValues(pipelineTask.Params, stringReplacements, arrayReplacements, objectReplacements)
pipelineTask.Params = pipelineTask.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements)
if pipelineTask.IsMatrixed() {
// Only string replacements from string, array or object results are supported
// We plan to support array replacements from array results soon (#5925)
pipelineTask.Matrix.Params = replaceParamValues(pipelineTask.Matrix.Params, stringReplacements, nil, nil)
pipelineTask.Matrix.Params = pipelineTask.Matrix.Params.ReplaceVariables(stringReplacements, nil, nil)
for i := range pipelineTask.Matrix.Include {
// matrix include parameters can only be type string
pipelineTask.Matrix.Include[i].Params = replaceParamValues(pipelineTask.Matrix.Include[i].Params, stringReplacements, nil, nil)
pipelineTask.Matrix.Include[i].Params = pipelineTask.Matrix.Include[i].Params.ReplaceVariables(stringReplacements, nil, nil)
}
}
pipelineTask.WhenExpressions = pipelineTask.WhenExpressions.ReplaceVariables(stringReplacements, arrayReplacements)
if pipelineTask.TaskRef != nil && pipelineTask.TaskRef.Params != nil {
pipelineTask.TaskRef.Params = replaceParamValues(pipelineTask.TaskRef.Params, stringReplacements, arrayReplacements, objectReplacements)
pipelineTask.TaskRef.Params = pipelineTask.TaskRef.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements)
}
resolvedPipelineRunTask.PipelineTask = pipelineTask
}
Expand All @@ -198,10 +198,10 @@ func ApplyPipelineTaskStateContext(state PipelineRunState, replacements map[stri
for _, resolvedPipelineRunTask := range state {
if resolvedPipelineRunTask.PipelineTask != nil {
pipelineTask := resolvedPipelineRunTask.PipelineTask.DeepCopy()
pipelineTask.Params = replaceParamValues(pipelineTask.Params, replacements, nil, nil)
pipelineTask.Params = pipelineTask.Params.ReplaceVariables(replacements, nil, nil)
pipelineTask.WhenExpressions = pipelineTask.WhenExpressions.ReplaceVariables(replacements, nil)
if pipelineTask.TaskRef != nil && pipelineTask.TaskRef.Params != nil {
pipelineTask.TaskRef.Params = replaceParamValues(pipelineTask.TaskRef.Params, replacements, nil, nil)
pipelineTask.TaskRef.Params = pipelineTask.TaskRef.Params.ReplaceVariables(replacements, nil, nil)
}
resolvedPipelineRunTask.PipelineTask = pipelineTask
}
Expand Down Expand Up @@ -229,37 +229,37 @@ func ApplyReplacements(p *v1beta1.PipelineSpec, replacements map[string]string,
p = p.DeepCopy()

for i := range p.Tasks {
p.Tasks[i].Params = replaceParamValues(p.Tasks[i].Params, replacements, arrayReplacements, objectReplacements)
p.Tasks[i].Params = p.Tasks[i].Params.ReplaceVariables(replacements, arrayReplacements, objectReplacements)
if p.Tasks[i].IsMatrixed() {
p.Tasks[i].Matrix.Params = replaceParamValues(p.Tasks[i].Matrix.Params, replacements, arrayReplacements, nil)
p.Tasks[i].Matrix.Params = p.Tasks[i].Matrix.Params.ReplaceVariables(replacements, arrayReplacements, nil)
for j := range p.Tasks[i].Matrix.Include {
p.Tasks[i].Matrix.Include[j].Params = replaceParamValues(p.Tasks[i].Matrix.Include[j].Params, replacements, nil, nil)
p.Tasks[i].Matrix.Include[j].Params = p.Tasks[i].Matrix.Include[j].Params.ReplaceVariables(replacements, nil, nil)
}
}
for j := range p.Tasks[i].Workspaces {
p.Tasks[i].Workspaces[j].SubPath = substitution.ApplyReplacements(p.Tasks[i].Workspaces[j].SubPath, replacements)
}
p.Tasks[i].WhenExpressions = p.Tasks[i].WhenExpressions.ReplaceVariables(replacements, arrayReplacements)
if p.Tasks[i].TaskRef != nil && p.Tasks[i].TaskRef.Params != nil {
p.Tasks[i].TaskRef.Params = replaceParamValues(p.Tasks[i].TaskRef.Params, replacements, arrayReplacements, objectReplacements)
p.Tasks[i].TaskRef.Params = p.Tasks[i].TaskRef.Params.ReplaceVariables(replacements, arrayReplacements, objectReplacements)
}
p.Tasks[i] = propagateParams(p.Tasks[i], replacements, arrayReplacements, objectReplacements)
}

for i := range p.Finally {
p.Finally[i].Params = replaceParamValues(p.Finally[i].Params, replacements, arrayReplacements, objectReplacements)
p.Finally[i].Params = p.Finally[i].Params.ReplaceVariables(replacements, arrayReplacements, objectReplacements)
if p.Finally[i].IsMatrixed() {
p.Finally[i].Matrix.Params = replaceParamValues(p.Finally[i].Matrix.Params, replacements, arrayReplacements, nil)
p.Finally[i].Matrix.Params = p.Finally[i].Matrix.Params.ReplaceVariables(replacements, arrayReplacements, nil)
for j := range p.Finally[i].Matrix.Include {
p.Finally[i].Matrix.Include[j].Params = replaceParamValues(p.Finally[i].Matrix.Include[j].Params, replacements, nil, nil)
p.Finally[i].Matrix.Include[j].Params = p.Finally[i].Matrix.Include[j].Params.ReplaceVariables(replacements, nil, nil)
}
}
for j := range p.Finally[i].Workspaces {
p.Finally[i].Workspaces[j].SubPath = substitution.ApplyReplacements(p.Finally[i].Workspaces[j].SubPath, replacements)
}
p.Finally[i].WhenExpressions = p.Finally[i].WhenExpressions.ReplaceVariables(replacements, arrayReplacements)
if p.Finally[i].TaskRef != nil && p.Finally[i].TaskRef.Params != nil {
p.Finally[i].TaskRef.Params = replaceParamValues(p.Finally[i].TaskRef.Params, replacements, arrayReplacements, objectReplacements)
p.Finally[i].TaskRef.Params = p.Finally[i].TaskRef.Params.ReplaceVariables(replacements, arrayReplacements, objectReplacements)
}
p.Finally[i] = propagateParams(p.Finally[i], replacements, arrayReplacements, objectReplacements)
}
Expand Down Expand Up @@ -313,13 +313,6 @@ func propagateParams(t v1beta1.PipelineTask, stringReplacements map[string]strin
return t
}

func replaceParamValues(params v1beta1.Params, stringReplacements map[string]string, arrayReplacements map[string][]string, objectReplacements map[string]map[string]string) v1beta1.Params {
for i := range params {
params[i].Value.ApplyReplacements(stringReplacements, arrayReplacements, objectReplacements)
}
return params
}

// ApplyTaskResultsToPipelineResults applies the results of completed TasksRuns and Runs to a Pipeline's
// list of PipelineResults, returning the computed set of PipelineRunResults. References to
// non-existent TaskResults or failed TaskRuns or Runs result in a PipelineResult being considered invalid
Expand Down
2 changes: 1 addition & 1 deletion pkg/reconciler/pipelinerun/resources/pipelineref.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func GetPipelineFunc(ctx context.Context, k8s kubernetes.Interface, tekton clien
for k, v := range GetContextReplacements("", pipelineRun) {
stringReplacements[k] = v
}
replacedParams := replaceParamValues(pr.Params, stringReplacements, arrayReplacements, objectReplacements)
replacedParams := pr.Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements)
resolver := resolution.NewResolver(requester, pipelineRun, string(pr.Resolver), "", "", replacedParams)
return resolvePipeline(ctx, resolver, name, k8s, verificationPolicies)
}
Expand Down