~rjarry/dlrepo

dlrepo: container: fix pull with no tag v1 APPLIED

Julien Floret: 1
 container: fix pull with no tag

 3 files changed, 24 insertions(+), 4 deletions(-)
#1389069 .build.yml success
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/56410/mbox | git am -3
Learn more about email & git

[PATCH dlrepo] container: fix pull with no tag Export this patch

When doing a container pull with no tag (or ":latest"):

> docker pull <registry>/<branch>/<job>

Before this patch, the "latest" tag was selected from all available
tags in /branches/<branch>, not from the tags available for that
specific container. As a consequence, if the container did not exist
in the latest tag, the "docker pull" or equivalent
command returned an error like:

> Error response from daemon: manifest for <img>:latest not found: manifest unknown: latest

Fix that by adding an optional "filter_names" argument to
Branch.get_tag(): when resolving a dynamic tag like "latest", tags
that are not part of filter_names are skipped.

In the container view, filter_names is set to
self.registry().job_tags(), because that method selects only the tags
available for the requested container (the tags where <job> exists AND
has a "container" format).

So, after this patch, the "latest" tag resolves to "the latest tag for
that container image". This is consistent with the output of the
/v2/<branch>/<job>/tags/list URL route.

The same logic is applied to the product view.

Signed-off-by: Julien Floret <julien.floret@6wind.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
---
 dlrepo/fs/branch.py       |  9 ++++++++-
 dlrepo/fs/product.py      |  9 ++++++++-
 dlrepo/views/container.py | 10 ++++++++--
 3 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/dlrepo/fs/branch.py b/dlrepo/fs/branch.py
index 8b6940c19d62..ebbcaf42bc5c 100644
--- a/dlrepo/fs/branch.py
+++ b/dlrepo/fs/branch.py
@@ -35,9 +35,16 @@ class Branch(SubDir):
                continue
            yield t

    def get_tag(self, name: str, access_cb: Callable[[str], bool] = None) -> Tag:
    def get_tag(
        self,
        name: str,
        access_cb: Callable[[str], bool] = None,
        filter_names: list[str] = None,
    ) -> Tag:
        if name in ("latest", "stable", "oldstable"):
            tags = list(self.get_tags(access_cb))
            if filter_names:
                tags = [tag for tag in tags if tag.name in filter_names]
            tags.sort(key=Tag.creation_date, reverse=True)
            first = True
            for t in tags:
diff --git a/dlrepo/fs/product.py b/dlrepo/fs/product.py
index 4c05440ff544..1e974c3765c1 100644
--- a/dlrepo/fs/product.py
+++ b/dlrepo/fs/product.py
@@ -63,10 +63,17 @@ class ProductBranch(SubDir):
            yield v

    def get_version(
        self, name: str, access_cb: Callable[[str], bool] = None
        self,
        name: str,
        access_cb: Callable[[str], bool] = None,
        filter_names: list[str] = None,
    ) -> "Version":
        if name in ("latest", "stable", "oldstable"):
            versions = list(self.get_versions(access_cb))
            if filter_names:
                versions = [
                    version for version in versions if version.name in filter_names
                ]
            versions.sort(key=Version.creation_date, reverse=True)
            first = True
            for v in versions:
diff --git a/dlrepo/views/container.py b/dlrepo/views/container.py
index 73ca7d8b262b..c4bb9b65c2a7 100644
--- a/dlrepo/views/container.py
+++ b/dlrepo/views/container.py
@@ -79,18 +79,24 @@ class ManifestReadOnlyView(ContainerView):
                digest = ref
            else:
                if "product" in match:
                    filter_names = self.registry().product_tags(
                        match["product"], match["variant"], match["product_branch"]
                    )
                    parent = (
                        self.repo()
                        .get_product(match["product"])
                        .get_variant(match["variant"])
                        .get_branch(match["product_branch"])
                        .get_version(ref, self.access_granted)
                        .get_version(ref, self.access_granted, filter_names)
                    )
                else:
                    filter_names = self.registry().job_tags(
                        match["branch"], match["job"]
                    )
                    parent = (
                        self.repo()
                        .get_branch(match["branch"])
                        .get_tag(ref, self.access_granted)
                        .get_tag(ref, self.access_granted, filter_names)
                        .get_job(match["job"])
                    )
                path, digest = registry.manifest_by_parent(parent.path())
-- 
2.39.2
Julien Floret <julien.floret@6wind.com> wrote:
dlrepo/patches/.build.yml: SUCCESS in 42s

[container: fix pull with no tag][0] from [Julien Floret][1]

[0]: https://lists.sr.ht/~rjarry/dlrepo/patches/56410
[1]: mailto:julien.floret@6wind.com

✓ #1389069 SUCCESS dlrepo/patches/.build.yml https://builds.sr.ht/~rjarry/job/1389069