Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ async def list_sandboxes(self, filter: SandboxFilter) -> PagedSandboxInfos:
raise ExceptionConverter.to_sandbox_exception(e) from e

async def get_sandbox_endpoint(
self, sandbox_id: str, port: int
self, sandbox_id: str, port: int, use_server_proxy: bool = False
) -> SandboxEndpoint:
"""Get network endpoint information for a sandbox service."""
logger.debug(f"Retrieving sandbox endpoint: {sandbox_id}, port {port}")
Expand All @@ -231,6 +231,7 @@ async def get_sandbox_endpoint(
client=client,
sandbox_id=sandbox_id,
port=port,
use_server_proxy=use_server_proxy,
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,28 @@
from ...client import AuthenticatedClient, Client
from ...models.endpoint import Endpoint
from ...models.error_response import ErrorResponse
from ...types import Response
from ...types import UNSET, Response, Unset


def _get_kwargs(
sandbox_id: str,
port: int,
*,
use_server_proxy: bool | Unset = False,
) -> dict[str, Any]:
params: dict[str, Any] = {}

params["use_server_proxy"] = use_server_proxy

params = {k: v for k, v in params.items() if v is not UNSET and v is not None}

_kwargs: dict[str, Any] = {
"method": "get",
"url": "/sandboxes/{sandbox_id}/endpoints/{port}".format(
sandbox_id=quote(str(sandbox_id), safe=""),
port=quote(str(port), safe=""),
),
"params": params,
}

return _kwargs
Expand Down Expand Up @@ -92,6 +101,7 @@ def sync_detailed(
port: int,
*,
client: AuthenticatedClient | Client,
use_server_proxy: bool | Unset = False,
) -> Response[Endpoint | ErrorResponse]:
"""Get sandbox access endpoint

Expand All @@ -102,6 +112,7 @@ def sync_detailed(
Args:
sandbox_id (str):
port (int):
use_server_proxy (bool | Unset): Default: False.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
Expand All @@ -114,6 +125,7 @@ def sync_detailed(
kwargs = _get_kwargs(
sandbox_id=sandbox_id,
port=port,
use_server_proxy=use_server_proxy,
)

response = client.get_httpx_client().request(
Expand All @@ -128,6 +140,7 @@ def sync(
port: int,
*,
client: AuthenticatedClient | Client,
use_server_proxy: bool | Unset = False,
) -> Endpoint | ErrorResponse | None:
"""Get sandbox access endpoint

Expand All @@ -138,6 +151,7 @@ def sync(
Args:
sandbox_id (str):
port (int):
use_server_proxy (bool | Unset): Default: False.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
Expand All @@ -151,6 +165,7 @@ def sync(
sandbox_id=sandbox_id,
port=port,
client=client,
use_server_proxy=use_server_proxy,
).parsed


Expand All @@ -159,6 +174,7 @@ async def asyncio_detailed(
port: int,
*,
client: AuthenticatedClient | Client,
use_server_proxy: bool | Unset = False,
) -> Response[Endpoint | ErrorResponse]:
"""Get sandbox access endpoint

Expand All @@ -169,6 +185,7 @@ async def asyncio_detailed(
Args:
sandbox_id (str):
port (int):
use_server_proxy (bool | Unset): Default: False.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
Expand All @@ -181,6 +198,7 @@ async def asyncio_detailed(
kwargs = _get_kwargs(
sandbox_id=sandbox_id,
port=port,
use_server_proxy=use_server_proxy,
)

response = await client.get_async_httpx_client().request(**kwargs)
Expand All @@ -193,6 +211,7 @@ async def asyncio(
port: int,
*,
client: AuthenticatedClient | Client,
use_server_proxy: bool | Unset = False,
) -> Endpoint | ErrorResponse | None:
"""Get sandbox access endpoint

Expand All @@ -203,6 +222,7 @@ async def asyncio(
Args:
sandbox_id (str):
port (int):
use_server_proxy (bool | Unset): Default: False.

Raises:
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
Expand All @@ -217,5 +237,6 @@ async def asyncio(
sandbox_id=sandbox_id,
port=port,
client=client,
use_server_proxy=use_server_proxy,
)
).parsed
7 changes: 7 additions & 0 deletions sdks/sandbox/python/src/opensandbox/config/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ class ConnectionConfig(BaseModel):
"with custom settings) to control connection pooling, proxies, retries, etc."
),
)
use_server_proxy: bool = Field(
default=False,
description=(
"Using sandbox server as proxy for process execd requests"
"It's useful when client sdk can't access the created sandbox directly"
),
)

# Environment variable names
_ENV_API_KEY = "OPEN_SANDBOX_API_KEY"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ class ConnectionConfigSync(BaseModel):
"with custom limits/proxies) to control connection pooling, proxies, retries, etc."
),
)
use_server_proxy: bool = Field(
default=False,
description=(
"Using sandbox server as proxy for process execd requests"
"It's useful when client sdk can't access the created sandbox directly"
),
)

_ENV_API_KEY = "OPEN_SANDBOX_API_KEY"
_ENV_DOMAIN = "OPEN_SANDBOX_DOMAIN"
Expand Down
10 changes: 6 additions & 4 deletions sdks/sandbox/python/src/opensandbox/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ async def get_endpoint(self, port: int) -> SandboxEndpoint:
Raises:
SandboxException: if endpoint cannot be retrieved
"""
return await self._sandbox_service.get_sandbox_endpoint(self.id, port)
return await self._sandbox_service.get_sandbox_endpoint(
self.id, port, self.connection_config.use_server_proxy
)

async def get_metrics(self) -> SandboxMetrics:
"""
Expand Down Expand Up @@ -422,7 +424,7 @@ async def create(
sandbox_id = response.id

execd_endpoint = await sandbox_service.get_sandbox_endpoint(
response.id, DEFAULT_EXECD_PORT
response.id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
Expand Down Expand Up @@ -510,7 +512,7 @@ async def connect(
try:
sandbox_service = factory.create_sandbox_service()
execd_endpoint = await sandbox_service.get_sandbox_endpoint(
sandbox_id, DEFAULT_EXECD_PORT
sandbox_id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
Expand Down Expand Up @@ -581,7 +583,7 @@ async def resume(
await sandbox_service.resume_sandbox(sandbox_id)

execd_endpoint = await sandbox_service.get_sandbox_endpoint(
sandbox_id, DEFAULT_EXECD_PORT
sandbox_id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
Expand Down
3 changes: 2 additions & 1 deletion sdks/sandbox/python/src/opensandbox/services/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,15 @@ async def list_sandboxes(self, filter: SandboxFilter) -> PagedSandboxInfos:
...

async def get_sandbox_endpoint(
self, sandbox_id: str, port: int
self, sandbox_id: str, port: int, use_server_proxy: bool = False
) -> SandboxEndpoint:
"""
Get sandbox endpoint.
Args:
sandbox_id: Sandbox ID
port: Endpoint port number
use_server_proxy: Whether to use server proxy for endpoint
Returns:
Target sandbox endpoint
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ def list_sandboxes(self, filter: SandboxFilter) -> PagedSandboxInfos:
logger.error("Failed to list sandboxes", exc_info=e)
raise ExceptionConverter.to_sandbox_exception(e) from e

def get_sandbox_endpoint(self, sandbox_id: str, port: int) -> SandboxEndpoint:
def get_sandbox_endpoint(
self, sandbox_id: str, port: int, use_server_proxy: bool = False
) -> SandboxEndpoint:
try:
from opensandbox.api.lifecycle.api.sandboxes import (
get_sandboxes_sandbox_id_endpoints_port,
Expand All @@ -184,6 +186,7 @@ def get_sandbox_endpoint(self, sandbox_id: str, port: int) -> SandboxEndpoint:
sandbox_id=sandbox_id,
port=port,
client=self._get_client(),
use_server_proxy=use_server_proxy,
)
handle_api_error(response_obj, f"Get endpoint for sandbox {sandbox_id} port {port}")
parsed = require_parsed(response_obj, ApiEndpoint, "Get endpoint")
Expand Down
16 changes: 12 additions & 4 deletions sdks/sandbox/python/src/opensandbox/sync/sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,9 @@ def get_endpoint(self, port: int) -> SandboxEndpoint:
Raises:
SandboxException: if endpoint cannot be retrieved
"""
return self._sandbox_service.get_sandbox_endpoint(self.id, port)
return self._sandbox_service.get_sandbox_endpoint(
self.id, port, self.connection_config.use_server_proxy
)

def get_metrics(self) -> SandboxMetrics:
"""
Expand Down Expand Up @@ -407,7 +409,9 @@ def create(
extensions,
)
sandbox_id = response.id
execd_endpoint = sandbox_service.get_sandbox_endpoint(response.id, DEFAULT_EXECD_PORT)
execd_endpoint = sandbox_service.get_sandbox_endpoint(
response.id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
sandbox_id=response.id,
Expand Down Expand Up @@ -484,7 +488,9 @@ def connect(

try:
sandbox_service = factory.create_sandbox_service()
execd_endpoint = sandbox_service.get_sandbox_endpoint(sandbox_id, DEFAULT_EXECD_PORT)
execd_endpoint = sandbox_service.get_sandbox_endpoint(
sandbox_id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
sandbox_id=sandbox_id,
Expand Down Expand Up @@ -553,7 +559,9 @@ def resume(
sandbox_service = factory.create_sandbox_service()
sandbox_service.resume_sandbox(sandbox_id)

execd_endpoint = sandbox_service.get_sandbox_endpoint(sandbox_id, DEFAULT_EXECD_PORT)
execd_endpoint = sandbox_service.get_sandbox_endpoint(
sandbox_id, DEFAULT_EXECD_PORT, config.use_server_proxy
)

sandbox = cls(
sandbox_id=sandbox_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,16 @@ def list_sandboxes(self, filter: SandboxFilter) -> PagedSandboxInfos:
"""
...

def get_sandbox_endpoint(self, sandbox_id: str, port: int) -> SandboxEndpoint:
def get_sandbox_endpoint(
self, sandbox_id: str, port: int, use_server_proxy: bool = False
) -> SandboxEndpoint:
"""
Get sandbox endpoint for an exposed port.

Args:
sandbox_id: Sandbox id.
port: Endpoint port number.
use_server_proxy: Whether to use server proxy for endpoint.

Returns:
Target sandbox endpoint.
Expand Down
4 changes: 2 additions & 2 deletions server/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ classifiers = [
dependencies = [
"docker",
"fastapi",
"httpx",
"httpx[socks]",
"kubernetes",
"pydantic",
"pydantic-settings",
Expand Down Expand Up @@ -119,4 +119,4 @@ venvPath = "."
venv = ".venv"

reportMissingImports = true
reportMissingTypeStubs = false
reportMissingTypeStubs = false
Loading