from __future__ import annotations import argparse import importlib import os import sys from pathlib import Path from .context import KnoeContext def _project_root() -> Path: # /knoe/ops/cli.py -> parents: ops, knoe, root return Path(__file__).resolve().parents[2] def main(argv: list[str] | None = None) -> int: p = argparse.ArgumentParser(prog="knoe-ops", add_help=True) p.add_argument("component", help="component name (e.g. common_core, openbao)") p.add_argument( "action", help="action to run (initialize, start, update, restart, stop, status)", ) p.add_argument("--mode", default=os.environ.get("PROLE_MODE", "dev")) p.add_argument("--namespace", default=os.environ.get("PROLE_NAMESPACE", "default")) p.add_argument( "--service-namespace", default=os.environ.get("PROLE_SERVICE_NAMESPACE", "default"), ) p.add_argument("--config", dest="config", default=os.environ.get("PROLE_CFG")) args = p.parse_args(argv) cfg_path = Path(args.config).expanduser().resolve() if args.config else None ctx = KnoeContext( project_root=_project_root(), cfg_path=cfg_path, mode=args.mode, namespace=args.namespace, service_namespace=args.service_namespace, env=dict(os.environ), logger=lambda m: print(m), err_logger=lambda m: print(m, file=sys.stderr), ) mod = importlib.import_module(f"knoe.ops.components.{args.component}") fn = getattr(mod, args.action) rc = fn(ctx) return 0 if rc is None else int(rc) if __name__ == "__main__": # pragma: no cover raise SystemExit(main())