Skip to content

Commit

Permalink
Tests for Custom Scheduler Name on Build and BuildRun objects
Browse files Browse the repository at this point in the history
Signed-off-by: Dylan Orzel <[email protected]>
  • Loading branch information
dorzel committed Feb 20, 2025
1 parent cd32beb commit 9b58069
Show file tree
Hide file tree
Showing 12 changed files with 681 additions and 3 deletions.
15 changes: 15 additions & 0 deletions pkg/reconciler/build/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -645,5 +645,20 @@ var _ = Describe("Reconcile Build", func() {
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})

Context("when SchedulerName is specified", func() {
It("should fail to validate when the SchedulerName is invalid", func() {
// set SchedulerName to be invalid
buildSample.Spec.SchedulerName = ptr.To(strings.Repeat("s", 64))
buildSample.Spec.Output.PushSecret = nil

statusCall := ctl.StubFunc(corev1.ConditionFalse, build.SchedulerNameNotValid, "Scheduler name not valid: name part "+validation.MaxLenError(63))
statusWriter.UpdateCalls(statusCall)

_, err := reconciler.Reconcile(context.TODO(), request)
Expect(err).To(BeNil())
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})
})
})
59 changes: 59 additions & 0 deletions pkg/reconciler/buildrun/buildrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1660,5 +1660,64 @@ var _ = Describe("Reconcile BuildRun", func() {
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})

Context("when SchedulerName is specified", func() {
It("should fail to validate when the SchedulerName is invalid", func() {
// set SchedulerName to be invalid
buildRunSample.Spec.SchedulerName = ptr.To(strings.Repeat("s", 64))

statusCall := ctl.StubFunc(corev1.ConditionFalse, build.SchedulerNameNotValid, validation.MaxLenError(64))
statusWriter.UpdateCalls(statusCall)

_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)
Expect(err).To(BeNil())
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})

Context("when a buildrun has a buildSpec defined and overrides nodeSelector", func() {
BeforeEach(func() {
buildRunSample = ctl.BuildRunWithNodeSelectorOverride(buildRunName, buildName, map[string]string{"Key": "testkey", "Value": "testvalue"})
})

It("should fail to register", func() {
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.BuildReason(resources.BuildRunBuildFieldOverrideForbidden), "cannot use 'nodeSelector' override and 'buildSpec' simultaneously")
statusWriter.UpdateCalls(statusCall)

_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)
Expect(err).To(BeNil())
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})

Context("when a buildrun has a buildSpec defined and overrides Tolerations", func() {
BeforeEach(func() {
buildRunSample = ctl.BuildRunWithTolerationsOverride(buildRunName, buildName, []corev1.Toleration{{Key: "testkey", Value: "testvalue", Operator: corev1.TolerationOpEqual, Effect: corev1.TaintEffectNoSchedule}})
})

It("should fail to register", func() {
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.BuildReason(resources.BuildRunBuildFieldOverrideForbidden), "cannot use 'tolerations' override and 'buildSpec' simultaneously")
statusWriter.UpdateCalls(statusCall)

_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)
Expect(err).To(BeNil())
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})

Context("when a buildrun has a buildSpec defined and overrides schedulerName", func() {
BeforeEach(func() {
buildRunSample = ctl.BuildRunWithSchedulerNameOverride(buildRunName, buildName, "testSchedulerName")
})

It("should fail to register", func() {
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.BuildReason(resources.BuildRunBuildFieldOverrideForbidden), "cannot use 'schedulerName' override and 'buildSpec' simultaneously")
statusWriter.UpdateCalls(statusCall)

_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)
Expect(err).To(BeNil())
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
})
})
})
})
22 changes: 22 additions & 0 deletions pkg/reconciler/buildrun/resources/taskrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -678,5 +678,27 @@ var _ = Describe("GenerateTaskrun", func() {
Expect(got.Spec.PodTemplate.Tolerations[0].Value).To(Equal(buildRun.Spec.Tolerations[0].Value))
})
})

Context("when the build and buildrun both specify a SchedulerName", func() {
BeforeEach(func() {
build, err = ctl.LoadBuildYAML([]byte(test.MinimalBuildWithSchedulerName))
Expect(err).To(BeNil())

buildRun, err = ctl.LoadBuildRunFromBytes([]byte(test.MinimalBuildRunWithSchedulerName))
Expect(err).To(BeNil())

buildStrategy, err = ctl.LoadBuildStrategyFromBytes([]byte(test.ClusterBuildStrategyNoOp))
Expect(err).To(BeNil())
})

JustBeforeEach(func() {
got, err = resources.GenerateTaskRun(config.NewDefaultConfig(), build, buildRun, serviceAccountName, buildStrategy)
Expect(err).To(BeNil())
})

It("should give precedence to the SchedulerName value specified in the buildRun", func() {
Expect(got.Spec.PodTemplate.SchedulerName).To(Equal(buildRun.Spec.SchedulerName))
})
})
})
})
109 changes: 109 additions & 0 deletions pkg/validate/nodeselector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright The Shipwright Contributors
//
// SPDX-License-Identifier: Apache-2.0

package validate_test

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

corev1 "k8s.io/apimachinery/pkg/apis/meta/v1"

. "github.com/shipwright-io/build/pkg/apis/build/v1beta1"
"github.com/shipwright-io/build/pkg/validate"
)

var _ = Describe("ValidateNodeSelector", func() {
var ctx context.Context

BeforeEach(func() {
ctx = context.TODO()
})

var validate = func(build *Build) {
GinkgoHelper()

var validator = &validate.NodeSelectorRef{Build: build}
Expect(validator.ValidatePath(ctx)).To(Succeed())
}

var sampleBuild = func(key string, value string) *Build {
return &Build{
ObjectMeta: corev1.ObjectMeta{
Namespace: "foo",
Name: "bar",
},
Spec: BuildSpec{
NodeSelector: map[string]string{key: value},
},
}
}

Context("when node selector is specified", func() {
It("should fail an empty key and value", func() {
build := sampleBuild("", "")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})

It("should fail an empty key and valid value", func() {
build := sampleBuild("", "validvalue")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})

It("should fail an empty key and invalid value", func() {
build := sampleBuild("", "invalidvalue!")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})

It("should pass a valid key and valid value", func() {
build := sampleBuild("validkey", "validvalue")
validate(build)
Expect(build.Status.Reason).To(BeNil())
Expect(build.Status.Message).To(BeNil())
})

It("should fail a valid key and invalid value", func() {
build := sampleBuild("validkey", "invalidvalue!")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector value not valid"))
})

It("should pass a valid key and empty value", func() {
build := sampleBuild("validkey", "")
validate(build)
Expect(build.Status.Reason).To(BeNil())
Expect(build.Status.Message).To(BeNil())
})

It("should fail an invalid key and empty value", func() {
build := sampleBuild("invalidkey!", "")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})

It("should fail an invalid key and valid value", func() {
build := sampleBuild("invalidkey!", "validvalue")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})

It("should fail both an invalid key and invalid value", func() {
build := sampleBuild("invalidkey!", "invalidvalue!")
validate(build)
Expect(*build.Status.Reason).To(Equal(NodeSelectorNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Node selector key not valid"))
})
})
})
60 changes: 60 additions & 0 deletions pkg/validate/scheduler_name_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright The Shipwright Contributors
//
// SPDX-License-Identifier: Apache-2.0

package validate_test

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

corev1 "k8s.io/apimachinery/pkg/apis/meta/v1"

. "github.com/shipwright-io/build/pkg/apis/build/v1beta1"
"github.com/shipwright-io/build/pkg/validate"
)

var _ = Describe("ValidateSchedulerName", func() {
var ctx context.Context

BeforeEach(func() {
ctx = context.TODO()
})

var validate = func(build *Build) {
GinkgoHelper()

var validator = &validate.SchedulerNameRef{Build: build}
Expect(validator.ValidatePath(ctx)).To(Succeed())
}

var sampleBuild = func(schedulerName string) *Build {
return &Build{
ObjectMeta: corev1.ObjectMeta{
Namespace: "foo",
Name: "bar",
},
Spec: BuildSpec{
SchedulerName: &schedulerName,
},
}
}

Context("when schedulerName is specified", func() {
It("should pass an empty name", func() {
build := sampleBuild("")
validate(build)
Expect(build.Status.Reason).To(BeNil())
Expect(build.Status.Message).To(BeNil())
})

It("should fail an invalid name", func() {
build := sampleBuild("invalidname!")
validate(build)
Expect(*build.Status.Reason).To(Equal(SchedulerNameNotValid))
Expect(*build.Status.Message).To(ContainSubstring("Scheduler name not valid"))
})
})
})
Loading

0 comments on commit 9b58069

Please sign in to comment.