diff --git a/src/statd/python/yanger/__main__.py b/src/statd/python/yanger/__main__.py index 28c3dc20..e5bfec27 100644 --- a/src/statd/python/yanger/__main__.py +++ b/src/statd/python/yanger/__main__.py @@ -10,13 +10,30 @@ from . import common from . import host def main(): + def dirpath(path): + if not os.path.isdir(path): + raise argparse.ArgumentTypeError(f"'{path}' is not a valid directory") + return path + parser = argparse.ArgumentParser(description="YANG data creator") parser.add_argument("model", help="YANG Model") - parser.add_argument("-p", "--param", default=None, help="Model dependent parameter") - parser.add_argument("-w", "--wrap-commands", default=None, help="Command execution wrapper") - parser.add_argument("-t", "--test", default=None, help="Test data base path") - args = parser.parse_args() + parser.add_argument("-p", "--param", + help="Model dependent parameter, e.g. interface name") + parser.add_argument("-x", "--cmd-prefix", metavar="PREFIX", + help="Use this prefix for all system commands, e.g. " + + "'ssh user@remotehost sudo'") + rrparser = parser.add_mutually_exclusive_group() + rrparser.add_argument("-r", "--replay", type=dirpath, metavar="DIR", + help="Generate output based on recorded system commands from DIR, " + + "rather than querying the local system") + rrparser.add_argument("-c", "--capture", type=dirpath, metavar="DIR", + help="Capture system command output in DIR, such that the current system " + + "state can be recreated offline (with --replay) for testing purposes") + + args = parser.parse_args() + if args.replay and args.cmd_prefix: + parser.error("--cmd-prefix cannot be used with --replay") # Set up syslog output for critical errors to aid debugging common.LOG = logging.getLogger('yanger') @@ -31,10 +48,10 @@ def main(): common.LOG.setLevel(logging.INFO) common.LOG.addHandler(log) - if args.wrap_commands: - host.HOST = host.Remotehost(args.wrap_commands, args.test) - elif args.test: - host.HOST = host.Testhost(args.test) + if args.cmd_prefix or args.capture: + host.HOST = host.Remotehost(args.cmd_prefix, args.capture) + elif args.replay: + host.HOST = host.Replayhost(args.replay) else: host.HOST = host.Localhost() diff --git a/src/statd/python/yanger/host.py b/src/statd/python/yanger/host.py index 0e31771b..cb3f572f 100644 --- a/src/statd/python/yanger/host.py +++ b/src/statd/python/yanger/host.py @@ -105,18 +105,18 @@ class Localhost(Host): class Remotehost(Localhost): - def __init__(self, wrap, basedir): + def __init__(self, prefix, capdir): super().__init__() - self.wrap = tuple(wrap.split()) - self.basedir = basedir - if basedir: + self.prefix = tuple(prefix.split()) if prefix else tuple() + self.capdir = capdir + if capdir: for subdir in ("rootfs", "run"): - os.makedirs(os.path.join(basedir, subdir), exist_ok=True) + os.makedirs(os.path.join(capdir, subdir), exist_ok=True) def now(self): timestamp = self._run(["date", "-u", "+%s"], default=None, log=True) - if self.basedir: - with open(os.path.join(self.basedir, "timestamp"), "w") as f: + if self.capdir: + with open(os.path.join(self.capdir, "timestamp"), "w") as f: f.write(f"{timestamp}\n") pass @@ -128,13 +128,13 @@ class Remotehost(Localhost): # arguments containing spaces so that commands like `vtysh -c # "show ip route json"` work as expected. cmd = " ".join([ arg if " " not in arg else f"\"{arg}\"" for arg in cmd ]) - return super().run(self.wrap + (cmd,), default, log) + return super().run(self.prefix + (cmd,), default, log) def run(self, cmd, default=None, log=True): - if not self.basedir: + if not self.capdir: return self._run(cmd, default, log) - storedpath = os.path.join(self.basedir, "run", Testhost.SlugOf(cmd)) + storedpath = os.path.join(self.capdir, "run", Replayhost.SlugOf(cmd)) if os.path.exists(storedpath): with open(storedpath) as f: return f.read() @@ -148,29 +148,29 @@ class Remotehost(Localhost): def read(self, path): out = self._run(("cat", path), default="", log=False) - if self.basedir: - dirname = os.path.join(self.basedir, "rootfs", os.path.dirname(path[1:])) + if self.capdir: + dirname = os.path.join(self.capdir, "rootfs", os.path.dirname(path[1:])) os.makedirs(dirname, exist_ok=True) - with open(os.path.join(self.basedir, "rootfs", path[1:]), "w") as f: + with open(os.path.join(self.capdir, "rootfs", path[1:]), "w") as f: f.write(out) return out -class Testhost(Host): +class Replayhost(Host): def SlugOf(cmd): return "_".join(cmd).replace("/", "+").replace(" ", "-") - def __init__(self, basedir): - self.basedir = basedir + def __init__(self, replaydir): + self.replaydir = replaydir def now(self): - with open(os.path.join(self.basedir, "timestamp")) as f: + with open(os.path.join(self.replaydir, "timestamp")) as f: timestamp = f.read().strip() return datetime.datetime.fromtimestamp(int(timestamp), datetime.timezone.utc) def run(self, cmd, default=None, log=True): - path = os.path.join(self.basedir, "run", Testhost.SlugOf(cmd)) + path = os.path.join(self.replaydir, "run", Replayhost.SlugOf(cmd)) try: with open(path, 'r') as f: @@ -184,7 +184,7 @@ class Testhost(Host): raise def read(self, path): - path = os.path.join(self.basedir, "rootfs", path[1:]) + path = os.path.join(self.replaydir, "rootfs", path[1:]) try: with open(path, 'r') as f: return f.read() diff --git a/test/case/statd/test.sh b/test/case/statd/test.sh index dd15ca43..941981fc 100644 --- a/test/case/statd/test.sh +++ b/test/case/statd/test.sh @@ -87,13 +87,10 @@ prepare_infamy_test() yanger_exec() { local opts= - while getopts "w:t:" opt; do + while getopts "c:r:x:" opt; do case ${opt} in - w) - opts="$opts -w \"$OPTARG\"" - ;; - t) - opts="$opts -t \"$OPTARG\"" + c|r|x) + opts="$opts -$opt \"$OPTARG\"" ;; esac done @@ -122,8 +119,8 @@ yanger_gen() while [ $# -gt 0 ]; do echo ">>> CAPTURING $1 from $gen_iface" >&2 yanger_exec \ - -t "$casedir/system" \ - -w "$wrapper" \ + -c "$casedir/system" \ + -x "$wrapper" \ $1 \ >"$casedir/$1.json" operfiles="$operfiles $casedir/$1.json" @@ -148,7 +145,7 @@ yanger_check() status="ok" if ! diff -up \ "$casedir/$1.json" \ - <(yanger_exec -t "$casedir/system" $1) \ + <(yanger_exec -r "$casedir/system" $1) \ >"$diff"; then cat $diff | sed 's/^/# /' status="not ok" @@ -168,7 +165,7 @@ yanger_cat() fi while [ $# -gt 0 ]; do - yanger_exec -t "$casedir/system" $1 + yanger_exec -r "$casedir/system" $1 shift done } @@ -180,7 +177,7 @@ yanger_live() fi while [ $# -gt 0 ]; do - yanger_exec -w "$wrapper" $1 + yanger_exec -x "$wrapper" $1 shift done }