ci: util: Add a registry checker for stale images

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@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
This commit is contained in:
Erik Skultety 2021-03-15 15:42:13 +01:00
parent c5f9617b1c
commit efa8ca47b9
2 changed files with 86 additions and 1 deletions

View File

@ -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):
@ -256,6 +264,39 @@ class Application:
self.generate_vars(host)
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_build(self):
self.make_run(f"ci-build@{self.args.target}")
@ -291,6 +332,9 @@ class Application:
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)

View File

@ -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