接入 OpenSandbox Kata Runner 控制面
test / python (pull_request) Successful in 9s
test / shell (pull_request) Successful in 21s

This commit is contained in:
2026-09-18 00:56:10 +00:00
parent 8d70df2128
commit d7ba64d6f3
9 changed files with 680 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
import asyncio
import json
import pytest
from gitea_dynamic_runner.models import RunnerRequest
from gitea_dynamic_runner import opensandbox_worker
from gitea_dynamic_runner.sandbox_kubernetes import allocated_pod_name
def request() -> RunnerRequest:
return RunnerRequest(
job_id=47,
run_id=12,
backend="vm",
repository="panxiao81/example",
job_name="publish image",
labels=("self-hosted", "vm"),
)
def test_sandbox_request_uses_pool_and_identity_gate(monkeypatch):
monkeypatch.setattr(opensandbox_worker, "OPENSANDBOX_POOL", "ci-vm")
document = opensandbox_worker.sandbox_request(request(), "gitea-vm-abcd")
assert document["pool"] == "ci-vm"
assert document["entrypoint"] == [
"/usr/local/libexec/gitea-opensandbox-runner"
]
assert document["env"]["GITEA_RUNNER_NAME"] == "gitea-vm-abcd"
assert document["env"]["GITEA_RUNNER_LABELS"] == "self-hosted:host,vm:host"
assert document["env"]["CI_SPIFFE_ID"].startswith(
"spiffe://ddupan.top/ci/panxiao81/example/publish-image-"
)
assert document["metadata"]["ci.ddupan.top/job-id"] == "47"
def test_identity_entry_is_bound_to_kata_pod_uid(monkeypatch):
monkeypatch.setattr(opensandbox_worker, "SPIRE_CLUSTER_NAME", "sandbox-kata")
monkeypatch.setattr(opensandbox_worker, "RUNNER_UID", 2000)
manifest = opensandbox_worker.identity_entry(
request(), sandbox_id="sandbox-123", pod_uid="pod-uid-456"
)
assert manifest["metadata"]["name"] == opensandbox_worker.entry_name(
"sandbox-123"
)
spec = manifest["spec"]
assert spec["parentID"] == (
"spiffe://ddupan.top/spire/agent/k8s_psat/"
"sandbox-kata/pod/pod-uid-456"
)
assert spec["selectors"] == ["unix:uid:2000"]
assert spec["spiffeID"].startswith(
"spiffe://ddupan.top/ci/panxiao81/example/publish-image-"
)
@pytest.mark.parametrize(
("annotation", "expected"),
[
(json.dumps({"pods": ["pool-pod-1"], "poolRef": "ci-vm"}), "pool-pod-1"),
(json.dumps({"pods": []}), None),
(json.dumps({"pods": ["one", "two"]}), None),
("not-json", None),
],
)
def test_allocated_pod_name(annotation, expected):
batchsandbox = {
"metadata": {
"annotations": {"sandbox.opensandbox.io/alloc-status": annotation}
}
}
assert allocated_pod_name(batchsandbox) == expected
class FakeKubernetesClient:
def __init__(self):
self.calls = 0
async def get_batchsandbox(self, sandbox_id):
self.calls += 1
if self.calls == 1:
return {"metadata": {"annotations": {}}}
return {
"metadata": {
"annotations": {
"sandbox.opensandbox.io/alloc-status": json.dumps(
{"pods": ["pool-pod-1"], "poolRef": "ci-vm"}
)
}
}
}
async def get_pod(self, name):
assert name == "pool-pod-1"
return {"metadata": {"uid": "pod-uid-1"}}
async def test_wait_for_allocation_returns_real_pod_uid(monkeypatch):
async def no_sleep(_):
return None
monkeypatch.setattr(asyncio, "sleep", no_sleep)
client = FakeKubernetesClient()
assert await opensandbox_worker.wait_for_allocation(client, "sandbox-1") == (
"pool-pod-1",
"pod-uid-1",
)
def test_entry_name_is_stable_and_dns_safe():
name = opensandbox_worker.entry_name("sandbox/with unsafe characters")
assert name == opensandbox_worker.entry_name("sandbox/with unsafe characters")
assert name.startswith("gitea-ci-")
assert "/" not in name