From c040441877b00fbb948a2761a44acb330eede26e Mon Sep 17 00:00:00 2001 From: Dylan Orzel Date: Wed, 2 Oct 2024 11:40:58 -0600 Subject: [PATCH] Tests for NodeSelectors on Build and BuildRun objects Signed-off-by: Dylan Orzel --- pkg/reconciler/build/build_test.go | 16 +++++++ pkg/reconciler/buildrun/buildrun_test.go | 14 ++++++ .../buildrun/resources/taskrun_test.go | 22 +++++++++ test/integration/build_to_taskruns_test.go | 41 +++++++++++++++++ .../integration/buildruns_to_taskruns_test.go | 46 +++++++++++++++++++ test/v1beta1_samples/build_samples.go | 40 +++++++++++++++- test/v1beta1_samples/buildrun_samples.go | 27 +++++++++++ 7 files changed, 204 insertions(+), 2 deletions(-) diff --git a/pkg/reconciler/build/build_test.go b/pkg/reconciler/build/build_test.go index 2ffa66dd3b..8b2b879056 100644 --- a/pkg/reconciler/build/build_test.go +++ b/pkg/reconciler/build/build_test.go @@ -7,6 +7,7 @@ package build_test import ( "context" "fmt" + "strings" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -613,5 +614,20 @@ var _ = Describe("Reconcile Build", func() { Expect(err).ToNot(HaveOccurred()) }) }) + + Context("when nodeSelector is specified", func() { + It("should fail to validate when the nodeSelector is invalid", func() { + // set nodeSelector to be invalid + buildSample.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"} + buildSample.Spec.Output.PushSecret = nil + + statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "must be no more than 63 characters") + statusWriter.UpdateCalls(statusCall) + + _, err := reconciler.Reconcile(context.TODO(), request) + Expect(err).To(BeNil()) + Expect(statusWriter.UpdateCallCount()).To(Equal(1)) + }) + }) }) }) diff --git a/pkg/reconciler/buildrun/buildrun_test.go b/pkg/reconciler/buildrun/buildrun_test.go index 7f6f4a1d38..3fd6d765e9 100644 --- a/pkg/reconciler/buildrun/buildrun_test.go +++ b/pkg/reconciler/buildrun/buildrun_test.go @@ -1631,5 +1631,19 @@ var _ = Describe("Reconcile BuildRun", func() { Expect(statusWriter.UpdateCallCount()).To(Equal(1)) }) }) + + Context("when nodeSelector is specified", func() { + It("fails when the nodeSelector is invalid", func() { + // set nodeSelector to be invalid + buildSample.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"} + + statusCall := ctl.StubFunc(corev1.ConditionFalse, build.NodeSelectorNotValid, "must be no more than 63 characters") + statusWriter.UpdateCalls(statusCall) + + _, err := reconciler.Reconcile(context.TODO(), buildRunRequest) + Expect(err).To(BeNil()) + Expect(statusWriter.UpdateCallCount()).To(Equal(1)) + }) + }) }) }) diff --git a/pkg/reconciler/buildrun/resources/taskrun_test.go b/pkg/reconciler/buildrun/resources/taskrun_test.go index bf0709377d..d134ca602d 100644 --- a/pkg/reconciler/buildrun/resources/taskrun_test.go +++ b/pkg/reconciler/buildrun/resources/taskrun_test.go @@ -632,5 +632,27 @@ var _ = Describe("GenerateTaskrun", func() { Expect(paramOutputImageFound).To(BeTrue()) }) }) + + Context("when the build and buildrun both specify a nodeSelector in the PodTemplate", func() { + BeforeEach(func() { + build, err = ctl.LoadBuildYAML([]byte(test.MinimalBuildRunWithNodeSelector)) + Expect(err).To(BeNil()) + + buildRun, err = ctl.LoadBuildRunFromBytes([]byte(test.MinimalBuildRunWithNodeSelector)) + 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 nodeSelector specified in the buildRun", func() { + Expect(got.Spec.PodTemplate.NodeSelector).To(Equal(buildRun.Spec.NodeSelector)) + }) + }) }) }) diff --git a/test/integration/build_to_taskruns_test.go b/test/integration/build_to_taskruns_test.go index ee3b43ae93..bfe2bf4442 100644 --- a/test/integration/build_to_taskruns_test.go +++ b/test/integration/build_to_taskruns_test.go @@ -5,6 +5,8 @@ package integration_test import ( + "strings" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" @@ -202,4 +204,43 @@ var _ = Describe("Integration tests Build and TaskRun", func() { }) }) }) + + Context("when a build with nodeSelector is defined", func() { + BeforeEach(func() { + buildSample = []byte(test.MinimalBuildWithNodeSelector) + buildRunSample = []byte(test.MinimalBuildRun) + }) + + Context("when the TaskRun is created", func() { + It("should have the nodeSelector specified in the PodTemplate", func() { + Expect(tb.CreateBuild(buildObject)).To(BeNil()) + + buildObject, err = tb.GetBuildTillValidation(buildObject.Name) + Expect(err).To(BeNil()) + + Expect(tb.CreateBR(buildRunObject)).To(BeNil()) + + _, err = tb.GetBRTillStartTime(buildRunObject.Name) + Expect(err).To(BeNil()) + + tr, err := tb.GetTaskRunFromBuildRun(buildRunObject.Name) + Expect(err).To(BeNil()) + Expect(buildObject.Spec.NodeSelector).To(Equal(tr.Spec.PodTemplate.NodeSelector)) + }) + }) + + Context("when the nodeSelector is invalid", func() { + It("fails the build with a proper error in Reason", func() { + // set nodeSelector label to be invalid + buildObject.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): ""} + Expect(tb.CreateBuild(buildObject)).To(BeNil()) + + buildObject, err = tb.GetBuildTillValidation(buildObject.Name) + Expect(err).To(BeNil()) + + Expect(*buildObject.Status.Registered).To(Equal(corev1.ConditionFalse)) + Expect(*buildObject.Status.Reason).To(Equal(v1beta1.NodeSelectorNotValid)) + }) + }) + }) }) diff --git a/test/integration/buildruns_to_taskruns_test.go b/test/integration/buildruns_to_taskruns_test.go index ecae76947b..59dc9abe52 100644 --- a/test/integration/buildruns_to_taskruns_test.go +++ b/test/integration/buildruns_to_taskruns_test.go @@ -536,4 +536,50 @@ var _ = Describe("Integration tests BuildRuns and TaskRuns", func() { Expect(err).To(HaveOccurred()) }) }) + + Context("when a buildrun is created with a nodeSelector defined", func() { + BeforeEach(func() { + buildSample = []byte(test.MinimalBuild) + buildRunSample = []byte(test.MinimalBuildRunWithNodeSelector) + }) + + Context("when the taskrun is created", func() { + It("should have the nodeSelector specified in the PodTemplate", func() { + Expect(tb.CreateBuild(buildObject)).To(BeNil()) + + buildObject, err = tb.GetBuildTillValidation(buildObject.Name) + Expect(err).To(BeNil()) + + Expect(tb.CreateBR(buildRunObject)).To(BeNil()) + + br, err := tb.GetBRTillCompletion(buildRunObject.Name) + Expect(err).To(BeNil()) + + tr, err := tb.GetTaskRunFromBuildRun(buildRunObject.Name) + Expect(err).To(BeNil()) + Expect(br.Spec.NodeSelector).To(Equal(tr.Spec.PodTemplate.NodeSelector)) + }) + }) + + Context("when the nodeSelector is invalid", func() { + It("fails the buildrun with a proper error in Reason", func() { + Expect(tb.CreateBuild(buildObject)).To(BeNil()) + + buildObject, err = tb.GetBuildTillValidation(buildObject.Name) + Expect(err).To(BeNil()) + + // set nodeSelector label to be invalid + buildRunObject.Spec.NodeSelector = map[string]string{strings.Repeat("s", 64): "amd64"} + Expect(tb.CreateBR(buildRunObject)).To(BeNil()) + + br, err := tb.GetBRTillCompletion(buildRunObject.Name) + Expect(err).To(BeNil()) + + condition := br.Status.GetCondition(v1beta1.Succeeded) + Expect(condition.Status).To(Equal(corev1.ConditionFalse)) + Expect(condition.Reason).To(Equal("PodCreationFailed")) + Expect(condition.Message).To(ContainSubstring("must be no more than 63 characters")) + }) + }) + }) }) diff --git a/test/v1beta1_samples/build_samples.go b/test/v1beta1_samples/build_samples.go index 325eee108a..46a892c147 100644 --- a/test/v1beta1_samples/build_samples.go +++ b/test/v1beta1_samples/build_samples.go @@ -51,6 +51,28 @@ spec: value: Dockerfile ` +// MinimalBuildahBuildWithNodeSelector defines a simple +// Build with a source, strategy, and nodeSelector +const MinimalBuildahBuildWithNodeSelector = ` +apiVersion: shipwright.io/v1beta1 +kind: Build +metadata: + name: buildah +spec: + source: + type: Git + git: + url: "https://github.com/shipwright-io/sample-go" + strategy: + name: buildah + kind: ClusterBuildStrategy + paramValues: + - name: dockerfile + value: Dockerfile + nodeSelector: + kubernetes.io/arch: amd64 +` + // BuildahBuildWithOutput defines a simple // Build with a source, strategy and output const BuildahBuildWithOutput = ` @@ -520,8 +542,8 @@ spec: image: image-registry.openshift-image-registry.svc:5000/example/buildpacks-app ` -// BuildWithRestrictedParam defines a Build using params that are reserved only -// for shipwright +// MinimalBuild defines a simple +// Build with a strategy output const MinimalBuild = ` apiVersion: shipwright.io/v1beta1 kind: Build @@ -532,6 +554,20 @@ spec: image: image-registry.openshift-image-registry.svc:5000/example/buildpacks-app ` +// MinimalBuildWithNodeSelector defines a simple +// Build with a strategy, output, and NodeSelector +const MinimalBuildWithNodeSelector = ` +apiVersion: shipwright.io/v1beta1 +kind: Build +spec: + strategy: + kind: ClusterBuildStrategy + output: + image: image-registry.openshift-image-registry.svc:5000/example/buildpacks-app + nodeSelector: + kubernetes.io/arch: amd64 +` + // BuildWithUndefinedParameter defines a param that was not declared under the // strategy parameters const BuildWithUndefinedParam = ` diff --git a/test/v1beta1_samples/buildrun_samples.go b/test/v1beta1_samples/buildrun_samples.go index 27ba30a0c5..7e55033585 100644 --- a/test/v1beta1_samples/buildrun_samples.go +++ b/test/v1beta1_samples/buildrun_samples.go @@ -56,6 +56,20 @@ spec: name: buildah ` +// MinimalBuildahBuildRunWithNodeSelector defines a simple +// BuildRun with a referenced Build and nodeSelector +const MinimalBuildahBuildRunWithNodeSelector = ` +apiVersion: shipwright.io/v1beta1 +kind: BuildRun +metadata: + name: buildah-run +spec: + build: + name: buildah + nodeSelector: + kubernetes.io/arch: amd64 +` + // BuildahBuildRunWithSA defines a BuildRun // with a service-account const BuildahBuildRunWithSA = ` @@ -213,6 +227,19 @@ spec: name: foobar ` +// MinimalBuildRunWithNodeSelector defines a minimal BuildRun +// with a reference to a not existing Build, +// and a nodeSelector +const MinimalBuildRunWithNodeSelector = ` +apiVersion: shipwright.io/v1beta1 +kind: BuildRun +spec: + build: + name: foobar + nodeSelector: + kubernetes.io/arch: amd64 +` + // MinimalBuildRunWithVulnerabilityScan defines a BuildRun with // an override for the Build Output const MinimalBuildRunWithVulnerabilityScan = `