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

Fix for #2362, adding support per TaskRun runtime settings. #2389

Merged
merged 1 commit into from
May 11, 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
23 changes: 23 additions & 0 deletions docs/pipelineruns.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ weight: 4
- [Speciying `Parameters`](#specifying-parameters)
- [Specifying custom `ServiceAccount` credentials](#specifying-custom-serviceaccount-credentials)
- [Mapping `ServiceAccount` credentials to `Tasks`](#mapping-serviceaccount-credentials-to-tasks)
- [Specifying `TaskRunSpecs`](#specifying-task-run-specs)
- [Specifying a `Pod` template](#specifying-a-pod-template)
- [Specifying `Workspaces`](#specifying-workspaces)
- [Specifying `LimitRange` values](#specifying-limitrange-values)
Expand Down Expand Up @@ -51,6 +52,7 @@ A `PipelineRun` definition supports the following fields:
object that supplies specific execution credentials for the `Pipeline`.
- [`serviceAccountNames`](#mapping-serviceaccount-credentials-to-tasks) - Maps specific `serviceAccountName` values
to `Tasks` in the `Pipeline`. This overrides the credentials set for the entire `Pipeline`.
- [`taskRunSpec`](#specifying-task-run-specs) - Specifies a list of `PipelineRunTaskSpec` which allows for setting `ServiceAccountName` and [`Pod` template](./podtemplates.md) for each task. This overrides the `Pod` template set for the entire `Pipeline`.
- [`timeout`](#configuring-a-failure-timeout) - Specifies the timeout before the `PipelineRun` fails.
- [`podTemplate`](#pod-template) - Specifies a [`Pod` template](./podtemplates.md) to use as the basis
for the configuration of the `Pod` that executes each `Task`.
Expand Down Expand Up @@ -349,3 +351,24 @@ Except as otherwise noted, the content of this page is licensed under the
[Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/),
and code samples are licensed under the
[Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0).

## Specifying task run specs

Specifies a list of `PipelineRunTaskSpec` which contains `TaskServiceAccountName`,`TaskPodTemplate` and `TaskName`. Mapping the specs to the corresponding `Task` based upon the `TaskName` a PipelineTask will run with the configured `TaskServiceAccountName` and `TaskPodTemplate` overwriting the pipeline wide [`ServiceAccountName`](#service-account) and [`podTemplate`](#pod-template) configuration, for example:

```yaml
spec:
podTemplate:
securityContext:
runAsUser: 1000
runAsGroup: 2000
fsGroup: 3000
taskRunSpecs:
- taskName: build-task
taskServiceAccountName: sa-for-build
taskPodTemplate:
nodeSelector:
disktype: ssd
```

If used with this `Pipeline`, `build-task` will use the task specific pod template (where `nodeSelector` has `disktype` equal to `ssd`).
86 changes: 86 additions & 0 deletions examples/v1beta1/pipelineruns/pipelinerun-taskrunspecs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: add-task-taskspec
spec:
params:
- name: first
description: the first operand
- name: second
description: the second operand
results:
- name: sum
description: the sum of the first and second operand
steps:
- name: add
image: alpine
env:
- name: OP1
value: $(params.first)
- name: OP2
value: $(params.second)
command: ["/bin/sh", "-c"]
args:
- echo -n $((${OP1}+${OP2})) | tee $(results.sum.path);
---
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
name: add-pipeline-taskspec
spec:
params:
- name: first
description: the first operand
- name: second
description: the second operand
- name: third
description: the third operand
tasks:
- name: first-add-taskspec
taskRef:
name: add-task-taskspec
params:
- name: first
value: $(params.first)
- name: second
value: $(params.second)
- name: second-add-taskspec
taskRef:
name: add-task-taskspec
params:
- name: first
value: $(tasks.first-add-taskspec.results.sum)
- name: second
value: $(params.third)
results:
- name: sum
description: the sum of all three operands
value: $(tasks.second-add-taskspec.results.sum)
- name: partial-sum
description: the sum of first two operands
value: $(tasks.first-add-taskspec.results.sum)
- name: all-sum
description: the sum of everything
value: $(tasks.second-add-taskspec.results.sum)-$(tasks.first-add-taskspec.results.sum)
---
apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
name: task-spec-pipeline
spec:
pipelineRef:
name: add-pipeline-taskspec
taskRunSpecs:
- pipelineTaskName: first-add-taskspec
taskServiceAccountName: 'default'
- pipelineTaskName: second-add-taskspec
taskPodTemplate:
nodeSelector:
disktype: ssd
params:
- name: first
value: "2"
- name: second
value: "10"
- name: third
value: "10"
24 changes: 24 additions & 0 deletions pkg/apis/pipeline/v1alpha1/pipelinerun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ type PipelineRunSpec struct {
// with those declared in the pipeline.
// +optional
Workspaces []WorkspaceBinding `json:"workspaces,omitempty"`
// TaskRunSpecs holds a set of task specific specs
// +optional
TaskRunSpecs []PipelineTaskRunSpec `json:"taskRunSpecs,omitempty"`
}

// PipelineRunSpecStatus defines the pipelinerun spec status the user can provide
Expand Down Expand Up @@ -217,3 +220,24 @@ func (pr *PipelineRun) HasVolumeClaimTemplate() bool {
}
return false
}

// PipelineTaskRunSpec holds task specific specs
type PipelineTaskRunSpec struct {
PipelineTaskName string `json:"pipelineTaskName,omitempty"`
TaskServiceAccountName string `json:"taskServiceAccountName,omitempty"`
TaskPodTemplate *PodTemplate `json:"taskPodTemplate,omitempty"`
}

// GetTaskRunSpecs returns the task specific spec for a given
// PipelineTask if configured, otherwise it returns the PipelineRun's default.
func (pr *PipelineRun) GetTaskRunSpecs(pipelineTaskName string) (string, *PodTemplate) {
serviceAccountName := pr.GetServiceAccountName(pipelineTaskName)
taskPodTemplate := pr.Spec.PodTemplate
for _, task := range pr.Spec.TaskRunSpecs {
if task.PipelineTaskName == pipelineTaskName {
taskPodTemplate = task.TaskPodTemplate
serviceAccountName = task.TaskServiceAccountName
}
}
return serviceAccountName, taskPodTemplate
}
107 changes: 107 additions & 0 deletions pkg/apis/pipeline/v1alpha1/pipelinerun_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,3 +281,110 @@ func TestPipelineRunGetServiceAccountName(t *testing.T) {
}
}
}

func TestPipelineRunGetPodSpecSABackcompatibility(t *testing.T) {
for _, tt := range []struct {
name string
pr *v1alpha1.PipelineRun
expectedSAs map[string]string
}{
{
name: "test backward compatibility",
pr: &v1alpha1.PipelineRun{
ObjectMeta: metav1.ObjectMeta{Name: "pr"},
Spec: v1alpha1.PipelineRunSpec{
PipelineRef: &v1alpha1.PipelineRef{Name: "prs"},
ServiceAccountName: "defaultSA",
ServiceAccountNames: []v1alpha1.PipelineRunSpecServiceAccountName{{
TaskName: "taskName", ServiceAccountName: "taskSA",
}},
TaskRunSpecs: []v1alpha1.PipelineTaskRunSpec{{
PipelineTaskName: "taskName",
TaskServiceAccountName: "newTaskSA",
}},
},
},
expectedSAs: map[string]string{
"unknown": "defaultSA",
"taskName": "newTaskSA",
},
},
{
name: "mixed default SA backward compatibility",
pr: &v1alpha1.PipelineRun{
ObjectMeta: metav1.ObjectMeta{Name: "pr"},
Spec: v1alpha1.PipelineRunSpec{
PipelineRef: &v1alpha1.PipelineRef{Name: "prs"},
ServiceAccountName: "defaultSA",
TaskRunSpecs: []v1alpha1.PipelineTaskRunSpec{{
PipelineTaskName: "taskNameOne",
TaskServiceAccountName: "TaskSAOne",
}, {
PipelineTaskName: "taskNameTwo",
TaskServiceAccountName: "newTaskTwo",
}},
},
},
expectedSAs: map[string]string{
"unknown": "defaultSA",
"taskNameOne": "TaskSAOne",
"taskNameTwo": "newTaskTwo",
},
},
} {
for taskName, expected := range tt.expectedSAs {
t.Run(tt.name, func(t *testing.T) {
sa, _ := tt.pr.GetTaskRunSpecs(taskName)
if expected != sa {
t.Errorf("%s: wrong service account: got: %v, want: %v", tt.name, sa, expected)
}
})
}
}
}

func TestPipelineRunGetPodSpec(t *testing.T) {
for _, tt := range []struct {
name string
pr *v1alpha1.PipelineRun
expectedPodTemplates map[string][]string
}{
{
name: "mix default and none default",
pr: &v1alpha1.PipelineRun{
ObjectMeta: metav1.ObjectMeta{Name: "pr"},
Spec: v1alpha1.PipelineRunSpec{
PodTemplate: &v1alpha1.PodTemplate{SchedulerName: "scheduleTest"},
PipelineRef: &v1alpha1.PipelineRef{Name: "prs"},
ServiceAccountName: "defaultSA",
TaskRunSpecs: []v1alpha1.PipelineTaskRunSpec{{
PipelineTaskName: "taskNameOne",
TaskServiceAccountName: "TaskSAOne",
TaskPodTemplate: &v1alpha1.PodTemplate{SchedulerName: "scheduleTestOne"},
}, {
PipelineTaskName: "taskNameTwo",
TaskServiceAccountName: "newTaskTwo",
TaskPodTemplate: &v1alpha1.PodTemplate{SchedulerName: "scheduleTestTwo"},
}},
},
},
expectedPodTemplates: map[string][]string{
"unknown": {"scheduleTest", "defaultSA"},
"taskNameOne": {"scheduleTestOne", "TaskSAOne"},
"taskNameTwo": {"scheduleTestTwo", "newTaskTwo"},
},
},
} {
for taskName, values := range tt.expectedPodTemplates {
t.Run(tt.name, func(t *testing.T) {
sa, taskPodTemplate := tt.pr.GetTaskRunSpecs(taskName)
if values[0] != taskPodTemplate.SchedulerName {
t.Errorf("%s: wrong task podtemplate scheduler name: got: %v, want: %v", tt.name, taskPodTemplate.SchedulerName, values[0])
}
if values[1] != sa {
t.Errorf("%s: wrong service account: got: %v, want: %v", tt.name, sa, values[1])
}
})
}
}
}
28 changes: 28 additions & 0 deletions pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions pkg/apis/pipeline/v1beta1/pipelinerun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ type PipelineRunSpec struct {
// with those declared in the pipeline.
// +optional
Workspaces []WorkspaceBinding `json:"workspaces,omitempty"`
// TaskRunSpecs holds a set of runtime specs
// +optional
TaskRunSpecs []PipelineTaskRunSpec `json:"taskRunSpecs,omitempty"`
}

// PipelineRunSpecStatus defines the pipelinerun spec status the user can provide
Expand Down Expand Up @@ -310,3 +313,25 @@ type PipelineRunList struct {
type PipelineTaskRun struct {
Name string `json:"name,omitempty"`
}

// PipelineTaskRunSpec can be used to configure specific
// specs for a concrete Task
type PipelineTaskRunSpec struct {
PipelineTaskName string `json:"pipelineTaskName,omitempty"`
TaskServiceAccountName string `json:"taskServiceAccountName,omitempty"`
TaskPodTemplate *PodTemplate `json:"taskPodTemplate,omitempty"`
}

// GetTaskRunSpecs returns the task specific spec for a given
// PipelineTask if configured, otherwise it returns the PipelineRun's default.
func (pr *PipelineRun) GetTaskRunSpecs(pipelineTaskName string) (string, *PodTemplate) {
serviceAccountName := pr.GetServiceAccountName(pipelineTaskName)
taskPodTemplate := pr.Spec.PodTemplate
for _, task := range pr.Spec.TaskRunSpecs {
if task.PipelineTaskName == pipelineTaskName {
taskPodTemplate = task.TaskPodTemplate
serviceAccountName = task.TaskServiceAccountName
}
}
return serviceAccountName, taskPodTemplate
}
Loading