diff options
Diffstat (limited to 'mdbp/ssh.py')
-rw-r--r-- | mdbp/ssh.py | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/mdbp/ssh.py b/mdbp/ssh.py new file mode 100644 index 0000000..8af6bde --- /dev/null +++ b/mdbp/ssh.py @@ -0,0 +1,73 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: MIT +"""mdbp backend wrapper via ssh""" + +import argparse +import io +import json +import pathlib +import subprocess +import sys +import tarfile +import typing + +from .common import JsonObject, buildjson, get_dsc_files, tar_add + +def produce_request_tar(buildjsonobj: JsonObject, + fileobj: typing.IO[bytes]) -> None: + """Write a tar file suitable for mdbp-streamapi into the given `fileobj` + based on the given `buildjsonobj`. + * An .output.directory is discarded. + * A referenced .dsc file and its components is included. + """ + sendjsonobj = buildjsonobj.copy() + sendjsonobj["output"] = sendjsonobj["output"].copy() + del sendjsonobj["output"]["directory"] + dscpath: typing.Optional[pathlib.Path] + try: + dscpath = pathlib.Path(buildjsonobj["input"]["dscpath"]) + except KeyError: + dscpath = None + else: + sendjsonobj["input"] = sendjsonobj["input"].copy() + sendjsonobj["input"]["dscpath"] = dscpath.name + tar = tarfile.open(mode="w|", fileobj=fileobj) + info = tarfile.TarInfo("build.json") + sendjsonfile = io.BytesIO() + for chunk in json.JSONEncoder().iterencode(sendjsonobj): + sendjsonfile.write(chunk.encode("utf8")) + info.size = sendjsonfile.tell() + sendjsonfile.seek(0) + tar.addfile(info, sendjsonfile) + if dscpath: + for path in [dscpath] + get_dsc_files(dscpath): + tar_add(tar, path) + +def main() -> None: + """Entry point for mdbp-ssh backend""" + parser = argparse.ArgumentParser() + parser.add_argument("host", type=str) + parser.add_argument("command", nargs=argparse.REMAINDER) + args = parser.parse_args() + if len(args.command) < 2: + parser.error("missing command or json file") + build = buildjson(args.command.pop()) + + cmd = ["ssh", args.host, "mdbp-streamapi", *args.command] + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=sys.stdout + if build["output"].get("log", True) + else subprocess.DEVNULL) + assert proc.stdin is not None + produce_request_tar(build, proc.stdin) + proc.stdin.close() + with tarfile.open(fileobj=proc.stdout, mode="r|") as outtar: + for member in outtar: + if "/" in member.name or not member.isfile(): + raise ValueError("expected flat tar as output") + outtar.extract(member, build["output"]["directory"], + set_attrs=False) + sys.exit(proc.wait()) + +if __name__ == "__main__": + main() |