def deploy_conda(tool_name: str, conda_env_name: str) -> bool: """Deploy a tool into a conda environment""" if not check_if_deploy_possible(conda_env_name): return False python_process = Process(str(get_python_path(conda_env_name))) deploy_arguments = ["-m", "pip", "install", "-U", tool_name] python_process.run_command(deploy_arguments) return True
def delete_conda_env(conda_process: Process, env_name: str) -> None: """Delete an existing conda environment""" if not conda_env_exists(env_name): LOG.info("Environment %s does not exist", env_name) return cmd_args = ["env", "remove", "-n", env_name] LOG.info("Removing environment %s", env_name) conda_process.run_command(parameters=cmd_args)
def fetch_package_version(python_process: Process, package_name: str) -> str: """Fetch the version of a package installed""" LOG.info("Fetch current version for package %s", package_name) cmd_args = ["-m", "pip", "show", package_name] try: python_process.run_command(cmd_args) except CalledProcessError: return "" for line in python_process.stdout_lines: split_line = line.split(":") if split_line[0] == "Version": return split_line[-1].strip() return ""
def check_cmd(context): """Run a check if deployment would be possible""" LOG.info("Running shipping check") host_config: HostConfig = context.obj["host_config"] app_config: AppConfig = context.obj["app_config"] env_name: str = context.obj["env_name"] LOG.info( "%s wants to deploy %s on host %s in environment %s", context.obj["current_user"], app_config.tool, context.obj["current_host"], env_name, ) if not check_if_deploy_possible(conda_env_name=env_name): LOG.info( "Please use 'shipping provision' to create valid conda environment" ) return python_process = Process(str(get_python_path(env_name))) current_version = fetch_package_version(python_process, app_config.tool) click.echo( get_log_line( time_zone=host_config.tz_object, user=context.obj["current_user"], tool=app_config.tool, current_version=current_version, ))
def create_conda_env( conda_process: Process, env_name: str, py_version: str, force: bool = False ) -> Path: """Create a conda environment and return the path to that env""" new_env_path = get_conda_path(env_name) cmd_args = ["create", "-n", env_name, f"python={py_version}", "--yes"] if conda_env_exists(env_name): LOG.warning("Environment %s already exists", env_name) if not force: return new_env_path LOG.info("Will overwrite existing environment") cmd_args.append("--force") LOG.info("Creating environment %s", env_name) conda_process.run_command(parameters=cmd_args) return new_env_path
def provision_conda(conda_env_name: str, py_version: str = "3.7") -> bool: """Set up a conda a conda environment If conda environment already exists do nothing """ if not environment.conda_exists(): LOG.warning("Please make sure conda is available") return False conda_process = Process(binary="conda") environment.create_conda_env( conda_process=conda_process, env_name=conda_env_name, py_version=py_version ) return True
def test_check_cmd_no_environment(env_name: str, context: dict, caplog): """Test to run the check command when the environment does not exist""" caplog.set_level(logging.DEBUG) # GIVEN a environment that does not exist delete_conda_env(Process("conda"), env_name) assert conda_env_exists(env_name) is False # GIVEN a cli runner runner = CliRunner() # GIVEN a context with basic information # WHEN running the command to check if deployment is possible runner.invoke(check_cmd, [], obj=context) # THEN assert that it communicates that the environment does not exist assert "Please use 'shipping provision' to create valid conda environment" in caplog.text
def test_deploy_non_existing_env(env_name: str, context: dict, caplog): """Test to deploy a package when an environment does not exist""" caplog.set_level(logging.DEBUG) # GIVEN that the environment does not exist delete_conda_env(Process("conda"), env_name) assert conda_env_exists(env_name) is False # GIVEN a cli runner runner = CliRunner() # WHEN deploying the tool result = runner.invoke(deploy_cmd, [], obj=context) # THEN assert that the program exits with a non zero exit code assert result.exit_code != 0 # THEN assert that the correct information is communicated assert f"Environment {env_name} does not exist" in caplog.text
def deploy_cmd(context): """Deploy a tool into an existing container system""" LOG.info("Running shipping deploy") app_config: AppConfig = context.obj["app_config"] host_config: HostConfig = context.obj["host_config"] env_name: str = context.obj["env_name"] python_process: Process = Process(str(get_python_path(env_name))) current_version: str = fetch_package_version(python_process, app_config.tool) LOG.info( "%s wants to deploy %s on host %s in environment %s", context.obj["current_user"], app_config.tool, context.obj["current_host"], env_name, ) result: bool = deploy_conda(tool_name=app_config.tool, conda_env_name=env_name) if result is False: raise click.Abort LOG.info("Tool was successfully deployed") updated_version: str = fetch_package_version(python_process, app_config.tool) log_line = get_log_line( time_zone=host_config.tz_object, user=context.obj["current_user"], tool=app_config.tool, current_version=current_version, updated_version=updated_version, ) log_path = host_config.log_path if not log_path: click.echo(log_line) return if not log_path.exists(): log_path.touch() log_deploy(log_line=log_line, log_file=log_path)
def test_get_package_version_other_env(other_python_process: Process, other_env: str, tool_name: str): # GIVEN a Process with the python binary from another environment other_python = other_python_process.binary # GIVEN a current environment with python and a process current_python = environment.get_python_path() current_python_process = Process(str(current_python)) assert current_python != other_python # GIVEN a package that exists in other environment but not in the current environment deploy_conda(tool_name=tool_name, conda_env_name=other_env) current_env_version = fetch_package_version( python_process=current_python_process, package_name=tool_name) assert current_env_version == "" # WHEN fetching the version from the other env version = fetch_package_version(python_process=other_python_process, package_name=tool_name) # THEN assert that a version was returned assert version != ""
def test_run_main(): python_process = Process("python") call = ["-m", "shipping", "--version"] python_process.run_command(call) assert __version__ in python_process.stdout