fix(server): handle null spec.template in pool-mode BatchSandbox#910
Merged
Merged
Conversation
In pool mode (extensions.poolRef), BatchSandbox CRs have spec.poolRef
and spec.taskTemplate but no spec.template. The K8s API returns the CR
with spec.template: null because the CRD declares it as an optional
preserve-unknown-fields object.
_extract_platform_from_workload did spec.get("template", {}).get("spec"),
which only returns {} when the key is absent — not when its value is
None — so the second .get() crashes with
'NoneType' object has no attribute 'get'.
The sandbox is actually created and reaches Running, but the server
fails to build the response and returns HTTP 500 to the client.
Fix: treat null and missing as the same case when reading template /
podTemplate. Same pattern is already used correctly in
_build_sandbox_from_workload (workload_mapper.py:50).
Add regression tests covering pool mode (null template, missing
template), template-mode platform extraction, podTemplate alias, null
spec, and empty workload.
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes a server-side crash when pool-mode BatchSandbox workloads have spec.template: null, ensuring platform extraction is defensive and pool-mode sandbox creation no longer fails with HTTP 500.
Changes:
- Hardened
_extract_platform_from_workloadto treat missing/Nonespec.templateandspec.podTemplateas empty objects. - Added regression/unit tests covering
null/missing template,null spec, and empty workload cases.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| server/opensandbox_server/services/k8s/workload_mapper.py | Makes platform extraction resilient to None template/podTemplate in dict workloads. |
| server/tests/k8s/test_workload_mapper.py | Adds regression tests for the spec.template: None crash and related edge cases. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Creating a sandbox via pool mode (
extensions.poolRef) returns HTTP 500 with{"code":"KUBERNETES::API_ERROR","message":"Failed to create sandbox: 'NoneType' object has no attribute 'get'"}, even though the underlying sandbox is created successfully and reaches Running state.Pool-mode
BatchSandboxCRs havespec.poolRefandspec.taskTemplatebut nospec.template. Because the CRD declarestemplateas an optionalpreserve-unknown-fieldsobject, the Kubernetes API server returns the CR withspec.template: null(key present, value None).In
server/opensandbox_server/services/k8s/workload_mapper.py:85:The default
{}is only returned when the key is absent — not when its value isNone. Sospec.get("template", {})returnsNoneand the next.get("spec")crashes.Impact
BatchSandboxis created and the Pod reaches Running, but clients see an error and have nosandbox_idreturned. Resources leak unless cleaned up out-of-band.POST /sandboxesthat usesextensions.poolRef(the documented way to use pools).Reproduction:
AVAILABLE >= 1.POST /sandboxeswithextensions.poolRef=<pool-name>.kubectl get batchsandboxshows the sandbox is actuallyALLOCATED=1 READY=1.Fix
Treat null and missing the same when reading
template/podTemplate. The sameor {}pattern is already used correctly in the sibling function_build_sandbox_from_workload(workload_mapper.py:50).Added
server/tests/k8s/test_workload_mapper.pywith 6 cases:podTemplatealias still worksspecTesting
POST /sandboxeswithextensions.poolRefnow returns the expectedCreateSandboxResponsewithstate: RunningBreaking Changes
Checklist