Skip to content

Commit

Permalink
Add envd version to SDKs (#548)
Browse files Browse the repository at this point in the history
# Description

Add envd version when creating sandbox to allow for check if features
are available
  • Loading branch information
jakubno authored Jan 23, 2025
2 parents 91b06e3 + 323c221 commit e3f953d
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 33 deletions.
9 changes: 8 additions & 1 deletion packages/js-sdk/src/envd/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,19 @@ export async function handleWatchDirStartEvent(

class EnvdApiClient {
readonly api: ReturnType<typeof createClient<paths>>
readonly version: string | undefined

constructor(config: Pick<ConnectionConfig, 'apiUrl' | 'logger'>) {
constructor(
config: Pick<ConnectionConfig, 'apiUrl' | 'logger'>,
metadata: {
version?: string
}
) {
this.api = createClient({
baseUrl: config.apiUrl,
// keepalive: true, // TODO: Return keepalive
})
this.version = metadata.version

if (config.logger) {
this.api.use(createApiLogger(config.logger))
Expand Down
28 changes: 17 additions & 11 deletions packages/js-sdk/src/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export class Sandbox extends SandboxApi {
constructor(
opts: Omit<SandboxOpts, 'timeoutMs' | 'envs' | 'metadata'> & {
sandboxId: string
envdVersion?: string
}
) {
super()
Expand All @@ -115,10 +116,15 @@ export class Sandbox extends SandboxApi {
interceptors: opts?.logger ? [createRpcLogger(opts.logger)] : undefined,
})

this.envdApi = new EnvdApiClient({
apiUrl: this.envdApiUrl,
logger: opts?.logger,
})
this.envdApi = new EnvdApiClient(
{
apiUrl: this.envdApiUrl,
logger: opts?.logger,
},
{
version: opts?.envdVersion
}
)
this.files = new Filesystem(
rpcTransport,
this.envdApi,
Expand Down Expand Up @@ -177,16 +183,16 @@ export class Sandbox extends SandboxApi {

const config = new ConnectionConfig(sandboxOpts)

const sandboxId = config.debug
? 'debug_sandbox_id'
: await this.createSandbox(
if (config.debug) {
return new this({ sandboxId: 'debug_sandbox_id', ...config }) as InstanceType<S>
} else {
const sandbox = await this.createSandbox(
template,
sandboxOpts?.timeoutMs ?? this.defaultSandboxTimeoutMs,
sandboxOpts
)

const sbx = new this({ sandboxId, ...config }) as InstanceType<S>
return sbx
)
return new this({ ...sandbox, ...config }) as InstanceType<S>
}
}

/**
Expand Down
16 changes: 11 additions & 5 deletions packages/js-sdk/src/sandbox/sandboxApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,10 @@ export class SandboxApi {
metadata?: Record<string, string>
envs?: Record<string, string>
}
): Promise<string> {
): Promise<{
sandboxId: string
envdVersion: string
}> {
const config = new ConnectionConfig(opts)
const client = new ApiClient(config)

Expand Down Expand Up @@ -191,10 +194,13 @@ export class SandboxApi {
'You can do this by running `e2b template build` in the directory with the template.'
)
}
return this.getSandboxId({
sandboxId: res.data!.sandboxID,
clientId: res.data!.clientID,
})
return {
sandboxId: this.getSandboxId({
sandboxId: res.data!.sandboxID,
clientId: res.data!.clientID,
}),
envdVersion: res.data!.envdVersion
}
}

private static timeoutToSeconds(timeout: number): number {
Expand Down
2 changes: 2 additions & 0 deletions packages/js-sdk/tests/sandbox/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ test.skipIf(isDebug)('create', async () => {
const sbx = await Sandbox.create(template, { timeoutMs: 5_000 })
try {
const isRunning = await sbx.isRunning()
// @ts-ignore It's only for testing
assert.isDefined(sbx.envdApi.version)
assert.isTrue(isRunning)
} finally {
await sbx.kill()
Expand Down
7 changes: 7 additions & 0 deletions packages/python-sdk/e2b/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
from dataclasses import dataclass

from typing import Optional, Union
from httpx import HTTPTransport, AsyncHTTPTransport
Expand All @@ -17,6 +18,12 @@
logger = logging.getLogger(__name__)


@dataclass
class SandboxCreateResponse:
sandbox_id: str
envd_version: str


def handle_api_exception(e: Response):
try:
body = json.loads(e.content) if e.content else {}
Expand Down
16 changes: 11 additions & 5 deletions packages/python-sdk/e2b/sandbox_async/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ async def handle_async_request(self, request):

class AsyncSandboxOpts(TypedDict):
sandbox_id: str
envd_version: Optional[str]
connection_config: ConnectionConfig


Expand Down Expand Up @@ -103,6 +104,7 @@ def __init__(self, **opts: Unpack[AsyncSandboxOpts]):
self._connection_config = opts["connection_config"]

self._envd_api_url = f"{'http' if self.connection_config.debug else 'https'}://{self.get_host(self.envd_port)}"
self._envd_version = opts["envd_version"]

self._transport = AsyncTransportWithLogger(limits=self._limits)
self._envd_api = httpx.AsyncClient(
Expand Down Expand Up @@ -198,10 +200,11 @@ async def create(
request_timeout=request_timeout,
)

sandbox_id = (
"debug_sandbox_id"
if connection_config.debug
else await SandboxApi._create_sandbox(
if connection_config.debug:
sandbox_id = "debug_sandbox_id"
envd_version = None
else:
response = await SandboxApi._create_sandbox(
template=template or cls.default_template,
api_key=api_key,
timeout=timeout or cls.default_sandbox_timeout,
Expand All @@ -211,10 +214,12 @@ async def create(
request_timeout=request_timeout,
env_vars=envs,
)
)
sandbox_id = response.sandbox_id
envd_version = response.envd_version

return cls(
sandbox_id=sandbox_id,
envd_version=envd_version,
connection_config=connection_config,
)

Expand Down Expand Up @@ -251,6 +256,7 @@ async def connect(

return cls(
sandbox_id=sandbox_id,
envd_version=None,
connection_config=connection_config,
)

Expand Down
13 changes: 8 additions & 5 deletions packages/python-sdk/e2b/sandbox_async/sandbox_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from e2b.sandbox.sandbox_api import SandboxInfo, SandboxApiBase
from e2b.exceptions import TemplateException
from e2b.api import AsyncApiClient
from e2b.api import AsyncApiClient, SandboxCreateResponse
from e2b.api.client.models import NewSandbox, PostSandboxesSandboxIDTimeoutBody
from e2b.api.client.api.sandboxes import (
post_sandboxes_sandbox_id_timeout,
Expand Down Expand Up @@ -142,7 +142,7 @@ async def _create_sandbox(
domain: Optional[str] = None,
debug: Optional[bool] = None,
request_timeout: Optional[float] = None,
) -> str:
) -> SandboxCreateResponse:
config = ConnectionConfig(
api_key=api_key,
domain=domain,
Expand Down Expand Up @@ -179,9 +179,12 @@ async def _create_sandbox(
"You can do this by running `e2b template build` in the directory with the template."
)

return SandboxApi._get_sandbox_id(
res.parsed.sandbox_id,
res.parsed.client_id,
return SandboxCreateResponse(
sandbox_id=SandboxApi._get_sandbox_id(
res.parsed.sandbox_id,
res.parsed.client_id,
),
envd_version=res.parsed.envd_version,
)

@staticmethod
Expand Down
6 changes: 5 additions & 1 deletion packages/python-sdk/e2b/sandbox_sync/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,14 @@ def __init__(

if self.connection_config.debug:
self._sandbox_id = "debug_sandbox_id"
self._envd_version = None
elif sandbox_id is not None:
self._sandbox_id = sandbox_id
self._envd_version = None
else:
template = template or self.default_template
timeout = timeout or self.default_sandbox_timeout
self._sandbox_id = SandboxApi._create_sandbox(
response = SandboxApi._create_sandbox(
template=template,
api_key=api_key,
timeout=timeout,
Expand All @@ -144,6 +146,8 @@ def __init__(
debug=debug,
request_timeout=request_timeout,
)
self._sandbox_id = response.sandbox_id
self._envd_version = response.envd_version

self._envd_api_url = f"{'http' if self.connection_config.debug else 'https'}://{self.get_host(self.envd_port)}"

Expand Down
13 changes: 8 additions & 5 deletions packages/python-sdk/e2b/sandbox_sync/sandbox_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from e2b.sandbox.sandbox_api import SandboxInfo, SandboxApiBase
from e2b.exceptions import TemplateException
from e2b.api import ApiClient
from e2b.api import ApiClient, SandboxCreateResponse
from e2b.api.client.models import NewSandbox, PostSandboxesSandboxIDTimeoutBody
from e2b.api.client.api.sandboxes import (
post_sandboxes_sandbox_id_timeout,
Expand Down Expand Up @@ -149,7 +149,7 @@ def _create_sandbox(
domain: Optional[str] = None,
debug: Optional[bool] = None,
request_timeout: Optional[float] = None,
) -> str:
) -> SandboxCreateResponse:
config = ConnectionConfig(
api_key=api_key,
domain=domain,
Expand Down Expand Up @@ -188,7 +188,10 @@ def _create_sandbox(
"You can do this by running `e2b template build` in the directory with the template."
)

return SandboxApi._get_sandbox_id(
res.parsed.sandbox_id,
res.parsed.client_id,
return SandboxCreateResponse(
sandbox_id=SandboxApi._get_sandbox_id(
res.parsed.sandbox_id,
res.parsed.client_id,
),
envd_version=res.parsed.envd_version,
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ async def test_start(template):
sbx = await AsyncSandbox.create(template, timeout=5)
try:
assert await sbx.is_running()
assert sbx._envd_version is not None
finally:
await sbx.kill()

Expand Down
1 change: 1 addition & 0 deletions packages/python-sdk/tests/sync/sandbox_sync/test_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ def test_start(template):
sbx = Sandbox(template, timeout=5)
try:
assert sbx.is_running()
assert sbx._envd_version is not None
finally:
sbx.kill()

Expand Down

0 comments on commit e3f953d

Please sign in to comment.