Loading contaminate/__init__.py +9 −1 Original line number Diff line number Diff line 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 ) contaminate/action.py +35 −16 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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[ Loading Loading @@ -90,11 +96,24 @@ 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) assert C is not None, "Empty rule set." return C contaminate/podman.py +6 −0 Original line number Diff line number Diff line Loading @@ -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 = "" Loading Loading @@ -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) Loading
contaminate/__init__.py +9 −1 Original line number Diff line number Diff line 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 )
contaminate/action.py +35 −16 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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[ Loading Loading @@ -90,11 +96,24 @@ 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) assert C is not None, "Empty rule set." return C
contaminate/podman.py +6 −0 Original line number Diff line number Diff line Loading @@ -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 = "" Loading Loading @@ -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)