~rjarry/dlrepo

dlrepo: container: fix push/pull with podman v1 APPLIED

Robin Jarry: 2
 container: fix push/pull with podman
 container: fix http return codes for blob upload

 2 files changed, 37 insertions(+), 9 deletions(-)
#966198 .build.yml success
dlrepo/patches/.build.yml: SUCCESS in 1m37s

[container: fix push/pull with podman][0] from [Robin Jarry][1]

[0]: https://lists.sr.ht/~rjarry/dlrepo/patches/40110
[1]: mailto:robin@jarry.cc

✓ #966198 SUCCESS dlrepo/patches/.build.yml https://builds.sr.ht/~rjarry/job/966198
Le sam. 1 avr. 2023 à 01:00, Robin Jarry <robin@jarry.cc> a écrit :
Next
Julien Floret, Apr 04, 2023 at 14:23:
Next
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~rjarry/dlrepo/patches/40110/mbox | git am -3
Learn more about email & git

[PATCH dlrepo 1/2] container: fix push/pull with podman Export this patch

podman uses the oci image formats. Make sure to handle them properly and
return the correct content type with manifest responses.
Signed-off-by: Robin Jarry <robin@jarry.cc>
---
 dlrepo/views/container.py | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/dlrepo/views/container.py b/dlrepo/views/container.py
index ed5c1fd4187f..94b07b38c581 100644
--- a/dlrepo/views/container.py
+++ b/dlrepo/views/container.py
@@ -3,6 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause

from http import HTTPStatus
import json

from aiohttp import web

@@ -61,8 +62,6 @@ class CatalogView(ContainerView):

# --------------------------------------------------------------------------------------
class ManifestReadOnlyView(ContainerView):
    CONTENT_TYPE = "application/vnd.docker.distribution.manifest.v2+json"

    @classmethod
    def urls(cls):
        yield "/v2/{branch}/{job}/manifests/{reference}"
@@ -103,15 +102,21 @@ class ManifestReadOnlyView(ContainerView):
        return path, digest

    async def head(self):
        self.get_manifest()
        return self.response()
        return await self.get()

    async def get(self):
        path, digest = self.get_manifest()
        try:
            manifest = json.loads(path.read_text())
            media_type = manifest["mediaType"]
        except (ValueError, KeyError) as e:
            raise errors.ManifestInvalid() from e
        if self.request.method == "HEAD":
            path = None
        return self.response(
            path=path,
            headers={
                "Content-Type": self.CONTENT_TYPE,
                "Content-Type": media_type,
                "Docker-Content-Digest": digest,
            },
        )
@@ -119,6 +124,11 @@ class ManifestReadOnlyView(ContainerView):

# --------------------------------------------------------------------------------------
class ManifestView(ManifestReadOnlyView):
    CONTENT_TYPES = (
        "application/vnd.oci.image.manifest.v1+json",
        "application/vnd.docker.distribution.manifest.v2+json",
    )

    @classmethod
    def urls(cls):
        yield "/v2/{branch}/{job}/manifests/{reference}"
@@ -140,7 +150,7 @@ class ManifestView(ManifestReadOnlyView):
            manifest = await self.request.json()
            if not isinstance(manifest, dict):
                raise ValueError()
            if manifest.get("mediaType") != self.CONTENT_TYPE:
            if manifest.get("mediaType") not in self.CONTENT_TYPES:
                raise errors.Unsupported()
            digest = self.registry().new_manifest(job, manifest)
        except PermissionError as e:
-- 
2.39.2
Le sam. 1 avr. 2023 à 01:00, Robin Jarry <robin@jarry.cc> a écrit :

[PATCH dlrepo 2/2] container: fix http return codes for blob upload Export this patch

Fix this error when pushing a tag with podman:

 Error: writing blob: uploading layer to http://.../blobs/uploads/...:
 received unexpected HTTP status: 204 No Content

This is incorrect, that PUT request should return 201 created. docker
seems to not care about the return codes. podman does.

Also fix the return code for PATCH, DELETE and add the missing GET
handler.
Link: https://docs.docker.com/registry/spec/api/#put-blob-upload
Signed-off-by: Robin Jarry <robin@jarry.cc>
---
 dlrepo/views/container.py | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/dlrepo/views/container.py b/dlrepo/views/container.py
index 94b07b38c581..5712880a7bf4 100644
--- a/dlrepo/views/container.py
+++ b/dlrepo/views/container.py
@@ -231,6 +231,24 @@ class BlobsUploadsView(ContainerView):
        yield "/v2/{branch}/{job}/blobs/uploads/{uuid}"
        yield "/v2/u/{user}/{branch}/{job}/blobs/uploads/{uuid}"

    async def get(self):
        uuid = self.request.match_info["uuid"]
        try:
            path = self.repo().upload_path(uuid)
            data_size = path.stat().st_size
        except PermissionError as e:
            raise errors.Denied(str(e)) from e
        except FileNotFoundError as e:
            raise errors.BlobUploadUnknown() from e
        return self.response(
            status=HTTPStatus.NO_CONTENT,
            headers={
                "Location": self.request.path,
                "Range": f"0-{data_size - 1}",
                "Docker-Upload-Uuid": uuid,
            },
        )

    async def patch(self):
        uuid = self.request.match_info["uuid"]
        try:
@@ -240,7 +258,7 @@ class BlobsUploadsView(ContainerView):
        except FileNotFoundError as e:
            raise errors.BlobUploadUnknown() from e
        return self.response(
            status=HTTPStatus.NO_CONTENT,
            status=HTTPStatus.ACCEPTED,
            headers={
                "Location": self.request.path,
                "Range": f"0-{data_size - 1}",
@@ -265,7 +283,7 @@ class BlobsUploadsView(ContainerView):
        except FileNotFoundError as e:
            raise errors.BlobUploadUnknown() from e
        return self.response(
            status=HTTPStatus.NO_CONTENT,
            status=HTTPStatus.CREATED,
            headers={
                "Location": self.request.path,
                "Docker-Content-Digest": digest,
@@ -277,7 +295,7 @@ class BlobsUploadsView(ContainerView):
            self.repo().cancel_upload(self.request.match_info["uuid"])
        except FileNotFoundError as e:
            raise errors.BlobUploadUnknown() from e
        return self.response()
        return self.response(status=HTTPStatus.NO_CONTENT)


# --------------------------------------------------------------------------------------
-- 
2.39.2
dlrepo/patches/.build.yml: SUCCESS in 1m37s

[container: fix push/pull with podman][0] from [Robin Jarry][1]

[0]: https://lists.sr.ht/~rjarry/dlrepo/patches/40110
[1]: mailto:robin@jarry.cc

✓ #966198 SUCCESS dlrepo/patches/.build.yml https://builds.sr.ht/~rjarry/job/966198
Le sam. 1 avr. 2023 à 01:00, Robin Jarry <robin@jarry.cc> a écrit :