Skip to content

Commit cd32beb

Browse files
committed
Add Custom Scheduler Name to Build and BuildRun objects
Signed-off-by: Dylan Orzel <[email protected]>
1 parent 717db46 commit cd32beb

File tree

11 files changed

+108
-38
lines changed

11 files changed

+108
-38
lines changed

deploy/crds/shipwright.io_buildruns.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7439,6 +7439,10 @@ spec:
74397439
format: duration
74407440
type: string
74417441
type: object
7442+
schedulerName:
7443+
description: SchedulerName specifies the scheduler to be used
7444+
to dispatch the Pod
7445+
type: string
74427446
source:
74437447
description: |-
74447448
Source refers to the location where the source code is,
@@ -9753,6 +9757,10 @@ spec:
97539757
format: duration
97549758
type: string
97559759
type: object
9760+
schedulerName:
9761+
description: SchedulerName specifies the scheduler to be used to dispatch
9762+
the Pod
9763+
type: string
97569764
serviceAccount:
97579765
description: |-
97589766
ServiceAccount refers to the kubernetes serviceaccount
@@ -11941,6 +11949,10 @@ spec:
1194111949
format: duration
1194211950
type: string
1194311951
type: object
11952+
schedulerName:
11953+
description: SchedulerName specifies the scheduler to be used
11954+
to dispatch the Pod
11955+
type: string
1194411956
source:
1194511957
description: |-
1194611958
Source refers to the location where the source code is,

deploy/crds/shipwright.io_builds.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,6 +2818,10 @@ spec:
28182818
format: duration
28192819
type: string
28202820
type: object
2821+
schedulerName:
2822+
description: SchedulerName specifies the scheduler to be used to dispatch
2823+
the Pod
2824+
type: string
28212825
source:
28222826
description: |-
28232827
Source refers to the location where the source code is,

pkg/apis/build/v1beta1/build_types.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ const (
8080
NodeSelectorNotValid BuildReason = "NodeSelectorNotValid"
8181
// TolerationNotValid indicates that the Toleration value is not valid
8282
TolerationNotValid BuildReason = "TolerationNotValid"
83-
83+
// SchedulerNameNotValid indicates that the Scheduler name is not valid
84+
SchedulerNameNotValid BuildReason = "SchedulerNameNotValid"
8485
// AllValidationsSucceeded indicates a Build was successfully validated
8586
AllValidationsSucceeded = "all validations succeeded"
8687
)
@@ -191,6 +192,10 @@ type BuildSpec struct {
191192
// +patchMergeKey=Key
192193
// +patchStrategy=merge
193194
Tolerations []corev1.Toleration `json:"tolerations,omitempty" patchStrategy:"merge" patchMergeKey:"Key"`
195+
196+
// SchedulerName specifies the scheduler to be used to dispatch the Pod
197+
// +optional
198+
SchedulerName *string `json:"schedulerName,omitempty"`
194199
}
195200

196201
// BuildVolume is a volume that will be mounted in build pod during build step

pkg/apis/build/v1beta1/buildrun_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ type BuildRunSpec struct {
121121
// +patchMergeKey=Key
122122
// +patchStrategy=merge
123123
Tolerations []corev1.Toleration `json:"tolerations,omitempty" patchStrategy:"merge" patchMergeKey:"Key"`
124+
125+
// SchedulerName specifies the scheduler to be used to dispatch the Pod
126+
// +optional
127+
SchedulerName *string `json:"schedulerName,omitempty"`
124128
}
125129

126130
// BuildRunRequestedState defines the buildrun state the user can provide to override whatever is the current state.

pkg/reconciler/build/build.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var validationTypes = [...]string{
3535
validate.Triggers,
3636
validate.NodeSelector,
3737
validate.Tolerations,
38+
validate.SchedulerName,
3839
}
3940

4041
// ReconcileBuild reconciles a Build object

pkg/reconciler/buildrun/buildrun.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ func (r *ReconcileBuildRun) Reconcile(ctx context.Context, request reconcile.Req
162162
validate.NewEnv(build),
163163
validate.NewNodeSelector(build),
164164
validate.NewTolerations(build),
165+
validate.NewSchedulerName(build),
165166
)
166167

167168
// an internal/technical error during validation happened
@@ -310,6 +311,15 @@ func (r *ReconcileBuildRun) Reconcile(ctx context.Context, request reconcile.Req
310311
return reconcile.Result{}, nil
311312
}
312313

314+
// Validate the schedulerName
315+
valid, reason, message = validate.BuildRunSchedulerName(buildRun.Spec.SchedulerName)
316+
if !valid {
317+
if err := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, message, reason); err != nil {
318+
return reconcile.Result{}, err
319+
}
320+
return reconcile.Result{}, nil
321+
}
322+
313323
// Create the TaskRun, this needs to be the last step in this block to be idempotent
314324
generatedTaskRun, err := r.createTaskRun(ctx, svcAccount, strategy, build, buildRun)
315325
if err != nil {

pkg/reconciler/buildrun/resources/taskrun.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ func GenerateTaskRun(
255255
taskRunPodTemplate.Tolerations = taskRunTolerations
256256
}
257257

258+
// Set custom scheduler name if specified, giving preference to BuildRun values
259+
if buildRun.Spec.SchedulerName != nil {
260+
taskRunPodTemplate.SchedulerName = *buildRun.Spec.SchedulerName
261+
} else if build.Spec.SchedulerName != nil {
262+
taskRunPodTemplate.SchedulerName = *build.Spec.SchedulerName
263+
}
264+
258265
if !(taskRunPodTemplate.Equals(&pod.PodTemplate{})) {
259266
expectedTaskRun.Spec.PodTemplate = taskRunPodTemplate
260267
}

pkg/validate/nodeselector.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,11 @@ func NewNodeSelector(build *build.Build) *NodeSelectorRef {
2828
// ValidatePath implements BuildPath interface and validates
2929
// that NodeSelector keys/values are valid labels
3030
func (b *NodeSelectorRef) ValidatePath(_ context.Context) error {
31-
for key, value := range b.Build.Spec.NodeSelector {
32-
if errs := validation.IsQualifiedName(key); len(errs) > 0 {
33-
b.Build.Status.Reason = ptr.To(build.NodeSelectorNotValid)
34-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Node selector key not valid: %v", strings.Join(errs, ", ")))
35-
}
36-
if errs := validation.IsValidLabelValue(value); len(errs) > 0 {
37-
b.Build.Status.Reason = ptr.To(build.NodeSelectorNotValid)
38-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Node selector value not valid: %v", strings.Join(errs, ", ")))
39-
}
31+
ok, reason, msg := BuildRunNodeSelector(b.Build.Spec.NodeSelector)
32+
if !ok {
33+
b.Build.Status.Reason = ptr.To(build.BuildReason(reason))
34+
b.Build.Status.Message = ptr.To(msg)
4035
}
41-
4236
return nil
4337
}
4438

pkg/validate/scheduler_name.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright The Shipwright Contributors
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package validate
6+
7+
import (
8+
"context"
9+
"fmt"
10+
"strings"
11+
12+
"k8s.io/apimachinery/pkg/util/validation"
13+
"k8s.io/utils/ptr"
14+
15+
build "github.com/shipwright-io/build/pkg/apis/build/v1beta1"
16+
)
17+
18+
// SchedulerNameRef contains all required fields
19+
// to validate a Scheduler name
20+
type SchedulerNameRef struct {
21+
Build *build.Build // build instance for analysis
22+
}
23+
24+
func NewSchedulerName(build *build.Build) *SchedulerNameRef {
25+
return &SchedulerNameRef{build}
26+
}
27+
28+
// ValidatePath implements BuildPath interface and validates
29+
// that SchedulerName values are valid
30+
func (b *SchedulerNameRef) ValidatePath(_ context.Context) error {
31+
ok, reason, msg := BuildRunSchedulerName(b.Build.Spec.SchedulerName)
32+
if !ok {
33+
b.Build.Status.Reason = ptr.To(build.BuildReason(reason))
34+
b.Build.Status.Message = ptr.To(msg)
35+
}
36+
return nil
37+
}
38+
39+
// BuildSchedulerName is used to validate the schedulerName in the BuildRun object
40+
func BuildRunSchedulerName(schedulerName *string) (bool, string, string) {
41+
if schedulerName != nil {
42+
if errs := validation.IsQualifiedName(*schedulerName); len(errs) > 0 {
43+
return false, string(build.SchedulerNameNotValid), fmt.Sprintf("Scheduler name not valid: %v", strings.Join(errs, ", "))
44+
}
45+
}
46+
return true, "", ""
47+
}

pkg/validate/tolerations.go

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,34 +29,11 @@ func NewTolerations(build *build.Build) *TolerationsRef {
2929
// ValidatePath implements BuildPath interface and validates
3030
// that tolerations key/operator/value are valid
3131
func (b *TolerationsRef) ValidatePath(_ context.Context) error {
32-
for _, toleration := range b.Build.Spec.Tolerations {
33-
// validate Key
34-
if errs := validation.IsQualifiedName(toleration.Key); errs != nil {
35-
b.Build.Status.Reason = ptr.To(build.TolerationNotValid)
36-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Toleration key not valid: %v", strings.Join(errs, ", ")))
37-
}
38-
// validate Operator
39-
if !((toleration.Operator == v1.TolerationOpExists) || (toleration.Operator == v1.TolerationOpEqual)) {
40-
b.Build.Status.Reason = ptr.To(build.TolerationNotValid)
41-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Toleration operator not valid. Must be one of: '%v', '%v'", v1.TolerationOpExists, v1.TolerationOpEqual))
42-
}
43-
// validate Value
44-
if errs := validation.IsValidLabelValue(toleration.Value); errs != nil {
45-
b.Build.Status.Reason = ptr.To(build.TolerationNotValid)
46-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Toleration value not valid: %v", strings.Join(errs, ", ")))
47-
}
48-
// validate Taint Effect, of which only "NoSchedule" is supported
49-
if !((toleration.Effect) == "" || (toleration.Effect == v1.TaintEffectNoSchedule)) {
50-
b.Build.Status.Reason = ptr.To(build.TolerationNotValid)
51-
b.Build.Status.Message = ptr.To(fmt.Sprintf("Only the '%v' toleration effect is supported.", v1.TaintEffectNoSchedule))
52-
}
53-
// validate TolerationSeconds, which should not be specified
54-
if toleration.TolerationSeconds != nil {
55-
b.Build.Status.Reason = ptr.To(build.TolerationNotValid)
56-
b.Build.Status.Message = ptr.To("Specifying TolerationSeconds is not supported.")
57-
}
32+
ok, reason, msg := BuildRunTolerations(b.Build.Spec.Tolerations)
33+
if !ok {
34+
b.Build.Status.Reason = ptr.To(build.BuildReason(reason))
35+
b.Build.Status.Message = ptr.To(msg)
5836
}
59-
6037
return nil
6138
}
6239

pkg/validate/validate.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ const (
3939
NodeSelector = "nodeselector"
4040
// Tolerations for validating `spec.tolerations` entry
4141
Tolerations = "tolerations"
42+
// SchedulerName for validating `spec.schedulerName` entry
43+
SchedulerName = "schedulername"
4244
)
4345

4446
const (
@@ -83,6 +85,8 @@ func NewValidation(
8385
return &NodeSelectorRef{Build: build}, nil
8486
case Tolerations:
8587
return &TolerationsRef{Build: build}, nil
88+
case SchedulerName:
89+
return &SchedulerNameRef{Build: build}, nil
8690
default:
8791
return nil, fmt.Errorf("unknown validation type")
8892
}
@@ -147,6 +151,11 @@ func BuildRunFields(buildRun *build.BuildRun) (string, string) {
147151
return resources.BuildRunBuildFieldOverrideForbidden,
148152
"cannot use 'tolerations' override and 'buildSpec' simultaneously"
149153
}
154+
155+
if buildRun.Spec.SchedulerName != nil {
156+
return resources.BuildRunBuildFieldOverrideForbidden,
157+
"cannot use 'schedulerName' override and 'buildSpec' simultaneously"
158+
}
150159
}
151160

152161
return "", ""

0 commit comments

Comments
 (0)