mirror of
https://github.com/quay/quay.git
synced 2026-01-26 06:21:37 +03:00
131 lines
3.9 KiB
Markdown
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`.
|