Fix Cove test script: parse Settings array format from API response

API returns Settings as list of single-key dicts, not a flat dict.
Also fixes AccountId display and status summary parsing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ivo Oskamp 2026-02-23 09:58:19 +01:00
parent a30d51bed0
commit dde2ccbb5d

View File

@ -174,7 +174,7 @@ def print_header(title: str) -> None:
print("=" * 70) 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_header("Cove Data Protection API Test")
print(f" URL: {url}") print(f" URL: {url}")
print(f" Username: {username}") 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) 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: if "error" in data:
err = data["error"] err = data["error"]
print(f" ❌ FAILED error {err.get('code')}: {err.get('message')}") 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") result = data.get("result")
if result is None: 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) sys.exit(0)
# Result can be a list directly or wrapped if debug:
accounts = result if isinstance(result, list) else result.get("Accounts", []) 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) total = len(accounts)
print(f" ✅ SUCCESS {total} account(s) returned") 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)") print_header(f"Step 3: Account Details ({total} total)")
for i, acc in enumerate(accounts): for i, acc in enumerate(accounts):
device_name = acc.get("I1", "(no name)") # Settings is a list of single-key dicts: [{"D09F00": "5"}, {"I1": "name"}, ...]
computer = acc.get("I18") or "(M365 tenant)" # Flatten to a single dict for easy lookup.
customer = acc.get("I8", "") s: dict = {}
active_ds = acc.get("I78", "") 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" Computer : {computer}")
print(f" Customer : {customer}") print(f" Customer : {customer}")
print(f" Datasrc : {active_ds}") print(f" Datasrc : {active_ds}")
# Total (D09) # 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" Total:")
print(f" Status : {fmt_status(d9_status)}") print(f" Status : {fmt_status(s.get('D09F00'))}")
print(f" Last session: {fmt_ts(d9_last)}") print(f" Last session: {fmt_ts(s.get('D09F15'))}")
print(f" Last success: {fmt_ts(d9_last_ok)}") print(f" Last success: {fmt_ts(s.get('D09F09'))}")
print(f" 28-day bar : {fmt_colorbar(d9_bar)}") print(f" 28-day bar : {fmt_colorbar(s.get('D09F08'))}")
# Per-datasource (only if active) # Per-datasource (only if present in response)
ds_pairs = [ ds_pairs = [
("D1", "D1F00", "D1F15"), ("D1", "D1F00", "D1F15"),
("D10", "D10F00", "D10F15"), ("D10", "D10F00", "D10F15"),
@ -246,8 +262,8 @@ def run(url: str, username: str, password: str, records: int) -> None:
("D23", "D23F00", "D23F15"), ("D23", "D23F00", "D23F15"),
] ]
for ds_code, f00_col, f15_col in ds_pairs: for ds_code, f00_col, f15_col in ds_pairs:
f00 = acc.get(f00_col) f00 = s.get(f00_col)
f15 = acc.get(f15_col) f15 = s.get(f15_col)
if f00 is None and f15 is None: if f00 is None and f15 is None:
continue continue
label = DATASOURCE_LABELS.get(ds_code, ds_code) 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") print_header("Summary")
status_counts: dict[str, int] = {} status_counts: dict[str, int] = {}
for acc in accounts: for acc in accounts:
s = acc.get("D09F00") flat: dict = {}
bc = STATUS_MAP.get(int(s), "Unknown") if s is not None else "No data" 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 status_counts[bc] = status_counts.get(bc, 0) + 1
for status, count in sorted(status_counts.items()): 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("--username", default=os.environ.get("COVE_USERNAME", ""))
parser.add_argument("--password", default=os.environ.get("COVE_PASSWORD", "")) 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("--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() args = parser.parse_args()
if not args.username or not args.password: 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.") print("Or set COVE_USERNAME and COVE_PASSWORD environment variables.")
sys.exit(1) 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__": if __name__ == "__main__":