Skip to main content

ECI-backed sandbox manager with an Agent interface.

Project description

English | 简体中文

eci-as-sandbox

ECI-backed sandbox manager built on alibabacloud-eci20180808 with a lightweight API for managing container-group sandboxes.

Install

pdm add eci-as-sandbox

Environment

The client auto-loads a .env file (searching upward from the working directory). You can also pass env_file=... or explicit credentials.

Required Alibaba Cloud credentials:

set ALIBABA_CLOUD_ACCESS_KEY_ID=...
set ALIBABA_CLOUD_ACCESS_KEY_SECRET=...
set ALIBABA_CLOUD_REGION_ID=cn-shanghai

Optional overrides:

set ECI_SANDBOX_ACCESS_KEY_ID=...
set ECI_SANDBOX_ACCESS_KEY_SECRET=...
set ECI_SANDBOX_REGION_ID=cn-shanghai
set ECI_SANDBOX_ENDPOINT=eci.cn-shanghai.aliyuncs.com
set ECI_SANDBOX_TIMEOUT_MS=60000

If you use a private image, configure registry credentials in ECI.

Quick start (sync)

from eci_as_sandbox import EciSandbox

client = EciSandbox()
result = client.create(
    image="registry.cn-hangzhou.aliyuncs.com/eci_open/nginx:latest",
    name="sandbox-demo",
    cpu=1.0,
    memory=2.0,
    v_switch_id="vsw-xxx",
    security_group_id="sg-xxx",
    ports=[{"port": 8080, "protocol": "TCP"}],
)

if result.success and result.sandbox:
    sandbox = result.sandbox
    info = sandbox.info()
    print(info.data.status)
    sandbox.delete()

Async quick start

import asyncio
from eci_as_sandbox import AsyncEciSandbox


async def main() -> None:
    client = AsyncEciSandbox()
    result = await client.create(
        image="registry.cn-hangzhou.aliyuncs.com/eci_open/nginx:latest",
        name="sandbox-demo",
        cpu=1.0,
        memory=2.0,
        v_switch_id="vsw-xxx",
        security_group_id="sg-xxx",
    )
    if result.success and result.sandbox:
        info = await result.sandbox.info()
        print(info.data.status)


asyncio.run(main())

Command helpers

exec_command runs a list-form command. With sync=True (default) it uses the ECI WebSocket stream to collect output. timeout is in seconds and caps the stream duration (default 600 seconds, max 600). Use sync=False if you want the WebSocket/HTTP URLs without waiting.

result = sandbox.exec_command(
    ["/bin/sh", "-c", "for i in 1 2 3; do echo tick-$i; sleep 2; done"],
    timeout=3,
)
print(result.output)

bash runs a shell command via bash -lc and supports exec_dir.

result = sandbox.bash(
    command="pwd; ls -la",
    exec_dir="/tmp",
    timeout=5,
)
print(result.output)

Listing

result = client.list(limit=10, status="Running")
print(result.sandbox_ids)

Long command execution (WebSocket)

ECI's API has a 2048-byte command limit. For longer commands, use bash_ws which sends commands through WebSocket stdin (no length limit).

# Execute a very long command (e.g., inline Python script)
long_script = """python3 << 'EOF'
import json
# ... hundreds of lines of code ...
print(json.dumps({"status": "done"}))
EOF
"""

result = client.bash_ws(
    sandbox_id=sandbox_id,
    command=long_script,
    exec_dir="/workspace",
    timeout=60,
)
print(result.output)

write_file_ws writes large content to a file via WebSocket:

result = client.write_file_ws(
    sandbox_id=sandbox_id,
    file_path="/tmp/large_script.py",
    content="# Very long file content...\n" * 1000,
    timeout=30,
)

Tmux session management

For non-blocking command execution with output capture, use tmux methods. Long commands are automatically handled via WebSocket file transfer.

# Start a command in tmux (non-blocking)
start_result = client.tmux_start(
    sandbox_id=sandbox_id,
    command="python train.py --epochs 100",
    exec_dir="/workspace",
)
print(f"Session: {start_result.session_id}")

# Poll for status and partial output
poll_result = client.tmux_poll(
    sandbox_id=sandbox_id,
    session_id=start_result.session_id,
)
print(f"Status: {poll_result.status}")  # RUNNING, COMPLETED, NOT_FOUND
print(f"Output: {poll_result.output}")

# Wait for completion with exponential backoff
wait_result = client.tmux_wait(
    sandbox_id=sandbox_id,
    session_id=start_result.session_id,
    timeout=300,  # max wait time
)
print(f"Exit code: {wait_result.exit_code}")
print(f"Output: {wait_result.output}")

# Kill a session manually
client.tmux_kill(sandbox_id=sandbox_id, session_id=start_result.session_id)

# List all tmux sessions
list_result = client.tmux_list(sandbox_id=sandbox_id)
print(list_result.data)  # [{"session_id": "...", "created": "...", "attached": False}]

API Reference

Client Methods

Method Description
create(image, name, cpu, memory, ...) Create a new sandbox container
get(sandbox_id) Get sandbox instance by ID
get_sandbox(sandbox_id) Get sandbox info
list(limit, status, tags, ...) List sandboxes
delete(sandbox_id, force) Delete a sandbox
restart(sandbox_id) Restart a sandbox
exec_command(sandbox_id, command, ...) Execute command (list form)
bash(sandbox_id, command, exec_dir, ...) Execute bash command
bash_ws(sandbox_id, command, exec_dir, ...) Execute bash via WebSocket (unlimited length)
write_file_ws(sandbox_id, file_path, content, ...) Write file via WebSocket (unlimited length)
tmux_start(sandbox_id, command, ...) Start command in tmux session
tmux_poll(sandbox_id, session_id, ...) Poll tmux session status
tmux_wait(sandbox_id, session_id, timeout, ...) Wait for tmux session completion
tmux_kill(sandbox_id, session_id) Kill tmux session
tmux_list(sandbox_id) List all tmux sessions

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

eci_as_sandbox-0.2.3.tar.gz (28.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

eci_as_sandbox-0.2.3-py3-none-any.whl (31.9 kB view details)

Uploaded Python 3

File details

Details for the file eci_as_sandbox-0.2.3.tar.gz.

File metadata

  • Download URL: eci_as_sandbox-0.2.3.tar.gz
  • Upload date:
  • Size: 28.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for eci_as_sandbox-0.2.3.tar.gz
Algorithm Hash digest
SHA256 ffcd1fbe1b0d5d72ca7e12721fddf74b91f853fa68eff07cf73d274dcea10d82
MD5 163294f5092d23aa5093b7ddbf85da1c
BLAKE2b-256 c36446c5c302a6e261c2b0bcc818ac8ed9d099e44adf52d30aef2b15bcc32668

See more details on using hashes here.

Provenance

The following attestation bundles were made for eci_as_sandbox-0.2.3.tar.gz:

Publisher: publish.yml on AndersonBY/eci-as-sandbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file eci_as_sandbox-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: eci_as_sandbox-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 31.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for eci_as_sandbox-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 8ded8ada2b1104801c373a82fe7e491d00c1f343289fcba6495a7c2021261059
MD5 1e1e13c4c351d7059b1fab3c88fbd3f6
BLAKE2b-256 22134d393ca395a11717fd1964888c1ecb1d871d92b97273d1dff7d3015425fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for eci_as_sandbox-0.2.3-py3-none-any.whl:

Publisher: publish.yml on AndersonBY/eci-as-sandbox

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page