build source
This commit is contained in:
commit
ee1fec43ed
4171 changed files with 1351288 additions and 0 deletions
194
internal/k8s/runners_test.go
Normal file
194
internal/k8s/runners_test.go
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
package k8s
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/iliaivanov/spec-kit-remote/cmd/dev-pod-api/internal/model"
|
||||
)
|
||||
|
||||
func defaultRunnerOpts() CreateRunnerPodOpts {
|
||||
return CreateRunnerPodOpts{
|
||||
User: "alice",
|
||||
RunnerID: "runner-abc12345",
|
||||
Tools: "go,rust",
|
||||
Task: "implement feature",
|
||||
RepoURL: "alice/myrepo",
|
||||
Branch: "main",
|
||||
CPUReq: "2",
|
||||
MemReq: "4Gi",
|
||||
ForgejoRunnerToken: "test-runner-token",
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateRunnerPod(t *testing.T) {
|
||||
client := newTestClient()
|
||||
ctx := context.Background()
|
||||
|
||||
if err := client.EnsureNamespace(ctx, "alice"); err != nil {
|
||||
t.Fatalf("ensure namespace: %v", err)
|
||||
}
|
||||
|
||||
opts := defaultRunnerOpts()
|
||||
podName, err := client.CreateRunnerPod(ctx, opts)
|
||||
if err != nil {
|
||||
t.Fatalf("create runner pod: %v", err)
|
||||
}
|
||||
|
||||
expectedPodName := model.RunnerPodName("runner-abc12345")
|
||||
if podName != expectedPodName {
|
||||
t.Errorf("expected pod name %q, got %q", expectedPodName, podName)
|
||||
}
|
||||
|
||||
ns := model.NamespaceName("alice")
|
||||
pod, err := client.Clientset.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("get runner pod: %v", err)
|
||||
}
|
||||
|
||||
if pod.Labels["app"] != "dev-pod-runner" {
|
||||
t.Errorf("expected app label dev-pod-runner, got %q", pod.Labels["app"])
|
||||
}
|
||||
if pod.Labels["runner-id"] != "runner-abc12345" {
|
||||
t.Errorf("expected runner-id label runner-abc12345, got %q", pod.Labels["runner-id"])
|
||||
}
|
||||
if pod.Labels["user"] != "alice" {
|
||||
t.Errorf("expected user label alice, got %q", pod.Labels["user"])
|
||||
}
|
||||
|
||||
if len(pod.Spec.Containers) != 2 {
|
||||
t.Fatalf("expected 2 containers (runner + ipip-sidecar), got %d", len(pod.Spec.Containers))
|
||||
}
|
||||
|
||||
container := pod.Spec.Containers[0]
|
||||
if container.Name != "runner" {
|
||||
t.Errorf("expected container name runner, got %q", container.Name)
|
||||
}
|
||||
|
||||
sidecar := pod.Spec.Containers[1]
|
||||
if sidecar.Name != "ipip-sidecar" {
|
||||
t.Errorf("expected sidecar name ipip-sidecar, got %q", sidecar.Name)
|
||||
}
|
||||
if sidecar.SecurityContext == nil || !*sidecar.SecurityContext.Privileged {
|
||||
t.Error("expected ipip-sidecar to be privileged")
|
||||
}
|
||||
|
||||
envMap := make(map[string]string)
|
||||
for _, e := range container.Env {
|
||||
envMap[e.Name] = e.Value
|
||||
}
|
||||
if envMap["RUNNER_MODE"] != "true" {
|
||||
t.Error("expected RUNNER_MODE=true")
|
||||
}
|
||||
if envMap["RUNNER_ID"] != "runner-abc12345" {
|
||||
t.Errorf("expected RUNNER_ID=runner-abc12345, got %q", envMap["RUNNER_ID"])
|
||||
}
|
||||
if envMap["DEV_POD_API_URL"] == "" {
|
||||
t.Error("expected DEV_POD_API_URL to be set")
|
||||
}
|
||||
if envMap["FORGEJO_RUNNER_TOKEN"] != "test-runner-token" {
|
||||
t.Errorf("expected FORGEJO_RUNNER_TOKEN=test-runner-token, got %q", envMap["FORGEJO_RUNNER_TOKEN"])
|
||||
}
|
||||
if envMap["RUNNER_REPO"] != "alice/myrepo" {
|
||||
t.Errorf("expected RUNNER_REPO=alice/myrepo, got %q", envMap["RUNNER_REPO"])
|
||||
}
|
||||
if envMap["RUNNER_BRANCH"] != "main" {
|
||||
t.Errorf("expected RUNNER_BRANCH=main, got %q", envMap["RUNNER_BRANCH"])
|
||||
}
|
||||
if envMap["DEV_TOOLS"] != "go,rust" {
|
||||
t.Errorf("expected DEV_TOOLS=go,rust, got %q", envMap["DEV_TOOLS"])
|
||||
}
|
||||
|
||||
cpuReq := container.Resources.Requests.Cpu()
|
||||
if cpuReq.String() != "2" {
|
||||
t.Errorf("expected cpu request 2, got %s", cpuReq.String())
|
||||
}
|
||||
memReq := container.Resources.Requests.Memory()
|
||||
if memReq.String() != "4Gi" {
|
||||
t.Errorf("expected memory request 4Gi, got %s", memReq.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateRunnerPod_DefaultResources(t *testing.T) {
|
||||
client := newTestClient()
|
||||
ctx := context.Background()
|
||||
|
||||
if err := client.EnsureNamespace(ctx, "alice"); err != nil {
|
||||
t.Fatalf("ensure namespace: %v", err)
|
||||
}
|
||||
|
||||
opts := CreateRunnerPodOpts{
|
||||
User: "alice",
|
||||
RunnerID: "runner-defaults",
|
||||
RepoURL: "alice/repo",
|
||||
}
|
||||
podName, err := client.CreateRunnerPod(ctx, opts)
|
||||
if err != nil {
|
||||
t.Fatalf("create runner pod: %v", err)
|
||||
}
|
||||
|
||||
ns := model.NamespaceName("alice")
|
||||
pod, err := client.Clientset.CoreV1().Pods(ns).Get(ctx, podName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("get runner pod: %v", err)
|
||||
}
|
||||
|
||||
container := pod.Spec.Containers[0]
|
||||
cpuReq := container.Resources.Requests.Cpu()
|
||||
if cpuReq.String() != "2" {
|
||||
t.Errorf("expected default cpu request 2, got %s", cpuReq.String())
|
||||
}
|
||||
memReq := container.Resources.Requests.Memory()
|
||||
if memReq.String() != "4Gi" {
|
||||
t.Errorf("expected default memory request 4Gi, got %s", memReq.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteRunnerPod(t *testing.T) {
|
||||
client := newTestClient()
|
||||
ctx := context.Background()
|
||||
|
||||
if err := client.EnsureNamespace(ctx, "alice"); err != nil {
|
||||
t.Fatalf("ensure namespace: %v", err)
|
||||
}
|
||||
|
||||
opts := defaultRunnerOpts()
|
||||
podName, err := client.CreateRunnerPod(ctx, opts)
|
||||
if err != nil {
|
||||
t.Fatalf("create runner pod: %v", err)
|
||||
}
|
||||
|
||||
if err := client.DeleteRunnerPod(ctx, "alice", podName); err != nil {
|
||||
t.Fatalf("delete runner pod: %v", err)
|
||||
}
|
||||
|
||||
ns := model.NamespaceName("alice")
|
||||
pods, err := client.Clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{
|
||||
LabelSelector: "app=dev-pod-runner",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("list pods: %v", err)
|
||||
}
|
||||
if len(pods.Items) != 0 {
|
||||
t.Errorf("expected 0 runner pods after delete, got %d", len(pods.Items))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteRunnerPod_NonExistent(t *testing.T) {
|
||||
client := newTestClient()
|
||||
ctx := context.Background()
|
||||
|
||||
err := client.DeleteRunnerPod(ctx, "alice", "nonexistent-pod")
|
||||
if err != nil {
|
||||
t.Fatalf("delete nonexistent pod should not fail, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunnerPodName(t *testing.T) {
|
||||
name := model.RunnerPodName("runner-abc123")
|
||||
if name != "dev-pod-runner-abc123" {
|
||||
t.Errorf("expected dev-pod-runner-abc123, got %s", name)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue