runbooks 1.0.3__py3-none-any.whl → 1.1.1__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 (48) hide show
  1. runbooks/__init__.py +10 -5
  2. runbooks/__init__.py.backup +134 -0
  3. runbooks/__init___optimized.py +110 -0
  4. runbooks/cloudops/base.py +56 -3
  5. runbooks/cloudops/cost_optimizer.py +496 -42
  6. runbooks/common/aws_pricing.py +236 -80
  7. runbooks/common/business_logic.py +485 -0
  8. runbooks/common/cli_decorators.py +219 -0
  9. runbooks/common/error_handling.py +424 -0
  10. runbooks/common/lazy_loader.py +186 -0
  11. runbooks/common/module_cli_base.py +378 -0
  12. runbooks/common/performance_monitoring.py +512 -0
  13. runbooks/common/profile_utils.py +133 -6
  14. runbooks/enterprise/logging.py +30 -2
  15. runbooks/enterprise/validation.py +177 -0
  16. runbooks/finops/README.md +311 -236
  17. runbooks/finops/aws_client.py +1 -1
  18. runbooks/finops/business_case_config.py +723 -19
  19. runbooks/finops/cli.py +136 -0
  20. runbooks/finops/commvault_ec2_analysis.py +25 -9
  21. runbooks/finops/config.py +272 -0
  22. runbooks/finops/dashboard_runner.py +136 -23
  23. runbooks/finops/ebs_cost_optimizer.py +39 -40
  24. runbooks/finops/enhanced_trend_visualization.py +7 -2
  25. runbooks/finops/enterprise_wrappers.py +45 -18
  26. runbooks/finops/finops_dashboard.py +50 -25
  27. runbooks/finops/finops_scenarios.py +22 -7
  28. runbooks/finops/helpers.py +115 -2
  29. runbooks/finops/multi_dashboard.py +7 -5
  30. runbooks/finops/optimizer.py +97 -6
  31. runbooks/finops/scenario_cli_integration.py +247 -0
  32. runbooks/finops/scenarios.py +12 -1
  33. runbooks/finops/unlimited_scenarios.py +393 -0
  34. runbooks/finops/validation_framework.py +19 -7
  35. runbooks/finops/workspaces_analyzer.py +1 -5
  36. runbooks/inventory/mcp_inventory_validator.py +2 -1
  37. runbooks/main.py +132 -94
  38. runbooks/main_final.py +358 -0
  39. runbooks/main_minimal.py +84 -0
  40. runbooks/main_optimized.py +493 -0
  41. runbooks/main_ultra_minimal.py +47 -0
  42. runbooks/utils/version_validator.py +1 -1
  43. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/METADATA +1 -1
  44. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/RECORD +48 -32
  45. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/WHEEL +0 -0
  46. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/entry_points.txt +0 -0
  47. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/licenses/LICENSE +0 -0
  48. {runbooks-1.0.3.dist-info → runbooks-1.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,485 @@
1
+ """
2
+ Business Logic Extraction for runbooks package - Universal Business Patterns
3
+
4
+ Extracts and standardizes business logic patterns from existing modules,
5
+ providing reusable components that maintain consistency across the platform.
6
+
7
+ Following KISS & DRY principles - extract proven patterns from existing successful modules.
8
+ """
9
+
10
+ from datetime import datetime
11
+ from typing import Dict, Any, List, Optional, Union
12
+ from dataclasses import dataclass, field
13
+ from enum import Enum
14
+
15
+ from .rich_utils import (
16
+ create_table, console, print_header, print_success, print_info,
17
+ print_warning, format_cost, create_panel, create_progress_bar
18
+ )
19
+ from .profile_utils import get_profile_for_operation
20
+
21
+
22
+ class BusinessImpactLevel(Enum):
23
+ """Business impact classification for operations and optimizations."""
24
+ CRITICAL = "CRITICAL" # >$100K annual impact
25
+ HIGH = "HIGH" # $20K-100K annual impact
26
+ MEDIUM = "MEDIUM" # $5K-20K annual impact
27
+ LOW = "LOW" # <$5K annual impact
28
+
29
+
30
+ class OptimizationType(Enum):
31
+ """Types of optimization operations supported."""
32
+ COST_REDUCTION = "COST_REDUCTION"
33
+ RESOURCE_EFFICIENCY = "RESOURCE_EFFICIENCY"
34
+ SECURITY_COMPLIANCE = "SECURITY_COMPLIANCE"
35
+ PERFORMANCE_IMPROVEMENT = "PERFORMANCE_IMPROVEMENT"
36
+ OPERATIONAL_EXCELLENCE = "OPERATIONAL_EXCELLENCE"
37
+
38
+
39
+ @dataclass
40
+ class BusinessMetrics:
41
+ """Universal business metrics for operations and optimizations."""
42
+ annual_savings: float = 0.0
43
+ monthly_cost_current: float = 0.0
44
+ monthly_cost_optimized: float = 0.0
45
+ roi_percentage: float = 0.0
46
+ payback_period_months: int = 0
47
+ confidence_level: float = 95.0
48
+ implementation_effort: str = "Medium"
49
+ business_risk: str = "Low"
50
+
51
+ def calculate_roi(self) -> float:
52
+ """Calculate ROI percentage from current metrics."""
53
+ if self.annual_savings > 0 and self.monthly_cost_current > 0:
54
+ investment_cost = self.monthly_cost_current * 12 # Annual current cost as investment
55
+ self.roi_percentage = (self.annual_savings / investment_cost) * 100
56
+ return self.roi_percentage
57
+
58
+ def determine_impact_level(self) -> BusinessImpactLevel:
59
+ """Determine business impact level from annual savings."""
60
+ if self.annual_savings >= 100000:
61
+ return BusinessImpactLevel.CRITICAL
62
+ elif self.annual_savings >= 20000:
63
+ return BusinessImpactLevel.HIGH
64
+ elif self.annual_savings >= 5000:
65
+ return BusinessImpactLevel.MEDIUM
66
+ else:
67
+ return BusinessImpactLevel.LOW
68
+
69
+
70
+ @dataclass
71
+ class OptimizationResult:
72
+ """Universal optimization result structure."""
73
+ resource_type: str
74
+ operation_type: OptimizationType
75
+ business_metrics: BusinessMetrics
76
+ recommendations: List[str] = field(default_factory=list)
77
+ implementation_steps: List[str] = field(default_factory=list)
78
+ technical_details: Dict[str, Any] = field(default_factory=dict)
79
+ timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
80
+ validated_by_mcp: bool = False
81
+
82
+ def get_executive_summary(self) -> str:
83
+ """Get executive-friendly summary of the optimization."""
84
+ impact = self.business_metrics.determine_impact_level()
85
+ return (
86
+ f"{self.resource_type} optimization with "
87
+ f"${self.business_metrics.annual_savings:,.0f} annual savings "
88
+ f"({impact.value} impact, {self.business_metrics.confidence_level:.1f}% confidence)"
89
+ )
90
+
91
+
92
+ class UniversalBusinessLogic:
93
+ """
94
+ Universal business logic extraction and standardization.
95
+
96
+ Provides reusable business logic patterns extracted from proven modules
97
+ like FinOps for consistent application across all runbooks modules.
98
+ """
99
+
100
+ def __init__(self, module_name: str):
101
+ self.module_name = module_name
102
+ self.session_metrics = []
103
+
104
+ def create_cost_analysis_table(self, cost_data: Dict[str, Any], title: str,
105
+ include_quarterly: bool = False) -> None:
106
+ """
107
+ Standardized cost analysis table creation following FinOps patterns.
108
+
109
+ Args:
110
+ cost_data: Cost data dictionary with resource costs
111
+ title: Table title for display
112
+ include_quarterly: Include quarterly intelligence columns
113
+ """
114
+ table = create_table(
115
+ title=title,
116
+ caption="Enterprise cost analysis with MCP validation"
117
+ )
118
+
119
+ # Standard columns based on successful FinOps patterns
120
+ table.add_column("Resource", style="cyan", no_wrap=True)
121
+ table.add_column("Current Cost", justify="right", style="cost")
122
+ table.add_column("Optimization %", justify="right", style="yellow")
123
+ table.add_column("Annual Savings", justify="right", style="bright_green")
124
+
125
+ if include_quarterly:
126
+ table.add_column("Q3 Trend", justify="right", style="magenta")
127
+ table.add_column("Strategic Context", style="dim", max_width=20)
128
+
129
+ # Add rows with consistent formatting
130
+ total_savings = 0.0
131
+ for resource, data in cost_data.items():
132
+ current_cost = data.get('current', 0.0)
133
+ optimization_pct = data.get('optimization_percentage', 0.0)
134
+ annual_savings = data.get('annual_savings', 0.0)
135
+ total_savings += annual_savings
136
+
137
+ row_data = [
138
+ resource,
139
+ format_cost(current_cost),
140
+ f"{optimization_pct:.1f}%",
141
+ format_cost(annual_savings)
142
+ ]
143
+
144
+ if include_quarterly:
145
+ quarterly_trend = data.get('quarterly_trend', 'Stable')
146
+ strategic_context = data.get('strategic_context', 'Monitor')
147
+ row_data.extend([quarterly_trend, strategic_context])
148
+
149
+ table.add_row(*row_data)
150
+
151
+ # Add total row
152
+ total_row = ["[bold]TOTAL[/]", "", "", f"[bold bright_green]{format_cost(total_savings)}[/]"]
153
+ if include_quarterly:
154
+ total_row.extend(["", ""])
155
+ table.add_row(*total_row)
156
+
157
+ console.print(table)
158
+
159
+ # Executive summary panel
160
+ if total_savings > 0:
161
+ impact_level = BusinessMetrics(annual_savings=total_savings).determine_impact_level()
162
+ summary_text = f"""
163
+ [bold bright_green]Total Annual Savings: {format_cost(total_savings)}[/]
164
+ [yellow]Business Impact: {impact_level.value}[/]
165
+ [cyan]Resources Analyzed: {len(cost_data)}[/]
166
+ [dim]Analysis Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}[/]
167
+ """
168
+ summary_panel = create_panel(
169
+ summary_text.strip(),
170
+ title="💰 Executive Summary",
171
+ border_style="green"
172
+ )
173
+ console.print(summary_panel)
174
+
175
+ def standardize_resource_operations(self, resource_type: str, operation: str,
176
+ profile: Optional[str] = None, **kwargs) -> Dict[str, Any]:
177
+ """
178
+ Standardized resource operation pattern following proven CLI patterns.
179
+
180
+ Args:
181
+ resource_type: Type of AWS resource (EC2, S3, RDS, etc.)
182
+ operation: Operation being performed (analyze, optimize, inventory)
183
+ profile: AWS profile to use
184
+ **kwargs: Additional operation parameters
185
+
186
+ Returns:
187
+ Dictionary with standardized operation results
188
+ """
189
+ # Apply proven profile management patterns
190
+ selected_profile = get_profile_for_operation("operational", profile)
191
+
192
+ print_header(f"{resource_type.title()} {operation.title()}", f"v1.0.0 - {self.module_name}")
193
+ print_info(f"Using profile: {selected_profile}")
194
+
195
+ # Standard operation tracking
196
+ operation_start = datetime.now()
197
+
198
+ # Standard result format following successful patterns
199
+ result = {
200
+ 'module': self.module_name,
201
+ 'resource_type': resource_type,
202
+ 'operation': operation,
203
+ 'profile_used': selected_profile,
204
+ 'timestamp': operation_start.isoformat(),
205
+ 'success': True,
206
+ 'results': {},
207
+ 'business_metrics': BusinessMetrics(),
208
+ 'recommendations': [],
209
+ 'performance_data': {
210
+ 'start_time': operation_start.isoformat(),
211
+ 'execution_time_seconds': 0.0
212
+ }
213
+ }
214
+
215
+ return result
216
+
217
+ def generate_optimization_recommendations(self, optimization_result: OptimizationResult) -> List[str]:
218
+ """
219
+ Generate standardized optimization recommendations based on business impact.
220
+
221
+ Args:
222
+ optimization_result: Optimization analysis result
223
+
224
+ Returns:
225
+ List of actionable recommendations
226
+ """
227
+ recommendations = []
228
+ metrics = optimization_result.business_metrics
229
+ impact = metrics.determine_impact_level()
230
+
231
+ # Impact-based recommendations
232
+ if impact == BusinessImpactLevel.CRITICAL:
233
+ recommendations.extend([
234
+ f"🚨 CRITICAL: Immediate action required - ${metrics.annual_savings:,.0f} annual savings opportunity",
235
+ "📋 Executive approval recommended for implementation",
236
+ "⏰ Target implementation: Within 30 days",
237
+ "📊 Monthly progress tracking recommended"
238
+ ])
239
+ elif impact == BusinessImpactLevel.HIGH:
240
+ recommendations.extend([
241
+ f"🔴 HIGH PRIORITY: ${metrics.annual_savings:,.0f} annual savings available",
242
+ "📋 Business case development recommended",
243
+ "⏰ Target implementation: Within 90 days",
244
+ "📊 Quarterly progress review recommended"
245
+ ])
246
+ elif impact == BusinessImpactLevel.MEDIUM:
247
+ recommendations.extend([
248
+ f"🟡 MEDIUM PRIORITY: ${metrics.annual_savings:,.0f} annual savings potential",
249
+ "📋 Consider in next planning cycle",
250
+ "⏰ Target implementation: Within 6 months"
251
+ ])
252
+ else:
253
+ recommendations.extend([
254
+ f"🟢 LOW PRIORITY: ${metrics.annual_savings:,.0f} annual savings",
255
+ "📋 Include in routine optimization reviews"
256
+ ])
257
+
258
+ # ROI-based recommendations
259
+ if metrics.roi_percentage > 200:
260
+ recommendations.append(f"💰 Excellent ROI: {metrics.roi_percentage:.1f}% return on investment")
261
+ elif metrics.roi_percentage > 100:
262
+ recommendations.append(f"💰 Good ROI: {metrics.roi_percentage:.1f}% return on investment")
263
+
264
+ # Risk-based recommendations
265
+ if metrics.business_risk == "Low":
266
+ recommendations.append("✅ Low implementation risk - safe to proceed")
267
+ elif metrics.business_risk == "Medium":
268
+ recommendations.append("⚠️ Medium risk - consider phased implementation")
269
+ else:
270
+ recommendations.append("🚨 High risk - detailed planning and approval required")
271
+
272
+ return recommendations
273
+
274
+ def create_executive_dashboard(self, results: List[OptimizationResult],
275
+ dashboard_title: str = "Executive Dashboard") -> None:
276
+ """
277
+ Create executive dashboard following successful FinOps patterns.
278
+
279
+ Args:
280
+ results: List of optimization results
281
+ dashboard_title: Title for the dashboard
282
+ """
283
+ print_header(dashboard_title, f"{self.module_name} Module")
284
+
285
+ if not results:
286
+ print_info("No optimization opportunities identified at this time")
287
+ return
288
+
289
+ # Summary metrics
290
+ total_savings = sum(r.business_metrics.annual_savings for r in results)
291
+ high_impact_count = len([r for r in results if r.business_metrics.determine_impact_level() in [BusinessImpactLevel.CRITICAL, BusinessImpactLevel.HIGH]])
292
+
293
+ # Executive summary table
294
+ summary_table = create_table(
295
+ title="📊 Executive Summary",
296
+ columns=[
297
+ {"name": "Metric", "style": "cyan", "justify": "left"},
298
+ {"name": "Value", "style": "bright_green", "justify": "right"},
299
+ {"name": "Impact", "style": "yellow", "justify": "left"}
300
+ ]
301
+ )
302
+
303
+ summary_table.add_row("Total Annual Savings", format_cost(total_savings), f"{len(results)} opportunities")
304
+ summary_table.add_row("High Priority Items", str(high_impact_count), "Immediate attention required")
305
+ summary_table.add_row("Average Confidence", f"{sum(r.business_metrics.confidence_level for r in results) / len(results):.1f}%", "Validation accuracy")
306
+
307
+ console.print(summary_table)
308
+
309
+ # Top opportunities table
310
+ if results:
311
+ # Sort by annual savings
312
+ top_results = sorted(results, key=lambda x: x.business_metrics.annual_savings, reverse=True)[:5]
313
+
314
+ opportunities_table = create_table(
315
+ title="🎯 Top Optimization Opportunities",
316
+ columns=[
317
+ {"name": "Resource", "style": "cyan", "justify": "left"},
318
+ {"name": "Annual Savings", "style": "bright_green", "justify": "right"},
319
+ {"name": "Impact", "style": "yellow", "justify": "center"},
320
+ {"name": "Confidence", "style": "blue", "justify": "right"},
321
+ {"name": "Next Action", "style": "white", "justify": "left"}
322
+ ]
323
+ )
324
+
325
+ for result in top_results:
326
+ impact = result.business_metrics.determine_impact_level()
327
+ next_action = "Executive Review" if impact == BusinessImpactLevel.CRITICAL else "Business Case"
328
+
329
+ opportunities_table.add_row(
330
+ result.resource_type,
331
+ format_cost(result.business_metrics.annual_savings),
332
+ impact.value,
333
+ f"{result.business_metrics.confidence_level:.1f}%",
334
+ next_action
335
+ )
336
+
337
+ console.print(opportunities_table)
338
+
339
+ def calculate_business_impact(self, resource_type: str, usage_data: Dict[str, Any]) -> BusinessMetrics:
340
+ """
341
+ Standardized business impact calculation following proven FinOps methodology.
342
+
343
+ Args:
344
+ resource_type: Type of resource being analyzed
345
+ usage_data: Resource usage and cost data
346
+
347
+ Returns:
348
+ BusinessMetrics with calculated impact values
349
+ """
350
+ metrics = BusinessMetrics()
351
+
352
+ # Extract costs
353
+ current_monthly = usage_data.get('monthly_cost_current', 0.0)
354
+ optimized_monthly = usage_data.get('monthly_cost_optimized', current_monthly * 0.7) # Default 30% optimization
355
+
356
+ metrics.monthly_cost_current = current_monthly
357
+ metrics.monthly_cost_optimized = optimized_monthly
358
+ metrics.annual_savings = (current_monthly - optimized_monthly) * 12
359
+
360
+ # Calculate ROI
361
+ metrics.calculate_roi()
362
+
363
+ # Set confidence based on resource type (following successful patterns)
364
+ confidence_levels = {
365
+ 'NAT Gateway': 95.0, # High confidence from proven results
366
+ 'Elastic IP': 90.0,
367
+ 'EBS Volume': 85.0,
368
+ 'EC2 Instance': 80.0,
369
+ 'RDS Instance': 75.0,
370
+ 'Generic': 70.0
371
+ }
372
+ metrics.confidence_level = confidence_levels.get(resource_type, 70.0)
373
+
374
+ # Estimate implementation effort and risk
375
+ if metrics.annual_savings > 50000:
376
+ metrics.implementation_effort = "High"
377
+ metrics.business_risk = "Medium"
378
+ elif metrics.annual_savings > 10000:
379
+ metrics.implementation_effort = "Medium"
380
+ metrics.business_risk = "Low"
381
+ else:
382
+ metrics.implementation_effort = "Low"
383
+ metrics.business_risk = "Low"
384
+
385
+ return metrics
386
+
387
+ def export_business_results(self, results: List[OptimizationResult],
388
+ export_formats: List[str] = None) -> Dict[str, str]:
389
+ """
390
+ Export business results in multiple formats following successful patterns.
391
+
392
+ Args:
393
+ results: List of optimization results
394
+ export_formats: List of formats to export ('csv', 'json', 'markdown')
395
+
396
+ Returns:
397
+ Dictionary with export file paths
398
+ """
399
+ if export_formats is None:
400
+ export_formats = ['csv', 'json', 'markdown']
401
+
402
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
403
+ base_filename = f"{self.module_name}_optimization_results_{timestamp}"
404
+
405
+ exported_files = {}
406
+
407
+ print_info(f"Exporting results in {len(export_formats)} formats...")
408
+
409
+ for fmt in export_formats:
410
+ filename = f"./awso_evidence/{base_filename}.{fmt}"
411
+
412
+ if fmt == 'csv':
413
+ # CSV export for analysis
414
+ csv_content = "Resource,Annual_Savings,Impact_Level,Confidence,ROI_Percentage\n"
415
+ for result in results:
416
+ csv_content += f"{result.resource_type},{result.business_metrics.annual_savings},"
417
+ csv_content += f"{result.business_metrics.determine_impact_level().value},"
418
+ csv_content += f"{result.business_metrics.confidence_level},{result.business_metrics.roi_percentage}\n"
419
+
420
+ with open(filename, 'w') as f:
421
+ f.write(csv_content)
422
+
423
+ elif fmt == 'json':
424
+ # JSON export for systems integration
425
+ import json
426
+ json_data = {
427
+ 'module': self.module_name,
428
+ 'timestamp': timestamp,
429
+ 'total_results': len(results),
430
+ 'total_annual_savings': sum(r.business_metrics.annual_savings for r in results),
431
+ 'results': [
432
+ {
433
+ 'resource_type': r.resource_type,
434
+ 'annual_savings': r.business_metrics.annual_savings,
435
+ 'impact_level': r.business_metrics.determine_impact_level().value,
436
+ 'confidence_level': r.business_metrics.confidence_level,
437
+ 'executive_summary': r.get_executive_summary()
438
+ }
439
+ for r in results
440
+ ]
441
+ }
442
+
443
+ with open(filename, 'w') as f:
444
+ json.dump(json_data, f, indent=2)
445
+
446
+ elif fmt == 'markdown':
447
+ # Markdown export for documentation and reports
448
+ md_content = f"# {self.module_name.title()} Optimization Results\n\n"
449
+ md_content += f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
450
+
451
+ total_savings = sum(r.business_metrics.annual_savings for r in results)
452
+ md_content += f"## Executive Summary\n\n"
453
+ md_content += f"- **Total Annual Savings**: ${total_savings:,.0f}\n"
454
+ md_content += f"- **Optimization Opportunities**: {len(results)}\n"
455
+ md_content += f"- **High Priority Items**: {len([r for r in results if r.business_metrics.determine_impact_level() in [BusinessImpactLevel.CRITICAL, BusinessImpactLevel.HIGH]])}\n\n"
456
+
457
+ md_content += "## Detailed Results\n\n"
458
+ for i, result in enumerate(results, 1):
459
+ md_content += f"### {i}. {result.resource_type}\n\n"
460
+ md_content += f"- **Annual Savings**: ${result.business_metrics.annual_savings:,.0f}\n"
461
+ md_content += f"- **Impact Level**: {result.business_metrics.determine_impact_level().value}\n"
462
+ md_content += f"- **Confidence**: {result.business_metrics.confidence_level:.1f}%\n"
463
+ md_content += f"- **ROI**: {result.business_metrics.roi_percentage:.1f}%\n\n"
464
+
465
+ with open(filename, 'w') as f:
466
+ f.write(md_content)
467
+
468
+ exported_files[fmt] = filename
469
+ print_success(f"Exported {fmt.upper()}: {filename}")
470
+
471
+ return exported_files
472
+
473
+
474
+ # Factory function for easy integration
475
+ def create_business_logic_handler(module_name: str) -> UniversalBusinessLogic:
476
+ """
477
+ Factory function to create business logic handler for any module.
478
+
479
+ Args:
480
+ module_name: Name of the module using business logic
481
+
482
+ Returns:
483
+ UniversalBusinessLogic instance configured for the module
484
+ """
485
+ return UniversalBusinessLogic(module_name)