runbooks 1.0.0__py3-none-any.whl → 1.0.2__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 (99) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/cfat/WEIGHT_CONFIG_README.md +368 -0
  3. runbooks/cfat/app.ts +27 -19
  4. runbooks/cfat/assessment/runner.py +6 -5
  5. runbooks/cfat/tests/test_weight_configuration.ts +449 -0
  6. runbooks/cfat/weight_config.ts +574 -0
  7. runbooks/cloudops/models.py +20 -14
  8. runbooks/common/__init__.py +26 -9
  9. runbooks/common/aws_pricing.py +1070 -105
  10. runbooks/common/aws_pricing_api.py +276 -44
  11. runbooks/common/date_utils.py +115 -0
  12. runbooks/common/dry_run_examples.py +587 -0
  13. runbooks/common/dry_run_framework.py +520 -0
  14. runbooks/common/enhanced_exception_handler.py +10 -7
  15. runbooks/common/mcp_cost_explorer_integration.py +5 -4
  16. runbooks/common/memory_optimization.py +533 -0
  17. runbooks/common/performance_optimization_engine.py +1153 -0
  18. runbooks/common/profile_utils.py +86 -118
  19. runbooks/common/rich_utils.py +3 -3
  20. runbooks/common/sre_performance_suite.py +574 -0
  21. runbooks/finops/business_case_config.py +314 -0
  22. runbooks/finops/cost_processor.py +19 -4
  23. runbooks/finops/dashboard_runner.py +47 -28
  24. runbooks/finops/ebs_cost_optimizer.py +1 -1
  25. runbooks/finops/ebs_optimizer.py +56 -9
  26. runbooks/finops/embedded_mcp_validator.py +642 -36
  27. runbooks/finops/enhanced_trend_visualization.py +7 -2
  28. runbooks/finops/executive_export.py +789 -0
  29. runbooks/finops/finops_dashboard.py +6 -5
  30. runbooks/finops/finops_scenarios.py +34 -27
  31. runbooks/finops/iam_guidance.py +6 -1
  32. runbooks/finops/nat_gateway_optimizer.py +46 -27
  33. runbooks/finops/notebook_utils.py +1 -1
  34. runbooks/finops/schemas.py +73 -58
  35. runbooks/finops/single_dashboard.py +20 -4
  36. runbooks/finops/tests/test_integration.py +3 -1
  37. runbooks/finops/vpc_cleanup_exporter.py +2 -1
  38. runbooks/finops/vpc_cleanup_optimizer.py +22 -29
  39. runbooks/inventory/core/collector.py +51 -28
  40. runbooks/inventory/discovery.md +197 -247
  41. runbooks/inventory/inventory_modules.py +2 -2
  42. runbooks/inventory/list_ec2_instances.py +3 -3
  43. runbooks/inventory/models/account.py +5 -3
  44. runbooks/inventory/models/inventory.py +1 -1
  45. runbooks/inventory/models/resource.py +5 -3
  46. runbooks/inventory/organizations_discovery.py +102 -13
  47. runbooks/inventory/unified_validation_engine.py +2 -15
  48. runbooks/main.py +255 -92
  49. runbooks/operate/base.py +9 -6
  50. runbooks/operate/deployment_framework.py +5 -4
  51. runbooks/operate/deployment_validator.py +6 -5
  52. runbooks/operate/mcp_integration.py +6 -5
  53. runbooks/operate/networking_cost_heatmap.py +17 -13
  54. runbooks/operate/vpc_operations.py +82 -13
  55. runbooks/remediation/base.py +3 -1
  56. runbooks/remediation/commons.py +5 -5
  57. runbooks/remediation/commvault_ec2_analysis.py +66 -18
  58. runbooks/remediation/config/accounts_example.json +31 -0
  59. runbooks/remediation/multi_account.py +120 -7
  60. runbooks/remediation/remediation_cli.py +710 -0
  61. runbooks/remediation/universal_account_discovery.py +377 -0
  62. runbooks/remediation/workspaces_list.py +2 -2
  63. runbooks/security/compliance_automation_engine.py +99 -20
  64. runbooks/security/config/__init__.py +24 -0
  65. runbooks/security/config/compliance_config.py +255 -0
  66. runbooks/security/config/compliance_weights_example.json +22 -0
  67. runbooks/security/config_template_generator.py +500 -0
  68. runbooks/security/security_cli.py +377 -0
  69. runbooks/validation/cli.py +8 -7
  70. runbooks/validation/comprehensive_2way_validator.py +26 -15
  71. runbooks/validation/mcp_validator.py +62 -8
  72. runbooks/vpc/config.py +49 -15
  73. runbooks/vpc/cross_account_session.py +5 -1
  74. runbooks/vpc/heatmap_engine.py +438 -59
  75. runbooks/vpc/mcp_no_eni_validator.py +115 -36
  76. runbooks/vpc/performance_optimized_analyzer.py +546 -0
  77. runbooks/vpc/runbooks_adapter.py +33 -12
  78. runbooks/vpc/tests/conftest.py +4 -2
  79. runbooks/vpc/tests/test_cost_engine.py +3 -1
  80. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/METADATA +1 -1
  81. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/RECORD +85 -79
  82. runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
  83. runbooks/finops/runbooks.security.report_generator.log +0 -0
  84. runbooks/finops/runbooks.security.run_script.log +0 -0
  85. runbooks/finops/runbooks.security.security_export.log +0 -0
  86. runbooks/finops/tests/results_test_finops_dashboard.xml +0 -1
  87. runbooks/inventory/artifacts/scale-optimize-status.txt +0 -12
  88. runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
  89. runbooks/inventory/runbooks.security.report_generator.log +0 -0
  90. runbooks/inventory/runbooks.security.run_script.log +0 -0
  91. runbooks/inventory/runbooks.security.security_export.log +0 -0
  92. runbooks/vpc/runbooks.inventory.organizations_discovery.log +0 -0
  93. runbooks/vpc/runbooks.security.report_generator.log +0 -0
  94. runbooks/vpc/runbooks.security.run_script.log +0 -0
  95. runbooks/vpc/runbooks.security.security_export.log +0 -0
  96. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/WHEEL +0 -0
  97. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/entry_points.txt +0 -0
  98. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/licenses/LICENSE +0 -0
  99. {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,7 @@ from datetime import datetime, timedelta
10
10
  from enum import Enum
11
11
  from typing import Any, Dict, List, Optional, Set
12
12
 
13
- from pydantic import BaseModel, Field, validator
13
+ from pydantic import BaseModel, Field, field_validator
14
14
 
15
15
  from runbooks.inventory.models.account import AWSAccount
16
16
  from runbooks.inventory.models.resource import AWSResource
@@ -10,7 +10,7 @@ from datetime import datetime
10
10
  from enum import Enum
11
11
  from typing import Any, Dict, List, Optional, Union
12
12
 
13
- from pydantic import BaseModel, Field, validator
13
+ from pydantic import BaseModel, Field, field_validator
14
14
 
15
15
 
16
16
  class ResourceState(str, Enum):
@@ -178,14 +178,16 @@ class AWSResource(BaseModel):
178
178
  use_enum_values = True
179
179
  json_encoders = {datetime: lambda v: v.isoformat() if v else None}
180
180
 
181
- @validator("resource_arn")
181
+ @field_validator("resource_arn")
182
+ @classmethod
182
183
  def validate_arn_format(cls, v):
183
184
  """Validate ARN format if provided."""
184
185
  if v and not v.startswith("arn:aws:"):
185
186
  raise ValueError('ARN must start with "arn:aws:"')
186
187
  return v
187
188
 
188
- @validator("account_id")
189
+ @field_validator("account_id")
190
+ @classmethod
189
191
  def validate_account_id(cls, v):
190
192
  """Validate account ID format."""
191
193
  if not v.isdigit() or len(v) != 12:
@@ -34,6 +34,7 @@ from rich.table import Table
34
34
  console = Console()
35
35
 
36
36
  from ..utils.logger import configure_logger
37
+ from ..common.performance_optimization_engine import get_optimization_engine
37
38
 
38
39
  logger = configure_logger(__name__)
39
40
 
@@ -62,12 +63,13 @@ def _set_global_organizations_cache(data):
62
63
  accounts_count = len(data.get('accounts', {}).get('discovered_accounts', [])) if data else 0
63
64
  console.print(f"[green]✅ Global Organizations cache: {accounts_count} accounts (TTL: {_GLOBAL_ORGS_CACHE['ttl_minutes']}min)[/green]")
64
65
 
65
- # Enterprise 4-Profile AWS SSO Architecture (Proven FinOps Success Pattern)
66
+ # Universal AWS Environment Profile Support (Compatible with ANY AWS Setup)
67
+ import os
66
68
  ENTERPRISE_PROFILES = {
67
- "BILLING_PROFILE": "ams-admin-Billing-ReadOnlyAccess-909135376185", # Cost Explorer access
68
- "MANAGEMENT_PROFILE": "ams-admin-ReadOnlyAccess-909135376185", # Organizations access
69
- "CENTRALISED_OPS_PROFILE": "ams-centralised-ops-ReadOnlyAccess-335083429030", # Operations access
70
- "SINGLE_ACCOUNT_PROFILE": "ams-shared-services-non-prod-ReadOnlyAccess-499201730520", # Single account ops
69
+ "BILLING_PROFILE": os.getenv("BILLING_PROFILE", "default"), # Universal compatibility
70
+ "MANAGEMENT_PROFILE": os.getenv("MANAGEMENT_PROFILE", "default"), # Works with any profile
71
+ "CENTRALISED_OPS_PROFILE": os.getenv("CENTRALISED_OPS_PROFILE", "default"), # Universal operations
72
+ "SINGLE_ACCOUNT_PROFILE": os.getenv("SINGLE_AWS_PROFILE", "default"), # Universal single account
71
73
  }
72
74
 
73
75
 
@@ -407,11 +409,25 @@ class EnhancedOrganizationsDiscovery:
407
409
  Discover complete organization structure with performance benchmarking
408
410
 
409
411
  Enhanced with:
410
- - Performance benchmark tracking (<45s target)
412
+ - Performance benchmark tracking (<30s target optimized from 52.3s)
411
413
  - Rich console progress monitoring
412
414
  - Comprehensive error recovery
413
415
  - Multi-profile fallback support
416
+ - Performance optimization engine integration
414
417
  """
418
+ # Get performance optimization engine
419
+ optimization_engine = get_optimization_engine(
420
+ max_workers=self.max_workers,
421
+ cache_ttl_minutes=30,
422
+ memory_limit_mb=2048
423
+ )
424
+
425
+ # Use optimized discovery with performance monitoring
426
+ with optimization_engine.optimize_operation("organization_structure_discovery", self.performance_target_seconds):
427
+ return await self._discover_organization_structure_optimized(optimization_engine)
428
+
429
+ async def _discover_organization_structure_optimized(self, optimization_engine) -> Dict:
430
+ """Optimized organization structure discovery implementation"""
415
431
  # Start performance benchmark
416
432
  self.current_benchmark = PerformanceBenchmark(
417
433
  operation_name="organization_structure_discovery",
@@ -419,7 +435,7 @@ class EnhancedOrganizationsDiscovery:
419
435
  target_seconds=self.performance_target_seconds,
420
436
  )
421
437
 
422
- logger.info("🏢 Starting enhanced organization structure discovery with performance tracking")
438
+ logger.info("🏢 Starting optimized organization structure discovery with SRE automation patterns")
423
439
 
424
440
  # Check global cache first to prevent duplicate calls
425
441
  cached_result = _get_global_organizations_cache()
@@ -471,9 +487,9 @@ class EnhancedOrganizationsDiscovery:
471
487
  ) as progress:
472
488
  discovery_task = progress.add_task("Discovering organization structure...", total=5)
473
489
 
474
- # Discover accounts
475
- progress.update(discovery_task, description="Discovering accounts...")
476
- accounts_result = await self._discover_accounts()
490
+ # Discover accounts using optimization engine
491
+ progress.update(discovery_task, description="Discovering accounts (optimized)...")
492
+ accounts_result = await self._discover_accounts_optimized(optimization_engine)
477
493
  self.current_benchmark.accounts_processed = accounts_result.get("total_accounts", 0)
478
494
  progress.advance(discovery_task)
479
495
 
@@ -587,6 +603,75 @@ class EnhancedOrganizationsDiscovery:
587
603
  "performance_benchmark": performance_benchmark_dict,
588
604
  }
589
605
 
606
+ async def _discover_accounts_optimized(self, optimization_engine) -> Dict:
607
+ """
608
+ Optimized account discovery using performance optimization engine
609
+
610
+ Addresses: Organization Discovery Performance (52.3s -> <30s target)
611
+ Features:
612
+ - Intelligent caching with TTL management
613
+ - Parallel account processing with batch optimization
614
+ - Connection pooling for Organizations API
615
+ - Memory-efficient processing
616
+ """
617
+ logger.info("📊 Discovering organization accounts with SRE optimization patterns")
618
+
619
+ # Use optimization engine for discovery
620
+ optimized_discover_accounts = optimization_engine.optimize_organization_discovery(
621
+ management_profile=self.management_profile,
622
+ use_parallel_processing=True,
623
+ batch_size=20
624
+ )
625
+
626
+ # Execute optimized discovery
627
+ try:
628
+ result = optimized_discover_accounts()
629
+
630
+ # Convert to expected format
631
+ accounts_data = result.get('accounts', [])
632
+
633
+ # Create AWSAccount objects for compatibility
634
+ for account_data in accounts_data:
635
+ account = AWSAccount(
636
+ account_id=account_data["Id"],
637
+ name=account_data["Name"],
638
+ email=account_data["Email"],
639
+ status=account_data["Status"],
640
+ joined_method=account_data["JoinedMethod"],
641
+ joined_timestamp=account_data.get("JoinedTimestamp"),
642
+ tags=account_data.get("Tags", {})
643
+ )
644
+ self.accounts_cache[account.account_id] = account
645
+
646
+ # Update metrics
647
+ self.discovery_metrics["accounts_discovered"] = len(accounts_data)
648
+
649
+ # Enhanced account categorization
650
+ 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"]
652
+ closed_accounts = [a for a in accounts_data if a.get("Status") == "CLOSED"]
653
+
654
+ optimization_info = result.get('optimizations_applied', [])
655
+ logger.info(f"✅ Optimized discovery: {len(accounts_data)} accounts ({len(active_accounts)} active)")
656
+ logger.info(f"🚀 Optimizations applied: {', '.join(optimization_info)}")
657
+
658
+ return {
659
+ "total_accounts": len(accounts_data),
660
+ "active_accounts": len(active_accounts),
661
+ "suspended_accounts": len(suspended_accounts),
662
+ "closed_accounts": len(closed_accounts),
663
+ "accounts": [asdict(account) for account_id, account in self.accounts_cache.items()],
664
+ "discovery_method": "optimized_organizations_api",
665
+ "profile_used": "management",
666
+ "optimizations_applied": optimization_info,
667
+ }
668
+
669
+ except Exception as e:
670
+ logger.error(f"Optimized account discovery failed: {e}")
671
+ # Fallback to original method
672
+ logger.info("Falling back to original discovery method...")
673
+ return await self._discover_accounts()
674
+
590
675
  async def _discover_accounts(self) -> Dict:
591
676
  """
592
677
  Discover all accounts in the organization using 4-profile architecture
@@ -1290,10 +1375,10 @@ async def run_enhanced_organizations_discovery(
1290
1375
  return org_results
1291
1376
 
1292
1377
 
1293
- # Legacy compatibility function
1378
+ # Legacy compatibility function with universal defaults
1294
1379
  async def run_organizations_discovery(
1295
- management_profile: str = "ams-admin-ReadOnlyAccess-909135376185",
1296
- billing_profile: str = "ams-admin-Billing-ReadOnlyAccess-909135376185",
1380
+ management_profile: str = None,
1381
+ billing_profile: str = None,
1297
1382
  ) -> Dict:
1298
1383
  """
1299
1384
  Legacy compatibility function - redirects to enhanced discovery
@@ -1303,6 +1388,10 @@ async def run_organizations_discovery(
1303
1388
  """
1304
1389
  console.print("[yellow]ℹ️ Using enhanced discovery engine for improved reliability and performance[/yellow]")
1305
1390
 
1391
+ # Apply universal environment defaults
1392
+ management_profile = management_profile or os.getenv("MANAGEMENT_PROFILE", "default-management-profile")
1393
+ billing_profile = billing_profile or os.getenv("BILLING_PROFILE", "default-billing-profile")
1394
+
1306
1395
  return await run_enhanced_organizations_discovery(
1307
1396
  management_profile=management_profile,
1308
1397
  billing_profile=billing_profile,
@@ -564,21 +564,8 @@ class UnifiedValidationEngine:
564
564
  total_weighted_accuracy = 0.0
565
565
  total_weight = 0.0
566
566
 
567
- # Resource weighting for enterprise accuracy calculation
568
- resource_weights = {
569
- "ec2": 3.0, # High weight - critical compute resources
570
- "vpc": 2.5, # High weight - foundational networking
571
- "s3": 2.0, # Medium-high weight - core storage
572
- "rds": 2.0, # Medium-high weight - critical databases
573
- "iam": 2.0, # Medium-high weight - security foundation
574
- "lambda": 1.5, # Medium weight - serverless compute
575
- "elbv2": 1.5, # Medium weight - load balancing
576
- "cloudformation": 1.0, # Medium weight - infrastructure management
577
- "route53": 1.0, # Medium weight - DNS services
578
- "sns": 0.8, # Lower weight - messaging
579
- "eni": 0.8, # Lower weight - network interfaces
580
- "ebs": 0.8, # Lower weight - block storage
581
- }
567
+ # Dynamic resource weighting based on actual discovery for universal compatibility
568
+ resource_weights = self._calculate_dynamic_resource_weights(resource_counts)
582
569
 
583
570
  for resource_type in self.supported_resources.keys():
584
571
  runbooks_count = resource_counts["runbooks"].get(resource_type, 0)