diff --git a/cove_api_test.py b/cove_api_test.py index 62bddfa..3a564a1 100644 --- a/cove_api_test.py +++ b/cove_api_test.py @@ -174,7 +174,7 @@ def print_header(title: str) -> None: print("=" * 70) -def run(url: str, username: str, password: str, records: int) -> None: +def run(url: str, username: str, password: str, records: int, debug: bool = False) -> None: print_header("Cove Data Protection API – Test") print(f" URL: {url}") print(f" Username: {username}") @@ -193,6 +193,10 @@ def run(url: str, username: str, password: str, records: int) -> None: data = enumerate_statistics(url, visa, partner_id, COLUMNS, records) + if debug: + print(f"\n RAW response (first 2000 chars):") + print(json.dumps(data, indent=2)[:2000]) + if "error" in data: err = data["error"] print(f" ❌ FAILED – error {err.get('code')}: {err.get('message')}") @@ -201,11 +205,21 @@ def run(url: str, username: str, password: str, records: int) -> None: result = data.get("result") if result is None: - print(" ⚠️ result is null (no accounts?)") + print(" ⚠️ result is null – raw response:") + print(json.dumps(data, indent=2)[:1000]) sys.exit(0) - # Result can be a list directly or wrapped - accounts = result if isinstance(result, list) else result.get("Accounts", []) + if debug: + print(f"\n result type: {type(result).__name__}") + if isinstance(result, dict): + print(f" result keys: {list(result.keys())}") + + # Unwrap possible nested result + if isinstance(result, dict) and "result" in result: + result = result["result"] + + # Result can be a list directly or wrapped in Accounts key + accounts = result if isinstance(result, list) else result.get("Accounts", []) if isinstance(result, dict) else [] total = len(accounts) print(f" ✅ SUCCESS – {total} account(s) returned") @@ -213,29 +227,31 @@ def run(url: str, username: str, password: str, records: int) -> None: print_header(f"Step 3: Account Details ({total} total)") for i, acc in enumerate(accounts): - device_name = acc.get("I1", "(no name)") - computer = acc.get("I18") or "(M365 tenant)" - customer = acc.get("I8", "") - active_ds = acc.get("I78", "") + # Settings is a list of single-key dicts: [{"D09F00": "5"}, {"I1": "name"}, ...] + # Flatten to a single dict for easy lookup. + s: dict = {} + for item in acc.get("Settings", []): + s.update(item) - print(f"\n [{i+1}/{total}] {device_name}") + account_id = acc.get("AccountId", "?") + device_name = s.get("I1", "(no name)") + computer = s.get("I18") or "(M365 tenant)" + customer = s.get("I8", "") + active_ds = s.get("I78", "") + + print(f"\n [{i+1}/{total}] {device_name} (AccountId: {account_id})") print(f" Computer : {computer}") print(f" Customer : {customer}") print(f" Datasrc : {active_ds}") # Total (D09) - d9_status = acc.get("D09F00") - d9_last_ok = acc.get("D09F09") - d9_last = acc.get("D09F15") - d9_bar = acc.get("D09F08") - print(f" Total:") - print(f" Status : {fmt_status(d9_status)}") - print(f" Last session: {fmt_ts(d9_last)}") - print(f" Last success: {fmt_ts(d9_last_ok)}") - print(f" 28-day bar : {fmt_colorbar(d9_bar)}") + print(f" Status : {fmt_status(s.get('D09F00'))}") + print(f" Last session: {fmt_ts(s.get('D09F15'))}") + print(f" Last success: {fmt_ts(s.get('D09F09'))}") + print(f" 28-day bar : {fmt_colorbar(s.get('D09F08'))}") - # Per-datasource (only if active) + # Per-datasource (only if present in response) ds_pairs = [ ("D1", "D1F00", "D1F15"), ("D10", "D10F00", "D10F15"), @@ -246,8 +262,8 @@ def run(url: str, username: str, password: str, records: int) -> None: ("D23", "D23F00", "D23F15"), ] for ds_code, f00_col, f15_col in ds_pairs: - f00 = acc.get(f00_col) - f15 = acc.get(f15_col) + f00 = s.get(f00_col) + f15 = s.get(f15_col) if f00 is None and f15 is None: continue label = DATASOURCE_LABELS.get(ds_code, ds_code) @@ -259,8 +275,11 @@ def run(url: str, username: str, password: str, records: int) -> None: print_header("Summary") status_counts: dict[str, int] = {} for acc in accounts: - s = acc.get("D09F00") - bc = STATUS_MAP.get(int(s), "Unknown") if s is not None else "No data" + flat: dict = {} + for item in acc.get("Settings", []): + flat.update(item) + raw = flat.get("D09F00") + bc = STATUS_MAP.get(int(raw), "Unknown") if raw is not None else "No data" status_counts[bc] = status_counts.get(bc, 0) + 1 for status, count in sorted(status_counts.items()): @@ -276,6 +295,7 @@ def main() -> None: parser.add_argument("--username", default=os.environ.get("COVE_USERNAME", "")) parser.add_argument("--password", default=os.environ.get("COVE_PASSWORD", "")) parser.add_argument("--records", type=int, default=50, help="Max accounts to fetch") + parser.add_argument("--debug", action="store_true", help="Print raw API responses") args = parser.parse_args() if not args.username or not args.password: @@ -283,7 +303,7 @@ def main() -> None: print("Or set COVE_USERNAME and COVE_PASSWORD environment variables.") sys.exit(1) - run(args.url, args.username, args.password, args.records) + run(args.url, args.username, args.password, args.records, args.debug) if __name__ == "__main__":