From bdc1c8de4c2fa7e5be11fd3df5e9a542c7aac965 Mon Sep 17 00:00:00 2001 From: badra001 Date: Tue, 10 Mar 2026 14:40:07 -0400 Subject: [PATCH] update report 2 --- .../assess_check_scheduling.py | 63 ++++++++++++++----- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/local-app/python-tools/cross-organization/assess_check_scheduling.py b/local-app/python-tools/cross-organization/assess_check_scheduling.py index 2968c5bb..e1858f65 100755 --- a/local-app/python-tools/cross-organization/assess_check_scheduling.py +++ b/local-app/python-tools/cross-organization/assess_check_scheduling.py @@ -2,61 +2,96 @@ import json, argparse, sys, os, glob from collections import Counter, defaultdict -__version__ = "1.0.0" +# --- VERSIONING --- +__version__ = "1.1.0" def find_latest_file(pattern): - files = glob.glob(pattern) + """Locates the most recent check_scheduling JSON file.""" + files = glob.glob("audit_results.check_scheduling.*.json") return max(files, key=os.path.getctime) if files else None def main(): - parser = argparse.ArgumentParser(description="PowerSchedule & FinOps Assessor") + parser = argparse.ArgumentParser(description="PowerSchedule & FinOps Assessor - v1.1.0") parser.add_argument("--input", help="JSON audit file") args = parser.parse_args() input_file = args.input or find_latest_file("audit_results.check_scheduling.*.json") - if not input_file: print("Error: No file found."); sys.exit(1) + if not input_file: + print("Error: No scheduling audit file found."); sys.exit(1) - with open(input_file, 'r') as f: data = json.load(f) + with open(input_file, 'r') as f: + data = json.load(f) + # Tracking structures # env -> schedule_value -> count - matrix = defaultdict(Counter) - total_resources = 0 + env_matrix = defaultdict(Counter) env_totals = Counter() + + # NEW: resource_type -> schedule_value -> count + type_matrix = defaultdict(Counter) + type_totals = Counter() + + total_resources = 0 for account in data: checks = account.get("data", {}) for key, val in checks.items(): - if key == "account_summary" or ":" not in key: continue + if key == "account_summary" or ":" not in key: + continue total_resources += 1 tags = val.get("tags", {}) + res_type = val.get("type", "unknown") # Normalize Environment key env = tags.get('Environment') or tags.get('environment') or "Undefined" schedule = tags.get('PowerSchedule', "No Schedule") - matrix[env][schedule] += 1 + # Aggregate by Environment + env_matrix[env][schedule] += 1 env_totals[env] += 1 + + # Aggregate by Resource Type (EC2 categories normalized to 'ec2') + display_type = "ec2" if res_type in ["plain", "asg_member", "eks_node"] else res_type + type_matrix[display_type][schedule] += 1 + type_totals[display_type] += 1 report_width = 120 print("-" * report_width) print(f"POWERSCHEDULE COMPLIANCE ASSESSMENT | Input: {os.path.basename(input_file)}") print("-" * report_width) - # Sort environments for consistent output - for env in sorted(matrix.keys()): + # REPORT 1: Breakdown by Environment + print(f"\nREPORT 1: BREAKDOWN BY ENVIRONMENT") + print("=" * 40) + for env in sorted(env_matrix.keys()): print(f"\nEnvironment: {env}") print(f" {'Schedule Value':<30} | {'Count':<10} | {'Percentage'}") print(f" {'-'*30} | {'-'*10} | {'-'*10}") - for sched, count in matrix[env].items(): + for sched, count in env_matrix[env].items(): pct = (count / env_totals[env]) * 100 print(f" {sched:<30} | {count:<10} | {pct:.1f}%") + # REPORT 2: Breakdown by Resource Type + print(f"\n\nREPORT 2: BREAKDOWN BY RESOURCE TYPE") + print("=" * 40) + for r_type in sorted(type_matrix.keys()): + print(f"\nResource Type: {r_type.upper()}") + print(f" {'Schedule Value':<30} | {'Count':<10} | {'Percentage'}") + print(f" {'-'*30} | {'-'*10} | {'-'*10}") + + for sched, count in type_matrix[r_type].items(): + pct = (count / type_totals[r_type]) * 100 + print(f" {sched:<30} | {count:<10} | {pct:.1f}%") + + # Organization Summary print("\n" + "=" * report_width) print(f"ORGANIZATION SUMMARY") print(f" Total Resources Scanned: {total_resources}") - print(f" Environments Found: {len(matrix)}") + print(f" Environments Found: {len(env_matrix)}") + print(f" Resource Types Found: {', '.join(sorted(type_matrix.keys())).upper()}") print("=" * report_width) -if __name__ == "__main__": main() +if __name__ == "__main__": + main()