CI / CI (pull_request) Successful in 2m8s
New X-Resource: sandbox on X-Service: sessions
POST ?session_id= → CreateOrResume
1. Ensure PVC workspace-session-<id> (Longhorn 1Gi)
2. If pod already Running → return DNS (resume path, idempotent)
3. Ensure pi-session-sandbox NetworkPolicy (shared, created once)
4. Create Pod pi-session-<id> + Service pi-session-<id>:8787
5. Wait up to 30s for Pod Ready
6. Fire-and-forget: merge pod_name/pvc_name/svc_dns/last_active_at
into session memory_entity summary
DELETE ?session_id= → delete Pod + Service + PVC
Idle reaper goroutine (5min interval, configurable via
SANDBOX_REAPER_INTERVAL_MINUTES): lists pi-session-* pods,
deletes Succeeded/Failed ones, preserves PVCs for resume.
Security: runAsNonRoot/1000, readOnlyRootFilesystem, drop ALL
caps, RuntimeDefault seccomp, automountServiceAccountToken:false.
Resources: 500m/512Mi req, 1/1Gi limit.
NetworkPolicy: egress → DNS + api:8080 only; ingress ← poimen-frontend.
RBAC: Role session-sandbox-manager + RoleBinding in poimen ns.
7 unit tests — all pass (mock k8s server).
Image: forgejo.riotpiao.com/riotpiao-poimen/poimen-pi-session-runtime:latest
124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package serviceadapter
|
|
|
|
import (
|
|
"forgejo.riotpiao.com/rock/homelab-frontend/internal/sessions"
|
|
)
|
|
|
|
// NewSessionAdapter creates a ServiceAdapter for the sessions service.
|
|
//
|
|
// Route mapping (all via X-Service: sessions):
|
|
//
|
|
// X-Resource Verb upstream path handler
|
|
// ──────────────────────────────────────────────────────────────
|
|
// sessions POST /v1/sessions/create create session
|
|
// sessions GET /v1/sessions/list list sessions (?status=,?cwd=)
|
|
// session GET /v1/sessions/get get session (?session_id=)
|
|
// session PATCH /v1/sessions/patch update session(?session_id=)
|
|
// milestones POST /v1/sessions/milestones/create create milestone(?session_id=)
|
|
// episodes GET /v1/sessions/episodes/list list episodes (?session_id=)
|
|
// episode GET /v1/sessions/episodes/get get episode (?session_id=,?episode_id=)
|
|
//
|
|
// Path params (:id, :eid) are passed as query params because the ServiceAdapter
|
|
// dispatcher does not substitute URL path parameters.
|
|
func NewSessionAdapter() *ServiceAdapter {
|
|
return &ServiceAdapter{
|
|
Namespace: "poimen",
|
|
ServiceName: "sessions",
|
|
Handler: sessions.NewHandler(),
|
|
Spec: *GetSessionSpec(),
|
|
}
|
|
}
|
|
|
|
// GetSessionSpec returns the ServiceAdapter spec for the sessions service.
|
|
func GetSessionSpec() *Spec {
|
|
return &Spec{
|
|
ServiceName: "sessions",
|
|
Upstream: Upstream{
|
|
URL: "internal://sessions",
|
|
TimeoutSeconds: 30,
|
|
},
|
|
Auth: Auth{
|
|
Required: true,
|
|
Capability: "sessions:read",
|
|
},
|
|
Resources: []Resource{
|
|
{
|
|
Name: "sessions",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "POST",
|
|
UpstreamPath: "/v1/sessions/create",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/list",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "session",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/get",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
{
|
|
Verb: "PATCH",
|
|
UpstreamPath: "/v1/sessions/patch",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "milestones",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "POST",
|
|
UpstreamPath: "/v1/sessions/milestones/create",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "episodes",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/episodes/list",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Name: "episode",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "GET",
|
|
UpstreamPath: "/v1/sessions/episodes/get",
|
|
Auth: &Auth{Required: true, Capability: "sessions:read"},
|
|
},
|
|
},
|
|
},
|
|
// sandbox — per-session k8s Pod+PVC+Service lifecycle (§4.15.4)
|
|
{
|
|
Name: "sandbox",
|
|
Methods: []Method{
|
|
{
|
|
Verb: "POST",
|
|
UpstreamPath: "/v1/sessions/sandbox",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
{
|
|
Verb: "DELETE",
|
|
UpstreamPath: "/v1/sessions/sandbox",
|
|
Auth: &Auth{Required: true, Capability: "sessions:write"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|