Skip to content

Commit

Permalink
TEP-0111 - Propagating workspaces in Taskrun
Browse files Browse the repository at this point in the history
This POC illustrates propagating workspaces defined at the `pipelinerun` stage and directly referred at the `spec`. There is no need to specify it in the `pipelinespec` followed by `tasks` and `taskspec`.
  • Loading branch information
chitrangpatel committed Sep 9, 2022
1 parent 11e5c37 commit 13ef6d8
Show file tree
Hide file tree
Showing 15 changed files with 512 additions and 91 deletions.
1 change: 1 addition & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ Features currently in "alpha" are:
| [Isolated `Step` & `Sidecar` `Workspaces`](./workspaces.md#isolated-workspaces) | [TEP-0029](https://github.com/tektoncd/community/blob/main/teps/0029-step-workspaces.md) | [v0.24.0](https://github.com/tektoncd/pipeline/releases/tag/v0.24.0) | |
| [Hermetic Execution Mode](./hermetic.md) | [TEP-0025](https://github.com/tektoncd/community/blob/main/teps/0025-hermekton.md) | [v0.25.0](https://github.com/tektoncd/pipeline/releases/tag/v0.25.0) | |
| [Propagated `Parameters`](./taskruns.md#propagated-parameters) | [TEP-0107](https://github.com/tektoncd/community/blob/main/teps/0107-propagating-parameters.md) | [v0.36.0](https://github.com/tektoncd/pipeline/releases/tag/v0.36.0) | |
| [Propagated `Workspaces`](./pipelineruns.md#propagated-workspaces) | [TEP-0111](https://github.com/tektoncd/community/blob/main/teps/0111-propagating-workspaces.md) | | |
| [Windows Scripts](./tasks.md#windows-scripts) | [TEP-0057](https://github.com/tektoncd/community/blob/main/teps/0057-windows-support.md) | [v0.28.0](https://github.com/tektoncd/pipeline/releases/tag/v0.28.0) | |
| [Remote Tasks](./taskruns.md#remote-tasks) and [Remote Pipelines](./pipelineruns.md#remote-pipelines) | [TEP-0060](https://github.com/tektoncd/community/blob/main/teps/0060-remote-resolutiond.md) | | |
| [Debug](./debug.md) | [TEP-0042](https://github.com/tektoncd/community/blob/main/teps/0042-taskrun-breakpoint-on-failure.md) | [v0.26.0](https://github.com/tektoncd/pipeline/releases/tag/v0.26.0) | |
Expand Down
80 changes: 80 additions & 0 deletions docs/taskruns.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,86 @@ For more information, see the following topics:
- For a list of supported `Volume` types, see [Specifying `VolumeSources` in `Workspaces`](workspaces.md#specifying-volumesources-in-workspaces).
- For an end-to-end example, see [`Workspaces` in a `TaskRun`](../examples/v1beta1/taskruns/workspace.yaml).

#### Propagated Workspaces

**([alpha only](https://github.com/tektoncd/pipeline/blob/main/docs/install.md#alpha-features))**

When using an embedded spec, workspaces from the parent `TaskRun` will be
propagated to any inlined specs without needing to be explicitly defined. This
allows authors to simplify specs by automatically propagating top-level
workspaces down to other inlined resources.
**Workspace substutions will only be made for `commands`, `args` and `script` fields of `steps`, `stepTemplates`, and `sidecars`.**

```yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: propagating-workspaces-
spec:
taskSpec:
steps:
- name: simple-step
image: ubuntu
command:
- echo
args:
- $(workspaces.tr-workspace.path)
workspaces:
- emptyDir: {}
name: tr-workspace
```

Upon execution, the workspaces will be interpolated during resolution.

```yaml
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
name: propagating-workspaces-ndxnc
...
spec:
serviceAccountName: default
taskSpec:
steps:
- args:
- $(workspaces.tr-workspace.path)
command:
- echo
image: ubuntu
name: simple-step
resources: {}
timeout: 1h0m0s
workspaces:
- emptyDir: {}
name: tr-workspace
status:
completionTime: "2022-09-09T17:34:22Z"
conditions:
- lastTransitionTime: "2022-09-09T17:34:22Z"
message: All Steps have completed executing
reason: Succeeded
status: "True"
type: Succeeded
podName: propagating-workspaces-ndxnc-pod
startTime: "2022-09-09T17:34:17Z"
steps:
...
taskSpec:
steps:
- args:
- /workspace/tr-workspace
command:
- echo
image: ubuntu
name: simple-step
resources: {}
workspaces:
- name: tr-workspace
```

Workspaces can be propagated to embedded task specs, not referenced Tasks. For more information, see [Referenced TaskRuns within Embedded PipelineRuns](pipelineruns.md#referenced-taskruns-within-embedded-pipelineruns).

### Specifying `Sidecars`

A `Sidecar` is a container that runs alongside the containers specified
Expand Down
2 changes: 2 additions & 0 deletions docs/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,8 @@ spec:
For more information, see [Using `Workspaces` in `Tasks`](workspaces.md#using-workspaces-in-tasks)
and the [`Workspaces` in a `TaskRun`](../examples/v1beta1/taskruns/workspace.yaml) example YAML file.

Workspaces can be propagated to embedded task specs, not referenced Tasks. For more information, see [Referenced TaskRuns within Embedded PipelineRuns](pipelineruns.md#referenced-taskruns-within-embedded-pipelineruns).

### Emitting `Results`

A Task is able to emit string results that can be viewed by users and passed to other Tasks in a Pipeline. These
Expand Down
16 changes: 16 additions & 0 deletions examples/v1beta1/taskruns/alpha/propagating_workspaces.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
generateName: propagating-workspaces-
spec:
taskSpec:
steps:
- name: simple-step
image: ubuntu
command:
- echo
args:
- $(workspaces.tr-workspace.path)
workspaces:
- emptyDir: {}
name: tr-workspace
55 changes: 55 additions & 0 deletions pkg/apis/pipeline/v1/task_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/kmeta"
)

Expand Down Expand Up @@ -95,6 +96,60 @@ type TaskSpec struct {
Results []TaskResult `json:"results,omitempty"`
}

func findWorkspaceSubstitutionLocationsInSidecars(sidecars []Sidecar) sets.String {
locationsToCheck := sets.NewString()
for _, sidecar := range sidecars {
locationsToCheck.Insert(sidecar.Script)

for i := range sidecar.Args {
locationsToCheck.Insert(sidecar.Args[i])
}

for i := range sidecar.Command {
locationsToCheck.Insert(sidecar.Command[i])
}
}
return locationsToCheck
}

func findWorkspaceSubstitutionLocationsInSteps(steps []Step) sets.String {
locationsToCheck := sets.NewString()
for _, step := range steps {
locationsToCheck.Insert(step.Script)

for i := range step.Args {
locationsToCheck.Insert(step.Args[i])
}

for i := range step.Command {
locationsToCheck.Insert(step.Command[i])
}
}
return locationsToCheck
}

func findWorkspaceSubstitutionLocationsInStepTemplate(stepTemplate *StepTemplate) sets.String {
locationsToCheck := sets.NewString()

for i := range stepTemplate.Args {
locationsToCheck.Insert(stepTemplate.Args[i])
}

for i := range stepTemplate.Command {
locationsToCheck.Insert(stepTemplate.Command[i])
}
return locationsToCheck
}

// FindWorkspaceSubstitutionLocationsInTask returns a set of all the locations in the TaskSpec where we can apply substitutions.
func (ts *TaskSpec) FindWorkspaceSubstitutionLocationsInTask() sets.String {
locationsToCheck := sets.NewString()
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInSteps(ts.Steps).List()...)
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInSidecars(ts.Sidecars).List()...)
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInStepTemplate(ts.StepTemplate).List()...)
return locationsToCheck
}

// TaskList contains a list of Task
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type TaskList struct {
Expand Down
75 changes: 75 additions & 0 deletions pkg/apis/pipeline/v1/task_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
Copyright 2019 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1_test

import (
"testing"

"github.com/google/go-cmp/cmp"
v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
"github.com/tektoncd/pipeline/test/diff"
"k8s.io/apimachinery/pkg/util/sets"
)

func TestTaskSpec_FindWorkspaceSubstitutionLocationsInTask(t *testing.T) {
tests := []struct {
name string
ts *v1.TaskSpec
want sets.String
}{{
name: "completespec",
ts: &v1.TaskSpec{
Steps: []v1.Step{{
Name: "step-name",
Image: "step-image",
Script: "step-script",
Command: []string{"step-command"},
Args: []string{"step-args"},
}},
Sidecars: []v1.Sidecar{{
Name: "sidecar-name",
Image: "sidecar-image",
Script: "sidecar-script",
Command: []string{"sidecar-command"},
Args: []string{"sidecar-args"},
}},
StepTemplate: &v1.StepTemplate{
Image: "steptemplate-image",
Command: []string{"steptemplate-command"},
Args: []string{"steptemplate-args"},
},
},
want: sets.NewString(
"step-script",
"step-args",
"step-command",
"sidecar-script",
"sidecar-args",
"sidecar-command",
"steptemplate-args",
"steptemplate-command",
),
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.ts.FindWorkspaceSubstitutionLocationsInTask()
if d := cmp.Diff(tt.want, got); d != "" {
t.Error(diff.PrintWantGot(d))
}
})
}
}
1 change: 0 additions & 1 deletion pkg/apis/pipeline/v1beta1/pipelinerun_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ func (ps *PipelineRunSpec) validatePipelineRunParameters(ctx context.Context) (e
}
}
}

return errs
}

Expand Down
56 changes: 56 additions & 0 deletions pkg/apis/pipeline/v1beta1/task_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
"knative.dev/pkg/kmeta"
)

Expand Down Expand Up @@ -78,6 +79,61 @@ func (*Task) GetGroupVersionKind() schema.GroupVersionKind {
return SchemeGroupVersion.WithKind(pipeline.TaskControllerName)
}

func findWorkspaceSubstitutionLocationsInSidecars(sidecars []Sidecar) sets.String {
locationsToCheck := sets.NewString()
for _, sidecar := range sidecars {
locationsToCheck.Insert(sidecar.Script)

for i := range sidecar.Args {
locationsToCheck.Insert(sidecar.Args[i])
}

for i := range sidecar.Command {
locationsToCheck.Insert(sidecar.Command[i])
}
}
return locationsToCheck
}

func findWorkspaceSubstitutionLocationsInSteps(steps []Step) sets.String {
locationsToCheck := sets.NewString()
for _, step := range steps {
locationsToCheck.Insert(step.Script)

for i := range step.Args {
locationsToCheck.Insert(step.Args[i])
}

for i := range step.Command {
locationsToCheck.Insert(step.Command[i])
}
}
return locationsToCheck
}

func findWorkspaceSubstitutionLocationsInStepTemplate(stepTemplate *StepTemplate) sets.String {
locationsToCheck := sets.NewString()

if stepTemplate != nil {
for i := range stepTemplate.Args {
locationsToCheck.Insert(stepTemplate.Args[i])
}
for i := range stepTemplate.Command {
locationsToCheck.Insert(stepTemplate.Command[i])
}
}
return locationsToCheck
}

// FindWorkspaceSubstitutionLocationsInTask returns a set of all the locations in the TaskSpec where we can apply substitutions.
func (ts *TaskSpec) FindWorkspaceSubstitutionLocationsInTask() sets.String {
locationsToCheck := sets.NewString()
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInSteps(ts.Steps).List()...)
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInSidecars(ts.Sidecars).List()...)
locationsToCheck.Insert(findWorkspaceSubstitutionLocationsInStepTemplate(ts.StepTemplate).List()...)
return locationsToCheck
}

// TaskSpec defines the desired state of Task.
type TaskSpec struct {
// Resources is a list input and output resource to run the task
Expand Down
Loading

0 comments on commit 13ef6d8

Please sign in to comment.