| .. | .. |
|---|
| 39 | 39 | data = json.loads(result["output"]) |
|---|
| 40 | 40 | return {"success": True, "data": data, "error": ""} |
|---|
| 41 | 41 | except json.JSONDecodeError as exc: |
|---|
| 42 | + raw = result["output"][:500] |
|---|
| 42 | 43 | return { |
|---|
| 43 | 44 | "success": False, |
|---|
| 44 | 45 | "data": None, |
|---|
| 45 | | - "error": f"Failed to parse JSON: {exc}\nRaw: {result['output'][:500]}", |
|---|
| 46 | + "error": f"Failed to parse JSON: {exc}\nRaw: {raw}", |
|---|
| 46 | 47 | } |
|---|
| 47 | 48 | |
|---|
| 48 | 49 | |
|---|
| .. | .. |
|---|
| 72 | 73 | return await _run_exec(_NSENTER_PREFIX + [OPS_CLI] + args, timeout=timeout) |
|---|
| 73 | 74 | |
|---|
| 74 | 75 | |
|---|
| 76 | +async def run_ops_host_json(args: list[str], timeout: int = _DEFAULT_TIMEOUT) -> dict: |
|---|
| 77 | + """Run the ops CLI on the host via nsenter with --json and return parsed JSON.""" |
|---|
| 78 | + result = await run_ops_host(args + ["--json"], timeout=timeout) |
|---|
| 79 | + if not result["success"]: |
|---|
| 80 | + return {"success": False, "data": None, "error": result["error"] or result["output"]} |
|---|
| 81 | + try: |
|---|
| 82 | + data = json.loads(result["output"]) |
|---|
| 83 | + return {"success": True, "data": data, "error": ""} |
|---|
| 84 | + except json.JSONDecodeError as exc: |
|---|
| 85 | + raw = result["output"][:500] |
|---|
| 86 | + return { |
|---|
| 87 | + "success": False, |
|---|
| 88 | + "data": None, |
|---|
| 89 | + "error": f"Failed to parse JSON: {exc}\nRaw: {raw}", |
|---|
| 90 | + } |
|---|
| 91 | + |
|---|
| 92 | + |
|---|
| 75 | 93 | async def stream_ops_host(args: list[str], timeout: int = _DEFAULT_TIMEOUT) -> AsyncGenerator[str, None]: |
|---|
| 76 | 94 | """Stream ops CLI output from the host via nsenter.""" |
|---|
| 77 | 95 | async for line in _stream_exec(_NSENTER_PREFIX + [OPS_CLI] + args, timeout=timeout): |
|---|
| 78 | 96 | yield line |
|---|
| 79 | 97 | |
|---|
| 80 | 98 | |
|---|
| 99 | +async def run_command_host(args: list[str], timeout: int = _DEFAULT_TIMEOUT) -> dict: |
|---|
| 100 | + """Run an arbitrary command on the host via nsenter.""" |
|---|
| 101 | + return await _run_exec(_NSENTER_PREFIX + args, timeout=timeout) |
|---|
| 102 | + |
|---|
| 103 | + |
|---|
| 104 | +async def stream_command_host(args: list[str], timeout: int = _DEFAULT_TIMEOUT) -> AsyncGenerator[str, None]: |
|---|
| 105 | + """Stream arbitrary command output from the host via nsenter.""" |
|---|
| 106 | + async for line in _stream_exec(_NSENTER_PREFIX + args, timeout=timeout): |
|---|
| 107 | + yield line |
|---|
| 108 | + |
|---|
| 109 | + |
|---|
| 81 | 110 | # --------------------------------------------------------------------------- |
|---|
| 82 | 111 | # Internal helpers |
|---|
| 83 | 112 | # --------------------------------------------------------------------------- |
|---|