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

3.9 KiB

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

# 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

# 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

# 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

# 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

# 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.