From baa4ec1cb1e5f496af55143f379ee37fc5e228ea Mon Sep 17 00:00:00 2001 From: "David M. Rogers" Date: Thu, 25 Jan 2024 11:31:20 -0500 Subject: [PATCH 1/2] Moved download into podman and added action.sequence_rules --- contaminate/__init__.py | 10 ++++++++- contaminate/action.py | 50 ++++++++++++++++++++++++++++------------- contaminate/podman.py | 6 +++++ 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/contaminate/__init__.py b/contaminate/__init__.py index 988d600..1a21e96 100644 --- a/contaminate/__init__.py +++ b/contaminate/__init__.py @@ -1,3 +1,11 @@ from .container import Container from .container_env import ContainerEnv -from .action import Return, Script, Shell, Upload, Download +from .action import ( + Action, + Return, + Script, + Shell, + Upload, + Download, + sequence_rules +) diff --git a/contaminate/action.py b/contaminate/action.py index 3cf408c..51b98cf 100644 --- a/contaminate/action.py +++ b/contaminate/action.py @@ -7,7 +7,7 @@ from pydantic import BaseModel, Field from .container import Container from .container_env import ContainerEnv -from .podman import runcmd +import contaminate.podman as podman class AReturn(BaseModel): action_type : Literal["return"] = "return" @@ -31,25 +31,31 @@ class AShell(BaseModel): return c.run_shell(self.script) class AUpload(BaseModel): + """ Note: paths in Upload and Download + must be strings, since docker uses ending '/' + to denote moving inside a directory, as opposed to + overwriting. + """ action_type : Literal["upload"] = "upload" - src : Path # local - dst : Path # remote + src : str # local + dst : str # remote extract : bool = False # use ADD instead of COPY def __call__(self, c : Container) -> Container: - cmd = f"COPY {self.src} {self.dst}" + src = podman.quote(self.src) + dst = podman.quote(self.dst) + cmd = f'COPY ["{src}", "{dst}"]' if self.extract: - cmd = f"ADD {self.src} {self.dst}" + cmd = f'ADD ["{src}", "{dst}"]' return c.run_cmd(cmd) class ADownload(BaseModel): action_type : Literal["download"] = "download" - src : Path # remote - dst : Path # local + src : str # remote + dst : str # local def __call__(self, c : Container) -> Container: - runcmd("podman", "cp", - f"{c.name}:{self.src}", self.dst) + podman.download(c.name, self.src, self.dst) return c ActionT = Annotated[ @@ -90,11 +96,23 @@ def Script(script : str) -> Action: def Shell(script : str) -> Action: return Action(AShell(script = script)) -def Upload(src : Union[str,Path], dst : Union[str,Path], +def Upload(src : str, dst : str, extract : bool = False) -> Action: - return Action(AUpload(src=Path(src), - dst=Path(dst), extract=extract)) - -def Download(src : Union[str,Path], dst : Union[str,Path] - ) -> Action: - return Action(ADownload(src=Path(src), dst=Path(dst))) + return Action(AUpload(src=src, + dst=dst, extract=extract)) + +def Download(src : str, dst : str) -> Action: + return Action(ADownload(src=src, dst=dst)) + +# Run a sequence of rules, saving a json state ea. time. +def sequence_rules(rules : dict[str, Action], *steps : str) -> Container: + C = None + for s in steps: + result = Path(s + ".json") + if result.exists(): + C = Container.load(result) + else: + assert C is not None, f"Starting file '{result}' not present." + C = C.run( rules[s], name = s ) + C.store(result) + return C diff --git a/contaminate/podman.py b/contaminate/podman.py index b737887..3151190 100644 --- a/contaminate/podman.py +++ b/contaminate/podman.py @@ -5,6 +5,9 @@ import os import string from pathlib import Path +def quote(s) -> str: + return str(s).replace("\\", "\\\\").replace('"', '\"') + def to_oneliner(cmds): # process end-of-lines shell = "" @@ -79,3 +82,6 @@ def build(name : str, if fname != "": os.remove(fname) return "\n".join(ans) + +def download(name, src, dst): + runcmd("podman", "cp", f"{c.name}:{self.src}", self.dst) -- GitLab From 4b868c566b7585d3820200c36206cf1ea4bbef1a Mon Sep 17 00:00:00 2001 From: "David M. Rogers" Date: Thu, 25 Jan 2024 11:38:27 -0500 Subject: [PATCH 2/2] Fixed potential None return. --- contaminate/action.py | 1 + 1 file changed, 1 insertion(+) diff --git a/contaminate/action.py b/contaminate/action.py index 51b98cf..41a80c4 100644 --- a/contaminate/action.py +++ b/contaminate/action.py @@ -115,4 +115,5 @@ def sequence_rules(rules : dict[str, Action], *steps : str) -> Container: assert C is not None, f"Starting file '{result}' not present." C = C.run( rules[s], name = s ) C.store(result) + assert C is not None, "Empty rule set." return C -- GitLab