From ee4b9ca2feea374a9dbbea78e6493f824f17ab20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 15:03:52 +0000 Subject: [PATCH] Add e2e tests for pod spec field propagation Agent-Logs-Url: https://github.com/flanksource/batch-runner/sessions/7a9cd0f6-c47b-48ff-acf9-b87bf673cd72 Co-authored-by: moshloop <1489660+moshloop@users.noreply.github.com> --- e2e_test.go | 81 +++++++++++++++++++++++++++++++++++++++++- fixtures/pod-spec.yaml | 59 ++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 fixtures/pod-spec.yaml diff --git a/e2e_test.go b/e2e_test.go index 4642fbf..436fc51 100644 --- a/e2e_test.go +++ b/e2e_test.go @@ -9,6 +9,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/samber/lo" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -41,7 +43,7 @@ var _ = Describe("Batch Runner Helm Chart", Ordered, func() { }) It("Should create the queues in LocalStack", func() { - queues := []string{"test-batch-runner-exec", "test-batch-runner-pod", "test-batch-runner-job"} + queues := []string{"test-batch-runner-exec", "test-batch-runner-pod", "test-batch-runner-job", "test-batch-runner-pod-spec"} for _, queueName := range queues { args := []string{ fmt.Sprintf("--endpoint-url=http://localhost:%d", localStackPort), @@ -141,5 +143,82 @@ var _ = Describe("Batch Runner Helm Chart", Ordered, func() { err = k8s.WaitForJob(ctx, "default", jobName, 5*time.Minute) Expect(err).NotTo(HaveOccurred()) }) + + It("Should apply all pod spec fields to the generated pod", func() { + result, err := k8s.ApplyFile(ctx, "./fixtures/pod-spec.yaml") + Expect(err).NotTo(HaveOccurred()) + logger.Infof(result.Pretty().ANSI()) + + podLabel := fmt.Sprintf("pod-%s", lo.RandomString(10, lo.LettersCharset)) + annotationValue := fmt.Sprintf("annotation-%s", lo.RandomString(10, lo.LettersCharset)) + envValue := fmt.Sprintf("env-%s", lo.RandomString(10, lo.LettersCharset)) + + args := []string{ + fmt.Sprintf(`--endpoint-url=http://localhost:%d`, localStackPort), + "sqs", "send-message", + fmt.Sprintf("--queue-url=http://localhost:%d/000000000000/test-batch-runner-pod-spec", localStackPort), + `--message-body`, fmt.Sprintf(`{"pod_label": "%s", "annotation_value": "%s", "env_value": "%s"}`, podLabel, annotationValue, envValue), + `--region`, `us-east-1`, + } + + p := clicky.Exec("aws", args...).WithEnv(awsLocalStackEnv).Run() + logger.Infof(p.Result().Stdout) + logger.Infof(p.Result().Stderr) + Expect(p.Err).NotTo(HaveOccurred()) + Expect(p.ExitCode()).To(Equal(0)) + + time.Sleep(10 * time.Second) + + k8s.WaitForPod(ctx, "default", "test-pod-spec", time.Minute*5) + + pod, err := k8s.CoreV1().Pods("default").Get(ctx, "test-pod-spec", metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred(), "Failed to get test-pod-spec: %v", err) + Expect(pod).NotTo(BeNil()) + + By("Verifying metadata labels") + Expect(pod.Labels["app"]).To(Equal(podLabel)) + Expect(pod.Labels["batch-runner"]).To(Equal("true")) + + By("Verifying metadata annotations") + Expect(pod.Annotations["example.com/static"]).To(Equal("test-annotation")) + Expect(pod.Annotations["example.com/dynamic"]).To(Equal(annotationValue)) + + By("Verifying tolerations") + Expect(pod.Spec.Tolerations).To(ContainElement(corev1.Toleration{ + Key: "dedicated", + Operator: corev1.TolerationOpEqual, + Value: "batch", + Effect: corev1.TaintEffectNoSchedule, + })) + + By("Verifying nodeSelector") + Expect(pod.Spec.NodeSelector).To(HaveKeyWithValue("kubernetes.io/os", "linux")) + + By("Verifying securityContext") + Expect(pod.Spec.SecurityContext).NotTo(BeNil()) + Expect(*pod.Spec.SecurityContext.RunAsUser).To(Equal(int64(1000))) + Expect(*pod.Spec.SecurityContext.RunAsGroup).To(Equal(int64(3000))) + Expect(*pod.Spec.SecurityContext.FSGroup).To(Equal(int64(2000))) + + By("Verifying serviceAccountName") + Expect(pod.Spec.ServiceAccountName).To(Equal("default")) + + By("Verifying initContainers") + Expect(pod.Spec.InitContainers).To(HaveLen(1)) + Expect(pod.Spec.InitContainers[0].Name).To(Equal("init-setup")) + Expect(pod.Spec.InitContainers[0].Image).To(Equal("busybox:latest")) + + By("Verifying container environment variables") + Expect(pod.Spec.Containers).To(HaveLen(1)) + container := pod.Spec.Containers[0] + Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: "STATIC_ENV", Value: "static-value"})) + Expect(container.Env).To(ContainElement(corev1.EnvVar{Name: "DYNAMIC_ENV", Value: envValue})) + + By("Verifying container resource limits and requests") + Expect(container.Resources.Limits[corev1.ResourceCPU]).To(Equal(resource.MustParse("100m"))) + Expect(container.Resources.Limits[corev1.ResourceMemory]).To(Equal(resource.MustParse("64Mi"))) + Expect(container.Resources.Requests[corev1.ResourceCPU]).To(Equal(resource.MustParse("50m"))) + Expect(container.Resources.Requests[corev1.ResourceMemory]).To(Equal(resource.MustParse("32Mi"))) + }) }) }) diff --git a/fixtures/pod-spec.yaml b/fixtures/pod-spec.yaml new file mode 100644 index 0000000..5490181 --- /dev/null +++ b/fixtures/pod-spec.yaml @@ -0,0 +1,59 @@ +apiVersion: batch.flanksource.com/v1 +kind: BatchTrigger +metadata: + name: test-pod-spec +spec: + sqs: + queue: arn:aws:sqs:us-east-1:000000000000:test-batch-runner-pod-spec + endpoint: http://localstack:4566 + accessKey: + value: test + secretKey: + value: test + region: us-east-1 + raw: false + pod: + apiVersion: v1 + kind: Pod + metadata: + name: test-pod-spec + namespace: default + labels: + app: '{{.pod_label}}' + batch-runner: "true" + annotations: + example.com/static: "test-annotation" + example.com/dynamic: '{{.annotation_value}}' + spec: + tolerations: + - key: "dedicated" + operator: "Equal" + value: "batch" + effect: "NoSchedule" + nodeSelector: + kubernetes.io/os: linux + securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 + serviceAccountName: default + initContainers: + - name: init-setup + image: busybox:latest + command: ["sh", "-c", "echo init done"] + containers: + - name: busybox + image: busybox:latest + command: ["sleep", "infinity"] + env: + - name: STATIC_ENV + value: "static-value" + - name: DYNAMIC_ENV + value: '{{.env_value}}' + resources: + limits: + cpu: "100m" + memory: "64Mi" + requests: + cpu: "50m" + memory: "32Mi"