Description
Skopeo copy will fail the push with the following error, but still write the manifest will still have been written to Quay's database:
gunicorn-registry stdout | Traceback (most recent call last): gunicorn-registry stdout | File "/quay-registry/image/oci/config.py", line 210, in __init__ gunicorn-registry stdout | validate_schema(self._parsed, OCIConfig.METASCHEMA) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/jsonschema/validators.py", line 934, in validate gunicorn-registry stdout | raise error gunicorn-registry stdout | jsonschema.exceptions.ValidationError: None is not of type 'array' gunicorn-registry stdout | Failed validating 'type' in schema['properties']['config']['properties']['Entrypoint']: gunicorn-registry stdout | {'type': 'array'} gunicorn-registry stdout | On instance['config']['Entrypoint']: gunicorn-registry stdout | None gunicorn-registry stdout | During handling of the above exception, another exception occurred: gunicorn-registry stdout | Traceback (most recent call last): gunicorn-registry stdout | File "/app/lib/python3.9/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 "/app/lib/python3.9/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 "/app/lib/python3.9/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 "/app/lib/python3.9/site-packages/flask/app.py", line 2463, in __call__ gunicorn-registry stdout | return self.wsgi_app(environ, start_response) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 169, in __call__ gunicorn-registry stdout | return self.app(environ, start_response) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 2449, in wsgi_app gunicorn-registry stdout | response = self.handle_exception(e) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 1866, in handle_exception gunicorn-registry stdout | reraise(exc_type, exc_value, tb) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise gunicorn-registry stdout | raise value gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 2446, in wsgi_app gunicorn-registry stdout | response = self.full_dispatch_request() gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 1951, in full_dispatch_request gunicorn-registry stdout | rv = self.handle_user_exception(e) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 1820, in handle_user_exception gunicorn-registry stdout | reraise(exc_type, exc_value, tb) gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise gunicorn-registry stdout | raise value gunicorn-registry stdout | File "/app/lib/python3.9/site-packages/flask/app.py", line 1949, in full_dispatch_request gunicorn-registry stdout | rv = self.dispatch_request() gunicorn-registry stdout | File "/app/lib/python3.9/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 228, 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 173, in wrapped gunicorn-registry stdout | return func(namespace_name, repo_name, *args, **kwargs) gunicorn-registry stdout | File "/quay-registry/endpoints/decorators.py", line 164, in wrapper gunicorn-registry stdout | return func(*args, **kwargs) gunicorn-registry stdout | File "/quay-registry/endpoints/decorators.py", line 189, 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 366, 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 408, 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 239, in get_or_create_manifest gunicorn-registry stdout | return _create_manifest( gunicorn-registry stdout | File "/quay-registry/data/model/oci/manifest.py", line 361, in _create_manifest gunicorn-registry stdout | labels = manifest_interface_instance.get_manifest_labels(retriever) gunicorn-registry stdout | File "/quay-registry/image/oci/manifest.py", line 257, in get_manifest_labels gunicorn-registry stdout | built_config = self._get_built_config(content_retriever) gunicorn-registry stdout | File "/quay-registry/image/oci/manifest.py", line 474, in _get_built_config gunicorn-registry stdout | self._cached_built_config = OCIConfig(Bytes.for_string_or_unicode(config_bytes)) gunicorn-registry stdout | File "/quay-registry/image/oci/config.py", line 212, in __init__ gunicorn-registry stdout | raise MalformedConfig("config data does not match schema: %s" % ve) gunicorn-registry stdout | image.oci.config.MalformedConfig: config data does not match schema: None is not of type 'array' gunicorn-registry stdout | Failed validating 'type' in schema['properties']['config']['properties']['Entrypoint']: gunicorn-registry stdout | {'type': 'array'} gunicorn-registry stdout | On instance['config']['Entrypoint']: gunicorn-registry stdout | None gunicorn-registry stdout | 2023-02-17 22:01:18,526 [215] [INFO] [gunicorn.access] - - [17/Feb/2023:22:01:18 +0000] "PUT /v2/devtable/ubuntu/manifests/latest HTTP/1.1" 500 0 "-" "-"// code placeholder
The parsed manifest failing validation in Quay when creating repo+pushing (w/ skopeo copy):
{'architecture': 'amd64', 'config': {'Hostname': '', 'Domainname': '', 'User': '', 'AttachStdin': False, 'AttachStdout': False, 'AttachStderr': False, 'Tty': False, 'OpenStdin': False, 'StdinOnce': False, 'Env': ['PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'], 'Cmd': ['/bin/bash'], 'Image': 'sha256:269190441c1f8398e85a287ba6ac5568574f55bfcae7fb99bd253afad8cd8e69', 'Volumes': None, 'WorkingDir': '', 'Entrypoint': None, 'OnBuild': None, 'Labels': {'org.opencontainers.image.ref.name': 'ubuntu', 'org.opencontainers.image.version': '22.04'}}, 'container': '6be7983e643200aa82c27e883bf03ae871243571f93a39f39d11dd3c79c96611', 'container_config': {'Hostname': '6be7983e6432', 'Domainname': '', 'User': '', 'AttachStdin': False, 'AttachStdout': False, 'AttachStderr': False, 'Tty': False, 'OpenStdin': False, 'StdinOnce': False, 'Env': ['PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'], 'Cmd': ['/bin/sh', '-c', '#(nop) ', 'CMD ["/bin/bash"]'], 'Image': 'sha256:269190441c1f8398e85a287ba6ac5568574f55bfcae7fb99bd253afad8cd8e69', 'Volumes': None, 'WorkingDir': '', 'Entrypoint': None, 'OnBuild': None, 'Labels': {'org.opencontainers.image.ref.name': 'ubuntu', 'org.opencontainers.image.version': '22.04'}}, 'created': '2023-01-26T04:58:02.385638665Z', 'docker_version': '20.10.12', 'history': [{'created': '2023-01-26T04:57:59.893830181Z', 'created_by': '/bin/sh -c #(nop) ARG RELEASE', 'empty_layer': True}, {'created': '2023-01-26T04:57:59.959936538Z', 'created_by': '/bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH', 'empty_layer': True}, {'created': '2023-01-26T04:58:00.031088326Z', 'created_by': '/bin/sh -c #(nop) LABEL org.opencontainers.image.ref.name=ubuntu', 'empty_layer': True}, {'created': '2023-01-26T04:58:00.098806406Z', 'created_by': '/bin/sh -c #(nop) LABEL org.opencontainers.image.version=22.04', 'empty_layer': True}, {'created': '2023-01-26T04:58:02.097080644Z', 'created_by': '/bin/sh -c #(nop) ADD file:18e71f049606f6339ce7a995839623f50e6ec6474bfd0a3a7ca799db726f47f6 in / '}, {'created': '2023-01-26T04:58:02.385638665Z', 'created_by': '/bin/sh -c #(nop) CMD ["/bin/bash"]', 'empty_layer': True}], 'os': 'linux', 'rootfs': {'type': 'layers', 'diff_ids': ['sha256:c5ff2d88f67954bdcf1cfdd46fe3d683858d69c2cadd6660812edfc83726c654']}
But the manifest written is:
{"schemaVersion": 2, "mediaType": "application/vnd.oci.image.manifest.v1+json", "config": {"mediaType": "application/vnd.oci.image.config.v1+json", "size": 2299, "digest": "sha256:58db3edaf2be6e80f628796355b1bdeaf8bea1692b402f48b7e7b8d1ff100b02"}, "layers": [{"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip", "size": 29528717, "digest": "sha256:677076032cca0a2362d25cf3660072e738d1b96fe860409a33ce901d695d7ee8"}]}