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

Add expansion of context.(pipeline|pipelinerun|task|taskRun).name and add tests #2880

Merged
merged 1 commit into from
Jul 1, 2020
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
5 changes: 5 additions & 0 deletions docs/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ This page documents the variable substitions supported by `Tasks` and `Pipelines
| -------- | ----------- |
| `params.<param name>` | The value of the parameter at runtime. |
| `tasks.<taskName>.results.<resultName>` | The value of the `Task's` result. Can alter `Task` execution order within a `Pipeline`.) |
| `context.pipelineRun.name` | The name of the `PipelineRun` that this `Pipeline` is running in. |
| `context.pipeline.name` | The name of this `Pipeline` . |


## Variables available in a `Task`

Expand All @@ -27,6 +30,8 @@ This page documents the variable substitions supported by `Tasks` and `Pipelines
| `workspaces.<workspaceName>.claim` | The name of the `PersistentVolumeClaim` specified as a volume source for the `Workspace`. Empty string for other volume types. |
| `workspaces.<workspaceName>.volume` | The name of the volume populating the `Workspace`. |
| `credentials.path` | The path to the credentials written by the `creds-init` init container. |
| `context.taskRun.name` | The name of the `TaskRun` that this `Task` is running in. |
| `context.task.name` | The name of this `Task`. |

### `PipelineResource` variables available in a `Task`

Expand Down
1 change: 1 addition & 0 deletions pkg/reconciler/pipelinerun/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1beta1.PipelineRun) err

// Apply parameter substitution from the PipelineRun
pipelineSpec = resources.ApplyParameters(pipelineSpec, pr)
pipelineSpec = resources.ApplyContexts(pipelineSpec, pipelineMeta.Name, pr)

// pipelineState holds a list of pipeline tasks after resolving conditions and pipeline resources
// pipelineState also holds a taskRun for each pipeline task after the taskRun is created
Expand Down
19 changes: 13 additions & 6 deletions pkg/reconciler/pipelinerun/pipelinerun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ func TestReconcile(t *testing.T) {
// TestReconcile runs "Reconcile" on a PipelineRun with one Task that has not been started yet.
// It verifies that the TaskRun is created, it checks the resulting API actions, status and events.
names.TestingSeed()

const pipelineRunName = "test-pipeline-run-success"
prs := []*v1beta1.PipelineRun{
tb.PipelineRun("test-pipeline-run-success",
tb.PipelineRun(pipelineRunName,
tb.PipelineRunNamespace("foo"),
tb.PipelineRunSpec("test-pipeline",
tb.PipelineRunServiceAccountName("test-sa"),
Expand All @@ -160,8 +160,11 @@ func TestReconcile(t *testing.T) {
funParam := tb.PipelineTaskParam("foo", "somethingfun")
moreFunParam := tb.PipelineTaskParam("bar", "$(params.bar)")
templatedParam := tb.PipelineTaskParam("templatedparam", "$(inputs.workspace.$(params.rev-param))")
contextRunParam := tb.PipelineTaskParam("contextRunParam", "$(context.pipelineRun.name)")
contextPipelineParam := tb.PipelineTaskParam("contextPipelineParam", "$(context.pipeline.name)")
const pipelineName = "test-pipeline"
ps := []*v1beta1.Pipeline{
tb.Pipeline("test-pipeline",
tb.Pipeline(pipelineName,
tb.PipelineNamespace("foo"),
tb.PipelineSpec(
tb.PipelineDeclaredResource("git-repo", "git"),
Expand All @@ -171,15 +174,15 @@ func TestReconcile(t *testing.T) {
tb.PipelineParamSpec("bar", v1beta1.ParamTypeString),
// unit-test-3 uses runAfter to indicate it should run last
tb.PipelineTask("unit-test-3", "unit-test-task",
funParam, moreFunParam, templatedParam,
funParam, moreFunParam, templatedParam, contextRunParam, contextPipelineParam,
tb.RunAfter("unit-test-2"),
tb.PipelineTaskInputResource("workspace", "git-repo"),
tb.PipelineTaskOutputResource("image-to-use", "best-image"),
tb.PipelineTaskOutputResource("workspace", "git-repo"),
),
// unit-test-1 can run right away because it has no dependencies
tb.PipelineTask("unit-test-1", "unit-test-task",
funParam, moreFunParam, templatedParam,
funParam, moreFunParam, templatedParam, contextRunParam, contextPipelineParam,
tb.PipelineTaskInputResource("workspace", "git-repo"),
tb.PipelineTaskOutputResource("image-to-use", "best-image"),
tb.PipelineTaskOutputResource("workspace", "git-repo"),
Expand All @@ -191,7 +194,7 @@ func TestReconcile(t *testing.T) {
// unit-test-cluster-task can run right away because it has no dependencies
tb.PipelineTask("unit-test-cluster-task", "unit-test-cluster-task",
tb.PipelineTaskRefKind(v1beta1.ClusterTaskKind),
funParam, moreFunParam, templatedParam,
funParam, moreFunParam, templatedParam, contextRunParam, contextPipelineParam,
tb.PipelineTaskInputResource("workspace", "git-repo"),
tb.PipelineTaskOutputResource("image-to-use", "best-image"),
tb.PipelineTaskOutputResource("workspace", "git-repo"),
Expand All @@ -202,6 +205,7 @@ func TestReconcile(t *testing.T) {
ts := []*v1beta1.Task{
tb.Task("unit-test-task", tb.TaskSpec(
tb.TaskParam("foo", v1beta1.ParamTypeString), tb.TaskParam("bar", v1beta1.ParamTypeString), tb.TaskParam("templatedparam", v1beta1.ParamTypeString),
tb.TaskParam("contextRunParam", v1beta1.ParamTypeString), tb.TaskParam("contextPipelineParam", v1beta1.ParamTypeString),
tb.TaskResources(
tb.TaskResourcesInput("workspace", resourcev1alpha1.PipelineResourceTypeGit),
tb.TaskResourcesOutput("image-to-use", resourcev1alpha1.PipelineResourceTypeImage),
Expand All @@ -215,6 +219,7 @@ func TestReconcile(t *testing.T) {
clusterTasks := []*v1beta1.ClusterTask{
tb.ClusterTask("unit-test-cluster-task", tb.ClusterTaskSpec(
tb.TaskParam("foo", v1beta1.ParamTypeString), tb.TaskParam("bar", v1beta1.ParamTypeString), tb.TaskParam("templatedparam", v1beta1.ParamTypeString),
tb.TaskParam("contextRunParam", v1beta1.ParamTypeString), tb.TaskParam("contextPipelineParam", v1beta1.ParamTypeString),
tb.TaskResources(
tb.TaskResourcesInput("workspace", resourcev1alpha1.PipelineResourceTypeGit),
tb.TaskResourcesOutput("image-to-use", resourcev1alpha1.PipelineResourceTypeImage),
Expand Down Expand Up @@ -283,6 +288,8 @@ func TestReconcile(t *testing.T) {
tb.TaskRunParam("foo", "somethingfun"),
tb.TaskRunParam("bar", "somethingmorefun"),
tb.TaskRunParam("templatedparam", "$(inputs.workspace.revision)"),
tb.TaskRunParam("contextRunParam", pipelineRunName),
tb.TaskRunParam("contextPipelineParam", pipelineName),
tb.TaskRunResources(
tb.TaskRunResourcesInput("workspace", tb.TaskResourceBindingRef("some-repo")),
tb.TaskRunResourcesOutput("image-to-use",
Expand Down
12 changes: 12 additions & 0 deletions pkg/reconciler/pipelinerun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ func ApplyParameters(p *v1beta1.PipelineSpec, pr *v1beta1.PipelineRun) *v1beta1.
return ApplyReplacements(p, stringReplacements, arrayReplacements)
}

// ApplyContexts applies the substitution from $(context.(pipelineRun|pipeline).*) with the specified values.
// Currently supports only name substitution. Uses "" as a default if name is not specified.
func ApplyContexts(spec *v1beta1.PipelineSpec, pipelineName string, pr *v1beta1.PipelineRun) *v1beta1.PipelineSpec {
stringReplacements := map[string]string{}
R2wenD2 marked this conversation as resolved.
Show resolved Hide resolved
stringReplacements["context.pipelineRun.name"] = pr.Name
stringReplacements["context.pipeline.name"] = pipelineName

return ApplyReplacements(spec,
map[string]string{"context.pipelineRun.name": pr.Name, "context.pipeline.name": pipelineName},
map[string][]string{})
}

// ApplyTaskResults applies the ResolvedResultRef to each PipelineTask.Params in targets
func ApplyTaskResults(targets PipelineRunState, resolvedResultRefs ResolvedResultRefs) {
stringReplacements := map[string]string{}
Expand Down
68 changes: 68 additions & 0 deletions pkg/reconciler/pipelinerun/resources/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,71 @@ func TestApplyTaskResults_Conditions(t *testing.T) {
})
}
}

func TestContext(t *testing.T) {
for _, tc := range []struct {
description string
pr *v1beta1.PipelineRun
original *v1beta1.Pipeline
expected *v1beta1.Pipeline
}{{
description: "context pipeline name replacement without pipelineRun in spec",
original: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "$(context.pipeline.name)-1"),
))),
expected: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "test-pipeline-1"),
))),
pr: &v1beta1.PipelineRun{},
}, {
description: "context pipeline name replacement with pipelineRun in spec",
pr: tb.PipelineRun("pipelineRunName"),
original: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "$(context.pipeline.name)-1"),
))),
expected: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "test-pipeline-1"),
))),
}, {
description: "context pipelineRunName replacement with defined pipelineRun in spec",
pr: tb.PipelineRun("pipelineRunName"),
original: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "$(context.pipelineRun.name)-1"),
))),
expected: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "pipelineRunName-1"),
))),
}, {
description: "context pipelineRunName replacement with no defined pipeline in spec",
pr: &v1beta1.PipelineRun{},
original: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "$(context.pipelineRun.name)-1"),
))),
expected: tb.Pipeline("test-pipeline",
tb.PipelineSpec(
tb.PipelineTask("first-task-1", "first-task",
tb.PipelineTaskParam("first-task-first-param", "-1"),
))),
}} {
t.Run(tc.description, func(t *testing.T) {
got := ApplyContexts(&tc.original.Spec, tc.original.Name, tc.pr)
if d := cmp.Diff(tc.expected.Spec, *got); d != "" {
t.Errorf(diff.PrintWantGot(d))
}
})
}
}
12 changes: 12 additions & 0 deletions pkg/reconciler/taskrun/resources/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@ func ApplyResources(spec *v1beta1.TaskSpec, resolvedResources map[string]v1beta1
return ApplyReplacements(spec, replacements, map[string][]string{})
}

// ApplyContexts applies the substitution from $(context.(taskRun|task).*) with the specified values.
// Currently supports only name substitution. Uses "" as a default if name is not specified.
func ApplyContexts(spec *v1beta1.TaskSpec, rtr *ResolvedTaskResources, tr *v1beta1.TaskRun) *v1beta1.TaskSpec {
stringReplacements := map[string]string{}
R2wenD2 marked this conversation as resolved.
Show resolved Hide resolved
stringReplacements["context.taskRun.name"] = tr.Name
stringReplacements["context.task.name"] = rtr.TaskName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to double-check, if I'm defining a TaskRun's TaskSpec inline, there won't be a Task name, and this context value will be "", right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, and I added a testcase to confirm.


return ApplyReplacements(spec,
map[string]string{"context.taskRun.name": tr.Name, "context.task.name": rtr.TaskName},
map[string][]string{})
}

// ApplyWorkspaces applies the substitution from paths that the workspaces in w are mounted to, the
// volumes that wb are realized with in the task spec ts and the PersistentVolumeClaim names for the
// workspaces.
Expand Down
133 changes: 133 additions & 0 deletions pkg/reconciler/taskrun/resources/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,139 @@ func TestApplyWorkspaces(t *testing.T) {
}
}

func TestContext(t *testing.T) {
for _, tc := range []struct {
description string
rtr resources.ResolvedTaskResources
tr v1beta1.TaskRun
spec v1beta1.TaskSpec
want v1beta1.TaskSpec
}{{
description: "context taskName replacement without taskRun in spec container",
rtr: resources.ResolvedTaskResources{
TaskName: "Task1",
},
tr: v1beta1.TaskRun{},
spec: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "$(context.task.name)-1",
},
}},
},
want: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "Task1-1",
},
}},
},
}, {
description: "context taskName replacement with taskRun in spec container",
rtr: resources.ResolvedTaskResources{
TaskName: "Task1",
},
tr: v1beta1.TaskRun{
ObjectMeta: metav1.ObjectMeta{
Name: "taskrunName",
},
},
spec: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "$(context.task.name)-1",
},
}},
},
want: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "Task1-1",
},
}},
},
}, {
description: "context taskRunName replacement with defined taskRun in spec container",
rtr: resources.ResolvedTaskResources{
TaskName: "Task1",
},
tr: v1beta1.TaskRun{
ObjectMeta: metav1.ObjectMeta{
Name: "taskrunName",
},
},
spec: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "$(context.taskRun.name)-1",
},
}},
},
want: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "taskrunName-1",
},
}},
},
}, {
description: "context taskRunName replacement with no defined taskRun in spec container",
rtr: resources.ResolvedTaskResources{
TaskName: "Task1",
},
tr: v1beta1.TaskRun{},
spec: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "$(context.taskRun.name)-1",
},
}},
},
want: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "-1",
},
}},
},
}, {
description: "context taskRunName replacement with no defined taskName in spec container",
rtr: resources.ResolvedTaskResources{},
tr: v1beta1.TaskRun{},
spec: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "$(context.task.name)-1",
},
}},
},
want: v1beta1.TaskSpec{
Steps: []v1beta1.Step{{
Container: corev1.Container{
Name: "ImageName",
Image: "-1",
},
}},
},
}} {
t.Run(tc.description, func(t *testing.T) {
got := resources.ApplyContexts(&tc.spec, &tc.rtr, &tc.tr)
if d := cmp.Diff(&tc.want, got); d != "" {
t.Errorf(diff.PrintWantGot(d))
}
})
}
}

func TestTaskResults(t *testing.T) {
names.TestingSeed()
ts := &v1beta1.TaskSpec{
Expand Down
3 changes: 3 additions & 0 deletions pkg/reconciler/taskrun/taskrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ func (c *Reconciler) createPod(ctx context.Context, tr *v1beta1.TaskRun, rtr *re
// Apply parameter substitution from the taskrun.
ts = resources.ApplyParameters(ts, tr, defaults...)

// Apply context substitution from the taskrun
ts = resources.ApplyContexts(ts, rtr, tr)

// Apply bound resource substitution from the taskrun.
ts = resources.ApplyResources(ts, inputResources, "inputs")
ts = resources.ApplyResources(ts, outputResources, "outputs")
Expand Down
5 changes: 4 additions & 1 deletion pkg/reconciler/taskrun/taskrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ var (
"--my-arg-with-default=$(inputs.params.myarghasdefault)",
"--my-arg-with-default2=$(inputs.params.myarghasdefault2)",
"--my-additional-arg=$(outputs.resources.myimage.url)",
"--my-taskname-arg=$(context.task.name)",
"--my-taskrun-arg=$(context.taskRun.name)",
)),
tb.Step("myotherimage", tb.StepName("myothercontainer"), tb.StepCommand("/mycmd"), tb.StepArgs(
"--my-other-arg=$(inputs.resources.workspace.url)",
Expand Down Expand Up @@ -955,7 +957,8 @@ func TestReconcile(t *testing.T) {
tb.Command(entrypointLocation),
tb.Args("-wait_file", "/tekton/tools/1", "-post_file", "/tekton/tools/2", "-termination_path",
"/tekton/termination", "-entrypoint", "/mycmd", "--", "--my-arg=foo", "--my-arg-with-default=bar",
"--my-arg-with-default2=thedefault", "--my-additional-arg=gcr.io/kristoff/sven"),
"--my-arg-with-default2=thedefault", "--my-additional-arg=gcr.io/kristoff/sven", "--my-taskname-arg=test-task-with-substitution",
"--my-taskrun-arg=test-taskrun-substitution"),
tb.WorkingDir(workspaceDir),
tb.EnvVar("HOME", "/tekton/home"),
tb.VolumeMount("tekton-internal-tools", "/tekton/tools"),
Expand Down