mirror of
https://github.com/azaion/loader.git
synced 2026-04-22 22:16:32 +00:00
4eaf218f09
Made-with: Cursor
110 lines
5.5 KiB
Markdown
110 lines
5.5 KiB
Markdown
# Module: main
|
||
|
||
## Purpose
|
||
|
||
FastAPI application entry point providing HTTP endpoints for health checks, authentication, encrypted resource loading/uploading, and a multi-step Docker image unlock workflow.
|
||
|
||
## Public Interface
|
||
|
||
### FastAPI Application
|
||
|
||
`app = FastAPI(title="Azaion.Loader")`
|
||
|
||
### Endpoints
|
||
|
||
| Method | Path | Request Body | Response | Description |
|
||
|--------|------------------|---------------------|----------------------------|----------------------------------------------------|
|
||
| GET | `/health` | — | `{"status": "healthy"}` | Liveness probe |
|
||
| GET | `/status` | — | `StatusResponse` | Auth status + model cache dir |
|
||
| POST | `/login` | `LoginRequest` | `{"status": "ok"}` | Set credentials on API client |
|
||
| POST | `/load/{filename}`| `LoadRequest` | binary (octet-stream) | Download + decrypt resource |
|
||
| POST | `/upload/{filename}`| multipart (file + folder) | `{"status": "ok"}` | Encrypt + upload resource (big/small split) |
|
||
| POST | `/unlock` | `LoginRequest` | `{"state": "..."}` | Start background unlock workflow |
|
||
| GET | `/unlock/status` | — | `{"state": "...", "error": ...}` | Poll unlock progress |
|
||
|
||
### Pydantic Models
|
||
|
||
| Model | Fields |
|
||
|-----------------|----------------------------------------------|
|
||
| LoginRequest | email: str, password: str |
|
||
| LoadRequest | filename: str, folder: str |
|
||
| HealthResponse | status: str |
|
||
| StatusResponse | status: str, authenticated: bool, modelCacheDir: str |
|
||
|
||
### Module-level State
|
||
|
||
| Name | Type | Description |
|
||
|-------------------|-------------------------|----------------------------------------------------------------|
|
||
| `_api_client` | `ApiClient` or `None` | Lazy-initialized singleton |
|
||
| `_api_client_lock`| `threading.Lock` | Protects lazy initialization of `_api_client` (double-checked) |
|
||
| `_unlock` | `_UnlockStateHolder` | Holds unlock workflow state and last error under an inner lock |
|
||
|
||
#### `_UnlockStateHolder`
|
||
|
||
| Member | Description |
|
||
|-----------|-----------------------------------------------------------------------------|
|
||
| `get()` | Returns `(state: UnlockState, error: Optional[str])` under lock |
|
||
| `set(state, error=None)` | Sets state and optional error message under lock |
|
||
| `state` (property) | Current `UnlockState` (read under lock) |
|
||
|
||
## Internal Logic
|
||
|
||
### `get_api_client()`
|
||
Double-checked locking: if `_api_client` is `None`, acquires `_api_client_lock`, re-checks, then imports `ApiClient` and constructs `ApiClient(RESOURCE_API_URL)` once.
|
||
|
||
### Unlock Workflow (`_run_unlock`)
|
||
Background task (via FastAPI BackgroundTasks) that runs these steps:
|
||
1. Check if Docker images already loaded → if yes, set `ready` (preserving any prior error from `get()`)
|
||
2. Authenticate with API (login)
|
||
3. Download key fragment from `/binary-split/key-fragment`
|
||
4. Decrypt archive at `IMAGES_PATH` → `.tar`
|
||
5. `docker load` the tar file
|
||
6. Remove tar file; on `OSError`, log a warning and continue
|
||
7. Set state to `ready` with no error (or `error` on failure)
|
||
|
||
State and error are updated only through `_unlock.set()` and read via `_unlock.get()` / `_unlock.state`.
|
||
|
||
### `/unlock` Endpoint
|
||
- If already `ready` → return immediately
|
||
- If already in progress → return current state
|
||
- If no encrypted archive found → check if images already loaded; if not, 404
|
||
- Otherwise, starts `_run_unlock` as a background task
|
||
|
||
## Dependencies
|
||
|
||
- **Internal**: `UnlockState` from `unlock_state`, `get_api_client()` (lazy `api_client` import), `binary_split` (lazy import in unlock paths)
|
||
- **External**: `os`, `threading` (stdlib), `fastapi`, `pydantic`, `loguru` (logger for tar cleanup warnings)
|
||
|
||
## Consumers
|
||
|
||
None — this is the entry point module.
|
||
|
||
## Data Models
|
||
|
||
`LoginRequest`, `LoadRequest`, `HealthResponse`, `StatusResponse` (Pydantic models defined inline).
|
||
|
||
## Configuration
|
||
|
||
| Env Variable | Default | Description |
|
||
|------------------|--------------------------------|--------------------------------|
|
||
| RESOURCE_API_URL | `https://api.azaion.com` | Azaion resource API base URL |
|
||
| IMAGES_PATH | `/opt/azaion/images.enc` | Path to encrypted Docker images |
|
||
| API_VERSION | `latest` | Expected Docker image version tag |
|
||
|
||
## External Integrations
|
||
|
||
- **Azaion Resource API**: via `ApiClient` (authenticated resource download/upload)
|
||
- **Docker CLI**: via `binary_split` (docker load, image inspect)
|
||
- **File system**: encrypted archive at `IMAGES_PATH`
|
||
|
||
## Security
|
||
|
||
- Login endpoint returns 401 on auth failure
|
||
- All resource endpoints use authenticated API client
|
||
- Unlock state and error are guarded by `_UnlockStateHolder`’s lock; API client initialization is guarded by `_api_client_lock`
|
||
- Lazy imports of Cython modules (`api_client`, `binary_split`) to avoid import-time side effects
|
||
|
||
## Tests
|
||
|
||
No tests found.
|