Skip to content

Commit

Permalink
Add expansion of context.(pipeline|pipelinerun|task|taskRun).name and
Browse files Browse the repository at this point in the history
add tests.
  • Loading branch information
R2wenD2 committed Jul 1, 2020
1 parent c7a60b8 commit 7abf545
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 7 deletions.
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{}
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{}
stringReplacements["context.taskRun.name"] = tr.Name
stringReplacements["context.task.name"] = rtr.TaskName

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

0 comments on commit 7abf545

Please sign in to comment.