-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add RemoteBin abstract class * Use abstract class * Remove bootstrap whitelist from Node config files * Add abstract stop method --------- Co-authored-by: sydhds <[email protected]>
- Loading branch information
Showing
2 changed files
with
132 additions
and
16 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
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,119 @@ | ||
import sys | ||
from contextlib import contextmanager | ||
from pathlib import Path | ||
from dataclasses import dataclass | ||
from abc import ABC, abstractmethod | ||
|
||
from typing import Optional, Dict, List | ||
|
||
from .server import Server | ||
from .compile import CompileUnit, CompileOpts | ||
from .remote import RemotePath, copy_file | ||
|
||
|
||
@dataclass | ||
class SrcDst: | ||
"""Source and Destination paths (usually for copy)""" | ||
src: Path | ||
dst: Path | ||
|
||
|
||
class RemoteBin(ABC): | ||
|
||
@abstractmethod | ||
def __init__(self, server: Server, compile_unit: CompileUnit): | ||
# Dummy code | ||
self.server = server | ||
self.compile_unit = compile_unit | ||
self.start_cmd = [""] | ||
self.install_folder = self.install({}) | ||
|
||
def install(self, to_install: Dict[str, Path | SrcDst], tmp_prefix: str = "remote_bin_") -> Path | RemotePath: | ||
|
||
""" | ||
Install files from compile unit to a server install folder (tmp folder) | ||
Args: | ||
to_install: a dict of key (filename), path (relative path in install folder) | ||
tmp_prefix: prefix for install folder (created as a tmp folder) | ||
""" | ||
|
||
tmp_folder = self.server.mkdtemp(prefix=tmp_prefix) | ||
# self.server.mkdir(tmp_folder) | ||
repo = self.compile_unit.repo | ||
|
||
for _filename, to_install_item in to_install.items(): | ||
if isinstance(to_install_item, SrcDst): | ||
src = repo / to_install_item.src | ||
dst = tmp_folder / to_install_item.dst | ||
else: | ||
src = repo / to_install_item | ||
dst = tmp_folder / to_install_item | ||
|
||
# print("server mkdir:", dst.parent) | ||
self.server.mkdir(dst.parent) | ||
# print(f"copy_file {src} -> {dst}") | ||
copy_file(src, dst) | ||
|
||
return tmp_folder | ||
|
||
@classmethod | ||
def from_compile_unit(cls, server: Server, compile_unit: CompileUnit) -> "RemoteBin": | ||
node = cls(server, compile_unit) | ||
return node | ||
|
||
@classmethod | ||
def from_dev( | ||
cls, server: Server, repo: Path, build_opts: Optional[List[str]] = None | ||
) -> "RemoteBin": | ||
compile_opts = CompileOpts() | ||
compile_opts.already_compiled = repo | ||
if build_opts: | ||
compile_opts.build_opts = build_opts | ||
cu = CompileUnit(server, compile_opts) | ||
node = cls(server, cu) | ||
return node | ||
|
||
@contextmanager | ||
def start( | ||
self, | ||
env: Optional[Dict[str, str]] = None, | ||
args: Optional[List[str]] = None, | ||
stdout=sys.stdout, | ||
stderr=sys.stderr, | ||
): | ||
cmd = " ".join(self.start_cmd) | ||
if args: | ||
args_joined = " ".join(args) | ||
if args_joined: | ||
cmd += " " | ||
cmd += args_joined | ||
|
||
print(f"{cmd=}") | ||
process = self.server.run( | ||
[cmd], | ||
cwd=str(self.install_folder), | ||
env=env, | ||
stdout=stdout, | ||
stderr=stderr, | ||
) | ||
with process as p: | ||
try: | ||
yield p | ||
except Exception: | ||
# Note: Need to catch every exception here as we need to stop subprocess.Popen | ||
# otherwise it will wait forever | ||
# so first print traceback then stop the process | ||
import traceback | ||
|
||
print(traceback.format_exc()) | ||
self.stop(p) | ||
# Re Raise exception so test will be marked as failed | ||
raise | ||
else: | ||
# Note: normal end | ||
self.stop(p) | ||
|
||
@abstractmethod | ||
def stop(self, process): | ||
pass |