1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/endpoints/v2/test/test_v2_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

68 lines
3.2 KiB
Python

"""
Tests for v2 endpoint capability headers.
"""
import pytest
from app import app as realapp
from endpoints.test.shared import toggle_feature
from test.fixtures import *
class TestV2CapabilityHeaders:
def test_v2_base_sparse_header_disabled(self, app):
"""Test v2 base endpoint includes sparse capability header when disabled."""
with toggle_feature("SPARSE_INDEX", False):
with app.test_client() as cl:
rv = cl.get("/v2/")
assert rv.headers.get("X-Sparse-Manifest-Support") == "false"
assert rv.headers.get("X-Required-Architectures") is None
def test_v2_base_sparse_header_enabled(self, app):
"""Test v2 base endpoint includes sparse capability header when enabled."""
with toggle_feature("SPARSE_INDEX", True):
with app.test_client() as cl:
rv = cl.get("/v2/")
assert rv.headers.get("X-Sparse-Manifest-Support") == "true"
def test_v2_base_required_archs_header(self, app):
"""Test v2 base endpoint includes required architectures header."""
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 app.test_client() as cl:
rv = cl.get("/v2/")
assert rv.headers.get("X-Sparse-Manifest-Support") == "true"
assert rv.headers.get("X-Required-Architectures") == "amd64,arm64"
finally:
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = original_archs
def test_v2_base_no_required_archs_header_when_empty(self, app):
"""Test v2 base endpoint does not include required architectures header when empty."""
with toggle_feature("SPARSE_INDEX", True):
original_archs = realapp.config.get("SPARSE_INDEX_REQUIRED_ARCHS", [])
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = []
try:
with app.test_client() as cl:
rv = cl.get("/v2/")
assert rv.headers.get("X-Sparse-Manifest-Support") == "true"
# No header when empty list
assert rv.headers.get("X-Required-Architectures") is None
finally:
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = original_archs
def test_v2_base_no_required_archs_header_when_disabled(self, app):
"""Test v2 base endpoint does not include required architectures header when sparse disabled."""
with toggle_feature("SPARSE_INDEX", False):
original_archs = realapp.config.get("SPARSE_INDEX_REQUIRED_ARCHS", [])
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = ["amd64", "arm64"]
try:
with app.test_client() as cl:
rv = cl.get("/v2/")
assert rv.headers.get("X-Sparse-Manifest-Support") == "false"
# No header when sparse is disabled, even if archs configured
assert rv.headers.get("X-Required-Architectures") is None
finally:
realapp.config["SPARSE_INDEX_REQUIRED_ARCHS"] = original_archs