-
Story
-
Resolution: Unresolved
-
Undefined
-
None
-
None
-
None
[API] Add Sparse Manifest Capability Detection Endpoint
Summary
Create a new API endpoint that allows clients (oc-mirror, skopeo) to query whether the registry supports sparse manifests. This enables clients to detect sparse manifest support before attempting filtered multi-architecture mirroring.
Acceptance Criteria
- [ ] New API endpoint returns sparse manifest capability status
- [ ] Response includes sparse_manifests_supported: true/false based on FEATURE_SPARSE_INDEX
- [ ] Response includes list of required architectures if configured
- [ ] Endpoint follows existing API patterns and authentication
- [ ] Endpoint is documented in API schema
- [ ] Clients can query without repository context (registry-level capability)
Technical Requirements
API Endpoint Design
Endpoint: GET /api/v1/registry/capabilities
Response:
{
"sparse_manifests": {
"supported": true,
"required_architectures": ["amd64", "arm64"],
"optional_architectures_allowed": true
},
"oci_artifacts": {
"supported": true
}
}
Alternative OCI distribution-spec compliant approach:
Endpoint: GET /v2/ (extend existing)
Add to the existing v2 discovery response via headers or body:
X-Sparse-Manifest-Support: true
X-Required-Architectures: amd64,arm64
Implementation
File: endpoints/api/capabilities.py (new file)
from endpoints.api import ( resource, require_scope, path_param, define_json_response, ) from auth.permissions import ReadRepositoryPermission from endpoints.exception import NotFound import features @resource("/v1/registry/capabilities") class RegistryCapabilities(ApiResource): """Resource for querying registry capabilities.""" @define_json_response("RegistryCapabilities") def get(self): """ Get registry capabilities. Returns information about supported registry features including sparse manifest support and required architectures. """ sparse_enabled = features.SPARSE_INDEX required_archs = app.config.get("SPARSE_INDEX_REQUIRED_ARCHS", []) return { "sparse_manifests": { "supported": sparse_enabled, "required_architectures": required_archs if sparse_enabled else [], "optional_architectures_allowed": sparse_enabled and len(required_archs) > 0, }, "oci_artifacts": { "supported": features.OCI_ARTIFACTS if hasattr(features, 'OCI_ARTIFACTS') else False, }, }
Register Endpoint
File: endpoints/api/__init__.py
Add import and registration for the new endpoint:
from endpoints.api.capabilities import RegistryCapabilities
OCI Distribution Spec Compliance
File: endpoints/v2/__init__.py
Also consider adding capability headers to the v2 base endpoint for OCI compliance:
@v2_bp.route("/") def v2_base(): """V2 API discovery endpoint.""" response = make_response("", 200) # Add sparse manifest capability headers if features.SPARSE_INDEX: response.headers["X-Sparse-Manifest-Support"] = "true" required_archs = app.config.get("SPARSE_INDEX_REQUIRED_ARCHS", []) if required_archs: response.headers["X-Required-Architectures"] = ",".join(required_archs) return response
Implementation Notes
Existing Patterns to Follow
- API structure: See endpoints/api/mirror.py for resource patterns
- Response format: See define_json_response() usage in other endpoints
- Feature flag access: See features.REPO_MIRROR pattern
Authentication
This endpoint should be accessible:
- Without authentication (public capability query)
- Or with minimal read permissions
@resource("/v1/registry/capabilities") class RegistryCapabilities(ApiResource): """Resource for querying registry capabilities.""" schemas = { "RegistryCapabilities": { "type": "object", "properties": { "sparse_manifests": { "type": "object", "properties": { "supported": {"type": "boolean"}, "required_architectures": { "type": "array", "items": {"type": "string"} }, "optional_architectures_allowed": {"type": "boolean"} } } } } } # No authentication required for capability query def get(self): ...
Response Headers for oc-mirror
oc-mirror may expect specific headers. Coordinate with oc-mirror team on expected format:
# Example headers oc-mirror might look for X-Sparse-Index-Supported: true X-Sparse-Index-Required-Archs: amd64,arm64
Error Handling
No special error handling needed - this endpoint should always return successfully:
def get(self):
try:
sparse_enabled = features.SPARSE_INDEX
required_archs = app.config.get("SPARSE_INDEX_REQUIRED_ARCHS", [])
except Exception:
# Default to disabled if configuration error
sparse_enabled = False
required_archs = []
return {"sparse_manifests": {"supported": sparse_enabled, ...}}
Dependencies
- Story 02: Registry core sparse manifest support (configuration must be in place)
Testing Requirements
Unit Tests
File: endpoints/api/test/test_capabilities.py (new file)
def test_capabilities_sparse_disabled():
"""Test capabilities endpoint when sparse manifests disabled."""
# FEATURE_SPARSE_INDEX = False
response = client.get("/api/v1/registry/capabilities")
assert response.status_code == 200
assert response.json["sparse_manifests"]["supported"] == False
assert response.json["sparse_manifests"]["required_architectures"] == []
def test_capabilities_sparse_enabled():
"""Test capabilities endpoint when sparse manifests enabled."""
# FEATURE_SPARSE_INDEX = True
response = client.get("/api/v1/registry/capabilities")
assert response.status_code == 200
assert response.json["sparse_manifests"]["supported"] == True
def test_capabilities_with_required_archs():
"""Test capabilities endpoint with required architectures configured."""
# FEATURE_SPARSE_INDEX = True
# SPARSE_INDEX_REQUIRED_ARCHS = ["amd64", "arm64"]
response = client.get("/api/v1/registry/capabilities")
assert response.json["sparse_manifests"]["required_architectures"] == ["amd64", "arm64"]
def test_capabilities_no_auth_required():
"""Test capabilities endpoint accessible without authentication."""
response = client.get("/api/v1/registry/capabilities")
assert response.status_code == 200
def test_v2_base_sparse_headers():
"""Test v2 base endpoint includes sparse capability headers."""
response = client.get("/v2/")
assert response.headers.get("X-Sparse-Manifest-Support") == "true"
Integration Tests
Test with actual client tools:
1. Query capabilities endpoint
2. Verify oc-mirror can detect sparse support
3. Verify skopeo can detect sparse support
Definition of Done
- [ ] Code implemented and follows project conventions
- [ ] All acceptance criteria met
- [ ] Unit tests written and passing
- [ ] API documentation updated
- [ ] Endpoint accessible to clients (oc-mirror, skopeo)
- [ ] Code reviewed and approved