1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/agent_docs/architecture.md

131 lines
3.9 KiB
Markdown

# Architecture & Patterns
## Backend Structure
```
├── app.py # Flask application factory
├── endpoints/
│ ├── api/ # REST API v1
│ │ ├── __init__.py # API setup, decorators, helpers
│ │ ├── repository.py # Repository endpoints
│ │ ├── user.py # User endpoints
│ │ ├── organization.py # Organization endpoints
│ │ └── ...
│ ├── v2/ # OCI/Docker Registry v2
│ │ ├── __init__.py # V2 setup, decorators
│ │ ├── manifest.py # Manifest operations
│ │ ├── blob.py # Blob operations
│ │ └── ...
│ └── decorators.py # Shared permission decorators
├── data/
│ ├── database.py # DB connection, session
│ ├── model/ # SQLAlchemy models
│ └── migrations/ # Alembic migrations
├── auth/
│ ├── permissions.py # Permission classes
│ ├── credentials.py # Credential validation
│ └── registry_jwt_auth.py # JWT for registry
├── storage/
│ ├── cloud.py # S3/GCS storage
│ ├── azurestorage.py # Azure blob storage
│ ├── swift.py # OpenStack Swift
│ └── local.py # Local filesystem
└── workers/ # Background processors
├── gcworker/ # Garbage collection
├── repomirrorworker/ # Repository mirroring
└── securityworker/ # Clair integration
```
## Request Flow
```
Request → Flask → Middleware → Endpoint Decorator → Handler → Model → Database
│ │
│ └── Permission check (auth/permissions.py)
└── Auth validation (auth/credentials.py)
```
## Key Patterns
### Permission Decorators
```python
# endpoints/decorators.py
@require_repo_read # Read access to repository
@require_repo_write # Write access to repository
@require_repo_admin # Admin access to repository
```
### Repository Access
```python
# endpoints/api/__init__.py
from endpoints.api import RepositoryParamResource
class MyEndpoint(RepositoryParamResource):
# Automatically parses namespace/repository from URL
def get(self, namespace, repository):
repo = model.repository.get_repository(namespace, repository)
```
### Data Models
```python
# data/model/repository.py
from data.database import db
def get_repository(namespace, repository):
return Repository.query.filter_by(
namespace_user=namespace,
name=repository
).first()
```
### Error Handling
```python
# endpoints/exception.py
from endpoints.exception import NotFound, Unauthorized, InvalidRequest
if not repo:
raise NotFound()
```
## Workers
Background job processors in `workers/`:
| Worker | Purpose |
|--------|---------|
| `gcworker` | Garbage collection |
| `repomirrorworker` | Repository mirroring |
| `securityworker` | Clair vulnerability scanning |
| `buildlogsarchiver` | Archive build logs |
| `notificationworker` | Send notifications |
| `storagereplication` | Geo-replicate storage |
Workers run as gunicorn sub-processes in local dev for hot-reload.
## Storage Backends
`storage/` implements multiple backends:
- `cloud.py` - S3, GCS, Cloudflare R2
- `azurestorage.py` - Azure Blob Storage
- `swift.py` - OpenStack Swift
- `local.py` - Local filesystem
`DistributedStorage` in `distributedstorage.py` handles failover between backends.
## Configuration
```python
# config.py - Configuration loading
from util.config import config
# Access config values
db_uri = config.get('DB_URI')
```
Config validated against JSON Schema in `config-tool/utils/generate/schema.json`.