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:
parent
a30d51bed0
commit
dde2ccbb5d
@ -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__":
|
||||
|
||||
Loading…
Reference in New Issue
Block a user