What's New
✨ Features
-
Sandbox metadata PATCH endpoint — new
PATCH /sandboxes/{sandboxId}/metadatafor incremental label updates: pass a value to set/update, passnullto delete a key. Smoke tests included. (#861) -
Stable Diagnostics API (server-side stub) — SDKs and CLI gain
osb diagnostics logs|eventswith requiredscope. The server returns501 DIAGNOSTICS_NOT_IMPLEMENTEDforscope-bearing requests until the stable backend lands; requests withoutscopekeep the legacy DevOpstext/plainbehavior, so existing clients are unaffected. (#869)
⚡ Performance
- Unblock the event loop, expose concurrency knobs — 17 lifecycle/pool route handlers that wrap synchronous Kubernetes/Docker SDK calls switched from
async defto syncdef, letting FastAPI auto-offload them to the anyio threadpool. The four sync K8s calls insidecreate_sandbox/_wait_for_sandbox_readyare now wrapped inasyncio.to_thread.list_custom_objectsserves from the informer cache when synced, falling back to the API for unsynced caches or unsupported label-selector grammars. New[server]keys:workers,limit_concurrency,backlog,thread_pool_size,loop,http— all additive, defaults preserve current behavior.uvicornupgraded touvicorn[standard](uvloop / httptools / watchfiles). 8 × 200 ms concurrentlist_sandboxesdrops from a 1.6 s serial floor to ~250 ms. Closes #887. (#903)
🐛 Bug Fixes
-
Pool-mode sandbox creation returned HTTP 500 — pool-mode
BatchSandboxCRs come back from the K8s API server withspec.template: null(key present, value None) because the CRD declarestemplateas an optionalpreserve-unknown-fieldsobject. The previousspec.get("template", {}).get("spec")in_extract_platform_from_workloadcrashed becausedict.getonly returns the default when the key is absent, not when its value isNone. The underlying sandbox actually reachedRunning, but clients saw a 500 with nosandbox_id, leaking resources. Switched to theor {}pattern that treats null and missing alike; six regression tests cover null template, missing template, template-mode happy path,podTemplatealias, null spec, and empty workload. (#910) -
image/entrypoint/resourceLimitsno longer required whenpoolRefis set — these fields are defined on the Pool CRD template, but the schema previously rejected pool-mode requests without dummy values (422). Validation inschema.py,kubernetes_service.py,docker_service.py, andcontainer_ops.pynow skips these fields whenpoolRefis present, explicitly rejects thepoolRef+snapshotIdcombination, and rejectspoolRefon the Docker provider (unsupported).specs/sandbox-lifecycle.ymlupdated accordingly. Fixes #885. (#883) -
K8s
patch_sandbox_metadatafailed to delete keys and returned stale state — two bugs combined to break the nightly e2etest_02_metadata_filter_and_logic: (1) JSON merge patch (RFC 7396) merges labels recursively, so keys absent from the patch body are kept; the old code computed the final desired dict (already without the deleted keys) and sent that, so the deletes never reached the API server. (2) After PATCH the code re-read via_get_workload_or_404, which prefers the informer cache and could land before the watch event arrived, returning pre-patch labels. Fix: build the merge-patch body with explicitNonefor deleted keys, and use the API server's PATCH response directly instead of re-reading the cache.WorkloadProvider.patch_labelsnow takesDict[str, Optional[str]]and returns the patched workload dict. (#899)
📦 Misc
- Dependency: urllib3
2.6.3 → 2.7.0, includes two high-severity security fixes —GHSA-mf9v-mfxr-j63j(decompression-bomb safeguard bypass ondrain_conn/ secondread(amt=N)with Brotli) andGHSA-qccp-gfcp-xxvc(ProxyManager.connection_from_urldid not stripRetry.remove_headers_on_redirectheaders on cross-host redirect). (#872) - Bundled runtime image bumps — egress → v1.0.11 / v1.0.12, execd → v1.0.15 / v1.0.16, synced across example configs and docker-compose. (#847, #876, #889, #907)
- Docs: fixed dead links to
example.config*.tomlinserver/README.mdandserver/configuration.md(files actually live underserver/opensandbox_server/examples/). (#904) - Example: added dockur windows pool example. (#878)
- Agent guidance: updated
server/AGENTS.md. (#839)
👥 Contributors
Thanks to these contributors ❤️
- PyPI: opensandbox-server==0.1.14
- Docker Hub: opensandbox/server:v0.1.14
- Aliyun Registry: sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/server:v0.1.14