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 | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- ci/util.py | 13 +++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/ci/helper b/ci/helper index 1b7675c58a..dbe3f80555 100755 --- a/ci/helper +++ b/ci/helper @@ -136,9 +136,16 @@ 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( + "--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): @@ -286,10 +293,55 @@ class Application: print("Available cross-compiler container images:\n") print("\t" + "\n\t".join(cross)) + def _list_stale_images(self): + # get list of hosts supported by lcitool + lcitool_hosts = self.lcitool_get_hosts() + + # get images from gitlab registry + registry_uri = util.get_registry_uri(self.args.namespace, + self.args.gitlab_uri) + images = util.get_registry_images(registry_uri) + + # extract distro names from the list of registry images + registry_distros = [util.get_image_distro(i["name"]) for i in images] + + # check for stale images in GitLab registry + stale = set(registry_distros) - set(lcitool_hosts) + if stale: + stale_images = {} + for item in stale: + for img in images: + if item in img["name"]: + stale_images[img["name"]] = img["id"] + + return stale_images + def action_refresh(self): + # refresh Dockerfiles and vars files self.refresh_containers() self.refresh_cirrus() + # check for stale images + if self.args.check_stale == "yes" and not self.args.quiet: + namespace = self.args.namespace + gitlab_uri = self.args.gitlab_uri + + stale_images = self._list_stale_images() + if stale_images: + spacing = "\n" + 4 * " " + stale_fmt = [f"{k}: {v}" for k, v in stale_images.items()] + + print(f""" +The following images are stale and can be purged from the registry: +{spacing + spacing.join(stale_fmt)} + +You can remove the above images over the API with the following code snippet: + + $ for image_id in {' '.join([str(id) for id in stale_images.values()])}; do + curl --request DELETE --header "PRIVATE-TOKEN: <access_token>" \\ + {util.get_registry_uri(namespace, gitlab_uri)}/$image_id + done""") + def run(self): self.args.func(self) diff --git a/ci/util.py b/ci/util.py index 8a2d6d8f47..f50c0e6100 100644 --- a/ci/util.py +++ b/ci/util.py @@ -37,3 +37,16 @@ def get_registry_images(uri: str) -> Dict[str, str]: # read the HTTP response and load the JSON part of it return json.loads(r.read().decode()) + + +def get_image_distro(image_name: str): + 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 -- 2.29.2