From c3e6f57b08a90854caa83ade104c3c8aba89bbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Behmo?= Date: Thu, 25 Nov 2021 09:53:49 +0100 Subject: [PATCH] feat: fail `images ... [image]` commands on incorrect image arg Previously, `tutor images build doesnotexist` was a no-op. This was counter-intuitive -- in particular, when users have a typo in their command. Now, the `images build/pull/push/printtag` commands fail if the corresponding image was not found. See discussion: https://discuss.overhang.io/t/return-something-when-tutor-images-build-contains-a-typo/2174 --- CHANGELOG.md | 2 ++ tutor/commands/images.py | 52 +++++++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f90cc1..7885492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ Note: Breaking changes between versions are indicated by "💥". ## Unreleased + +- 💥[Improvement] Fail on incorrect image name argument in `images build/pull/push/printtag` commands. - [Bugfix] Remove trailing slashes in docker-compose files for [compatibility with docker-compose v2 in WSL](https://github.com/docker/compose/issues/8558). - [Improvement] `settheme` now works with preview domain. - [Feature] Allow specifying extra pip packages through config.yml. diff --git a/tutor/commands/images.py b/tutor/commands/images.py index 0bda321..978a6b3 100644 --- a/tutor/commands/images.py +++ b/tutor/commands/images.py @@ -111,40 +111,71 @@ def push(context: Context, image_names: List[str]) -> None: def printtag(context: Context, image_names: List[str]) -> None: config = tutor_config.load(context.root) for image in image_names: + to_print = [] for _img, tag in iter_images(config, image, BASE_IMAGE_NAMES): - print(tag) + to_print.append(tag) for _plugin, _img, tag in iter_plugin_images(config, image, "build-image"): + to_print.append(tag) + + if not to_print: + raise ImageNotFoundError(image) + + for tag in to_print: print(tag) def build_image(root: str, config: Config, image: str, *args: str) -> None: + to_build = [] + # Build base images for img, tag in iter_images(config, image, BASE_IMAGE_NAMES): - images.build(tutor_env.pathjoin(root, "build", img), tag, *args) + to_build.append((tutor_env.pathjoin(root, "build", img), tag, args)) # Build plugin images for plugin, img, tag in iter_plugin_images(config, image, "build-image"): - images.build( - tutor_env.pathjoin(root, "plugins", plugin, "build", img), tag, *args + to_build.append( + (tutor_env.pathjoin(root, "plugins", plugin, "build", img), tag, args) ) # Build dev images with user id argument - dev_build_arg = ["--build-arg", "USERID={}".format(utils.get_user_id())] + dev_build_arg = ("--build-arg", "USERID={}".format(utils.get_user_id())) for img, tag in iter_images(config, image, DEV_IMAGE_NAMES): - images.build(tutor_env.pathjoin(root, "build", img), tag, *dev_build_arg, *args) + to_build.append( + (tutor_env.pathjoin(root, "build", img), tag, dev_build_arg + args) + ) + + if not to_build: + raise ImageNotFoundError(image) + + for path, tag, build_args in to_build: + images.build(path, tag, *args) def pull_image(config: Config, image: str) -> None: + to_pull = [] for _img, tag in iter_images(config, image, all_image_names(config)): - images.pull(tag) + to_pull.append(tag) for _plugin, _img, tag in iter_plugin_images(config, image, "remote-image"): + to_pull.append(tag) + + if not to_pull: + raise ImageNotFoundError(image) + + for tag in to_pull: images.pull(tag) def push_image(config: Config, image: str) -> None: + to_push = [] for _img, tag in iter_images(config, image, BASE_IMAGE_NAMES): - images.push(tag) + to_push.append(tag) for _plugin, _img, tag in iter_plugin_images(config, image, "remote-image"): + to_push.append(tag) + + if not to_push: + raise ImageNotFoundError(image) + + for tag in to_push: images.push(tag) @@ -185,6 +216,11 @@ def vendor_image_names(config: Config) -> List[str]: return vendor_images +class ImageNotFoundError(exceptions.TutorError): + def __init__(self, image_name: str): + super().__init__("Image '{}' could not be found".format(image_name)) + + images_command.add_command(build) images_command.add_command(pull) images_command.add_command(push)