Setup command execution (#469)
This commit is contained in:
		
							parent
							
								
									63a94bae0e
								
							
						
					
					
						commit
						758ec168bd
					
				| @ -13,9 +13,10 @@ | |||||||
| # You should have received a copy of the GNU Affero General Public License | # You should have received a copy of the GNU Affero General Public License | ||||||
| # along with this program.  If not, see <http:#www.gnu.org/licenses/>. | # along with this program.  If not, see <http:#www.gnu.org/licenses/>. | ||||||
| 
 | 
 | ||||||
| from dataclasses import dataclass |  | ||||||
| from app.util import get_yaml | from app.util import get_yaml | ||||||
|  | from app.deploy_types import DeployCommandContext, DeploymentContext | ||||||
| from app.stack_state import State | from app.stack_state import State | ||||||
|  | from app.deploy_util import VolumeMapping, run_container_command | ||||||
| 
 | 
 | ||||||
| default_spec_file_content = """config: | default_spec_file_content = """config: | ||||||
|     node_moniker: my-node-name |     node_moniker: my-node-name | ||||||
| @ -25,38 +26,26 @@ default_spec_file_content = """config: | |||||||
| init_help_text = """Add helpful text here on setting config variables. | init_help_text = """Add helpful text here on setting config variables. | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| @dataclass |  | ||||||
| class VolumeMapping: |  | ||||||
|     host_path: str |  | ||||||
|     container_path: str |  | ||||||
| 
 | 
 | ||||||
| 
 | def setup(command_context: DeployCommandContext): | ||||||
| # In order to make this, we need the ability to run the stack |  | ||||||
| # In theory we can make this same way as we would run deploy up |  | ||||||
| def run_container_command(ctx, ontainer, command, mounts): |  | ||||||
|     deploy_context = ctx.obj |  | ||||||
|     pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def setup(ctx): |  | ||||||
|     node_moniker = "dbdb-node" |     node_moniker = "dbdb-node" | ||||||
|     chain_id = "laconic_81337-1" |     chain_id = "laconic_81337-1" | ||||||
|     mounts = [ |     mounts = [ | ||||||
|         VolumeMapping("./path", "~/.laconicd") |         VolumeMapping("./path", "~/.laconicd") | ||||||
|     ] |     ] | ||||||
|     output, status = run_container_command(ctx, "laconicd", f"laconicd init {node_moniker} --chain-id {chain_id}", mounts) |     output, status = run_container_command(command_context.cluster_context, "laconicd", f"laconicd init {node_moniker} --chain-id {chain_id}", mounts) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def init(command_context): | def init(command_context: DeployCommandContext): | ||||||
|     print(init_help_text) |     print(init_help_text) | ||||||
|     yaml = get_yaml() |     yaml = get_yaml() | ||||||
|     return yaml.load(default_spec_file_content) |     return yaml.load(default_spec_file_content) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def get_state(command_context): | def get_state(command_context: DeployCommandContext): | ||||||
|     print("Here we get state") |     print("Here we get state") | ||||||
|     return State.CONFIGURED |     return State.CONFIGURED | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def change_state(command_context): | def change_state(command_context: DeployCommandContext): | ||||||
|     pass |     pass | ||||||
|  | |||||||
							
								
								
									
										54
									
								
								app/data/stacks/test/deploy/commands.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								app/data/stacks/test/deploy/commands.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | # 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 | ||||||
|  | # the Free Software Foundation, either version 3 of the License, or | ||||||
|  | # (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | # This program is distributed in the hope that it will be useful, | ||||||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | # GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  | # You should have received a copy of the GNU Affero General Public License | ||||||
|  | # along with this program.  If not, see <http:#www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | from app.util import get_yaml | ||||||
|  | from app.deploy_types import DeployCommandContext, DeploymentContext | ||||||
|  | from app.stack_state import State | ||||||
|  | from app.deploy_util import VolumeMapping, run_container_command | ||||||
|  | import os | ||||||
|  | from pathlib import Path | ||||||
|  | 
 | ||||||
|  | default_spec_file_content = """config: | ||||||
|  |     config_variable: test-value | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | init_help_text = """Add helpful text here on setting config variables. | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | # Output a known string to a know file in the bind mounted directory ./container-output-dir | ||||||
|  | # for test purposes -- test checks that the file was written. | ||||||
|  | def setup(command_context: DeployCommandContext, extra_args): | ||||||
|  |     host_directory = "./container-output-dir" | ||||||
|  |     host_directory_absolute = Path(extra_args[0]).absolute().joinpath(host_directory) | ||||||
|  |     host_directory_absolute.mkdir(parents=True, exist_ok=True) | ||||||
|  |     mounts = [ | ||||||
|  |         VolumeMapping(host_directory_absolute, "/data") | ||||||
|  |     ] | ||||||
|  |     output, status = run_container_command(command_context, "test", "echo output-data > /data/output-file && echo success", mounts) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def init(command_context: DeployCommandContext): | ||||||
|  |     print(init_help_text) | ||||||
|  |     yaml = get_yaml() | ||||||
|  |     return yaml.load(default_spec_file_content) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_state(command_context: DeployCommandContext): | ||||||
|  |     print("Here we get state") | ||||||
|  |     return State.CONFIGURED | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def change_state(command_context: DeployCommandContext): | ||||||
|  |     pass | ||||||
| @ -27,17 +27,12 @@ from python_on_whales import DockerClient, DockerException | |||||||
| import click | import click | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from app.util import include_exclude_check, get_parsed_stack_config, global_options2 | from app.util import include_exclude_check, get_parsed_stack_config, global_options2 | ||||||
|  | from app.deploy_types import ClusterContext, DeployCommandContext | ||||||
| from app.deployment_create import create as deployment_create | from app.deployment_create import create as deployment_create | ||||||
| from app.deployment_create import init as deployment_init | from app.deployment_create import init as deployment_init | ||||||
| from app.deployment_create import setup as deployment_setup | from app.deployment_create import setup as deployment_setup | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DeployCommandContext(object): |  | ||||||
|     def __init__(self, cluster_context, docker): |  | ||||||
|         self.cluster_context = cluster_context |  | ||||||
|         self.docker = docker |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| @click.group() | @click.group() | ||||||
| @click.option("--include", help="only start these components") | @click.option("--include", help="only start these components") | ||||||
| @click.option("--exclude", help="don\'t start these components") | @click.option("--exclude", help="don\'t start these components") | ||||||
| @ -58,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/ |     # 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, |     docker = DockerClient(compose_files=cluster_context.compose_files, compose_project_name=cluster_context.cluster, | ||||||
|                           compose_env_file=cluster_context.env_file) |                           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): | def up_operation(ctx, services_list, stay_attached=False): | ||||||
| @ -313,17 +308,7 @@ def _make_cluster_context(ctx, stack, include, exclude, cluster, env_file): | |||||||
|     if ctx.verbose: |     if ctx.verbose: | ||||||
|         print(f"files: {compose_files}") |         print(f"files: {compose_files}") | ||||||
| 
 | 
 | ||||||
|     return cluster_context(cluster, compose_files, pre_start_commands, post_start_commands, cluster_config, env_file) |     return ClusterContext(cluster, compose_files, pre_start_commands, post_start_commands, cluster_config, env_file) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class cluster_context: |  | ||||||
|     def __init__(self, cluster, compose_files, pre_start_commands, post_start_commands, config, env_file) -> None: |  | ||||||
|         self.cluster = cluster |  | ||||||
|         self.compose_files = compose_files |  | ||||||
|         self.pre_start_commands = pre_start_commands |  | ||||||
|         self.post_start_commands = post_start_commands |  | ||||||
|         self.config = config |  | ||||||
|         self.env_file = env_file |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _convert_to_new_format(old_pod_array): | def _convert_to_new_format(old_pod_array): | ||||||
|  | |||||||
							
								
								
									
										47
									
								
								app/deploy_types.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/deploy_types.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | # Copyright © 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 | ||||||
|  | # the Free Software Foundation, either version 3 of the License, or | ||||||
|  | # (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | # This program is distributed in the hope that it will be useful, | ||||||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | # GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  | # You should have received a copy of the GNU Affero General Public License | ||||||
|  | # along with this program.  If not, see <http:#www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | from typing import List | ||||||
|  | from dataclasses import dataclass | ||||||
|  | from pathlib import Path | ||||||
|  | from python_on_whales import DockerClient | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class ClusterContext: | ||||||
|  |     cluster: str | ||||||
|  |     compose_files: List[str] | ||||||
|  |     pre_start_commands: List[str] | ||||||
|  |     post_start_commands: List[str] | ||||||
|  |     config: str | ||||||
|  |     env_file: str | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class DeployCommandContext: | ||||||
|  |     stack: str | ||||||
|  |     cluster_context: ClusterContext | ||||||
|  |     docker: DockerClient | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class DeploymentContext: | ||||||
|  |     deployment_dir: Path | ||||||
|  |     command_context: DeployCommandContext | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @dataclass | ||||||
|  | class VolumeMapping: | ||||||
|  |     host_path: str | ||||||
|  |     container_path: str | ||||||
							
								
								
									
										56
									
								
								app/deploy_util.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/deploy_util.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | # 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 | ||||||
|  | # the Free Software Foundation, either version 3 of the License, or | ||||||
|  | # (at your option) any later version. | ||||||
|  | 
 | ||||||
|  | # This program is distributed in the hope that it will be useful, | ||||||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | # GNU Affero General Public License for more details. | ||||||
|  | 
 | ||||||
|  | # You should have received a copy of the GNU Affero General Public License | ||||||
|  | # along with this program.  If not, see <http:#www.gnu.org/licenses/>. | ||||||
|  | 
 | ||||||
|  | import os | ||||||
|  | from typing import List | ||||||
|  | from dataclasses import dataclass | ||||||
|  | from app.deploy_types import DeployCommandContext, VolumeMapping | ||||||
|  | from app.util import get_parsed_stack_config, get_yaml, get_compose_file_dir | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def _container_image_from_service(stack:str, service: str): | ||||||
|  |     # Parse the compose files looking for the image name of the specified service | ||||||
|  |     image_name = None | ||||||
|  |     parsed_stack = get_parsed_stack_config(stack) | ||||||
|  |     pods = parsed_stack["pods"] | ||||||
|  |     yaml = get_yaml() | ||||||
|  |     for pod in pods: | ||||||
|  |         pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml") | ||||||
|  |         parsed_pod_file = yaml.load(open(pod_file_path, "r")) | ||||||
|  |         if "services" in parsed_pod_file: | ||||||
|  |             services = parsed_pod_file["services"] | ||||||
|  |             if service in services: | ||||||
|  |                 service_definition = services[service] | ||||||
|  |                 if "image" in service_definition: | ||||||
|  |                     image_name = service_definition["image"] | ||||||
|  |     return image_name | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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(ctx.stack, 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) | ||||||
| @ -20,26 +20,14 @@ import os | |||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from shutil import copyfile, copytree | from shutil import copyfile, copytree | ||||||
| import sys | import sys | ||||||
| from app.util import get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config, global_options, get_yaml | from app.util import get_stack_file_path, get_parsed_deployment_spec, get_parsed_stack_config, global_options, get_yaml, get_compose_file_dir | ||||||
| 
 | from app.deploy_types import DeploymentContext, DeployCommandContext | ||||||
| @dataclass |  | ||||||
| class DeploymentContext: |  | ||||||
|     stack: str |  | ||||||
|     deployment_dir: Path |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _make_default_deployment_dir(): | def _make_default_deployment_dir(): | ||||||
|     return "deployment-001" |     return "deployment-001" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _get_compose_file_dir(): |  | ||||||
|     # TODO: refactor to use common code with deploy command |  | ||||||
|     # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure |  | ||||||
|     data_dir = Path(__file__).absolute().parent.joinpath("data") |  | ||||||
|     source_compose_dir = data_dir.joinpath("compose") |  | ||||||
|     return source_compose_dir |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def _get_named_volumes(stack): | def _get_named_volumes(stack): | ||||||
|     # Parse the compose files looking for named volumes |     # Parse the compose files looking for named volumes | ||||||
|     named_volumes = [] |     named_volumes = [] | ||||||
| @ -47,7 +35,7 @@ def _get_named_volumes(stack): | |||||||
|     pods = parsed_stack["pods"] |     pods = parsed_stack["pods"] | ||||||
|     yaml = get_yaml() |     yaml = get_yaml() | ||||||
|     for pod in pods: |     for pod in pods: | ||||||
|         pod_file_path = os.path.join(_get_compose_file_dir(), f"docker-compose-{pod}.yml") |         pod_file_path = os.path.join(get_compose_file_dir(), f"docker-compose-{pod}.yml") | ||||||
|         parsed_pod_file = yaml.load(open(pod_file_path, "r")) |         parsed_pod_file = yaml.load(open(pod_file_path, "r")) | ||||||
|         if "volumes" in parsed_pod_file: |         if "volumes" in parsed_pod_file: | ||||||
|             volumes = parsed_pod_file["volumes"] |             volumes = parsed_pod_file["volumes"] | ||||||
| @ -94,27 +82,27 @@ def _fixup_pod_file(pod, spec, compose_dir): | |||||||
|                     pod["volumes"][volume] = new_volume_spec |                     pod["volumes"][volume] = new_volume_spec | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def call_stack_deploy_init(stack): | def call_stack_deploy_init(deploy_command_context): | ||||||
|     # Link with the python file in the stack |     # Link with the python file in the stack | ||||||
|     # Call a function in it |     # Call a function in it | ||||||
|     # If no function found, return None |     # 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) |     spec = util.spec_from_file_location("commands", python_file_path) | ||||||
|     imported_stack = util.module_from_spec(spec) |     imported_stack = util.module_from_spec(spec) | ||||||
|     spec.loader.exec_module(imported_stack) |     spec.loader.exec_module(imported_stack) | ||||||
|     return imported_stack.init(None) |     return imported_stack.init(deploy_command_context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # TODO: fold this with function above | # TODO: fold this with function above | ||||||
| def call_stack_deploy_setup(stack): | def call_stack_deploy_setup(deploy_command_context, extra_args): | ||||||
|     # Link with the python file in the stack |     # Link with the python file in the stack | ||||||
|     # Call a function in it |     # Call a function in it | ||||||
|     # If no function found, return None |     # 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) |     spec = util.spec_from_file_location("commands", python_file_path) | ||||||
|     imported_stack = util.module_from_spec(spec) |     imported_stack = util.module_from_spec(spec) | ||||||
|     spec.loader.exec_module(imported_stack) |     spec.loader.exec_module(imported_stack) | ||||||
|     return imported_stack.setup(None) |     return imported_stack.setup(deploy_command_context, extra_args) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # TODO: fold this with function above | # TODO: fold this with function above | ||||||
| @ -154,7 +142,7 @@ def init(ctx, output): | |||||||
|     yaml = get_yaml() |     yaml = get_yaml() | ||||||
|     stack = global_options(ctx).stack |     stack = global_options(ctx).stack | ||||||
|     verbose = global_options(ctx).verbose |     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} |     spec_file_content = {"stack": stack} | ||||||
|     if default_spec_file_content: |     if default_spec_file_content: | ||||||
|         spec_file_content.update(default_spec_file_content) |         spec_file_content.update(default_spec_file_content) | ||||||
| @ -217,7 +205,7 @@ def create(ctx, spec_file, deployment_dir): | |||||||
|                 if not os.path.exists(destination_config_dir): |                 if not os.path.exists(destination_config_dir): | ||||||
|                     copytree(source_config_dir, destination_config_dir) |                     copytree(source_config_dir, destination_config_dir) | ||||||
|     # Delegate to the stack's Python code |     # 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) |     call_stack_deploy_create(deployment_context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -227,7 +215,7 @@ def create(ctx, spec_file, deployment_dir): | |||||||
| @click.option("--initialize-network", is_flag=True, default=False, help="Help goes here") | @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("--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.option("--create-network", is_flag=True, default=False, help="Help goes here") | ||||||
|  | @click.argument('extra_args', nargs=-1) | ||||||
| @click.pass_context | @click.pass_context | ||||||
| def setup(ctx, node_moniker, key_name, initialize_network, join_network, create_network): | def setup(ctx, node_moniker, key_name, initialize_network, join_network, create_network, extra_args): | ||||||
|     stack = global_options(ctx).stack |     call_stack_deploy_setup(ctx.obj, extra_args) | ||||||
|     call_stack_deploy_setup(stack) |  | ||||||
|  | |||||||
| @ -56,6 +56,14 @@ def get_parsed_stack_config(stack): | |||||||
|         sys.exit(1) |         sys.exit(1) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def get_compose_file_dir(): | ||||||
|  |     # TODO: refactor to use common code with deploy command | ||||||
|  |     # See: https://stackoverflow.com/questions/25389095/python-get-path-of-root-project-structure | ||||||
|  |     data_dir = Path(__file__).absolute().parent.joinpath("data") | ||||||
|  |     source_compose_dir = data_dir.joinpath("compose") | ||||||
|  |     return source_compose_dir | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def get_parsed_deployment_spec(spec_file): | def get_parsed_deployment_spec(spec_file): | ||||||
|     spec_file_path = Path(spec_file) |     spec_file_path = Path(spec_file) | ||||||
|     try: |     try: | ||||||
|  | |||||||
| @ -23,6 +23,26 @@ mkdir -p $CERC_REPO_BASE_DIR | |||||||
| # with and without volume removal | # with and without volume removal | ||||||
| $TEST_TARGET_SO --stack test setup-repositories | $TEST_TARGET_SO --stack test setup-repositories | ||||||
| $TEST_TARGET_SO --stack test build-containers | $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 [ ! -d "$CERC_REPO_BASE_DIR/container-output-dir" ]; then | ||||||
|  |     echo "deploy setup test: output directory not present" | ||||||
|  |     echo "deploy setup test: FAILED" | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  | if [ ! -f "$CERC_REPO_BASE_DIR/container-output-dir/output-file" ]; then | ||||||
|  |     echo "deploy setup test: output file not present" | ||||||
|  |     echo "deploy setup test: FAILED" | ||||||
|  |     exit 1 | ||||||
|  | fi | ||||||
|  | output_file_content=$(<$CERC_REPO_BASE_DIR/container-output-dir/output-file) | ||||||
|  | if [ ! "$output_file_content" == "output-data"  ]; then | ||||||
|  |     echo "deploy setup test: output file contents not correct" | ||||||
|  |     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_TARGET_SO --stack test deploy up | ||||||
| # Test deploy port command | # Test deploy port command | ||||||
| deploy_port_output=$( $TEST_TARGET_SO --stack test deploy port test 80 ) | deploy_port_output=$( $TEST_TARGET_SO --stack test deploy port test 80 ) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user