# Extension Registry Service A high-performance Rust microservice that provides a unified REST API for extension discovery, versioning, and download from multiple Git-based sources and OCI registries. > **Source**: `provisioning/platform/crates/extension-registry/` ## Features - **Multi-Backend Source Support**: Fetch extensions from Gitea, Forgejo, and GitHub releases - **Multi-Registry Distribution Support**: Distribute extensions to Zot, Harbor, Docker Hub, GHCR, Quay, and other OCI-compliant registries - **Unified REST API**: Single API for all extension operations across all backends - **Smart Caching**: LRU cache with TTL to reduce backend API calls - **Prometheus Metrics**: Built-in metrics for monitoring - **Health Monitoring**: Parallel health checks for all backends with aggregated status - **Aggregation & Fallback**: Intelligent request routing with aggregation and fallback strategies - **Type-Safe**: Strong typing for extension metadata - **Async/Await**: High-performance async operations with Tokio - **Backward Compatible**: Old single-instance configs auto-migrate to new multi-instance format ## Architecture ### Dual-Trait System The extension registry uses a trait-based architecture separating source and distribution backends: ```plaintext ┌────────────────────────────────────────────────────────────────────┐ │ Extension Registry API │ │ (axum) │ ├────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─ SourceClients ────────────┐ ┌─ DistributionClients ────────┐ │ │ │ │ │ │ │ │ │ • Gitea (Git releases) │ │ • OCI Registries │ │ │ │ • Forgejo (Git releases) │ │ - Zot │ │ │ │ • GitHub (Releases API) │ │ - Harbor │ │ │ │ │ │ - Docker Hub │ │ │ │ Strategy: Aggregation + │ │ - GHCR / Quay │ │ │ │ Fallback across all sources │ │ - Any OCI-compliant │ │ │ │ │ │ │ │ │ └─────────────────────────────┘ └──────────────────────────────┘ │ │ │ │ ┌─ LRU Cache ───────────────────────────────────────────────────┐ │ │ │ • Metadata cache (with TTL) │ │ │ │ • List cache (with TTL) │ │ │ │ • Version cache (version strings only) │ │ │ └───────────────────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────┘ ```plaintext ### Request Strategies #### Aggregation Strategy (list_extensions, list_versions, search) 1. **Parallel Execution**: Spawn concurrent tasks for all source and distribution clients 2. **Merge Results**: Combine results from all backends 3. **Deduplication**: Remove duplicates, preferring more recent versions 4. **Pagination**: Apply limit/offset to merged results 5. **Caching**: Store merged results with composite cache key #### Fallback Strategy (get_extension, download_extension) 1. **Sequential Retry**: Try source clients first (in configured order) 2. **Distribution Fallback**: If all sources fail, try distribution clients 3. **Return First Success**: Return result from first successful client 4. **Caching**: Cache successful result with backend-specific key ## Installation ```bash cd provisioning/platform/extension-registry cargo build --release ```plaintext ## Configuration ### Single-Instance Configuration (Legacy - Auto-Migrated) Old format is automatically migrated to new multi-instance format: ```toml [server] host = "0.0.0.0" port = 8082 # Single Gitea instance (auto-migrated to sources.gitea[0]) [gitea] url = "https://gitea.example.com" organization = "provisioning-extensions" token_path = "/path/to/gitea-token.txt" # Single OCI registry (auto-migrated to distributions.oci[0]) [oci] registry = "registry.example.com" namespace = "provisioning" auth_token_path = "/path/to/oci-token.txt" [cache] capacity = 1000 ttl_seconds = 300 ```plaintext ### Multi-Instance Configuration (Recommended) New format supporting multiple backends of each type: ```toml [server] host = "0.0.0.0" port = 8082 workers = 4 enable_cors = false enable_compression = true # Multiple Gitea sources [sources.gitea] [[sources.gitea]] id = "internal-gitea" url = "https://gitea.internal.example.com" organization = "provisioning" token_path = "/etc/secrets/gitea-internal-token.txt" timeout_seconds = 30 verify_ssl = true [[sources.gitea]] id = "public-gitea" url = "https://gitea.public.example.com" organization = "extensions" token_path = "/etc/secrets/gitea-public-token.txt" timeout_seconds = 30 verify_ssl = true # Forgejo sources (API compatible with Gitea) [sources.forgejo] [[sources.forgejo]] id = "community-forgejo" url = "https://forgejo.community.example.com" organization = "provisioning" token_path = "/etc/secrets/forgejo-token.txt" timeout_seconds = 30 verify_ssl = true # GitHub sources [sources.github] [[sources.github]] id = "org-github" organization = "my-organization" token_path = "/etc/secrets/github-token.txt" timeout_seconds = 30 verify_ssl = true # Multiple OCI distribution registries [distributions.oci] [[distributions.oci]] id = "internal-zot" registry = "zot.internal.example.com" namespace = "extensions" timeout_seconds = 30 verify_ssl = true [[distributions.oci]] id = "public-harbor" registry = "harbor.public.example.com" namespace = "extensions" auth_token_path = "/etc/secrets/harbor-token.txt" timeout_seconds = 30 verify_ssl = true [[distributions.oci]] id = "docker-hub" registry = "docker.io" namespace = "myorg" auth_token_path = "/etc/secrets/docker-hub-token.txt" timeout_seconds = 30 verify_ssl = true # Cache configuration [cache] capacity = 1000 ttl_seconds = 300 enable_metadata_cache = true enable_list_cache = true ```plaintext ### Configuration Notes - **Backend Identifiers**: Use `id` field to uniquely identify each backend instance (auto-generated if omitted) - **Gitea/Forgejo Compatible**: Both use same config format; organization field is required for Git repos - **GitHub Configuration**: Uses organization as owner; token_path points to GitHub Personal Access Token - **OCI Registries**: Support any OCI-compliant registry (Zot, Harbor, Docker Hub, GHCR, Quay, etc.) - **Optional Fields**: `id`, `verify_ssl`, `timeout_seconds` have sensible defaults - **Token Files**: Should contain only the token with no extra whitespace; permissions should be `0600` ### Environment Variable Overrides Legacy environment variable support (for backward compatibility): ```bash REGISTRY_SERVER_HOST=127.0.0.1 REGISTRY_SERVER_PORT=8083 REGISTRY_SERVER_WORKERS=8 REGISTRY_GITEA_URL=https://gitea.example.com REGISTRY_GITEA_ORG=extensions REGISTRY_GITEA_TOKEN_PATH=/path/to/token REGISTRY_OCI_REGISTRY=registry.example.com REGISTRY_OCI_NAMESPACE=extensions REGISTRY_CACHE_CAPACITY=2000 REGISTRY_CACHE_TTL=600 ```plaintext ## API Endpoints ### Extension Operations #### List Extensions ```bash GET /api/v1/extensions?type=provider&limit=10 ```plaintext #### Get Extension ```bash GET /api/v1/extensions/{type}/{name} ```plaintext #### List Versions ```bash GET /api/v1/extensions/{type}/{name}/versions ```plaintext #### Download Extension ```bash GET /api/v1/extensions/{type}/{name}/{version} ```plaintext #### Search Extensions ```bash GET /api/v1/extensions/search?q=kubernetes&type=taskserv ```plaintext ### System Endpoints #### Health Check ```bash GET /api/v1/health ```plaintext **Response** (with multi-backend aggregation): ```json { "status": "healthy|degraded|unhealthy", "version": "0.1.0", "uptime": 3600, "backends": { "gitea": { "enabled": true, "healthy": true, "error": null }, "oci": { "enabled": true, "healthy": true, "error": null } } } ```plaintext **Status Values**: - `healthy`: All configured backends are healthy - `degraded`: At least one backend is healthy, but some are failing - `unhealthy`: No backends are responding #### Metrics ```bash GET /api/v1/metrics ```plaintext #### Cache Statistics ```bash GET /api/v1/cache/stats ```plaintext **Response**: ```json { "metadata_hits": 1024, "metadata_misses": 256, "list_hits": 512, "list_misses": 128, "version_hits": 2048, "version_misses": 512, "size": 4096 } ```plaintext ## Extension Naming Conventions ### Gitea Repositories - **Providers**: `{name}_prov` (for example, `aws_prov`) - **Task Services**: `{name}_taskserv` (for example, `kubernetes_taskserv`) - **Clusters**: `{name}_cluster` (for example, `buildkit_cluster`) ### OCI Artifacts - **Providers**: `{namespace}/{name}-provider` - **Task Services**: `{namespace}/{name}-taskserv` - **Clusters**: `{namespace}/{name}-cluster` ## Deployment ### Docker ```bash docker build -t extension-registry:latest . docker run -d -p 8082:8082 -v $(pwd)/config.toml:/app/config.toml:ro extension-registry:latest ```plaintext ### Kubernetes ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: extension-registry spec: replicas: 3 template: spec: containers: - name: extension-registry image: extension-registry:latest ports: - containerPort: 8082 ```plaintext ## Migration Guide: Single to Multi-Instance ### Automatic Migration Old single-instance configs are automatically detected and migrated to the new multi-instance format during startup: 1. **Detection**: Registry checks if old-style fields (`gitea`, `oci`) contain values 2. **Migration**: Single instances are moved to new Vec-based format (`sources.gitea[0]`, `distributions.oci[0]`) 3. **Logging**: Migration event is logged for audit purposes 4. **Transparency**: No user action required; old configs continue to work ### Before Migration ```toml [gitea] url = "https://gitea.example.com" organization = "extensions" token_path = "/path/to/token" [oci] registry = "registry.example.com" namespace = "extensions" ```plaintext ### After Migration (Automatic) ```toml [sources.gitea] [[sources.gitea]] url = "https://gitea.example.com" organization = "extensions" token_path = "/path/to/token" [distributions.oci] [[distributions.oci]] registry = "registry.example.com" namespace = "extensions" ```plaintext ### Gradual Upgrade Path To adopt the new format manually: 1. **Backup current config** - Keep old format as reference 2. **Adopt new format** - Replace old fields with new structure 3. **Test** - Verify all backends are reachable and extensions are discovered 4. **Add new backends** - Use new format to add Forgejo, GitHub, or additional OCI registries 5. **Remove old fields** - Delete deprecated `gitea` and `oci` top-level sections ### Benefits of Upgrading - **Multiple Sources**: Support Gitea, Forgejo, and GitHub simultaneously - **Multiple Registries**: Distribute to multiple OCI registries - **Better Resilience**: If one backend fails, others continue to work - **Flexible Configuration**: Each backend can have different credentials and timeouts - **Future-Proof**: New backends can be added without config restructuring ## Related Documentation - **Extension Development**: [Module System](../development/extensions.md) - **Extension Development Quickstart**: [Getting Started Guide](../guides/extension-development-quickstart.md) - **ADR-005**: [Extension Framework Architecture](../architecture/adr/adr-005-extension-framework.md) - **OCI Registry Integration**: [OCI Registry Guide](../integration/oci-registry-guide.md)