Skip to content

Commit 4fc27b2

Browse files
committed
Puts the new timeouts field under feature gates
1 parent 72458c6 commit 4fc27b2

File tree

10 files changed

+333
-204
lines changed

10 files changed

+333
-204
lines changed

examples/v1beta1/pipelineruns/no-ci/pipeline-timeout.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ spec:
1414
- sleep 90s
1515
args:
1616
- "$(inputs.params.MESSAGE)"
17-
---
1817

18+
---
1919
apiVersion: tekton.dev/v1beta1
2020
kind: PipelineRun
2121
metadata:
@@ -54,8 +54,7 @@ spec:
5454
- name: NIGHT_GREETINGS
5555
value: "Good Night, Bob!"
5656

57-
---
58-
57+
---
5958
apiVersion: tekton.dev/v1beta1
6059
kind: PipelineRun
6160
metadata:
@@ -64,7 +63,10 @@ spec:
6463
# 1 hour and half timeout for the pipeline
6564
# 1 hour and fifteen minutes for the pipeline tasks
6665
# 15 minutes for the finally tasks
67-
timeouts:
66+
#
67+
# This field requires enable-api-fields: "alpha" flag
68+
# Check https://github.com/tektoncd/pipeline/blob/main/config/config-feature-flags.yaml
69+
timeouts:
6870
pipeline: 1h30m
6971
tasks: 1h15m
7072
pipelineSpec:

go.sum

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/builder/v1beta1/pipeline.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -529,32 +529,32 @@ func PipelineRunNilTimeout(prs *v1beta1.PipelineRunSpec) {
529529
prs.Timeout = nil
530530
}
531531

532+
func initTimeouts(prs *v1beta1.PipelineRunSpec) {
533+
if prs.Timeouts == nil {
534+
prs.Timeouts = &v1beta1.TimeoutFields{}
535+
}
536+
}
537+
532538
// PipelineRunTasksTimeout sets the timeout to the PipelineRunSpec.
533539
func PipelineRunTasksTimeout(duration time.Duration) PipelineRunSpecOp {
534540
return func(prs *v1beta1.PipelineRunSpec) {
535-
if prs.Timeouts == nil {
536-
prs.Timeouts = &v1beta1.TimeoutFields{}
537-
}
541+
initTimeouts(prs)
538542
prs.Timeouts.Tasks = &metav1.Duration{Duration: duration}
539543
}
540544
}
541545

542546
// PipelineRunFinallyTimeout sets the timeout to the PipelineRunSpec.
543547
func PipelineRunFinallyTimeout(duration time.Duration) PipelineRunSpecOp {
544548
return func(prs *v1beta1.PipelineRunSpec) {
545-
if prs.Timeouts == nil {
546-
prs.Timeouts = &v1beta1.TimeoutFields{}
547-
}
549+
initTimeouts(prs)
548550
prs.Timeouts.Finally = &metav1.Duration{Duration: duration}
549551
}
550552
}
551553

552554
// PipelineRunPipelineTimeout sets the timeout to the PipelineRunSpec.
553555
func PipelineRunPipelineTimeout(duration time.Duration) PipelineRunSpecOp {
554556
return func(prs *v1beta1.PipelineRunSpec) {
555-
if prs.Timeouts == nil {
556-
prs.Timeouts = &v1beta1.TimeoutFields{}
557-
}
557+
initTimeouts(prs)
558558
prs.Timeouts.Pipeline = &metav1.Duration{Duration: duration}
559559
}
560560
}

pkg/apis/pipeline/v1beta1/openapi_generated.go

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/pipeline/v1beta1/pipelinerun_types.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ type PipelineRunSpec struct {
179179
// Used for cancelling a pipelinerun (and maybe more later on)
180180
// +optional
181181
Status PipelineRunSpecStatus `json:"status,omitempty"`
182+
// This is an alpha field. You must set the "enable-api-fields" feature flag to "alpha"
183+
// for this field to be supported.
184+
//
182185
// Time after which the Pipeline times out.
183186
// Currently three keys are accepted in the map
184187
// pipeline, tasks and finally
@@ -201,9 +204,12 @@ type PipelineRunSpec struct {
201204
}
202205

203206
type TimeoutFields struct {
207+
// Pipeline sets the maximum allowed duration for execution of the entire pipeline. The sum of individual timeouts for tasks and finally must not exceed this value.
204208
Pipeline *metav1.Duration `json:"pipeline,omitempty"`
205-
Tasks *metav1.Duration `json:"tasks,omitempty"`
206-
Finally *metav1.Duration `json:"finally,omitempty"`
209+
// Tasks sets the maximum allowed duration of this pipeline's tasks
210+
Tasks *metav1.Duration `json:"tasks,omitempty"`
211+
// Finally sets the maximum allowed duration of this pipeline's finally
212+
Finally *metav1.Duration `json:"finally,omitempty"`
207213
}
208214

209215
// PipelineRunSpecStatus defines the pipelinerun spec status the user can provide

pkg/apis/pipeline/v1beta1/pipelinerun_validation.go

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/google/go-containerregistry/pkg/name"
2525
"github.com/tektoncd/pipeline/pkg/apis/config"
2626
"github.com/tektoncd/pipeline/pkg/apis/validate"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
"knative.dev/pkg/apis"
2829
)
2930

@@ -83,34 +84,30 @@ func (ps *PipelineRunSpec) Validate(ctx context.Context) (errs *apis.FieldError)
8384
}
8485
}
8586

87+
// This is an alpha feature and will fail validation if it's used in a pipelinerun spec
88+
// when the enable-api-fields feature gate is anything but "alpha".
8689
if ps.Timeouts != nil {
8790
if ps.Timeout != nil {
8891
// can't have both at the same time
8992
errs = errs.Also(apis.ErrDisallowedFields("timeout", "timeouts"))
9093
}
9194

95+
errs = errs.Also(ValidateEnabledAPIFields(ctx, "timeouts", config.AlphaAPIFields))
96+
9297
// tasks timeout should be a valid duration of at least 0.
93-
if ps.Timeouts.Tasks != nil && ps.Timeouts.Tasks.Duration < 0 {
94-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s should be >= 0", ps.Timeouts.Tasks.Duration.String()), "timeouts.tasks"))
95-
}
98+
errs = errs.Also(validateTimeoutDuration("tasks", ps.Timeouts.Tasks))
9699

97100
// finally timeout should be a valid duration of at least 0.
98-
if ps.Timeouts.Finally != nil && ps.Timeouts.Finally.Duration < 0 {
99-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s should be >= 0", ps.Timeouts.Finally.Duration.String()), "timeouts.finally"))
100-
}
101+
errs = errs.Also(validateTimeoutDuration("finally", ps.Timeouts.Finally))
101102

102-
if ps.Timeouts.Pipeline != nil {
103-
// pipeline timeout should be a valid duration of at least 0.
104-
if ps.Timeouts.Pipeline.Duration < 0 {
105-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s should be >= 0", ps.Timeouts.Pipeline.Duration.String()), "timeouts.pipeline"))
106-
}
103+
// pipeline timeout should be a valid duration of at least 0.
104+
errs = errs.Also(validateTimeoutDuration("pipeline", ps.Timeouts.Pipeline))
107105

106+
if ps.Timeouts.Pipeline != nil {
108107
errs = errs.Also(ps.validatePipelineTimeout(ps.Timeouts.Pipeline.Duration, "should be <= pipeline duration"))
109-
110108
} else {
111109
defaultTimeout := time.Duration(config.FromContextOrDefaults(ctx).Defaults.DefaultTimeoutMinutes)
112110
errs = errs.Also(ps.validatePipelineTimeout(defaultTimeout, "should be <= default timeout duration"))
113-
114111
}
115112
}
116113

@@ -134,19 +131,27 @@ func (ps *PipelineRunSpec) Validate(ctx context.Context) (errs *apis.FieldError)
134131
return errs
135132
}
136133

134+
func validateTimeoutDuration(field string, d *metav1.Duration) (errs *apis.FieldError) {
135+
if d != nil && d.Duration < 0 {
136+
fieldPath := fmt.Sprintf("timeouts.%s", field)
137+
return errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s should be >= 0", d.Duration.String()), fieldPath))
138+
}
139+
return nil
140+
}
141+
137142
func (ps *PipelineRunSpec) validatePipelineTimeout(timeout time.Duration, errorMsg string) (errs *apis.FieldError) {
138143
if ps.Timeouts.Tasks != nil && ps.Timeouts.Tasks.Duration > timeout {
139-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s "+errorMsg, ps.Timeouts.Tasks.Duration.String()), "timeouts.tasks"))
144+
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s %s", ps.Timeouts.Tasks.Duration.String(), errorMsg), "timeouts.tasks"))
140145
}
141146

142147
if ps.Timeouts.Finally != nil && ps.Timeouts.Finally.Duration > timeout {
143-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s "+errorMsg, ps.Timeouts.Finally.Duration.String()), "timeouts.finally"))
148+
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s %s", ps.Timeouts.Finally.Duration.String(), errorMsg), "timeouts.finally"))
144149
}
145150

146151
if ps.Timeouts.Tasks != nil && ps.Timeouts.Finally != nil {
147152
if ps.Timeouts.Tasks.Duration+ps.Timeouts.Finally.Duration > timeout {
148-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s + %s "+errorMsg, ps.Timeouts.Tasks.Duration.String(), ps.Timeouts.Finally.Duration.String()), "timeouts.tasks"))
149-
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s + %s "+errorMsg, ps.Timeouts.Tasks.Duration.String(), ps.Timeouts.Finally.Duration.String()), "timeouts.finally"))
153+
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s + %s %s", ps.Timeouts.Tasks.Duration.String(), ps.Timeouts.Finally.Duration.String(), errorMsg), "timeouts.tasks"))
154+
errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("%s + %s %s", ps.Timeouts.Tasks.Duration.String(), ps.Timeouts.Finally.Duration.String(), errorMsg), "timeouts.finally"))
150155
}
151156
}
152157
return errs

0 commit comments

Comments
 (0)