/ server / DEVELOPMENT.md
DEVELOPMENT.md
  1  # Development Guide
  2  
  3  This guide provides comprehensive information for developers working on OpenSandbox Server, including environment setup, architecture deep-dive, testing strategies, and contribution workflows.
  4  
  5  ## 📋 Table of Contents
  6  
  7  - [Development Environment Setup](#development-environment-setup)
  8  - [Project Structure](#project-structure)
  9  - [Architecture Deep Dive](#architecture-deep-dive)
 10  - [Development Workflow](#development-workflow)
 11  - [Testing Guide](#testing-guide)
 12  - [Working with Docker Runtime](#working-with-docker-runtime)
 13  - [Working with Kubernetes Runtime](#working-with-kubernetes-runtime)
 14  - [Code Style and Standards](#code-style-and-standards)
 15  - [Debugging](#debugging)
 16  - [Performance Optimization](#performance-optimization)
 17  - [Contributing](#contributing)
 18  
 19  ## Development Environment Setup
 20  
 21  ### Prerequisites
 22  
 23  - **Python 3.10+**: Check version with `python --version`
 24  - **uv**: Install from [https://github.com/astral-sh/uv](https://github.com/astral-sh/uv)
 25  - **Docker**: For local development and testing
 26  - **Git**: Version control
 27  - **IDE**: VS Code, PyCharm, or Cursor (recommended for AI assistance)
 28  
 29  ### Initial Setup
 30  
 31  1. **Clone and Navigate**
 32     ```bash
 33     git clone https://github.com/alibaba/OpenSandbox.git
 34     cd OpenSandbox/server
 35     ```
 36  
 37  2. **Install Dependencies**
 38     ```bash
 39     uv sync
 40     ```
 41  
 42  3. **Verify Installation**
 43     ```bash
 44     uv run python -c "import fastapi; print(fastapi.__version__)"
 45     ```
 46  
 47  4. **Configure Development Environment**
 48     ```bash
 49     cp opensandbox_server/examples/example.config.toml ~/.sandbox.toml
 50     ```
 51  
 52     Edit `~/.sandbox.toml` for local development:
 53     ```toml
 54     [server]
 55     host = "0.0.0.0"
 56     port = 8080
 57     api_key = "your-secret-api-key-change-this"
 58  
 59     [log]
 60     level = "DEBUG"
 61  
 62     [runtime]
 63     type = "docker"
 64     execd_image = "opensandbox/execd:v1.0.13"
 65  
 66     [docker]
 67     network_mode = "host"
 68     ```
 69  
 70  5. **Run Development Server**
 71     ```bash
 72     uv run python -m opensandbox_server.main
 73     ```
 74  
 75  ### IDE Configuration
 76  
 77  #### VS Code / Cursor
 78  
 79  Create `.vscode/launch.json`:
 80  
 81  ```json
 82  {
 83      "version": "0.2.0",
 84      "configurations": [
 85          {
 86              "name": "Python: FastAPI",
 87              "type": "python",
 88              "request": "launch",
 89              "module": "opensandbox_server.main",
 90              "justMyCode": false,
 91              "env": {
 92                  "SANDBOX_CONFIG_PATH": "${workspaceFolder}/.sandbox.toml"
 93              }
 94          }
 95      ]
 96  }
 97  ```
 98  
 99  #### PyCharm
100  
101  1. Open project in PyCharm
102  2. Configure Python interpreter: **Settings → Project → Python Interpreter**
103  3. Select the virtual environment created by `uv sync`
104  4. Enable pytest: **Settings → Tools → Python Integrated Tools → Testing → pytest**
105  
106  ## Project Structure
107  
108  ```
109  server/
110  ├── opensandbox_server/           # Source code
111  │   ├── main.py                   # FastAPI application entry point
112  │   ├── config.py                 # Configuration management
113  │   ├── api/                      # API layer
114  │   │   ├── lifecycle.py          # Sandbox lifecycle routes
115  │   │   └── schema.py             # Pydantic models
116  │   ├── middleware/               # Middleware components
117  │   │   └── auth.py               # API Key authentication
118  │   └── services/                 # Business logic layer
119  │       ├── sandbox_service.py    # Abstract base class
120  │       ├── docker.py             # Docker implementation
121  │       └── factory.py            # Service factory
122  ├── tests/                        # Test suite
123  ├── scripts/                      # Utility scripts
124  ├── pyproject.toml                # Project metadata and dependencies
125  └── example.config.toml           # Example configuration
126  ```
127  
128  ## Architecture Deep Dive
129  
130  ### Layered Architecture
131  
132  The server follows a clean layered architecture:
133  
134  1. **HTTP Layer** (FastAPI routes) - Request validation and response serialization
135  2. **Middleware Layer** - Authentication and cross-cutting concerns
136  3. **Service Layer** - Business logic abstraction
137  4. **Runtime Implementation Layer** - Docker/Kubernetes specific code
138  
139  ### Request Flow
140  
141  #### Create Sandbox (Async)
142  
143  ```
144  Client → POST /sandboxes
145    ↓
146  Auth Middleware validates API key
147    ↓
148  lifecycle.create_sandbox() receives CreateSandboxRequest
149    ↓
150  sandbox_service.create_sandbox_async(request)
151    ↓
152  Returns 202 Accepted with Pending status immediately
153    ↓
154  Background thread provisions the sandbox
155  ```
156  
157  ### Internal Systems
158  
159  #### Expiration Timer System
160  
161  Tracks sandbox timeouts using in-memory data structures:
162  - `_sandbox_expirations: Dict[str, datetime]` - Expiration times
163  - `_expiration_timers: Dict[str, Timer]` - Active timer threads
164  - `_expiration_lock: Lock` - Thread synchronization
165  
166  #### Async Provisioning System
167  
168  Avoids blocking API requests during slow operations by:
169  1. Storing sandboxes in pending state
170  2. Starting background provisioning thread
171  3. Returning 202 Accepted immediately
172  4. Transitioning to running state when ready
173  
174  ## Development Workflow
175  
176  ### Feature Development
177  
178  ```bash
179  git checkout -b feature/my-feature
180  # Implement feature
181  uv run pytest
182  git commit -m "feat: add my feature"
183  git push origin feature/my-feature
184  ```
185  
186  ### Bug Fixes
187  
188  ```bash
189  git checkout -b fix/bug-description
190  # Write failing test
191  # Fix bug
192  uv run pytest
193  git commit -m "fix: resolve bug"
194  ```
195  
196  ## Testing Guide
197  
198  ### Running Tests
199  > **Note**: A local Docker daemon is required to run the full test suite, as integration tests interact with the Docker Engine.
200  
201  ```bash
202  # All tests
203  uv run pytest
204  
205  # Specific file
206  uv run pytest tests/test_docker_service.py
207  
208  # With coverage
209  uv run pytest --cov=opensandbox_server --cov-report=html
210  ```
211  
212  ### Writing Tests
213  
214  Example unit test:
215  
216  ```python
217  @patch("opensandbox_server.services.docker.docker")
218  def test_create_sandbox_validates_entrypoint(mock_docker):
219      service = DockerSandboxService(config=test_config())
220      request = CreateSandboxRequest(
221          image=ImageSpec(uri="python:3.11"),
222          timeout=120,
223          entrypoint=[]  # Invalid
224      )
225      with pytest.raises(HTTPException):
226          service.create_sandbox(request)
227  ```
228  
229  ## Working with Docker Runtime
230  
231  ### Local Development
232  
233  ```bash
234  # Use local Docker
235  export DOCKER_HOST="unix:///var/run/docker.sock"
236  uv run python -m opensandbox_server.main
237  
238  # Use remote Docker
239  export DOCKER_HOST="ssh://user@remote-host"
240  uv run python -m opensandbox_server.main
241  ```
242  
243  ### Network Modes
244  
245  **Host Mode (Default):**
246  - Sandboxes share host network
247  - Direct port access
248  - Endpoint format: `http://{domain}/{sandbox_id}/{port}`
249  
250  **Bridge Mode:**
251  - Isolated networks
252  - HTTP proxy required
253  - Endpoint format: `http://{server}/route/{sandbox_id}/{port}/path`
254  
255  ### Egress sidecar (bridge + `networkPolicy`)
256  
257  - Config: set `[egress].image`; sidecar starts only when the request carries `networkPolicy`. Requires Docker `network_mode="bridge"`.
258  - Network & privileges: main container shares the sidecar netns (`network_mode=container:<sidecar>`); main container explicitly drops `NET_ADMIN`; sidecar keeps `NET_ADMIN` to manage iptables / DNS transparent redirect.
259  - Ports: host port bindings live on the sidecar; main container labels record the mapped ports for upstream endpoint resolution.
260  - Lifecycle: on create failure / delete / expiration / abnormal recovery, the sidecar is cleaned up; startup also removes orphaned sidecars.
261  - Injection: `OPENSANDBOX_EGRESS_RULES` env passes the `networkPolicy` JSON; sidecar image is pulled/ensured before start.
262  
263  ## Working with Kubernetes Runtime
264  
265  > **Status:** Planned / Configuration Ready
266  
267  Architecture will include:
268  - Pod management with execd init container
269  - Service/Ingress for networking
270  - CronJob or operator for expiration handling
271  
272  ## Code Style and Standards
273  
274  Follow PEP 8 with Ruff enforcement:
275  
276  ```bash
277  uv run ruff check opensandbox_server tests
278  ```
279  
280  ### Naming Conventions
281  
282  - Functions: `snake_case`
283  - Classes: `PascalCase`
284  - Constants: `UPPER_SNAKE_CASE`
285  - Private: `_leading_underscore`
286  
287  ### Type Hints
288  
289  Always use type hints:
290  
291  ```python
292  def get_sandbox(self, sandbox_id: str) -> Sandbox:
293      pass
294  ```
295  
296  ## Debugging
297  
298  ### Enable Debug Logging
299  
300  ```toml
301  [log]
302  level = "DEBUG"
303  ```
304  
305  ### Interactive Debugging
306  
307  Use VS Code/Cursor breakpoints or:
308  
309  ```python
310  breakpoint()  # Python 3.7+
311  ```
312  
313  ### Docker Debugging
314  
315  ```python
316  import logging
317  logging.getLogger("docker").setLevel(logging.DEBUG)
318  ```
319  
320  ## Performance Optimization
321  
322  ### Profiling
323  
324  ```bash
325  python -m cProfile -o profile.stats -m opensandbox_server.main
326  ```
327  
328  ### Optimization Tips
329  
330  1. **Async Operations**: Use async provisioning to avoid blocking
331  2. **Connection Pooling**: Reuse Docker client connections
332  3. **Caching**: Cache configuration and frequently accessed data
333  4. **Resource Limits**: Set appropriate container resource limits
334  5. **Monitoring**: Track container creation/deletion metrics
335  
336  ## Contributing
337  
338  ### Pull Request Process
339  
340  1. Fork the repository
341  2. Create feature branch from `main`
342  3. Write tests for new functionality
343  4. Ensure all tests pass: `uv run pytest`
344  5. Run linter: `uv run ruff check`
345  6. Write clear commit messages
346  7. Submit PR with description
347  
348  ### Code Review Guidelines
349  
350  - Focus on readability and maintainability
351  - Ensure test coverage for new code
352  - Check for proper error handling
353  - Verify documentation updates
354  - Test Docker and potential Kubernetes compatibility
355  
356  ### Commit Message Format
357  
358  ```
359  <type>: <description>
360  
361  Types: feat, fix, docs, style, refactor, test, chore
362  ```
363  
364  Examples:
365  - `feat: add Kubernetes runtime support`
366  - `fix: resolve expiration timer memory leak`
367  - `docs: update API documentation`
368  
369  ---
370  
371  For questions or support, please open an issue on the project repository.