From d454a4ffc12d631f08a41c3d48672adefad84a70 Mon Sep 17 00:00:00 2001 From: David Boreham Date: Thu, 19 Jan 2023 14:13:57 -0700 Subject: [PATCH] Error check stack config --- app/build_containers.py | 14 ++++---------- app/build_npms.py | 16 +++++----------- app/deploy_system.py | 15 +++++---------- app/util.py | 28 +++++++++++++++++++++++++++- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/app/build_containers.py b/app/build_containers.py index 75e78f2d..52ba3103 100644 --- a/app/build_containers.py +++ b/app/build_containers.py @@ -1,4 +1,4 @@ -# Copyright © 2022 Cerc +# Copyright © 2022, 2023 Cerc # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -27,8 +27,7 @@ import subprocess import click import importlib.resources from pathlib import Path -import yaml -from .util import include_exclude_check +from .util import include_exclude_check, get_parsed_stack_config # TODO: find a place for this # epilog="Config provided either in .env or settings.ini or env vars: CERC_REPO_BASE_DIR (defaults to ~/cerc)" @@ -70,13 +69,8 @@ def command(ctx, include, exclude): containers_in_scope = [] if stack: - # In order to be compatible with Python 3.8 we need to use this hack to get the path: - # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure - stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml") - with stack_file_path: - stack_config = yaml.safe_load(open(stack_file_path, "r")) - # TODO: syntax check the input here - containers_in_scope = stack_config['containers'] + stack_config = get_parsed_stack_config(stack) + containers_in_scope = stack_config['containers'] else: containers_in_scope = all_containers diff --git a/app/build_npms.py b/app/build_npms.py index 4f0ea219..3cf7d404 100644 --- a/app/build_npms.py +++ b/app/build_npms.py @@ -1,4 +1,4 @@ -# Copyright © 2022 Cerc +# Copyright © 2022, 2023 Cerc # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -23,10 +23,8 @@ import sys from decouple import config import click import importlib.resources -from pathlib import Path from python_on_whales import docker, DockerException -import yaml -from .util import include_exclude_check +from .util import include_exclude_check, get_parsed_stack_config @click.command() @click.option('--include', help="only build these packages") @@ -62,13 +60,9 @@ def command(ctx, include, exclude): packages_in_scope = [] if stack: - # In order to be compatible with Python 3.8 we need to use this hack to get the path: - # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure - stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml") - with stack_file_path: - stack_config = yaml.safe_load(open(stack_file_path, "r")) - # TODO: syntax check the input here - packages_in_scope = stack_config['npms'] + stack_config = get_parsed_stack_config(stack) + # TODO: syntax check the input here + packages_in_scope = stack_config['npms'] else: packages_in_scope = all_packages diff --git a/app/deploy_system.py b/app/deploy_system.py index 6fc8b540..6771e5ee 100644 --- a/app/deploy_system.py +++ b/app/deploy_system.py @@ -1,4 +1,4 @@ -# Copyright © 2022 Cerc +# Copyright © 2022, 2023 Cerc # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -22,8 +22,7 @@ from python_on_whales import DockerClient import click import importlib.resources from pathlib import Path -import yaml -from .util import include_exclude_check +from .util import include_exclude_check, get_parsed_stack_config @click.command() @@ -62,13 +61,9 @@ def command(ctx, include, exclude, cluster, command, services): pods_in_scope = [] if stack: - # In order to be compatible with Python 3.8 we need to use this hack to get the path: - # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure - stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml") - with stack_file_path: - stack_config = yaml.safe_load(open(stack_file_path, "r")) - # TODO: syntax check the input here - pods_in_scope = stack_config['pods'] + stack_config = get_parsed_stack_config(stack) + # TODO: syntax check the input here + pods_in_scope = stack_config['pods'] else: pods_in_scope = all_pods diff --git a/app/util.py b/app/util.py index bbf84398..127de213 100644 --- a/app/util.py +++ b/app/util.py @@ -1,4 +1,4 @@ -# Copyright © 2022 Cerc +# Copyright © 2022, 2023 Cerc # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -13,6 +13,12 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import os.path +import sys +import yaml +from pathlib import Path + + def include_exclude_check(s, include, exclude): if include is None and exclude is None: return True @@ -22,3 +28,23 @@ def include_exclude_check(s, include, exclude): if exclude is not None: exclude_list = exclude.split(",") return s not in exclude_list + + +def get_parsed_stack_config(stack): + # In order to be compatible with Python 3.8 we need to use this hack to get the path: + # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure + stack_file_path = Path(__file__).absolute().parent.joinpath("data", "stacks", stack, "stack.yml") + try: + with stack_file_path: + stack_config = yaml.safe_load(open(stack_file_path, "r")) + return stack_config + except FileNotFoundError as error: + # We try here to generate a useful diagnostic error + # First check if the stack directory is present + stack_directory = stack_file_path.parent + if os.path.exists(stack_directory): + print(f"Error: stack.yml file is missing from stack: {stack}") + else: + print(f"Error: stack: {stack} does not exist") + print(f"Exiting, error: {error}") + sys.exit(1)