From 3718276f1c50d4a6e6ad66478fbc150882711a39 Mon Sep 17 00:00:00 2001 From: David Boreham Date: Sat, 29 Jul 2023 21:51:16 -0600 Subject: [PATCH] Mostly working implementation --- app/deploy.py | 2 +- app/deploy_types.py | 2 +- app/deploy_util.py | 26 +++++++++++++++++++++++--- app/deployment_create.py | 25 ++++++++++++------------- tests/deploy/run-deploy-test.sh | 8 ++++++++ 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/app/deploy.py b/app/deploy.py index d9e0abff..64b3f11c 100644 --- a/app/deploy.py +++ b/app/deploy.py @@ -53,7 +53,7 @@ def create_deploy_context(global_context, stack, include, exclude, cluster, env_ # See: https://gabrieldemarmiesse.github.io/python-on-whales/sub-commands/compose/ docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster, compose_env_file=cluster_context.env_file) - return DeployCommandContext(cluster_context, docker) + return DeployCommandContext(stack, cluster_context, docker) def up_operation(ctx, services_list, stay_attached=False): diff --git a/app/deploy_types.py b/app/deploy_types.py index 35836256..c6df5784 100644 --- a/app/deploy_types.py +++ b/app/deploy_types.py @@ -30,13 +30,13 @@ class ClusterContext: @dataclass class DeployCommandContext: + stack: str cluster_context: ClusterContext docker: DockerClient @dataclass class DeploymentContext: - stack: str deployment_dir: Path command_context: DeployCommandContext diff --git a/app/deploy_util.py b/app/deploy_util.py index 7b76538d..c853fc83 100644 --- a/app/deploy_util.py +++ b/app/deploy_util.py @@ -13,8 +13,28 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from typing import List from dataclasses import dataclass -from app.deploy_types import DeploymentContext, VolumeMapping +from app.deploy_types import DeployCommandContext, VolumeMapping -def run_container_command(ctx: DeploymentContext, container, command, mounts): - print("Write some code!") + +def _container_image_from_service(service: str): + return "cerc/test-container:local" + + +def _volumes_to_docker(mounts: List[VolumeMapping]): +# Example from doc: [("/", "/host"), ("/etc/hosts", "/etc/hosts", "rw")] + result = [] + for mount in mounts: + docker_volume = (mount.host_path, mount.container_path) + result.append(docker_volume) + return result + + +def run_container_command(ctx: DeployCommandContext, service: str, command: str, mounts: List[VolumeMapping]): + docker = ctx.docker + container_image = _container_image_from_service(service) + docker_volumes = _volumes_to_docker(mounts) + docker_output = docker.run(container_image, ["-c", command], entrypoint="bash", volumes=docker_volumes) + # There doesn't seem to be a way to get an exit code from docker.run() + return (docker_output, 0) diff --git a/app/deployment_create.py b/app/deployment_create.py index 0292db35..0766e22b 100644 --- a/app/deployment_create.py +++ b/app/deployment_create.py @@ -21,7 +21,7 @@ from pathlib import Path from shutil import copyfile, copytree import sys from app.util import get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config, global_options, get_yaml -import app.deploy_types +from app.deploy_types import DeploymentContext, DeployCommandContext def _make_default_deployment_dir(): @@ -90,27 +90,27 @@ def _fixup_pod_file(pod, spec, compose_dir): pod["volumes"][volume] = new_volume_spec -def call_stack_deploy_init(deployment_context): +def call_stack_deploy_init(deploy_command_context): # Link with the python file in the stack # Call a function in it # If no function found, return None - python_file_path = get_stack_file_path(stack).parent.joinpath("deploy", "commands.py") + python_file_path = get_stack_file_path(deploy_command_context.stack).parent.joinpath("deploy", "commands.py") spec = util.spec_from_file_location("commands", python_file_path) imported_stack = util.module_from_spec(spec) spec.loader.exec_module(imported_stack) - return imported_stack.init(deployment_context) + return imported_stack.init(deploy_command_context) # TODO: fold this with function above -def call_stack_deploy_setup(deployment_context): +def call_stack_deploy_setup(deploy_command_context, extra_args): # Link with the python file in the stack # Call a function in it # If no function found, return None - python_file_path = get_stack_file_path(deployment_context.stack).parent.joinpath("deploy", "commands.py") + python_file_path = get_stack_file_path(deploy_command_context.stack).parent.joinpath("deploy", "commands.py") spec = util.spec_from_file_location("commands", python_file_path) imported_stack = util.module_from_spec(spec) spec.loader.exec_module(imported_stack) - return imported_stack.setup(deployment_context) + return imported_stack.setup(deploy_command_context, extra_args) # TODO: fold this with function above @@ -150,7 +150,7 @@ def init(ctx, output): yaml = get_yaml() stack = global_options(ctx).stack verbose = global_options(ctx).verbose - default_spec_file_content = call_stack_deploy_init(stack) + default_spec_file_content = call_stack_deploy_init(ctx.obj) spec_file_content = {"stack": stack} if default_spec_file_content: spec_file_content.update(default_spec_file_content) @@ -213,7 +213,7 @@ def create(ctx, spec_file, deployment_dir): if not os.path.exists(destination_config_dir): copytree(source_config_dir, destination_config_dir) # Delegate to the stack's Python code - deployment_context = DeploymentContext(stack_name, Path(deployment_dir)) + deployment_context = DeploymentContext(Path(deployment_dir), ctx.obj) call_stack_deploy_create(deployment_context) @@ -223,8 +223,7 @@ def create(ctx, spec_file, deployment_dir): @click.option("--initialize-network", is_flag=True, default=False, help="Help goes here") @click.option("--join-network", is_flag=True, default=False, help="Help goes here") @click.option("--create-network", is_flag=True, default=False, help="Help goes here") +@click.argument('extra_args', nargs=-1) @click.pass_context -def setup(ctx, node_moniker, key_name, initialize_network, join_network, create_network): - stack_name = global_options(ctx).stack - deployment_context = DeploymentContext(stack_name, Path(deployment_dir)) - call_stack_deploy_setup(deployment_context) +def setup(ctx, node_moniker, key_name, initialize_network, join_network, create_network, extra_args): + call_stack_deploy_setup(ctx.obj, extra_args) diff --git a/tests/deploy/run-deploy-test.sh b/tests/deploy/run-deploy-test.sh index 8e84a6b5..f2dee67c 100755 --- a/tests/deploy/run-deploy-test.sh +++ b/tests/deploy/run-deploy-test.sh @@ -23,6 +23,14 @@ mkdir -p $CERC_REPO_BASE_DIR # with and without volume removal $TEST_TARGET_SO --stack test setup-repositories $TEST_TARGET_SO --stack test build-containers +# Test deploy command execution +$TEST_TARGET_SO --stack test deploy setup $CERC_REPO_BASE_DIR +# Check that we now have the expected output directory +if []; then + echo "deploy setup test: FAILED" + exit 1 +fi +# Check that we now have the expected output file $TEST_TARGET_SO --stack test deploy up # Test deploy port command deploy_port_output=$( $TEST_TARGET_SO --stack test deploy port test 80 )