package podbackend import ( "context" "testing" runnerv1 "gitea.dev/actionslib/runner/v1" "git.ddupan.top/panxiao81/gitea-dynamic-runner/internal/taskassignment" "git.ddupan.top/panxiao81/gitea-dynamic-runner/internal/taskidentity" "git.ddupan.top/panxiao81/gitea-dynamic-runner/internal/taskworker" ) type fakeAPI struct { pods []Pod selector string created PodManifest entry IdentityEntry entryGone string deleted string } func (a *fakeAPI) ListPods(_ context.Context, _ string, selector string) ([]Pod, error) { a.selector = selector return a.pods, nil } func (a *fakeAPI) CreatePod(_ context.Context, manifest PodManifest) (Pod, error) { a.created = manifest return Pod{Name: manifest.Name, Namespace: manifest.Namespace, UID: "pod-uid", Phase: "Pending"}, nil } func (a *fakeAPI) DeletePod(_ context.Context, _, name string) error { a.deleted = name return nil } func (a *fakeAPI) EnsureIdentityEntry(_ context.Context, entry IdentityEntry) error { a.entry = entry return nil } func (a *fakeAPI) DeleteIdentityEntry(_ context.Context, name string) error { a.entryGone = name return nil } func backend(api API) Backend { return Backend{API: api, Config: Config{ Namespace: "gitea-actions", Image: "zot/ci-executor:main", ServiceAccount: "gitea-task-executor", ExecutorArgs: []string{"execute"}, TrustDomain: "ddupan.top", SPIRECluster: "homelab", SPIREClass: "spire-mgmt-spire", ExecutorUID: 2000, }} } func assignment() taskassignment.Assignment { return taskassignment.Assignment{ ID: "gitea-task-42", Backend: taskassignment.BackendPod, Task: &runnerv1.Task{Id: 42}, Identity: taskidentity.Identity{ Repository: "owner/repo", Task: "publish", SPIFFEID: "spiffe://ddupan.top/ci/owner/repo/publish", }, } } func TestFindRecoversPodByAssignmentLabel(t *testing.T) { api := &fakeAPI{pods: []Pod{{Name: "gitea-task-42", UID: "uid", Phase: "Running"}}} executor, err := backend(api).Find(context.Background(), "gitea-task-42") if err != nil { t.Fatal(err) } if api.selector != "ci.ddupan.top/assignment-id=gitea-task-42" || executor.Name != "gitea-task-42" || executor.IdentityTarget != "uid" || executor.Phase != taskworker.PhaseRunning { t.Fatalf("selector=%q executor=%#v", api.selector, executor) } } func TestCreateUsesDeterministicNameAndRecoveryMetadata(t *testing.T) { api := &fakeAPI{} metadata := taskworker.BackendMetadata(assignment()) executor, err := backend(api).Create(context.Background(), assignment(), metadata) if err != nil { t.Fatal(err) } if api.created.Name != "gitea-task-42" || api.created.Labels[assignmentLabel] != "gitea-task-42" { t.Fatalf("manifest = %#v", api.created) } if api.created.Annotations["ci.ddupan.top/spiffe-id"] != assignment().Identity.SPIFFEID { t.Fatalf("annotations = %#v", api.created.Annotations) } if len(api.created.Args) != 2 || api.created.Args[1] != "gitea-task-42" || executor.IdentityTarget != "pod-uid" { t.Fatalf("args=%v executor=%#v", api.created.Args, executor) } } func TestBindIdentityCreatesEntryPinnedToPodUID(t *testing.T) { api := &fakeAPI{} executor := &taskworker.Executor{Name: "gitea-task-42", IdentityTarget: "pod-uid"} if err := backend(api).BindIdentity(context.Background(), executor, assignment().Identity); err != nil { t.Fatal(err) } if api.entry.Name != executor.Name || api.entry.SPIFFEID != assignment().Identity.SPIFFEID || api.entry.ParentID != "spiffe://ddupan.top/spire/agent/k8s_psat/homelab/pod/pod-uid" || len(api.entry.Selectors) != 1 || api.entry.Selectors[0] != "unix:uid:2000" { t.Fatalf("entry=%#v", api.entry) } } func TestDeleteRemovesIdentityBeforePod(t *testing.T) { api := &fakeAPI{} executor := &taskworker.Executor{Name: "gitea-task-42", IdentityTarget: "pod-uid"} if err := backend(api).Delete(context.Background(), executor); err != nil { t.Fatal(err) } if api.entryGone != executor.Name || api.deleted != executor.Name { t.Fatalf("entry=%q pod=%q", api.entryGone, api.deleted) } } func TestFindRejectsDuplicatePods(t *testing.T) { api := &fakeAPI{pods: []Pod{{Name: "one"}, {Name: "two"}}} if _, err := backend(api).Find(context.Background(), "gitea-task-42"); err == nil { t.Fatal("expected duplicate executor error") } }