runbooks 1.1.3__py3-none-any.whl → 1.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. runbooks/__init__.py +31 -2
  2. runbooks/__init___optimized.py +18 -4
  3. runbooks/_platform/__init__.py +1 -5
  4. runbooks/_platform/core/runbooks_wrapper.py +141 -138
  5. runbooks/aws2/accuracy_validator.py +812 -0
  6. runbooks/base.py +7 -0
  7. runbooks/cfat/WEIGHT_CONFIG_README.md +1 -1
  8. runbooks/cfat/assessment/compliance.py +8 -8
  9. runbooks/cfat/assessment/runner.py +1 -0
  10. runbooks/cfat/cloud_foundations_assessment.py +227 -239
  11. runbooks/cfat/models.py +6 -2
  12. runbooks/cfat/tests/__init__.py +6 -1
  13. runbooks/cli/__init__.py +13 -0
  14. runbooks/cli/commands/cfat.py +274 -0
  15. runbooks/cli/commands/finops.py +1164 -0
  16. runbooks/cli/commands/inventory.py +379 -0
  17. runbooks/cli/commands/operate.py +239 -0
  18. runbooks/cli/commands/security.py +248 -0
  19. runbooks/cli/commands/validation.py +825 -0
  20. runbooks/cli/commands/vpc.py +310 -0
  21. runbooks/cli/registry.py +107 -0
  22. runbooks/cloudops/__init__.py +23 -30
  23. runbooks/cloudops/base.py +96 -107
  24. runbooks/cloudops/cost_optimizer.py +549 -547
  25. runbooks/cloudops/infrastructure_optimizer.py +5 -4
  26. runbooks/cloudops/interfaces.py +226 -227
  27. runbooks/cloudops/lifecycle_manager.py +5 -4
  28. runbooks/cloudops/mcp_cost_validation.py +252 -235
  29. runbooks/cloudops/models.py +78 -53
  30. runbooks/cloudops/monitoring_automation.py +5 -4
  31. runbooks/cloudops/notebook_framework.py +179 -215
  32. runbooks/cloudops/security_enforcer.py +125 -159
  33. runbooks/common/accuracy_validator.py +11 -0
  34. runbooks/common/aws_pricing.py +349 -326
  35. runbooks/common/aws_pricing_api.py +211 -212
  36. runbooks/common/aws_profile_manager.py +341 -0
  37. runbooks/common/aws_utils.py +75 -80
  38. runbooks/common/business_logic.py +127 -105
  39. runbooks/common/cli_decorators.py +36 -60
  40. runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
  41. runbooks/common/cross_account_manager.py +198 -205
  42. runbooks/common/date_utils.py +27 -39
  43. runbooks/common/decorators.py +235 -0
  44. runbooks/common/dry_run_examples.py +173 -208
  45. runbooks/common/dry_run_framework.py +157 -155
  46. runbooks/common/enhanced_exception_handler.py +15 -4
  47. runbooks/common/enhanced_logging_example.py +50 -64
  48. runbooks/common/enhanced_logging_integration_example.py +65 -37
  49. runbooks/common/env_utils.py +16 -16
  50. runbooks/common/error_handling.py +40 -38
  51. runbooks/common/lazy_loader.py +41 -23
  52. runbooks/common/logging_integration_helper.py +79 -86
  53. runbooks/common/mcp_cost_explorer_integration.py +478 -495
  54. runbooks/common/mcp_integration.py +63 -74
  55. runbooks/common/memory_optimization.py +140 -118
  56. runbooks/common/module_cli_base.py +37 -58
  57. runbooks/common/organizations_client.py +176 -194
  58. runbooks/common/patterns.py +204 -0
  59. runbooks/common/performance_monitoring.py +67 -71
  60. runbooks/common/performance_optimization_engine.py +283 -274
  61. runbooks/common/profile_utils.py +248 -39
  62. runbooks/common/rich_utils.py +643 -92
  63. runbooks/common/sre_performance_suite.py +177 -186
  64. runbooks/enterprise/__init__.py +1 -1
  65. runbooks/enterprise/logging.py +144 -106
  66. runbooks/enterprise/security.py +187 -204
  67. runbooks/enterprise/validation.py +43 -56
  68. runbooks/finops/__init__.py +29 -33
  69. runbooks/finops/account_resolver.py +1 -1
  70. runbooks/finops/advanced_optimization_engine.py +980 -0
  71. runbooks/finops/automation_core.py +268 -231
  72. runbooks/finops/business_case_config.py +184 -179
  73. runbooks/finops/cli.py +660 -139
  74. runbooks/finops/commvault_ec2_analysis.py +157 -164
  75. runbooks/finops/compute_cost_optimizer.py +336 -320
  76. runbooks/finops/config.py +20 -20
  77. runbooks/finops/cost_optimizer.py +488 -622
  78. runbooks/finops/cost_processor.py +332 -214
  79. runbooks/finops/dashboard_runner.py +1006 -172
  80. runbooks/finops/ebs_cost_optimizer.py +991 -657
  81. runbooks/finops/elastic_ip_optimizer.py +317 -257
  82. runbooks/finops/enhanced_mcp_integration.py +340 -0
  83. runbooks/finops/enhanced_progress.py +40 -37
  84. runbooks/finops/enhanced_trend_visualization.py +3 -2
  85. runbooks/finops/enterprise_wrappers.py +230 -292
  86. runbooks/finops/executive_export.py +203 -160
  87. runbooks/finops/helpers.py +130 -288
  88. runbooks/finops/iam_guidance.py +1 -1
  89. runbooks/finops/infrastructure/__init__.py +80 -0
  90. runbooks/finops/infrastructure/commands.py +506 -0
  91. runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
  92. runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
  93. runbooks/finops/markdown_exporter.py +338 -175
  94. runbooks/finops/mcp_validator.py +1952 -0
  95. runbooks/finops/nat_gateway_optimizer.py +1513 -482
  96. runbooks/finops/network_cost_optimizer.py +657 -587
  97. runbooks/finops/notebook_utils.py +226 -188
  98. runbooks/finops/optimization_engine.py +1136 -0
  99. runbooks/finops/optimizer.py +25 -29
  100. runbooks/finops/rds_snapshot_optimizer.py +367 -411
  101. runbooks/finops/reservation_optimizer.py +427 -363
  102. runbooks/finops/scenario_cli_integration.py +77 -78
  103. runbooks/finops/scenarios.py +1278 -439
  104. runbooks/finops/schemas.py +218 -182
  105. runbooks/finops/snapshot_manager.py +2289 -0
  106. runbooks/finops/tests/test_finops_dashboard.py +3 -3
  107. runbooks/finops/tests/test_reference_images_validation.py +2 -2
  108. runbooks/finops/tests/test_single_account_features.py +17 -17
  109. runbooks/finops/tests/validate_test_suite.py +1 -1
  110. runbooks/finops/types.py +3 -3
  111. runbooks/finops/validation_framework.py +263 -269
  112. runbooks/finops/vpc_cleanup_exporter.py +191 -146
  113. runbooks/finops/vpc_cleanup_optimizer.py +593 -575
  114. runbooks/finops/workspaces_analyzer.py +171 -182
  115. runbooks/hitl/enhanced_workflow_engine.py +1 -1
  116. runbooks/integration/__init__.py +89 -0
  117. runbooks/integration/mcp_integration.py +1920 -0
  118. runbooks/inventory/CLAUDE.md +816 -0
  119. runbooks/inventory/README.md +3 -3
  120. runbooks/inventory/Tests/common_test_data.py +30 -30
  121. runbooks/inventory/__init__.py +2 -2
  122. runbooks/inventory/cloud_foundations_integration.py +144 -149
  123. runbooks/inventory/collectors/aws_comprehensive.py +28 -11
  124. runbooks/inventory/collectors/aws_networking.py +111 -101
  125. runbooks/inventory/collectors/base.py +4 -0
  126. runbooks/inventory/core/collector.py +495 -313
  127. runbooks/inventory/discovery.md +2 -2
  128. runbooks/inventory/drift_detection_cli.py +69 -96
  129. runbooks/inventory/find_ec2_security_groups.py +1 -1
  130. runbooks/inventory/inventory_mcp_cli.py +48 -46
  131. runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
  132. runbooks/inventory/mcp_inventory_validator.py +549 -465
  133. runbooks/inventory/mcp_vpc_validator.py +359 -442
  134. runbooks/inventory/organizations_discovery.py +56 -52
  135. runbooks/inventory/rich_inventory_display.py +33 -32
  136. runbooks/inventory/unified_validation_engine.py +278 -251
  137. runbooks/inventory/vpc_analyzer.py +733 -696
  138. runbooks/inventory/vpc_architecture_validator.py +293 -348
  139. runbooks/inventory/vpc_dependency_analyzer.py +382 -378
  140. runbooks/inventory/vpc_flow_analyzer.py +3 -3
  141. runbooks/main.py +152 -9147
  142. runbooks/main_final.py +91 -60
  143. runbooks/main_minimal.py +22 -10
  144. runbooks/main_optimized.py +131 -100
  145. runbooks/main_ultra_minimal.py +7 -2
  146. runbooks/mcp/__init__.py +36 -0
  147. runbooks/mcp/integration.py +679 -0
  148. runbooks/metrics/dora_metrics_engine.py +2 -2
  149. runbooks/monitoring/performance_monitor.py +9 -4
  150. runbooks/operate/dynamodb_operations.py +3 -1
  151. runbooks/operate/ec2_operations.py +145 -137
  152. runbooks/operate/iam_operations.py +146 -152
  153. runbooks/operate/mcp_integration.py +1 -1
  154. runbooks/operate/networking_cost_heatmap.py +33 -10
  155. runbooks/operate/privatelink_operations.py +1 -1
  156. runbooks/operate/rds_operations.py +223 -254
  157. runbooks/operate/s3_operations.py +107 -118
  158. runbooks/operate/vpc_endpoints.py +1 -1
  159. runbooks/operate/vpc_operations.py +648 -618
  160. runbooks/remediation/base.py +1 -1
  161. runbooks/remediation/commons.py +10 -7
  162. runbooks/remediation/commvault_ec2_analysis.py +71 -67
  163. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
  164. runbooks/remediation/multi_account.py +24 -21
  165. runbooks/remediation/rds_snapshot_list.py +91 -65
  166. runbooks/remediation/remediation_cli.py +92 -146
  167. runbooks/remediation/universal_account_discovery.py +83 -79
  168. runbooks/remediation/workspaces_list.py +49 -44
  169. runbooks/security/__init__.py +19 -0
  170. runbooks/security/assessment_runner.py +1150 -0
  171. runbooks/security/baseline_checker.py +812 -0
  172. runbooks/security/cloudops_automation_security_validator.py +509 -535
  173. runbooks/security/compliance_automation_engine.py +17 -17
  174. runbooks/security/config/__init__.py +2 -2
  175. runbooks/security/config/compliance_config.py +50 -50
  176. runbooks/security/config_template_generator.py +63 -76
  177. runbooks/security/enterprise_security_framework.py +1 -1
  178. runbooks/security/executive_security_dashboard.py +519 -508
  179. runbooks/security/integration_test_enterprise_security.py +5 -3
  180. runbooks/security/multi_account_security_controls.py +959 -1210
  181. runbooks/security/real_time_security_monitor.py +422 -444
  182. runbooks/security/run_script.py +1 -1
  183. runbooks/security/security_baseline_tester.py +1 -1
  184. runbooks/security/security_cli.py +143 -112
  185. runbooks/security/test_2way_validation.py +439 -0
  186. runbooks/security/two_way_validation_framework.py +852 -0
  187. runbooks/sre/mcp_reliability_engine.py +6 -6
  188. runbooks/sre/production_monitoring_framework.py +167 -177
  189. runbooks/tdd/__init__.py +15 -0
  190. runbooks/tdd/cli.py +1071 -0
  191. runbooks/utils/__init__.py +14 -17
  192. runbooks/utils/logger.py +7 -2
  193. runbooks/utils/version_validator.py +51 -48
  194. runbooks/validation/__init__.py +6 -6
  195. runbooks/validation/cli.py +9 -3
  196. runbooks/validation/comprehensive_2way_validator.py +754 -708
  197. runbooks/validation/mcp_validator.py +906 -228
  198. runbooks/validation/terraform_citations_validator.py +104 -115
  199. runbooks/validation/terraform_drift_detector.py +447 -451
  200. runbooks/vpc/README.md +617 -0
  201. runbooks/vpc/__init__.py +8 -1
  202. runbooks/vpc/analyzer.py +577 -0
  203. runbooks/vpc/cleanup_wrapper.py +476 -413
  204. runbooks/vpc/cli_cloudtrail_commands.py +339 -0
  205. runbooks/vpc/cli_mcp_validation_commands.py +480 -0
  206. runbooks/vpc/cloudtrail_audit_integration.py +717 -0
  207. runbooks/vpc/config.py +92 -97
  208. runbooks/vpc/cost_engine.py +411 -148
  209. runbooks/vpc/cost_explorer_integration.py +553 -0
  210. runbooks/vpc/cross_account_session.py +101 -106
  211. runbooks/vpc/enhanced_mcp_validation.py +917 -0
  212. runbooks/vpc/eni_gate_validator.py +961 -0
  213. runbooks/vpc/heatmap_engine.py +190 -162
  214. runbooks/vpc/mcp_no_eni_validator.py +681 -640
  215. runbooks/vpc/nat_gateway_optimizer.py +358 -0
  216. runbooks/vpc/networking_wrapper.py +15 -8
  217. runbooks/vpc/pdca_remediation_planner.py +528 -0
  218. runbooks/vpc/performance_optimized_analyzer.py +219 -231
  219. runbooks/vpc/runbooks_adapter.py +1167 -241
  220. runbooks/vpc/tdd_red_phase_stubs.py +601 -0
  221. runbooks/vpc/test_data_loader.py +358 -0
  222. runbooks/vpc/tests/conftest.py +314 -4
  223. runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
  224. runbooks/vpc/tests/test_cost_engine.py +0 -2
  225. runbooks/vpc/topology_generator.py +326 -0
  226. runbooks/vpc/unified_scenarios.py +1302 -1129
  227. runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
  228. runbooks-1.1.5.dist-info/METADATA +328 -0
  229. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
  230. runbooks/finops/README.md +0 -414
  231. runbooks/finops/accuracy_cross_validator.py +0 -647
  232. runbooks/finops/business_cases.py +0 -950
  233. runbooks/finops/dashboard_router.py +0 -922
  234. runbooks/finops/ebs_optimizer.py +0 -956
  235. runbooks/finops/embedded_mcp_validator.py +0 -1629
  236. runbooks/finops/enhanced_dashboard_runner.py +0 -527
  237. runbooks/finops/finops_dashboard.py +0 -584
  238. runbooks/finops/finops_scenarios.py +0 -1218
  239. runbooks/finops/legacy_migration.py +0 -730
  240. runbooks/finops/multi_dashboard.py +0 -1519
  241. runbooks/finops/single_dashboard.py +0 -1113
  242. runbooks/finops/unlimited_scenarios.py +0 -393
  243. runbooks-1.1.3.dist-info/METADATA +0 -799
  244. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
  245. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
  246. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
  247. {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -39,32 +39,34 @@ from ..common.performance_optimization_engine import get_optimization_engine
39
39
  logger = configure_logger(__name__)
40
40
 
41
41
  # Global Organizations cache to prevent duplicate API calls across all instances
42
- _GLOBAL_ORGS_CACHE = {
43
- 'data': None,
44
- 'timestamp': None,
45
- 'ttl_minutes': 30
46
- }
42
+ _GLOBAL_ORGS_CACHE = {"data": None, "timestamp": None, "ttl_minutes": 30}
43
+
47
44
 
48
45
  def _get_global_organizations_cache():
49
46
  """Get cached Organizations data if valid (module-level cache)."""
50
- if not _GLOBAL_ORGS_CACHE['timestamp']:
47
+ if not _GLOBAL_ORGS_CACHE["timestamp"]:
51
48
  return None
52
-
53
- cache_age_minutes = (datetime.now(timezone.utc) - _GLOBAL_ORGS_CACHE['timestamp']).total_seconds() / 60
54
- if cache_age_minutes < _GLOBAL_ORGS_CACHE['ttl_minutes']:
49
+
50
+ cache_age_minutes = (datetime.now(timezone.utc) - _GLOBAL_ORGS_CACHE["timestamp"]).total_seconds() / 60
51
+ if cache_age_minutes < _GLOBAL_ORGS_CACHE["ttl_minutes"]:
55
52
  console.print("[blue]🚀 Global performance optimization: Using cached Organizations data[/blue]")
56
- return _GLOBAL_ORGS_CACHE['data']
53
+ return _GLOBAL_ORGS_CACHE["data"]
57
54
  return None
58
55
 
56
+
59
57
  def _set_global_organizations_cache(data):
60
58
  """Cache Organizations data globally (module-level cache)."""
61
- _GLOBAL_ORGS_CACHE['data'] = data
62
- _GLOBAL_ORGS_CACHE['timestamp'] = datetime.now(timezone.utc)
63
- accounts_count = len(data.get('accounts', {}).get('discovered_accounts', [])) if data else 0
64
- console.print(f"[green]✅ Global Organizations cache: {accounts_count} accounts (TTL: {_GLOBAL_ORGS_CACHE['ttl_minutes']}min)[/green]")
59
+ _GLOBAL_ORGS_CACHE["data"] = data
60
+ _GLOBAL_ORGS_CACHE["timestamp"] = datetime.now(timezone.utc)
61
+ accounts_count = len(data.get("accounts", {}).get("discovered_accounts", [])) if data else 0
62
+ console.print(
63
+ f"[green]✅ Global Organizations cache: {accounts_count} accounts (TTL: {_GLOBAL_ORGS_CACHE['ttl_minutes']}min)[/green]"
64
+ )
65
+
65
66
 
66
67
  # Universal AWS Environment Profile Support (Compatible with ANY AWS Setup)
67
68
  import os
69
+
68
70
  ENTERPRISE_PROFILES = {
69
71
  "BILLING_PROFILE": os.getenv("BILLING_PROFILE", "default"), # Universal compatibility
70
72
  "MANAGEMENT_PROFILE": os.getenv("MANAGEMENT_PROFILE", "default"), # Works with any profile
@@ -246,40 +248,44 @@ class EnhancedOrganizationsDiscovery:
246
248
  """Check if Organizations cache is still valid."""
247
249
  if not self._organizations_cache_timestamp:
248
250
  return False
249
-
251
+
250
252
  from datetime import datetime, timedelta
253
+
251
254
  cache_age_minutes = (datetime.now() - self._organizations_cache_timestamp).total_seconds() / 60
252
255
  return cache_age_minutes < self._cache_ttl_minutes
253
256
 
254
257
  async def discover_all_accounts(self) -> Dict:
255
258
  """
256
259
  Cached wrapper for Organizations discovery to prevent duplicate API calls.
257
-
258
- This method implements both global and instance-level caching to avoid the
259
- performance penalty of duplicate Organizations API calls when multiple
260
+
261
+ This method implements both global and instance-level caching to avoid the
262
+ performance penalty of duplicate Organizations API calls when multiple
260
263
  components need the same account data.
261
264
  """
262
265
  # Check global cache first (shared across all instances)
263
266
  global_cached_result = _get_global_organizations_cache()
264
267
  if global_cached_result:
265
268
  return global_cached_result
266
-
269
+
267
270
  # Check instance cache
268
271
  if self._is_organizations_cache_valid() and self._organizations_cache:
269
272
  console.print("[blue]🚀 Performance optimization: Using cached Organizations data[/blue]")
270
273
  return self._organizations_cache
271
-
274
+
272
275
  # Cache miss - perform discovery
273
276
  console.print("[cyan]🔍 Performing Organizations discovery (cache miss)[/cyan]")
274
277
  results = await self.discover_organization_structure()
275
-
278
+
276
279
  # Cache the results
277
- if results and results.get('accounts'):
280
+ if results and results.get("accounts"):
278
281
  self._organizations_cache = results
279
282
  from datetime import datetime
283
+
280
284
  self._organizations_cache_timestamp = datetime.now()
281
- console.print(f"[green]✅ Cached Organizations data: {len(results.get('accounts', {}).get('discovered_accounts', []))} accounts (TTL: {self._cache_ttl_minutes}min)[/green]")
282
-
285
+ console.print(
286
+ f"[green]✅ Cached Organizations data: {len(results.get('accounts', {}).get('discovered_accounts', []))} accounts (TTL: {self._cache_ttl_minutes}min)[/green]"
287
+ )
288
+
283
289
  return results
284
290
 
285
291
  def initialize_sessions(self) -> Dict[str, str]:
@@ -417,13 +423,13 @@ class EnhancedOrganizationsDiscovery:
417
423
  """
418
424
  # Get performance optimization engine
419
425
  optimization_engine = get_optimization_engine(
420
- max_workers=self.max_workers,
421
- cache_ttl_minutes=30,
422
- memory_limit_mb=2048
426
+ max_workers=self.max_workers, cache_ttl_minutes=30, memory_limit_mb=2048
423
427
  )
424
-
428
+
425
429
  # Use optimized discovery with performance monitoring
426
- with optimization_engine.optimize_operation("organization_structure_discovery", self.performance_target_seconds):
430
+ with optimization_engine.optimize_operation(
431
+ "organization_structure_discovery", self.performance_target_seconds
432
+ ):
427
433
  return await self._discover_organization_structure_optimized(optimization_engine)
428
434
 
429
435
  async def _discover_organization_structure_optimized(self, optimization_engine) -> Dict:
@@ -436,7 +442,7 @@ class EnhancedOrganizationsDiscovery:
436
442
  )
437
443
 
438
444
  logger.info("🏢 Starting optimized organization structure discovery with SRE automation patterns")
439
-
445
+
440
446
  # Check global cache first to prevent duplicate calls
441
447
  cached_result = _get_global_organizations_cache()
442
448
  if cached_result:
@@ -446,7 +452,7 @@ class EnhancedOrganizationsDiscovery:
446
452
  self.discovery_metrics["end_time"] = self.current_benchmark.end_time
447
453
  self.discovery_metrics["duration_seconds"] = self.current_benchmark.duration_seconds
448
454
  return cached_result
449
-
455
+
450
456
  self.discovery_metrics["start_time"] = self.current_benchmark.start_time
451
457
 
452
458
  with Status("Initializing enterprise discovery...", console=console, spinner="dots"):
@@ -561,10 +567,10 @@ class EnhancedOrganizationsDiscovery:
561
567
  "performance_benchmark": performance_benchmark_dict,
562
568
  "timestamp": datetime.now().isoformat(),
563
569
  }
564
-
570
+
565
571
  # Cache the successful result to prevent duplicate calls
566
572
  _set_global_organizations_cache(discovery_result)
567
-
573
+
568
574
  return discovery_result
569
575
 
570
576
  except Exception as e:
@@ -606,7 +612,7 @@ class EnhancedOrganizationsDiscovery:
606
612
  async def _discover_accounts_optimized(self, optimization_engine) -> Dict:
607
613
  """
608
614
  Optimized account discovery using performance optimization engine
609
-
615
+
610
616
  Addresses: Organization Discovery Performance (52.3s -> <30s target)
611
617
  Features:
612
618
  - Intelligent caching with TTL management
@@ -615,46 +621,44 @@ class EnhancedOrganizationsDiscovery:
615
621
  - Memory-efficient processing
616
622
  """
617
623
  logger.info("📊 Discovering organization accounts with SRE optimization patterns")
618
-
624
+
619
625
  # Use optimization engine for discovery
620
626
  optimized_discover_accounts = optimization_engine.optimize_organization_discovery(
621
- management_profile=self.management_profile,
622
- use_parallel_processing=True,
623
- batch_size=20
627
+ management_profile=self.management_profile, use_parallel_processing=True, batch_size=20
624
628
  )
625
-
629
+
626
630
  # Execute optimized discovery
627
631
  try:
628
632
  result = optimized_discover_accounts()
629
-
633
+
630
634
  # Convert to expected format
631
- accounts_data = result.get('accounts', [])
632
-
635
+ accounts_data = result.get("accounts", [])
636
+
633
637
  # Create AWSAccount objects for compatibility
634
638
  for account_data in accounts_data:
635
639
  account = AWSAccount(
636
640
  account_id=account_data["Id"],
637
- name=account_data["Name"],
641
+ name=account_data["Name"],
638
642
  email=account_data["Email"],
639
643
  status=account_data["Status"],
640
644
  joined_method=account_data["JoinedMethod"],
641
645
  joined_timestamp=account_data.get("JoinedTimestamp"),
642
- tags=account_data.get("Tags", {})
646
+ tags=account_data.get("Tags", {}),
643
647
  )
644
648
  self.accounts_cache[account.account_id] = account
645
-
649
+
646
650
  # Update metrics
647
651
  self.discovery_metrics["accounts_discovered"] = len(accounts_data)
648
-
652
+
649
653
  # Enhanced account categorization
650
654
  active_accounts = [a for a in accounts_data if a.get("Status") == "ACTIVE"]
651
- suspended_accounts = [a for a in accounts_data if a.get("Status") == "SUSPENDED"]
655
+ suspended_accounts = [a for a in accounts_data if a.get("Status") == "SUSPENDED"]
652
656
  closed_accounts = [a for a in accounts_data if a.get("Status") == "CLOSED"]
653
-
654
- optimization_info = result.get('optimizations_applied', [])
657
+
658
+ optimization_info = result.get("optimizations_applied", [])
655
659
  logger.info(f"✅ Optimized discovery: {len(accounts_data)} accounts ({len(active_accounts)} active)")
656
660
  logger.info(f"🚀 Optimizations applied: {', '.join(optimization_info)}")
657
-
661
+
658
662
  return {
659
663
  "total_accounts": len(accounts_data),
660
664
  "active_accounts": len(active_accounts),
@@ -665,7 +669,7 @@ class EnhancedOrganizationsDiscovery:
665
669
  "profile_used": "management",
666
670
  "optimizations_applied": optimization_info,
667
671
  }
668
-
672
+
669
673
  except Exception as e:
670
674
  logger.error(f"Optimized account discovery failed: {e}")
671
675
  # Fallback to original method
@@ -1138,7 +1142,7 @@ class EnhancedOrganizationsDiscovery:
1138
1142
  medium_spend_accounts = {
1139
1143
  k: round(v, 2)
1140
1144
  for k, v in cost_by_account.items()
1141
- if 100 <= v <= 1000 # $100-$1000/month
1145
+ if 100 <= v <= 1000 # significant value range$1000/month
1142
1146
  }
1143
1147
 
1144
1148
  logger.info(f"✅ Cost validation complete: ${total_cost:.2f} across {len(cost_by_account)} accounts")
@@ -349,18 +349,18 @@ def display_account_tree(accounts_data: Dict[str, Dict]) -> None:
349
349
 
350
350
 
351
351
  def display_results_rich(
352
- results_list: List[Dict[str, Any]],
353
- fdisplay_dict: Dict[str, Dict],
354
- defaultAction: Any = None,
355
- file_to_save: Optional[str] = None,
352
+ results_list: List[Dict[str, Any]],
353
+ fdisplay_dict: Dict[str, Dict],
354
+ defaultAction: Any = None,
355
+ file_to_save: Optional[str] = None,
356
356
  subdisplay: bool = False,
357
- title: str = "Inventory Results"
357
+ title: str = "Inventory Results",
358
358
  ) -> None:
359
359
  """
360
360
  Rich CLI replacement for legacy display_results function.
361
-
361
+
362
362
  Provides backwards-compatible interface while using Rich formatting.
363
-
363
+
364
364
  Args:
365
365
  results_list: List of dictionaries with resource data
366
366
  fdisplay_dict: Display configuration dictionary with format:
@@ -369,7 +369,7 @@ def display_results_rich(
369
369
  file_to_save: Optional filename to save results
370
370
  subdisplay: Whether this is a sub-display (affects formatting)
371
371
  title: Title for the table display
372
-
372
+
373
373
  Example:
374
374
  display_dict = {
375
375
  'AccountId': {'DisplayOrder': 1, 'Heading': 'Account'},
@@ -379,59 +379,60 @@ def display_results_rich(
379
379
  display_results_rich(instance_data, display_dict, title="EC2 Instances")
380
380
  """
381
381
  from datetime import datetime
382
-
382
+
383
383
  if not results_list:
384
384
  print_info("ℹ️ No results to display")
385
385
  return
386
-
386
+
387
387
  # Sort display fields by DisplayOrder
388
- sorted_fields = sorted(fdisplay_dict.items(), key=lambda x: x[1].get('DisplayOrder', 999))
389
-
388
+ sorted_fields = sorted(fdisplay_dict.items(), key=lambda x: x[1].get("DisplayOrder", 999))
389
+
390
390
  # Create Rich table
391
391
  table = create_table(
392
392
  title=f"📊 {title}",
393
- caption=f"Found {len(results_list)} results • {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
393
+ caption=f"Found {len(results_list)} results • {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
394
394
  )
395
-
395
+
396
396
  # Add columns based on display dictionary
397
397
  for field_name, field_config in sorted_fields:
398
- heading = field_config.get('Heading', field_name)
398
+ heading = field_config.get("Heading", field_name)
399
399
  table.add_column(heading, style="cyan" if "Id" in field_name else "white", no_wrap=True)
400
-
400
+
401
401
  # Add rows
402
402
  for result in results_list[:100]: # Limit to first 100 for performance
403
403
  row_data = []
404
-
404
+
405
405
  for field_name, field_config in sorted_fields:
406
406
  # Apply condition filter if specified
407
- condition = field_config.get('Condition', [])
407
+ condition = field_config.get("Condition", [])
408
408
  if condition:
409
409
  value = result.get(field_name, defaultAction)
410
410
  if value not in condition:
411
411
  continue
412
-
412
+
413
413
  # Get field value with default fallback
414
414
  value = result.get(field_name, defaultAction)
415
415
  if value is None:
416
416
  value = "N/A"
417
-
417
+
418
418
  # Format value as string
419
419
  row_data.append(str(value)[:50]) # Truncate long values
420
-
420
+
421
421
  table.add_row(*row_data)
422
-
422
+
423
423
  # Display the table
424
424
  console.print(table)
425
-
425
+
426
426
  # Show truncation notice if needed
427
427
  if len(results_list) > 100:
428
428
  console.print(f"[dim]Showing first 100 results. Total found: {len(results_list)}[/dim]")
429
-
429
+
430
430
  # Save to file if requested
431
431
  if file_to_save:
432
432
  try:
433
433
  import json
434
- with open(file_to_save, 'w') as f:
434
+
435
+ with open(file_to_save, "w") as f:
435
436
  json.dump(results_list, f, indent=2, default=str)
436
437
  print_success(f"💾 Results saved to: {file_to_save}")
437
438
  except Exception as e:
@@ -441,7 +442,7 @@ def display_results_rich(
441
442
  def display_progress_rich(current: int, total: int, description: str = "Processing") -> None:
442
443
  """
443
444
  Rich CLI replacement for legacy progress indicators.
444
-
445
+
445
446
  Args:
446
447
  current: Current progress count
447
448
  total: Total items to process
@@ -454,21 +455,21 @@ def display_progress_rich(current: int, total: int, description: str = "Processi
454
455
  def print_colorized_rich(text: str, color: str = "white") -> None:
455
456
  """
456
457
  Rich CLI replacement for colorama print statements.
457
-
458
+
458
459
  Args:
459
460
  text: Text to print
460
461
  color: Color name (red, green, yellow, cyan, blue, white)
461
462
  """
462
463
  color_map = {
463
464
  "red": "red",
464
- "green": "green",
465
+ "green": "green",
465
466
  "yellow": "yellow",
466
467
  "cyan": "cyan",
467
468
  "blue": "blue",
468
469
  "white": "white",
469
- "magenta": "magenta"
470
+ "magenta": "magenta",
470
471
  }
471
-
472
+
472
473
  rich_color = color_map.get(color.lower(), "white")
473
474
  console.print(f"[{rich_color}]{text}[/{rich_color}]")
474
475
 
@@ -476,13 +477,13 @@ def print_colorized_rich(text: str, color: str = "white") -> None:
476
477
  # Export public functions
477
478
  __all__ = [
478
479
  "display_inventory_header",
479
- "create_inventory_progress",
480
+ "create_inventory_progress",
480
481
  "display_ec2_inventory_results",
481
482
  "display_generic_inventory_results",
482
483
  "display_inventory_error",
483
484
  "display_multi_resource_summary",
484
485
  "display_account_tree",
485
486
  "display_results_rich",
486
- "display_progress_rich",
487
+ "display_progress_rich",
487
488
  "print_colorized_rich",
488
489
  ]