126 lines
4.4 KiB
Go
126 lines
4.4 KiB
Go
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{"executor"},
|
|
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(), taskworker.LaunchSpec{
|
|
Metadata: metadata, Environment: map[string]string{"CI_RUNNER_CAPABILITY": "capability"},
|
|
})
|
|
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 api.created.Environment["CI_RUNNER_CAPABILITY"] != "capability" {
|
|
t.Fatalf("environment = %#v", api.created.Environment)
|
|
}
|
|
if len(api.created.Args) != 1 || api.created.Args[0] != "executor" || 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")
|
|
}
|
|
}
|