1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/endpoints/api/test/test_capabilities.py
Marcus Kok 074c88af13 api: Add sparse manifest capability detection endpoint (PROJQUAY-10258) (#4870)
Add new endpoint for clients to query registry sparse manifest support:

- GET /api/v1/registry/capabilities returns JSON with sparse_manifests
  capability info (supported, required_architectures, optional allowed)
- V2 base endpoint now includes X-Sparse-Manifest-Support and
  X-Required-Architectures headers for OCI compliance
- Endpoint accessible without authentication for client discovery

This enables oc-mirror and skopeo to detect sparse manifest support
before attempting filtered multi-architecture mirroring.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 15:21:18 -05:00

95 lines
4.6 KiB
Python

"""
Tests for the registry capabilities API endpoint.
"""
import pytest
from app import app as realapp
from endpoints.api.test.shared import conduct_api_call
from endpoints.test.shared import client_with_identity, toggle_feature
from test.fixtures import *
class TestRegistryCapabilities:
def test_capabilities_no_auth_required(self, app):
"""Test capabilities endpoint accessible without authentication."""
from endpoints.api.capabilities import RegistryCapabilities
from endpoints.test.shared import add_csrf_param
with app.test_client() as cl:
params = add_csrf_param(cl, {})
rv = cl.get(
"/api/v1/registry/capabilities",
headers={"Content-Type": "application/json"},
)
assert rv.status_code == 200
def test_capabilities_sparse_disabled(self, app):
"""Test capabilities endpoint when sparse manifests disabled."""
from endpoints.api.capabilities import RegistryCapabilities
with toggle_feature("SPARSE_INDEX", False):
with client_with_identity("devtable", app) as cl:
resp = conduct_api_call(cl, RegistryCapabilities, "GET", {}, None, 200)
assert resp.json["sparse_manifests"]["supported"] is False
assert resp.json["sparse_manifests"]["required_architectures"] == []
assert resp.json["sparse_manifests"]["optional_architectures_allowed"] is False
def test_capabilities_sparse_enabled(self, app):
"""Test capabilities endpoint when sparse manifests enabled."""
from endpoints.api.capabilities import RegistryCapabilities
with toggle_feature("SPARSE_INDEX", True):
with client_with_identity("devtable", app) as cl:
resp = conduct_api_call(cl, RegistryCapabilities, "GET", {}, None, 200)
assert resp.json["sparse_manifests"]["supported"] is True
def test_capabilities_with_required_archs(self, app):
"""Test capabilities endpoint with required architectures configured."""
from endpoints.api.capabilities import RegistryCapabilities
with toggle_feature("SPARSE_INDEX", True):
original_archs = realapp.config.get("SPARSE_INDEX_REQUIRED_ARCHS", [])
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = ["amd64", "arm64"]
try:
with client_with_identity("devtable", app) as cl:
resp = conduct_api_call(cl, RegistryCapabilities, "GET", {}, None, 200)
assert resp.json["sparse_manifests"]["supported"] is True
assert resp.json["sparse_manifests"]["required_architectures"] == [
"amd64",
"arm64",
]
assert resp.json["sparse_manifests"]["optional_architectures_allowed"] is True
finally:
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = original_archs
def test_capabilities_sparse_enabled_no_required_archs(self, app):
"""Test capabilities endpoint when sparse enabled but no required archs."""
from endpoints.api.capabilities import RegistryCapabilities
with toggle_feature("SPARSE_INDEX", True):
original_archs = realapp.config.get("SPARSE_INDEX_REQUIRED_ARCHS", [])
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = []
try:
with client_with_identity("devtable", app) as cl:
resp = conduct_api_call(cl, RegistryCapabilities, "GET", {}, None, 200)
assert resp.json["sparse_manifests"]["supported"] is True
assert resp.json["sparse_manifests"]["required_architectures"] == []
# optional_architectures_allowed is False when no required archs
assert resp.json["sparse_manifests"]["optional_architectures_allowed"] is False
finally:
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = original_archs
def test_capabilities_response_structure(self, app):
"""Test capabilities endpoint response has correct structure."""
from endpoints.api.capabilities import RegistryCapabilities
with client_with_identity("devtable", app) as cl:
resp = conduct_api_call(cl, RegistryCapabilities, "GET", {}, None, 200)
# Verify top-level keys exist
assert "sparse_manifests" in resp.json
# Verify sparse_manifests structure
assert "supported" in resp.json["sparse_manifests"]
assert "required_architectures" in resp.json["sparse_manifests"]
assert "optional_architectures_allowed" in resp.json["sparse_manifests"]