Uploaded image for project: 'Project Quay'
  1. Project Quay
  2. PROJQUAY-4810

Support nested OCI indexes

XMLWordPrintable

    • BU Product Work
    • False
    • None
    • False
    • PROJQUAY-4657 - Implement OCI 1.1

      When pushing a nested OCI index image, that is, an OCI index that in turn points to another OCI index, Quay errors out to the client with an HTTP 500 code.

      In the logs the following can be seen:

      gunicorn-registry stdout | 2022-12-05 09:30:58,163 [222] [ERROR] [gunicorn.error] Error handling request /v2/dmesser/oci-index/manifests/nested
      gunicorn-registry stdout | Traceback (most recent call last):
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 55, in handle
      gunicorn-registry stdout |     self.handle_request(listener_name, req, client, addr)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/ggevent.py", line 127, in handle_request
      gunicorn-registry stdout |     super().handle_request(listener_name, req, sock, addr)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base_async.py", line 108, in handle_request
      gunicorn-registry stdout |     respiter = self.wsgi(environ, resp.start_response)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2463, in __call__
      gunicorn-registry stdout |     return self.wsgi_app(environ, start_response)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/werkzeug/middleware/proxy_fix.py", line 232, in __call__
      gunicorn-registry stdout |     return self.app(environ, start_response)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2449, in wsgi_app
      gunicorn-registry stdout |     response = self.handle_exception(e)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1866, in handle_exception
      gunicorn-registry stdout |     reraise(exc_type, exc_value, tb)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
      gunicorn-registry stdout |     raise value
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 2446, in wsgi_app
      gunicorn-registry stdout |     response = self.full_dispatch_request()
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1951, in full_dispatch_request
      gunicorn-registry stdout |     rv = self.handle_user_exception(e)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1820, in handle_user_exception
      gunicorn-registry stdout |     reraise(exc_type, exc_value, tb)
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
      gunicorn-registry stdout |     raise value
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1949, in full_dispatch_request
      gunicorn-registry stdout |     rv = self.dispatch_request()
      gunicorn-registry stdout |   File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1935, in dispatch_request
      gunicorn-registry stdout |     return self.view_functions[rule.endpoint](**req.view_args)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/decorators.py", line 218, in wrapper
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/decorators.py", line 91, in wrapper
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/v2/manifest.py", line 224, in wrapped
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/auth/registry_jwt_auth.py", line 177, in wrapper
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/v2/__init__.py", line 143, in wrapped
      gunicorn-registry stdout |     return func(namespace_name, repo_name, *args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/decorators.py", line 154, in wrapper
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/decorators.py", line 179, in wrapper
      gunicorn-registry stdout |     return func(*args, **kwargs)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/v2/manifest.py", line 256, in write_manifest_by_tagname
      gunicorn-registry stdout |     return _write_manifest_and_log(namespace_name, repo_name, manifest_ref, parsed)
      gunicorn-registry stdout |   File "/quay-registry/endpoints/v2/manifest.py", line 362, in _write_manifest_and_log
      gunicorn-registry stdout |     repository_ref, manifest, tag = _write_manifest(
      gunicorn-registry stdout |   File "/quay-registry/endpoints/v2/manifest.py", line 404, in _write_manifest
      gunicorn-registry stdout |     manifest, tag = registry_model.create_manifest_and_retarget_tag(
      gunicorn-registry stdout |   File "/quay-registry/data/registry_model/registry_oci_model.py", line 360, in create_manifest_and_retarget_tag
      gunicorn-registry stdout |     created_manifest = oci.manifest.get_or_create_manifest(
      gunicorn-registry stdout |   File "/quay-registry/data/model/oci/manifest.py", line 220, in get_or_create_manifest
      gunicorn-registry stdout |     return _create_manifest(
      gunicorn-registry stdout |   File "/quay-registry/data/model/oci/manifest.py", line 260, in _create_manifest
      gunicorn-registry stdout |     child_manifest = child_manifest_ref.manifest_obj
      gunicorn-registry stdout |   File "/quay-registry/image/shared/schemautil.py", line 82, in manifest_obj
      gunicorn-registry stdout |     self._loaded_manifest = self._load_manifest()
      gunicorn-registry stdout |   File "/quay-registry/image/shared/schemautil.py", line 106, in _load_manifest
      gunicorn-registry stdout |     return self._supported_types[content_type](
      gunicorn-registry stdout | TypeError: __init__() got an unexpected keyword argument 'validate'
      gunicorn-registry stdout | 2022-12-05 09:30:58,189 [222] [INFO] [gunicorn.access]  - - [05/Dec/2022:09:30:58 +0000] "PUT /v2/dmesser/oci-index/manifests/nested HTTP/1.1" 500 0 "-" "-"
      nginx stdout | 10.0.4.251 (-) - - [05/Dec/2022:09:30:58 +0000] "PUT /v2/dmesser/oci-index/manifests/nested HTTP/1.1" 500 141 "-" "crane/0.12.1 go-containerregistry/(devel)" (0.053 1848 0.052) 

      The below tarball contains a nested OCI index in the OCI directory layout that pushes successfully to distribution registries and DockerHub, like so:

      crane push nested-oci docker.io/repo/oci-index:nested

      nested-oci.tar.gz

      Nested OCI indexes are expected to become more prevalent when more complex multi-artifact structures like cloud native applications are packaged as OCI artifacts.

              Unassigned Unassigned
              DanielMesser Daniel Messer
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated: