Skip to content

Commit

Permalink
Add support for params between Step and StepActions
Browse files Browse the repository at this point in the history
Following the previous [PR](#7317), which introduced Params to the `StepAction` CRD,
this PR integrates `param` usage between `Steps` and `StepActions`. This
completes support for params in `StepActions`. This work is part of
issue #7259.
  • Loading branch information
chitrangpatel authored and tekton-robot committed Nov 9, 2023
1 parent 85f9863 commit c2098de
Show file tree
Hide file tree
Showing 11 changed files with 939 additions and 40 deletions.
67 changes: 67 additions & 0 deletions examples/v1/pipelineruns/alpha/stepaction-params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: step-action
spec:
params:
- name: string-param
default: "a string param"
- name: array-param
type: array
default:
- an
- array
- param
- name: object-param
type: object
properties:
key1:
type: string
key2:
type: string
key3:
type: string
default:
key1: "step-action default key1"
key2: "step-action default key2"
key3: "step-action default key3"
image: bash:3.2
args: [
"echo",
"$(params.array-param[*])",
"$(params.string-param)",
"$(params.object-param.key1)",
"$(params.object-param.key2)"
]
---
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
name: step-action-pipeline-run-propagated
spec:
params:
- name: stringparam
value: "pipelinerun stringparam"
- name: arrayparam
value:
- "pipelinerun"
- "array"
- "param"
- name: objectparam
value:
key2: "pipelinerun key2"
PipelineSpec:
tasks:
- name: run-action
taskSpec:
steps:
- name: action-runner
ref:
name: step-action
params:
- name: string-param
value: $(params.stringparam)
- name: array-param
value: $(params.arrayparam[*])
- name: object-param
value: $(params.objectparam[*])
82 changes: 82 additions & 0 deletions examples/v1/taskruns/alpha/stepaction-params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
apiVersion: tekton.dev/v1alpha1
kind: StepAction
metadata:
name: step-action
spec:
params:
- name: string-param
default: "a string param"
- name: array-param
type: array
default:
- an
- array
- param
- name: object-param
type: object
properties:
key1:
type: string
key2:
type: string
key3:
type: string
default:
key1: "step-action default key1"
key2: "step-action default key2"
key3: "step-action default key3"
image: ubuntu
script: |
#!/bin/bash
ARRAYVALUE=("$(params.array-param[0])" "$(params.array-param[1])" "$(params.array-param[2])" "$(params.string-param)" "$(params.object-param.key1)" "$(params.object-param.key2)" "$(params.object-param.key3)")
ARRAYEXPECTED=("taskrun" "array" "param" "taskrun stringparam" "taskspec default key1" "taskrun key2" "step-action default key3")
for i in "${!ARRAYVALUE[@]}"; do
VALUE="${ARRAYVALUE[i]}"
EXPECTED="${ARRAYEXPECTED[i]}"
diff=$(diff <(printf "%s\n" "${VALUE[@]}") <(printf "%s\n" "${EXPECTED[@]}"))
if [[ -z "$diff" ]]; then
echo "Got expected: ${VALUE}"
else
echo "Want: ${EXPECTED} Got: ${VALUE}"
exit 1
fi
done
---
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: step-action-run
spec:
params:
- name: stringparam
value: "taskrun stringparam"
- name: arrayparam
value:
- "taskrun"
- "array"
- "param"
- name: objectparam
value:
key2: "taskrun key2"
TaskSpec:
params:
- name: objectparam
properties:
key1:
type: string
key2:
type: string
default:
key1: "taskspec default key1"
key2: "taskspec default key2"
steps:
- name: action-runner
ref:
name: step-action
params:
- name: string-param
value: $(params.stringparam)
- name: array-param
value: $(params.arrayparam[*])
- name: object-param
value: $(params.objectparam[*])
6 changes: 3 additions & 3 deletions pkg/reconciler/pipelinerun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,9 @@ func propagateParams(t v1.PipelineTask, stringReplacements map[string]string, ar
}
}
}
t.TaskSpec.TaskSpec = *resources.ApplyReplacements(&t.TaskSpec.TaskSpec, stringReplacementsDup, arrayReplacementsDup)
t.TaskSpec.TaskSpec = *resources.ApplyReplacements(&t.TaskSpec.TaskSpec, stringReplacementsDup, arrayReplacementsDup, objectReplacementsDup)
} else {
t.TaskSpec.TaskSpec = *resources.ApplyReplacements(&t.TaskSpec.TaskSpec, stringReplacements, arrayReplacements)
t.TaskSpec.TaskSpec = *resources.ApplyReplacements(&t.TaskSpec.TaskSpec, stringReplacements, arrayReplacements, objectReplacements)
}
return t
}
Expand All @@ -395,7 +395,7 @@ func PropagateResults(rpt *ResolvedPipelineTask, runStates PipelineRunState) {
}
}
}
rpt.ResolvedTask.TaskSpec = resources.ApplyReplacements(rpt.ResolvedTask.TaskSpec, stringReplacements, arrayReplacements)
rpt.ResolvedTask.TaskSpec = resources.ApplyReplacements(rpt.ResolvedTask.TaskSpec, stringReplacements, arrayReplacements, map[string]map[string]string{})
}

// ApplyTaskResultsToPipelineResults applies the results of completed TasksRuns and Runs to a Pipeline's
Expand Down
103 changes: 78 additions & 25 deletions pkg/reconciler/taskrun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,66 @@ var (
}
)

// ApplyParameters applies the params from a TaskRun.Input.Parameters to a TaskSpec
func ApplyParameters(ctx context.Context, spec *v1.TaskSpec, tr *v1.TaskRun, defaults ...v1.ParamSpec) *v1.TaskSpec {
// applyStepActionParameters applies the params from the Task and the underlying Step to the referenced StepAction.
func applyStepActionParameters(step *v1.Step, spec *v1.TaskSpec, tr *v1.TaskRun, stepParams v1.Params, defaults []v1.ParamSpec) *v1.Step {
if stepParams != nil {
stringR, arrayR, objectR := getTaskParameters(spec, tr, spec.Params...)
stepParams = stepParams.ReplaceVariables(stringR, arrayR, objectR)
}
// Set params from StepAction defaults
stringReplacements, arrayReplacements, _ := replacementsFromDefaultParams(defaults)

// Set and overwrite params with the ones from the Step
stepStrings, stepArrays, _ := replacementsFromParams(stepParams)
for k, v := range stepStrings {
stringReplacements[k] = v
}
for k, v := range stepArrays {
arrayReplacements[k] = v
}

container.ApplyStepReplacements(step, stringReplacements, arrayReplacements)
return step
}

// getTaskParameters gets the string, array and object parameter variable replacements needed in the Task
func getTaskParameters(spec *v1.TaskSpec, tr *v1.TaskRun, defaults ...v1.ParamSpec) (map[string]string, map[string][]string, map[string]map[string]string) {
// This assumes that the TaskRun inputs have been validated against what the Task requests.
// Set params from Task defaults
stringReplacements, arrayReplacements, objectReplacements := replacementsFromDefaultParams(defaults)

// stringReplacements is used for standard single-string stringReplacements, while arrayReplacements contains arrays
// that need to be further processed.
// Set and overwrite params with the ones from the TaskRun
trStrings, trArrays, trObjects := replacementsFromParams(tr.Spec.Params)
for k, v := range trStrings {
stringReplacements[k] = v
}
for k, v := range trArrays {
arrayReplacements[k] = v
}
for k, v := range trObjects {
for key, val := range v {
if objectReplacements != nil {
if objectReplacements[k] != nil {
objectReplacements[k][key] = val
} else {
objectReplacements[k] = v
}
}
}
}
return stringReplacements, arrayReplacements, objectReplacements
}

// ApplyParameters applies the params from a TaskRun.Parameters to a TaskSpec
func ApplyParameters(spec *v1.TaskSpec, tr *v1.TaskRun, defaults ...v1.ParamSpec) *v1.TaskSpec {
stringReplacements, arrayReplacements, objectReplacements := getTaskParameters(spec, tr, defaults...)
return ApplyReplacements(spec, stringReplacements, arrayReplacements, objectReplacements)
}

func replacementsFromDefaultParams(defaults v1.ParamSpecs) (map[string]string, map[string][]string, map[string]map[string]string) {
stringReplacements := map[string]string{}
arrayReplacements := map[string][]string{}
objectReplacements := map[string]map[string]string{}

// Set all the default stringReplacements
for _, p := range defaults {
Expand All @@ -67,6 +119,9 @@ func ApplyParameters(ctx context.Context, spec *v1.TaskSpec, tr *v1.TaskRun, def
arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.ArrayVal
}
case v1.ParamTypeObject:
for _, pattern := range paramPatterns {
objectReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.ObjectVal
}
for k, v := range p.Default.ObjectVal {
stringReplacements[fmt.Sprintf(objectIndividualVariablePattern, p.Name, k)] = v
}
Expand All @@ -79,25 +134,17 @@ func ApplyParameters(ctx context.Context, spec *v1.TaskSpec, tr *v1.TaskRun, def
}
}
}
// Set and overwrite params with the ones from the TaskRun
trStrings, trArrays := paramsFromTaskRun(ctx, tr)
for k, v := range trStrings {
stringReplacements[k] = v
}
for k, v := range trArrays {
arrayReplacements[k] = v
}

return ApplyReplacements(spec, stringReplacements, arrayReplacements)
return stringReplacements, arrayReplacements, objectReplacements
}

func paramsFromTaskRun(ctx context.Context, tr *v1.TaskRun) (map[string]string, map[string][]string) {
func replacementsFromParams(params v1.Params) (map[string]string, map[string][]string, map[string]map[string]string) {
// stringReplacements is used for standard single-string stringReplacements, while arrayReplacements contains arrays
// that need to be further processed.
// and objectReplacements contains objects that need to be further processed.
stringReplacements := map[string]string{}
arrayReplacements := map[string][]string{}
objectReplacements := map[string]map[string]string{}

for _, p := range tr.Spec.Params {
for _, p := range params {
switch p.Value.Type {
case v1.ParamTypeArray:
for _, pattern := range paramPatterns {
Expand All @@ -107,6 +154,9 @@ func paramsFromTaskRun(ctx context.Context, tr *v1.TaskRun) (map[string]string,
arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.ArrayVal
}
case v1.ParamTypeObject:
for _, pattern := range paramPatterns {
objectReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.ObjectVal
}
for k, v := range p.Value.ObjectVal {
stringReplacements[fmt.Sprintf(objectIndividualVariablePattern, p.Name, k)] = v
}
Expand All @@ -119,7 +169,7 @@ func paramsFromTaskRun(ctx context.Context, tr *v1.TaskRun) (map[string]string,
}
}

return stringReplacements, arrayReplacements
return stringReplacements, arrayReplacements, objectReplacements
}

func getContextReplacements(taskName string, tr *v1.TaskRun) map[string]string {
Expand All @@ -135,7 +185,7 @@ func getContextReplacements(taskName string, tr *v1.TaskRun) map[string]string {
// ApplyContexts applies the substitution from $(context.(taskRun|task).*) with the specified values.
// Uses "" as a default if a value is not available.
func ApplyContexts(spec *v1.TaskSpec, taskName string, tr *v1.TaskRun) *v1.TaskSpec {
return ApplyReplacements(spec, getContextReplacements(taskName, tr), map[string][]string{})
return ApplyReplacements(spec, getContextReplacements(taskName, tr), map[string][]string{}, map[string]map[string]string{})
}

// ApplyWorkspaces applies the substitution from paths that the workspaces in declarations mounted to, the
Expand Down Expand Up @@ -170,7 +220,7 @@ func ApplyWorkspaces(ctx context.Context, spec *v1.TaskSpec, declarations []v1.W
stringReplacements[fmt.Sprintf("workspaces.%s.claim", binding.Name)] = ""
}
}
return ApplyReplacements(spec, stringReplacements, map[string][]string{})
return ApplyReplacements(spec, stringReplacements, map[string][]string{}, map[string]map[string]string{})
}

// applyWorkspaceMountPath accepts a workspace path variable of the form $(workspaces.foo.path) and replaces
Expand Down Expand Up @@ -204,7 +254,7 @@ func applyWorkspaceMountPath(variable string, spec *v1.TaskSpec, declaration v1.
// Replace any remaining instances of the workspace path variable, which should fall
// back to the mount path specified in the declaration.
stringReplacements[variable] = defaultMountPath
return ApplyReplacements(spec, stringReplacements, emptyArrayReplacements)
return ApplyReplacements(spec, stringReplacements, emptyArrayReplacements, map[string]map[string]string{})
}

// ApplyTaskResults applies the substitution from values in results which are referenced in spec as subitems
Expand All @@ -223,7 +273,7 @@ func ApplyTaskResults(spec *v1.TaskSpec) *v1.TaskSpec {
stringReplacements[fmt.Sprintf(pattern, result.Name)] = filepath.Join(pipeline.DefaultResultPath, result.Name)
}
}
return ApplyReplacements(spec, stringReplacements, map[string][]string{})
return ApplyReplacements(spec, stringReplacements, map[string][]string{}, map[string]map[string]string{})
}

// ApplyStepExitCodePath replaces the occurrences of exitCode path with the absolute tekton internal path
Expand All @@ -235,7 +285,7 @@ func ApplyStepExitCodePath(spec *v1.TaskSpec) *v1.TaskSpec {
stringReplacements[fmt.Sprintf("steps.%s.exitCode.path", pod.StepName(step.Name, i))] =
filepath.Join(pipeline.StepsDir, pod.StepName(step.Name, i), "exitCode")
}
return ApplyReplacements(spec, stringReplacements, map[string][]string{})
return ApplyReplacements(spec, stringReplacements, map[string][]string{}, map[string]map[string]string{})
}

// ApplyCredentialsPath applies a substitution of the key $(credentials.path) with the path that credentials
Expand All @@ -244,16 +294,19 @@ func ApplyCredentialsPath(spec *v1.TaskSpec, path string) *v1.TaskSpec {
stringReplacements := map[string]string{
"credentials.path": path,
}
return ApplyReplacements(spec, stringReplacements, map[string][]string{})
return ApplyReplacements(spec, stringReplacements, map[string][]string{}, map[string]map[string]string{})
}

// ApplyReplacements replaces placeholders for declared parameters with the specified replacements.
func ApplyReplacements(spec *v1.TaskSpec, stringReplacements map[string]string, arrayReplacements map[string][]string) *v1.TaskSpec {
func ApplyReplacements(spec *v1.TaskSpec, stringReplacements map[string]string, arrayReplacements map[string][]string, objectReplacements map[string]map[string]string) *v1.TaskSpec {
spec = spec.DeepCopy()

// Apply variable expansion to steps fields.
steps := spec.Steps
for i := range steps {
if steps[i].Params != nil {
steps[i].Params = steps[i].Params.ReplaceVariables(stringReplacements, arrayReplacements, objectReplacements)
}
container.ApplyStepReplacements(&steps[i], stringReplacements, arrayReplacements)
}

Expand Down
Loading

0 comments on commit c2098de

Please sign in to comment.