runbooks 0.9.7__py3-none-any.whl → 0.9.8__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.
runbooks/main.py CHANGED
@@ -5850,8 +5850,8 @@ def _parse_profiles_parameter(profiles_tuple):
5850
5850
  )
5851
5851
  @click.option(
5852
5852
  "--scenario",
5853
- type=click.Choice(["workspaces", "snapshots", "commvault", "nat-gateway", "elastic-ip", "ebs"], case_sensitive=False),
5854
- help="Business scenario analysis: workspaces (FinOps-24: $13,020 savings), snapshots (FinOps-23: $119,700 savings), commvault (FinOps-25: investigation), nat-gateway (FinOps-26: $8K-$12K potential), elastic-ip (FinOps-EIP: $3.65/month direct savings), ebs (FinOps-EBS: 15-20% storage optimization)"
5853
+ type=click.Choice(["workspaces", "snapshots", "commvault", "nat-gateway", "elastic-ip", "ebs", "vpc-cleanup"], case_sensitive=False),
5854
+ help="Business scenario analysis: workspaces (FinOps-24: $13,020 savings), snapshots (FinOps-23: $119,700 savings), commvault (FinOps-25: investigation), nat-gateway (FinOps-26: $8K-$12K potential), elastic-ip (FinOps-EIP: $3.65/month direct savings), ebs (FinOps-EBS: 15-20% storage optimization), vpc-cleanup (AWSO-05: $5,869.20 VPC cleanup savings)"
5855
5855
  )
5856
5856
  @click.pass_context
5857
5857
  def finops(
@@ -5891,13 +5891,14 @@ def finops(
5891
5891
  Comprehensive cost analysis supporting both UnblendedCost (technical)
5892
5892
  and AmortizedCost (financial) perspectives for enterprise reporting.
5893
5893
 
5894
- BUSINESS SCENARIOS ($132,720+ proven savings):
5894
+ BUSINESS SCENARIOS ($138,589+ proven savings):
5895
5895
  runbooks finops --scenario workspaces # FinOps-24: WorkSpaces cleanup ($13,020 annual)
5896
5896
  runbooks finops --scenario snapshots # FinOps-23: RDS snapshots ($119,700 annual)
5897
5897
  runbooks finops --scenario commvault # FinOps-25: EC2 investigation framework
5898
5898
  runbooks finops --scenario nat-gateway # FinOps-26: NAT Gateway optimization ($8K-$12K potential)
5899
5899
  runbooks finops --scenario elastic-ip # FinOps-EIP: Elastic IP cleanup ($3.65/month per EIP)
5900
5900
  runbooks finops --scenario ebs # FinOps-EBS: Storage optimization (15-20% cost reduction)
5901
+ runbooks finops --scenario vpc-cleanup # AWSO-05: VPC cleanup ($5,869.20 annual savings)
5901
5902
 
5902
5903
  GENERAL ANALYTICS:
5903
5904
  runbooks finops --audit --csv --report-name audit_report
@@ -5923,10 +5924,12 @@ def finops(
5923
5924
  import asyncio
5924
5925
 
5925
5926
  # Initialize CloudOps cost optimizer with enterprise patterns
5926
- execution_mode = ExecutionMode.ANALYSIS if dry_run else ExecutionMode.EXECUTION
5927
+ execution_mode = ExecutionMode.DRY_RUN if dry_run else ExecutionMode.EXECUTE
5928
+ # Ensure profile is a string, not a tuple
5929
+ profile_str = profile[0] if isinstance(profile, (tuple, list)) and profile else profile or "default"
5927
5930
  cost_optimizer = CostOptimizer(
5928
- profile=primary_profile or "default",
5929
- region=region or "us-east-1",
5931
+ profile=profile_str,
5932
+ dry_run=dry_run,
5930
5933
  execution_mode=execution_mode
5931
5934
  )
5932
5935
 
@@ -6004,8 +6007,9 @@ def finops(
6004
6007
  # Use dedicated NAT Gateway optimizer for specialized analysis
6005
6008
  from runbooks.finops.nat_gateway_optimizer import NATGatewayOptimizer
6006
6009
 
6010
+ profile_str = profile[0] if isinstance(profile, (tuple, list)) and profile else profile or "default"
6007
6011
  nat_optimizer = NATGatewayOptimizer(
6008
- profile_name=primary_profile or "default",
6012
+ profile_name=profile_str,
6009
6013
  regions=regions or ["us-east-1", "us-west-2", "eu-west-1"]
6010
6014
  )
6011
6015
 
@@ -6038,8 +6042,9 @@ def finops(
6038
6042
  # Use dedicated Elastic IP optimizer for specialized analysis
6039
6043
  from runbooks.finops.elastic_ip_optimizer import ElasticIPOptimizer
6040
6044
 
6045
+ profile_str = profile[0] if isinstance(profile, (tuple, list)) and profile else profile or "default"
6041
6046
  eip_optimizer = ElasticIPOptimizer(
6042
- profile_name=primary_profile or "default",
6047
+ profile_name=profile_str,
6043
6048
  regions=regions or ["us-east-1", "us-west-2", "eu-west-1", "us-east-2"]
6044
6049
  )
6045
6050
 
@@ -6074,8 +6079,9 @@ def finops(
6074
6079
  # Use dedicated EBS optimizer for specialized analysis
6075
6080
  from runbooks.finops.ebs_optimizer import EBSOptimizer
6076
6081
 
6082
+ profile_str = profile[0] if isinstance(profile, (tuple, list)) and profile else profile or "default"
6077
6083
  ebs_optimizer = EBSOptimizer(
6078
- profile_name=primary_profile or "default",
6084
+ profile_name=profile_str,
6079
6085
  regions=regions or ["us-east-1", "us-west-2", "eu-west-1"]
6080
6086
  )
6081
6087
 
@@ -6111,6 +6117,61 @@ def finops(
6111
6117
  }
6112
6118
  }
6113
6119
 
6120
+ elif scenario.lower() == "vpc-cleanup":
6121
+ print_info("AWSO-05: VPC Cleanup cost optimization ($5,869.20 annual savings)")
6122
+ print_info("🚀 Enterprise three-bucket strategy with dependency validation")
6123
+
6124
+ # Use dedicated VPC Cleanup optimizer for AWSO-05 analysis
6125
+ from runbooks.finops.vpc_cleanup_optimizer import VPCCleanupOptimizer
6126
+
6127
+ profile_str = profile[0] if isinstance(profile, (tuple, list)) and profile else profile or "default"
6128
+ vpc_optimizer = VPCCleanupOptimizer(
6129
+ profile=profile_str
6130
+ )
6131
+
6132
+ vpc_result = vpc_optimizer.analyze_vpc_cleanup_opportunities()
6133
+
6134
+ # Convert to legacy format for backward compatibility
6135
+ results = {
6136
+ "scenario": "AWSO-05",
6137
+ "business_case": "VPC Cleanup Cost Optimization",
6138
+ "annual_savings": vpc_result.total_annual_savings,
6139
+ "monthly_savings": vpc_result.total_annual_savings / 12,
6140
+ "total_vpcs_analyzed": vpc_result.total_vpcs_analyzed,
6141
+ "bucket_1_internal": len(vpc_result.bucket_1_internal),
6142
+ "bucket_2_external": len(vpc_result.bucket_2_external),
6143
+ "bucket_3_control": len(vpc_result.bucket_3_control),
6144
+ "cleanup_ready_vpcs": len([v for v in vpc_result.cleanup_candidates if v.cleanup_recommendation == "ready"]),
6145
+ "investigation_vpcs": len([v for v in vpc_result.cleanup_candidates if v.cleanup_recommendation == "investigate"]),
6146
+ "manual_review_vpcs": len([v for v in vpc_result.cleanup_candidates if v.cleanup_recommendation == "manual_review"]),
6147
+ "mcp_validation_accuracy": vpc_result.mcp_validation_accuracy,
6148
+ "evidence_hash": vpc_result.evidence_hash,
6149
+ "analysis_timestamp": vpc_result.analysis_timestamp.isoformat(),
6150
+ "success": True,
6151
+ "risk_level": "GRADUATED", # Three-bucket graduated risk approach
6152
+ "safety_assessment": vpc_result.safety_assessment,
6153
+ "three_bucket_breakdown": {
6154
+ "internal_data_plane": {
6155
+ "count": len(vpc_result.bucket_1_internal),
6156
+ "annual_savings": sum(v.annual_savings for v in vpc_result.bucket_1_internal),
6157
+ "risk_level": "LOW",
6158
+ "status": "Ready for deletion"
6159
+ },
6160
+ "external_interconnects": {
6161
+ "count": len(vpc_result.bucket_2_external),
6162
+ "annual_savings": sum(v.annual_savings for v in vpc_result.bucket_2_external),
6163
+ "risk_level": "MEDIUM",
6164
+ "status": "Dependency analysis required"
6165
+ },
6166
+ "control_plane": {
6167
+ "count": len(vpc_result.bucket_3_control),
6168
+ "annual_savings": sum(v.annual_savings for v in vpc_result.bucket_3_control),
6169
+ "risk_level": "HIGH",
6170
+ "status": "Security enhancement focus"
6171
+ }
6172
+ }
6173
+ }
6174
+
6114
6175
  # Handle output file if report_name specified
6115
6176
  if report_name:
6116
6177
  import json
@@ -116,7 +116,13 @@ class RichConsoleWrapper:
116
116
  return print_warning(message)
117
117
 
118
118
  def print_header(self, title, subtitle=None):
119
- return print_header(title, subtitle)
119
+ """Print header with Rich CLI standards - convert subtitle to version parameter."""
120
+ if subtitle:
121
+ # Convert subtitle to version format for Rich CLI compatibility
122
+ version_text = subtitle if len(subtitle) <= 10 else subtitle[:10] + "..."
123
+ return print_header(title, version_text)
124
+ else:
125
+ return print_header(title)
120
126
 
121
127
 
122
128
  @dataclass
runbooks/vpc/__init__.py CHANGED
@@ -22,6 +22,9 @@ from .heatmap_engine import NetworkingCostHeatMapEngine
22
22
  from .manager_interface import BusinessRecommendation, ManagerDashboardConfig, VPCManagerInterface
23
23
  from .networking_wrapper import VPCNetworkingWrapper
24
24
  from .rich_formatters import display_cost_table, display_heatmap, display_optimization_recommendations
25
+ from .vpc_cleanup_integration import VPCCleanupFramework, VPCCleanupCandidate, VPCCleanupRisk, VPCCleanupPhase
26
+ from .cleanup_wrapper import VPCCleanupCLI, analyze_cleanup_candidates, validate_cleanup_safety, generate_business_report
27
+ from .runbooks_adapter import RunbooksAdapter
25
28
 
26
29
  __all__ = [
27
30
  "VPCNetworkingWrapper",
@@ -33,6 +36,15 @@ __all__ = [
33
36
  "display_cost_table",
34
37
  "display_heatmap",
35
38
  "display_optimization_recommendations",
39
+ "VPCCleanupFramework",
40
+ "VPCCleanupCandidate",
41
+ "VPCCleanupRisk",
42
+ "VPCCleanupPhase",
43
+ "VPCCleanupCLI",
44
+ "analyze_cleanup_candidates",
45
+ "validate_cleanup_safety",
46
+ "generate_business_report",
47
+ "RunbooksAdapter",
36
48
  ]
37
49
 
38
50
  # Import centralized version from main runbooks package