[libvirt PATCH v4 5/6] ci: util: Add a registry checker for stale images

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This function checks whether there are any stale Docker images in the
registry that can be purged. Since we're pulling available container
images from our GitLab registry with the 'list-images' action, it
could happen that we'd list old (already unsupported) images and make
them available for the user to consume and run a build in them.
Naturally, the build will most likely fail leaving the user confused.

Signed-off-by: Erik Skultety <eskultet@xxxxxxxxxx>
---
 ci/helper  | 46 +++++++++++++++++++++++++++++++++++++++++++++-
 ci/util.py | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/ci/helper b/ci/helper
index 31cf72fbdf..0743f95e13 100755
--- a/ci/helper
+++ b/ci/helper
@@ -10,6 +10,7 @@ import pty
 import shutil
 import subprocess
 import sys
+import textwrap
 
 import util
 
@@ -130,7 +131,7 @@ class Parser:
         refreshparser = subparsers.add_parser(
             "refresh",
             help="refresh data generated with lcitool",
-            parents=[lcitoolparser],
+            parents=[lcitoolparser, gitlabparser],
             formatter_class=argparse.ArgumentDefaultsHelpFormatter,
         )
         refreshparser.add_argument(
@@ -139,6 +140,13 @@ class Parser:
             default=False,
             help="refresh data silently"
         )
+        refreshparser.add_argument(
+            "--check-stale",
+            action="store",
+            choices=["yes", "no"],
+            default="yes",
+            help="check for existence of stale images on the GitLab instance"
+        )
         refreshparser.set_defaults(func=Application.action_refresh)
 
     def parse(self):
@@ -287,10 +295,46 @@ class Application:
             print("Available cross-compiler container images:\n")
             print(spacing + ("\n" + spacing).join(cross))
 
+    def check_stale_images(self):
+        namespace = self.args.namespace
+        gitlab_uri = self.args.gitlab_uri
+        registry_uri = util.get_registry_uri(namespace, gitlab_uri)
+        lcitool_hosts = self.lcitool_get_hosts()
+
+        stale_images = util.get_registry_stale_images(registry_uri,
+                                                      lcitool_hosts)
+        if stale_images:
+            spacing = "\n" + 4 * " "
+            stale_fmt = [f"{k} (ID: {v})" for k, v in stale_images.items()]
+            stale_details = spacing.join(stale_fmt)
+            stale_ids = ' '.join([str(id) for id in stale_images.values()])
+            registry_uri = util.get_registry_uri(namespace, gitlab_uri)
+
+            msg = textwrap.dedent(f"""
+                The following images are stale and can be purged from the registry:
+
+                    STALE_DETAILS
+
+                You can delete the images listed above using this shell snippet:
+
+                    $ for image_id in {stale_ids}; do
+                        curl --request DELETE --header "PRIVATE-TOKEN: <access_token>" \\
+                            {registry_uri}/$image_id;
+                      done
+
+                You can generate a personal access token here:
+
+                    {gitlab_uri}/-/profile/personal_access_tokens
+            """)
+            print(msg.replace("STALE_DETAILS", stale_details))
+
     def action_refresh(self):
         self.refresh_containers()
         self.refresh_cirrus()
 
+        if self.args.check_stale == "yes" and not self.args.quiet:
+            self.check_stale_images()
+
     def run(self):
         self.args.func(self)
 
diff --git a/ci/util.py b/ci/util.py
index f9f8320276..90d58454be 100644
--- a/ci/util.py
+++ b/ci/util.py
@@ -38,3 +38,44 @@ def get_registry_images(uri: str) -> List[Dict]:
 
     # read the HTTP response and load the JSON part of it
     return json.loads(r.read().decode())
+
+
+def get_image_distro(image_name: str) -> str:
+    """
+    Extract the name of the distro in the GitLab image registry name, e.g.
+        ci-debian-9-cross-mipsel --> debian-9
+
+    :param image_name: name of the GitLab registry image
+    :return: distro name as a string
+    """
+    name_prefix = "ci-"
+    name_suffix = "-cross-"
+
+    distro = image_name[len(name_prefix):]
+
+    index = distro.find(name_suffix)
+    if index > 0:
+        distro = distro[:index]
+
+    return distro
+
+
+def get_registry_stale_images(registry_uri: str,
+                              supported_distros: List[str]) -> Dict[str, int]:
+    """
+    Check the GitLab image registry for images that we no longer support and
+    which should be deleted.
+
+    :param uri: URI pointing to a GitLab instance's image registry
+    :param supported_distros: list of hosts supported by lcitool
+    :return: dictionary formatted as: {<gitlab_image_name>: <gitlab_image_id>}
+    """
+
+    images = get_registry_images(registry_uri)
+
+    stale_images = {}
+    for img in images:
+        if get_image_distro(img["name"]) not in supported_distros:
+            stale_images[img["name"]] = img["id"]
+
+    return stale_images
-- 
2.30.2




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux