From a6c47bc17bba167af8def01568f5eacbcb394326 Mon Sep 17 00:00:00 2001 From: "M. Rehan" Date: Tue, 24 Dec 2024 16:34:29 +0500 Subject: [PATCH] Properly support OCI image manifest (cherry picked from commit da72cc0ab5af48950d8caa60feaa038be00e5673) --- .../middlewared/plugins/apps_images/client.py | 12 ++++++++---- .../middlewared/plugins/apps_images/utils.py | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/middlewared/middlewared/plugins/apps_images/client.py b/src/middlewared/middlewared/plugins/apps_images/client.py index b40da8f7eab4b..a27f2bc79fa8c 100644 --- a/src/middlewared/middlewared/plugins/apps_images/client.py +++ b/src/middlewared/middlewared/plugins/apps_images/client.py @@ -9,7 +9,7 @@ from .utils import ( DEFAULT_DOCKER_REGISTRY, DOCKER_AUTH_SERVICE, DOCKER_AUTH_HEADER, DOCKER_AUTH_URL, DOCKER_CONTENT_DIGEST_HEADER, DOCKER_MANIFEST_LIST_SCHEMA_V2, DOCKER_MANIFEST_SCHEMA_V1, DOCKER_MANIFEST_SCHEMA_V2, DOCKER_RATELIMIT_URL, - parse_auth_header, parse_digest_from_schema, + DOCKER_MANIFEST_OCI_V1, parse_auth_header, parse_digest_from_schema, ) @@ -30,7 +30,10 @@ async def _api_call(url, options=None, headers=None, mode='get'): except asyncio.TimeoutError: response['error'] = f'Unable to connect with {url} in {timeout} seconds.' except aiohttp.ClientResponseError as e: - response['error'] = str(e) + response.update({ + 'error': str(e), + 'error_obj': e, + }) else: response['response_obj'] = req if req.status != 200: @@ -63,7 +66,7 @@ async def _get_manifest_response(self, registry, image, tag, headers, mode, rais manifest_url = f'https://{registry}/v2/{image}/manifests/{tag}' # 1) try getting manifest response = await self._api_call(manifest_url, headers=headers, mode=mode) - if (error := response['error']) and isinstance(error, aiohttp.ClientResponseError): + if (error := response.get('error_obj')) and isinstance(error, aiohttp.ClientResponseError): if error.status == 401: # 2) try to get token from manifest api call's response headers auth_data = parse_auth_header(error.headers[DOCKER_AUTH_HEADER]) @@ -89,7 +92,8 @@ async def _get_repo_digest(self, registry, image, tag): registry, image, tag, await self.get_manifest_call_headers(registry, image, { 'Accept': (f'{DOCKER_MANIFEST_SCHEMA_V2}, ' f'{DOCKER_MANIFEST_LIST_SCHEMA_V2}, ' - f'{DOCKER_MANIFEST_SCHEMA_V1}') + f'{DOCKER_MANIFEST_SCHEMA_V1}, ' + f'{DOCKER_MANIFEST_OCI_V1}') }), 'get', True ) digests = parse_digest_from_schema(response) diff --git a/src/middlewared/middlewared/plugins/apps_images/utils.py b/src/middlewared/middlewared/plugins/apps_images/utils.py index 869b611947cef..158b33974f475 100644 --- a/src/middlewared/middlewared/plugins/apps_images/utils.py +++ b/src/middlewared/middlewared/plugins/apps_images/utils.py @@ -18,6 +18,7 @@ DOCKER_AUTH_HEADER = 'WWW-Authenticate' DOCKER_AUTH_URL = 'https://auth.docker.io/token' DOCKER_AUTH_SERVICE = 'registry.docker.io' +DOCKER_MANIFEST_OCI_V1 = 'application/vnd.oci.image.index.v1+json' DOCKER_MANIFEST_SCHEMA_V1 = 'application/vnd.docker.distribution.manifest.v1+json' DOCKER_MANIFEST_SCHEMA_V2 = 'application/vnd.docker.distribution.manifest.v2+json' DOCKER_MANIFEST_LIST_SCHEMA_V2 = 'application/vnd.docker.distribution.manifest.list.v2+json'