Skip to content

Commit 9aeffed

Browse files
committed
Tests for Tolerations on Build and BuildRun objects
Signed-off-by: Dylan Orzel <dorzel@redhat.com>
1 parent 895cf85 commit 9aeffed

12 files changed

+353
-4
lines changed

pkg/reconciler/build/build_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"k8s.io/apimachinery/pkg/api/errors"
1717
"k8s.io/apimachinery/pkg/runtime/schema"
1818
"k8s.io/apimachinery/pkg/types"
19+
"k8s.io/apimachinery/pkg/util/validation"
1920
"k8s.io/utils/ptr"
2021
crc "sigs.k8s.io/controller-runtime/pkg/client"
2122
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
@@ -621,7 +622,22 @@ var _ = Describe("Reconcile Build", func() {
621622
buildSample.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"}
622623
buildSample.Spec.Output.PushSecret = nil
623624

624-
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "name part must be no more than 63 characters")
625+
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "name part "+validation.MaxLenError(63))
626+
statusWriter.UpdateCalls(statusCall)
627+
628+
_, err := reconciler.Reconcile(context.TODO(), request)
629+
Expect(err).To(BeNil())
630+
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
631+
})
632+
})
633+
634+
Context("when Tolerations is specified", func() {
635+
It("should fail to validate when the Toleration is invalid", func() {
636+
// set Toleration to be invalid
637+
buildSample.Spec.Tolerations = []corev1.Toleration{{Key: strings.Repeat("s", 64), Operator: "Equal", Value: "test-value"}}
638+
buildSample.Spec.Output.PushSecret = nil
639+
640+
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.TolerationNotValid, "name part "+validation.MaxLenError(63))
625641
statusWriter.UpdateCalls(statusCall)
626642

627643
_, err := reconciler.Reconcile(context.TODO(), request)

pkg/reconciler/buildrun/buildrun_test.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"k8s.io/apimachinery/pkg/runtime"
2121
"k8s.io/apimachinery/pkg/runtime/schema"
2222
"k8s.io/apimachinery/pkg/types"
23+
"k8s.io/apimachinery/pkg/util/validation"
2324
"k8s.io/client-go/kubernetes/scheme"
2425
"k8s.io/utils/ptr"
2526
knativeapi "knative.dev/pkg/apis"
@@ -1635,9 +1636,23 @@ var _ = Describe("Reconcile BuildRun", func() {
16351636
Context("when nodeSelector is specified", func() {
16361637
It("fails when the nodeSelector is invalid", func() {
16371638
// set nodeSelector to be invalid
1638-
buildSample.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"}
1639+
buildRunSample.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"}
16391640

1640-
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "must be no more than 63 characters")
1641+
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "name part "+validation.MaxLenError(63))
1642+
statusWriter.UpdateCalls(statusCall)
1643+
1644+
_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)
1645+
Expect(err).To(BeNil())
1646+
Expect(statusWriter.UpdateCallCount()).To(Equal(1))
1647+
})
1648+
})
1649+
1650+
Context("when Tolerations is specified", func() {
1651+
It("should fail to validate when the Toleration is invalid", func() {
1652+
// set Toleration to be invalid
1653+
buildRunSample.Spec.Tolerations = []corev1.Toleration{{Key: strings.Repeat("s", 64), Operator: "Equal", Value: "test-value"}}
1654+
1655+
statusCall := ctl.StubFunc(corev1.ConditionFalse, build.TolerationNotValid, validation.MaxLenError(63))
16411656
statusWriter.UpdateCalls(statusCall)
16421657

16431658
_, err := reconciler.Reconcile(context.TODO(), buildRunRequest)

pkg/reconciler/buildrun/resources/taskrun_test.go

+25-1
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ var _ = Describe("GenerateTaskrun", func() {
635635

636636
Context("when the build and buildrun both specify a nodeSelector", func() {
637637
BeforeEach(func() {
638-
build, err = ctl.LoadBuildYAML([]byte(test.MinimalBuildRunWithNodeSelector))
638+
build, err = ctl.LoadBuildYAML([]byte(test.MinimalBuildWithNodeSelector))
639639
Expect(err).To(BeNil())
640640

641641
buildRun, err = ctl.LoadBuildRunFromBytes([]byte(test.MinimalBuildRunWithNodeSelector))
@@ -654,5 +654,29 @@ var _ = Describe("GenerateTaskrun", func() {
654654
Expect(got.Spec.PodTemplate.NodeSelector).To(Equal(buildRun.Spec.NodeSelector))
655655
})
656656
})
657+
658+
Context("when the build and buildrun both specify a Toleration", func() {
659+
BeforeEach(func() {
660+
build, err = ctl.LoadBuildYAML([]byte(test.MinimalBuildWithToleration))
661+
Expect(err).To(BeNil())
662+
663+
buildRun, err = ctl.LoadBuildRunFromBytes([]byte(test.MinimalBuildRunWithToleration))
664+
Expect(err).To(BeNil())
665+
666+
buildStrategy, err = ctl.LoadBuildStrategyFromBytes([]byte(test.ClusterBuildStrategyNoOp))
667+
Expect(err).To(BeNil())
668+
})
669+
670+
JustBeforeEach(func() {
671+
got, err = resources.GenerateTaskRun(config.NewDefaultConfig(), build, buildRun, serviceAccountName, buildStrategy)
672+
Expect(err).To(BeNil())
673+
})
674+
675+
It("should give precedence to the Toleration values specified in the buildRun", func() {
676+
Expect(got.Spec.PodTemplate.Tolerations[0].Key).To(Equal(buildRun.Spec.Tolerations[0].Key))
677+
Expect(got.Spec.PodTemplate.Tolerations[0].Operator).To(Equal(buildRun.Spec.Tolerations[0].Operator))
678+
Expect(got.Spec.PodTemplate.Tolerations[0].Value).To(Equal(buildRun.Spec.Tolerations[0].Value))
679+
})
680+
})
657681
})
658682
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
apiVersion: shipwright.io/v1beta1
3+
kind: Build
4+
metadata:
5+
name: buildah-tolerations-build
6+
spec:
7+
source:
8+
type: Git
9+
git:
10+
url: https://github.com/shipwright-io/sample-go
11+
contextDir: docker-build
12+
strategy:
13+
name: buildah-shipwright-managed-push
14+
kind: ClusterBuildStrategy
15+
output:
16+
image: image-registry.openshift-image-registry.svc:5000/build-examples/taxi-app
17+
tolerations:
18+
- key: "test-key"
19+
value: "test-value"
20+
operator: "Equal"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
apiVersion: shipwright.io/v1beta1
3+
kind: BuildRun
4+
metadata:
5+
name: buildah-tolerations-buildrun
6+
spec:
7+
build:
8+
name: buildah-tolerations-build

test/e2e/v1beta1/e2e_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package e2e_test
66

77
import (
88
"os"
9+
"time"
910

1011
v1 "github.com/google/go-containerregistry/pkg/v1"
1112
. "github.com/onsi/ginkgo/v2"
@@ -15,6 +16,8 @@ import (
1516

1617
buildv1beta1 "github.com/shipwright-io/build/pkg/apis/build/v1beta1"
1718
shpgit "github.com/shipwright-io/build/pkg/git"
19+
20+
corev1 "k8s.io/api/core/v1"
1821
)
1922

2023
var _ = Describe("For a Kubernetes cluster with Tekton and build installed", func() {
@@ -706,4 +709,63 @@ var _ = Describe("For a Kubernetes cluster with Tekton and build installed", fun
706709
})
707710
})
708711

712+
Context("when tolerations are specified", Serial, func() {
713+
714+
BeforeEach(func() {
715+
testID = generateTestID("tolerations")
716+
717+
// create the build definition
718+
build = createBuild(
719+
testBuild,
720+
testID,
721+
"test/data/v1beta1/build_buildah_tolerations_cr.yaml",
722+
)
723+
724+
// Add a taint to both of the kind worker nodes
725+
nodes, err := testBuild.GetNodes()
726+
Expect(err).ToNot(HaveOccurred())
727+
for _, node := range nodes.Items {
728+
if node.Name == "kind-worker" || node.Name == "kind-worker2" {
729+
taint := corev1.Taint{Key: "test-key", Value: "test-vaue", Effect: "NoSchedule"}
730+
err := testBuild.AddNodeTaint(node.Name, &taint)
731+
Expect(err).ToNot(HaveOccurred())
732+
}
733+
}
734+
})
735+
736+
AfterEach(func() {
737+
nodes, err := testBuild.GetNodes()
738+
Expect(err).ToNot(HaveOccurred())
739+
for _, node := range nodes.Items {
740+
if node.Name == "kind-worker" || node.Name == "kind-worker2" {
741+
taint := corev1.Taint{Key: "test-key", Value: "test-vaue", Effect: "NoSchedule"}
742+
err := testBuild.RemoveNodeTaint(node.Name, &taint)
743+
Expect(err).ToNot(HaveOccurred())
744+
}
745+
}
746+
})
747+
748+
It("successfully runs a build when it tolerates the node taint", func() {
749+
buildRun, err = buildRunTestData(testBuild.Namespace, testID, "test/data/v1beta1/buildrun_buildah_tolerations_cr.yaml")
750+
Expect(err).ToNot(HaveOccurred(), "Error retrieving buildrun test data")
751+
752+
buildRun = validateBuildRunToSucceed(testBuild, buildRun)
753+
})
754+
755+
It("fails to schedule when the build does not tolerate the node taint", func() {
756+
buildRun, err = buildRunTestData(testBuild.Namespace, testID, "test/data/v1beta1/buildrun_buildah_tolerations_cr.yaml")
757+
Expect(err).ToNot(HaveOccurred(), "Error retrieving buildrun test data")
758+
759+
buildRun.Spec.Tolerations[0].Key = "untolerated"
760+
buildRun.Spec.Timeout.Duration = time.Minute
761+
762+
validateBuildRunToFail(testBuild, buildRun)
763+
buildRun, err = testBuild.LookupBuildRun(types.NamespacedName{Name: buildRun.Name, Namespace: testBuild.Namespace})
764+
765+
// Pod should fail to schedule and the BuildRun should timeout.
766+
Expect(buildRun.Status.GetCondition(buildv1beta1.Succeeded).Status).To(Equal(corev1.ConditionFalse))
767+
Expect(buildRun.Status.GetCondition(buildv1beta1.Succeeded).Reason).To(Equal("BuildRunTimeout"))
768+
Expect(buildRun.Status.GetCondition(buildv1beta1.Succeeded).Message).To(ContainSubstring("failed to finish within"))
769+
})
770+
})
709771
})

test/integration/build_to_taskruns_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -246,4 +246,50 @@ var _ = Describe("Integration tests Build and TaskRun", func() {
246246
})
247247
})
248248
})
249+
250+
Context("when a build with Tolerations is defined", func() {
251+
BeforeEach(func() {
252+
buildSample = []byte(test.MinimalBuildWithToleration)
253+
buildRunSample = []byte(test.MinimalBuildRun)
254+
})
255+
256+
Context("when the TaskRun is created", func() {
257+
It("should have the Tolerations specified in the PodTemplate", func() {
258+
Expect(tb.CreateBuild(buildObject)).To(BeNil())
259+
260+
buildObject, err = tb.GetBuildTillValidation(buildObject.Name)
261+
Expect(err).To(BeNil())
262+
Expect(*buildObject.Status.Message).To(Equal(v1beta1.AllValidationsSucceeded))
263+
Expect(*buildObject.Status.Registered).To(Equal(corev1.ConditionTrue))
264+
Expect(*buildObject.Status.Reason).To(Equal(v1beta1.SucceedStatus))
265+
266+
Expect(tb.CreateBR(buildRunObject)).To(BeNil())
267+
268+
_, err = tb.GetBRTillStartTime(buildRunObject.Name)
269+
Expect(err).To(BeNil())
270+
271+
tr, err := tb.GetTaskRunFromBuildRun(buildRunObject.Name)
272+
Expect(err).To(BeNil())
273+
Expect(buildObject.Spec.Tolerations[0].Key).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Key))
274+
Expect(buildObject.Spec.Tolerations[0].Operator).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Operator))
275+
Expect(buildObject.Spec.Tolerations[0].Value).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Value))
276+
Expect(tr.Spec.PodTemplate.Tolerations[0].TolerationSeconds).To(Equal(corev1.Toleration{}.TolerationSeconds))
277+
Expect(tr.Spec.PodTemplate.Tolerations[0].Effect).To(Equal(corev1.TaintEffectNoSchedule))
278+
})
279+
})
280+
281+
Context("when the Toleration is invalid", func() {
282+
It("fails the build with a proper error in Reason", func() {
283+
// set Toleration Key to be invalid
284+
buildObject.Spec.Tolerations[0].Key = strings.Repeat("s", 64)
285+
Expect(tb.CreateBuild(buildObject)).To(BeNil())
286+
287+
buildObject, err = tb.GetBuildTillValidation(buildObject.Name)
288+
Expect(err).To(BeNil())
289+
290+
Expect(*buildObject.Status.Registered).To(Equal(corev1.ConditionFalse))
291+
Expect(*buildObject.Status.Reason).To(Equal(v1beta1.TolerationNotValid))
292+
})
293+
})
294+
})
249295
})

test/integration/buildruns_to_taskruns_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
corev1 "k8s.io/api/core/v1"
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2323
"k8s.io/apimachinery/pkg/types"
24+
"k8s.io/apimachinery/pkg/util/validation"
2425
"k8s.io/apimachinery/pkg/util/wait"
2526
"k8s.io/apimachinery/pkg/watch"
2627
)
@@ -582,4 +583,54 @@ var _ = Describe("Integration tests BuildRuns and TaskRuns", func() {
582583
})
583584
})
584585
})
586+
587+
Context("when a buildrun is created with a Toleration defined", func() {
588+
BeforeEach(func() {
589+
buildSample = []byte(test.MinimalBuild)
590+
buildRunSample = []byte(test.MinimalBuildRunWithToleration)
591+
})
592+
593+
Context("when the taskrun is created", func() {
594+
It("should have the Toleration specified in the PodTemplate", func() {
595+
Expect(tb.CreateBuild(buildObject)).To(BeNil())
596+
597+
buildObject, err = tb.GetBuildTillValidation(buildObject.Name)
598+
Expect(err).To(BeNil())
599+
600+
Expect(tb.CreateBR(buildRunObject)).To(BeNil())
601+
602+
br, err := tb.GetBRTillCompletion(buildRunObject.Name)
603+
Expect(err).To(BeNil())
604+
605+
tr, err := tb.GetTaskRunFromBuildRun(buildRunObject.Name)
606+
Expect(err).To(BeNil())
607+
Expect(br.Spec.Tolerations[0].Key).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Key))
608+
Expect(br.Spec.Tolerations[0].Operator).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Operator))
609+
Expect(br.Spec.Tolerations[0].Value).To(Equal(tr.Spec.PodTemplate.Tolerations[0].Value))
610+
Expect(tr.Spec.PodTemplate.Tolerations[0].TolerationSeconds).To(Equal(corev1.Toleration{}.TolerationSeconds))
611+
Expect(tr.Spec.PodTemplate.Tolerations[0].Effect).To(Equal(corev1.TaintEffectNoSchedule))
612+
})
613+
})
614+
615+
Context("when the Toleration is invalid", func() {
616+
It("fails the buildrun with a proper error in Reason", func() {
617+
Expect(tb.CreateBuild(buildObject)).To(BeNil())
618+
619+
buildObject, err = tb.GetBuildTillValidation(buildObject.Name)
620+
Expect(err).To(BeNil())
621+
622+
// set Toleration Key to be invalid
623+
buildRunObject.Spec.Tolerations[0].Key = strings.Repeat("s", 64)
624+
Expect(tb.CreateBR(buildRunObject)).To(BeNil())
625+
626+
br, err := tb.GetBRTillCompletion(buildRunObject.Name)
627+
Expect(err).To(BeNil())
628+
629+
condition := br.Status.GetCondition(v1beta1.Succeeded)
630+
Expect(condition.Status).To(Equal(corev1.ConditionFalse))
631+
Expect(condition.Reason).To(Equal("PodCreationFailed"))
632+
Expect(condition.Message).To(ContainSubstring(validation.MaxLenError(63)))
633+
})
634+
})
635+
})
585636
})

test/kind/config_three_node.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
kind: Cluster
2+
apiVersion: kind.x-k8s.io/v1alpha4
3+
kubeadmConfigPatches:
4+
- |
5+
kind: ClusterConfiguration
6+
metadata:
7+
name: config
8+
apiServer:
9+
extraArgs:
10+
enable-admission-plugins: PodSecurity
11+
nodes:
12+
- role: control-plane
13+
extraPortMappings:
14+
- containerPort: 32222
15+
hostPort: 32222
16+
- role: worker
17+
- role: worker

0 commit comments

Comments
 (0)