Skip to content

Commit 74117c2

Browse files
Gujiasshsisyphus-dev-ai
authored andcommitted
fix(server): normalize BatchSandbox create status
Stop leaking the internal Allocated state once create_sandbox has already passed its usability gate, and cover the create-path contract with a focused regression test. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent 6ff8763 commit 74117c2

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

server/opensandbox_server/services/k8s/kubernetes_service.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ async def _wait_for_sandbox_ready(
185185
continue
186186

187187
# Get status
188-
status_info = self.workload_provider.get_status(workload)
188+
status_info = self._normalize_create_status(
189+
self.workload_provider.get_status(workload)
190+
)
189191
current_state = status_info["state"]
190192
current_message = status_info["message"]
191193

@@ -224,6 +226,17 @@ async def _wait_for_sandbox_ready(
224226
),
225227
},
226228
)
229+
230+
@staticmethod
231+
def _normalize_create_status(status_info: Dict[str, Any]) -> Dict[str, Any]:
232+
if status_info.get("state") != "Allocated":
233+
return status_info
234+
235+
return {
236+
**status_info,
237+
"state": "Running",
238+
"message": "Pod has IP assigned and sandbox is ready for requests",
239+
}
227240

228241
def _ensure_network_policy_support(self, request: CreateSandboxRequest) -> None:
229242
"""
@@ -363,7 +376,9 @@ async def create_sandbox(self, request: CreateSandboxRequest) -> CreateSandboxRe
363376
)
364377

365378
# Get final status
366-
status_info = self.workload_provider.get_status(workload)
379+
status_info = self._normalize_create_status(
380+
self.workload_provider.get_status(workload)
381+
)
367382

368383
# Build and return response with Running state
369384
return CreateSandboxResponse(

server/tests/k8s/test_kubernetes_service.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,28 @@ async def test_create_sandbox_with_valid_request_succeeds(
129129
assert response.status.state == "Running"
130130
k8s_service.workload_provider.create_workload.assert_called_once()
131131

132+
@pytest.mark.asyncio
133+
async def test_create_sandbox_normalizes_allocated_status_to_running(
134+
self, k8s_service, create_sandbox_request, mock_workload
135+
):
136+
k8s_service.workload_provider.create_workload.return_value = {
137+
"name": "test-sandbox-123",
138+
"uid": "abc-123",
139+
}
140+
k8s_service.workload_provider.get_workload.return_value = mock_workload
141+
k8s_service.workload_provider.get_status.return_value = {
142+
"state": "Allocated",
143+
"reason": "IP_ASSIGNED",
144+
"message": "Pod has IP assigned but not ready",
145+
"last_transition_at": datetime.now(timezone.utc),
146+
}
147+
148+
response = await k8s_service.create_sandbox(create_sandbox_request)
149+
150+
assert response.status.state == "Running"
151+
assert response.status.reason == "IP_ASSIGNED"
152+
assert response.status.message == "Pod has IP assigned and sandbox is ready for requests"
153+
132154
@pytest.mark.asyncio
133155
async def test_create_sandbox_uses_configured_timeout_and_poll_interval(
134156
self, k8s_service, create_sandbox_request, mock_workload

0 commit comments

Comments
 (0)