-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #137 from fgcz/main
app_runner 0.0.15
- Loading branch information
Showing
21 changed files
with
415 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build" | |
[project] | ||
name = "bfabric" | ||
description = "Python client for the B-Fabric API" | ||
version = "1.13.18" | ||
version = "1.13.19" | ||
license = { text = "GPL-3.0" } | ||
authors = [ | ||
{ name = "Christian Panse", email = "[email protected]" }, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,14 +5,14 @@ build-backend = "hatchling.build" | |
[project] | ||
name = "bfabric_app_runner" | ||
description = "Application runner for B-Fabric apps" | ||
version = "0.0.14" | ||
version = "0.0.15" | ||
license = { text = "GPL-3.0" } | ||
authors = [ | ||
{name = "Leonardo Schwarz", email = "[email protected]"}, | ||
] | ||
requires-python = ">=3.12" | ||
dependencies = [ | ||
"bfabric==1.13.18", | ||
"bfabric==1.13.19", | ||
"pydantic", | ||
"glom", | ||
"mako", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
bfabric_app_runner/src/bfabric_app_runner/input_preparation/prepare_file_spec.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import shlex | ||
import shutil | ||
import subprocess | ||
from pathlib import Path | ||
from shutil import SameFileError | ||
from subprocess import CalledProcessError | ||
from typing import assert_never | ||
|
||
from loguru import logger | ||
|
||
from bfabric import Bfabric | ||
from bfabric_app_runner.specs.inputs.file_copy_spec import ( | ||
FileSpec, | ||
FileSourceSsh, | ||
FileSourceLocal, | ||
FileSourceSshValue, | ||
) | ||
from bfabric_app_runner.util.scp import scp | ||
|
||
|
||
def prepare_file_spec(spec: FileSpec, client: Bfabric, working_dir: Path, ssh_user: str | None) -> None: | ||
"""Prepares the file specified by the spec.""" | ||
output_path = working_dir / spec.resolve_filename(client=client) | ||
output_path.parent.mkdir(exist_ok=True, parents=True) | ||
|
||
if not spec.link: | ||
success = _operation_copy_rsync(spec, output_path, ssh_user) | ||
if not success: | ||
success = _operation_copy(spec, output_path, ssh_user) | ||
else: | ||
success = _operation_link_symbolic(spec, output_path) | ||
if not success: | ||
raise RuntimeError(f"Failed to copy file: {spec}") | ||
|
||
|
||
def _operation_copy_rsync(spec: FileSpec, output_path: Path, ssh_user: str | None) -> bool: | ||
match spec.source: | ||
case FileSourceLocal(local=local): | ||
source_str = str(Path(local).resolve()) | ||
case FileSourceSsh(ssh=FileSourceSshValue(host=host, path=path)): | ||
source_str = f"{ssh_user}@{host}:{path}" if ssh_user else f"{host}:{path}" | ||
case _: | ||
assert_never(spec.source) | ||
cmd = ["rsync", "-Pav", source_str, str(output_path)] | ||
logger.info(shlex.join(cmd)) | ||
result = subprocess.run(cmd, check=False) | ||
return result.returncode == 0 | ||
|
||
|
||
def _operation_copy(spec: FileSpec, output_path: Path, ssh_user: str | None) -> bool: | ||
match spec.source: | ||
case FileSourceLocal(): | ||
return _operation_copy_cp(spec, output_path) | ||
case FileSourceSsh(): | ||
return _operation_copy_scp(spec, output_path, ssh_user) | ||
case _: | ||
assert_never(spec.source) | ||
|
||
|
||
def _operation_copy_scp(spec: FileSpec, output_path: Path, ssh_user: str | None) -> bool: | ||
try: | ||
source_str = f"{spec.source.ssh.host}:{spec.source.ssh.path}" | ||
scp(source=source_str, target=output_path, user=ssh_user) | ||
except CalledProcessError: | ||
return False | ||
return True | ||
|
||
|
||
def _operation_copy_cp(spec: FileSpec, output_path: Path) -> bool: | ||
cmd = [str(Path(spec.source.local).resolve()), str(output_path)] | ||
logger.info(shlex.join(["cp", *cmd])) | ||
try: | ||
shutil.copyfile(*cmd) | ||
except (OSError, SameFileError): | ||
return False | ||
return True | ||
|
||
|
||
def _operation_link_symbolic(spec: FileSpec, output_path: Path) -> bool: | ||
# the link is created relative to the output file, so it should be more portable across apptainer images etc | ||
source_path = Path(spec.source.local).resolve().relative_to(output_path.resolve().parent, walk_up=True) | ||
|
||
# if the file exists, and only if it is a link as well | ||
if output_path.is_symlink(): | ||
# check if it points to the same file, in which case we don't need to do anything | ||
if output_path.resolve() == source_path.resolve(): | ||
logger.info("Link already exists and points to the correct file") | ||
return True | ||
else: | ||
logger.info(f"rm {output_path}") | ||
output_path.unlink() | ||
elif output_path.exists(): | ||
raise RuntimeError(f"Output path already exists and is not a symlink: {output_path}") | ||
cmd = ["ln", "-s", str(source_path), str(output_path)] | ||
logger.info(shlex.join(cmd)) | ||
result = subprocess.run(cmd, check=False) | ||
return result.returncode == 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
bfabric_app_runner/src/bfabric_app_runner/specs/inputs/file_copy_spec.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from __future__ import annotations | ||
|
||
from typing import Literal, TYPE_CHECKING, Self | ||
|
||
from pydantic import BaseModel, model_validator | ||
|
||
from bfabric_app_runner.specs.common_types import RelativeFilePath, AbsoluteFilePath # noqa: TC001 | ||
|
||
if TYPE_CHECKING: | ||
from bfabric import Bfabric | ||
|
||
|
||
class FileSourceLocal(BaseModel): | ||
local: AbsoluteFilePath | ||
|
||
def get_filename(self) -> str: | ||
return self.local.split("/")[-1] | ||
|
||
|
||
class FileSourceSshValue(BaseModel): | ||
host: str | ||
path: AbsoluteFilePath | ||
|
||
|
||
class FileSourceSsh(BaseModel): | ||
ssh: FileSourceSshValue | ||
|
||
def get_filename(self) -> str: | ||
return self.ssh.path.split("/")[-1] | ||
|
||
|
||
class FileSpec(BaseModel): | ||
type: Literal["file"] = "file" | ||
source: FileSourceSsh | FileSourceLocal | ||
filename: RelativeFilePath | None = None | ||
link: bool = False | ||
|
||
@model_validator(mode="after") | ||
def validate_no_link_ssh(self) -> Self: | ||
if isinstance(self.source, FileSourceSsh) and self.link: | ||
raise ValueError("Cannot link to a remote file.") | ||
return self | ||
|
||
def resolve_filename(self, client: Bfabric) -> str: | ||
return self.filename if self.filename else self.source.get_filename() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.