runbooks 0.9.0__py3-none-any.whl → 0.9.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.
- runbooks/__init__.py +1 -1
- runbooks/cfat/assessment/compliance.py +4 -1
- runbooks/cloudops/__init__.py +123 -0
- runbooks/cloudops/base.py +385 -0
- runbooks/cloudops/cost_optimizer.py +811 -0
- runbooks/cloudops/infrastructure_optimizer.py +29 -0
- runbooks/cloudops/interfaces.py +828 -0
- runbooks/cloudops/lifecycle_manager.py +29 -0
- runbooks/cloudops/mcp_cost_validation.py +678 -0
- runbooks/cloudops/models.py +251 -0
- runbooks/cloudops/monitoring_automation.py +29 -0
- runbooks/cloudops/notebook_framework.py +676 -0
- runbooks/cloudops/security_enforcer.py +449 -0
- runbooks/common/mcp_cost_explorer_integration.py +900 -0
- runbooks/common/mcp_integration.py +19 -10
- runbooks/common/rich_utils.py +1 -1
- runbooks/finops/README.md +31 -0
- runbooks/finops/cost_optimizer.py +1340 -0
- runbooks/finops/finops_dashboard.py +211 -5
- runbooks/finops/schemas.py +589 -0
- runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/inventory/runbooks.security.security_export.log +0 -0
- runbooks/main.py +525 -0
- runbooks/operate/ec2_operations.py +428 -0
- runbooks/operate/iam_operations.py +598 -3
- runbooks/operate/rds_operations.py +508 -0
- runbooks/operate/s3_operations.py +508 -0
- runbooks/remediation/base.py +5 -3
- runbooks/security/__init__.py +101 -0
- runbooks/security/cloudops_automation_security_validator.py +1164 -0
- runbooks/security/compliance_automation_engine.py +4 -4
- runbooks/security/enterprise_security_framework.py +4 -5
- runbooks/security/executive_security_dashboard.py +1247 -0
- runbooks/security/multi_account_security_controls.py +2254 -0
- runbooks/security/real_time_security_monitor.py +1196 -0
- runbooks/security/security_baseline_tester.py +3 -3
- runbooks/sre/production_monitoring_framework.py +584 -0
- runbooks/validation/mcp_validator.py +29 -15
- runbooks/vpc/networking_wrapper.py +6 -3
- runbooks-0.9.1.dist-info/METADATA +308 -0
- {runbooks-0.9.0.dist-info → runbooks-0.9.1.dist-info}/RECORD +45 -23
- runbooks-0.9.0.dist-info/METADATA +0 -718
- {runbooks-0.9.0.dist-info → runbooks-0.9.1.dist-info}/WHEEL +0 -0
- {runbooks-0.9.0.dist-info → runbooks-0.9.1.dist-info}/entry_points.txt +0 -0
- {runbooks-0.9.0.dist-info → runbooks-0.9.1.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.9.0.dist-info → runbooks-0.9.1.dist-info}/top_level.txt +0 -0
runbooks/__init__.py
CHANGED
@@ -67,7 +67,7 @@ try:
|
|
67
67
|
__version__ = _pkg_version("runbooks")
|
68
68
|
except Exception:
|
69
69
|
# Fallback if metadata is unavailable during editable installs
|
70
|
-
__version__ = "0.
|
70
|
+
__version__ = "1.0.0"
|
71
71
|
|
72
72
|
# Core module exports
|
73
73
|
from runbooks.config import RunbooksConfig, load_config, save_config
|
@@ -12,6 +12,8 @@ from typing import Any, Dict, List, Optional
|
|
12
12
|
import boto3
|
13
13
|
from rich.console import Console
|
14
14
|
|
15
|
+
from runbooks.common.profile_utils import create_management_session
|
16
|
+
|
15
17
|
# Initialize Rich console for enhanced CLI output
|
16
18
|
console = Console()
|
17
19
|
|
@@ -44,7 +46,8 @@ class ComplianceAssessor:
|
|
44
46
|
"""Initialize enhanced compliance assessor with automation capabilities."""
|
45
47
|
self.profile = profile
|
46
48
|
self.automation_mode = automation_mode
|
47
|
-
|
49
|
+
# Use management profile for CFAT assessments requiring cross-account access
|
50
|
+
self.session = create_management_session(profile=profile)
|
48
51
|
self.checks = []
|
49
52
|
self.frameworks = ["well_architected", "soc2", "pci_dss", "hipaa", "cis_aws"]
|
50
53
|
self.remediation_scripts = {}
|
@@ -0,0 +1,123 @@
|
|
1
|
+
"""
|
2
|
+
CloudOps Automation API Wrapper
|
3
|
+
Enterprise-grade business scenario automation
|
4
|
+
|
5
|
+
Transforms CloudOps-Automation notebooks into unified business-focused APIs
|
6
|
+
with Rich CLI integration and type-safe business models.
|
7
|
+
|
8
|
+
Strategic Context:
|
9
|
+
- Source: 61 CloudOps-Automation notebooks in /README/CloudOps-Automation/AWS/
|
10
|
+
- Target: Business scenarios for CloudOps/SRE/FinOps stakeholders
|
11
|
+
- Integration: Multi-account strategies with Landing Zone support
|
12
|
+
|
13
|
+
NEW: Business Interface Layer for Notebook Usage
|
14
|
+
- Simple synchronous functions wrapping complex async operations
|
15
|
+
- Business-friendly parameters (cost thresholds, risk levels, savings targets)
|
16
|
+
- Executive-ready results with export capabilities
|
17
|
+
- Professional Rich CLI integration
|
18
|
+
"""
|
19
|
+
|
20
|
+
# Core async API classes (for advanced users)
|
21
|
+
from .cost_optimizer import CostOptimizer
|
22
|
+
from .security_enforcer import SecurityEnforcer
|
23
|
+
from .lifecycle_manager import ResourceLifecycleManager
|
24
|
+
from .infrastructure_optimizer import InfrastructureOptimizer
|
25
|
+
from .monitoring_automation import MonitoringAutomation
|
26
|
+
|
27
|
+
# Business Interface Layer (recommended for notebook usage)
|
28
|
+
from .interfaces import (
|
29
|
+
BusinessResultSummary,
|
30
|
+
emergency_cost_response,
|
31
|
+
optimize_unused_resources,
|
32
|
+
governance_campaign,
|
33
|
+
security_incident_response,
|
34
|
+
optimize_infrastructure
|
35
|
+
)
|
36
|
+
|
37
|
+
# Enterprise Notebook Framework (NEW in v0.9.1)
|
38
|
+
from .notebook_framework import (
|
39
|
+
NotebookFramework,
|
40
|
+
NotebookMode,
|
41
|
+
AuthenticationStatus,
|
42
|
+
ScenarioMetadata
|
43
|
+
)
|
44
|
+
|
45
|
+
# Type-safe models
|
46
|
+
from .models import (
|
47
|
+
CloudOpsExecutionResult,
|
48
|
+
CostOptimizationResult,
|
49
|
+
SecurityEnforcementResult,
|
50
|
+
BusinessScenario,
|
51
|
+
ResourceImpact
|
52
|
+
)
|
53
|
+
|
54
|
+
__version__ = "0.9.1"
|
55
|
+
__author__ = "CloudOps Enterprise Team"
|
56
|
+
|
57
|
+
__all__ = [
|
58
|
+
# RECOMMENDED: Business Interface Functions (simple notebook usage)
|
59
|
+
"BusinessResultSummary",
|
60
|
+
"emergency_cost_response",
|
61
|
+
"optimize_unused_resources",
|
62
|
+
"governance_campaign",
|
63
|
+
"security_incident_response",
|
64
|
+
"optimize_infrastructure",
|
65
|
+
|
66
|
+
# ENTERPRISE NOTEBOOK FRAMEWORK (v0.9.1)
|
67
|
+
"NotebookFramework",
|
68
|
+
"NotebookMode",
|
69
|
+
"AuthenticationStatus",
|
70
|
+
"ScenarioMetadata",
|
71
|
+
|
72
|
+
# ADVANCED: Core API Classes (async operations)
|
73
|
+
"CostOptimizer",
|
74
|
+
"SecurityEnforcer",
|
75
|
+
"ResourceLifecycleManager",
|
76
|
+
"InfrastructureOptimizer",
|
77
|
+
"MonitoringAutomation",
|
78
|
+
|
79
|
+
# Type-Safe Models
|
80
|
+
"CloudOpsExecutionResult",
|
81
|
+
"CostOptimizationResult",
|
82
|
+
"SecurityEnforcementResult",
|
83
|
+
"BusinessScenario",
|
84
|
+
"ResourceImpact"
|
85
|
+
]
|
86
|
+
|
87
|
+
# Enterprise Usage Examples - Business Interface Layer
|
88
|
+
BUSINESS_SCENARIO_EXAMPLES = {
|
89
|
+
"notebook_consolidation": {
|
90
|
+
"description": "Enterprise notebook framework for consolidated scenarios (NEW in v0.9.1)",
|
91
|
+
"simple_example": "from runbooks.cloudops import NotebookFramework, NotebookMode; framework = NotebookFramework(profile='default', mode=NotebookMode.EXECUTIVE)",
|
92
|
+
"advanced_example": "See notebooks/cloudops/consolidated-cost-optimization.ipynb for comprehensive example"
|
93
|
+
},
|
94
|
+
"cost_emergency": {
|
95
|
+
"description": "Emergency cost optimization for $10K+ monthly spikes",
|
96
|
+
"simple_example": "from runbooks.cloudops import emergency_cost_response; result = emergency_cost_response(profile='billing', cost_spike_threshold=25000)",
|
97
|
+
"advanced_example": "from runbooks.cloudops import CostOptimizer; optimizer = CostOptimizer(); optimizer.optimize_nat_gateways()"
|
98
|
+
},
|
99
|
+
"unused_resources": {
|
100
|
+
"description": "Find unused AWS resources for immediate cost savings",
|
101
|
+
"simple_example": "from runbooks.cloudops import optimize_unused_resources; result = optimize_unused_resources(profile='operations', minimum_cost_threshold=50)",
|
102
|
+
"advanced_example": "from runbooks.cloudops import CostOptimizer; optimizer = CostOptimizer(); optimizer.optimize_idle_ec2_instances()"
|
103
|
+
},
|
104
|
+
"security_incident": {
|
105
|
+
"description": "Automated security compliance remediation",
|
106
|
+
"simple_example": "from runbooks.cloudops import security_incident_response; result = security_incident_response(profile='security', incident_type='s3_encryption')",
|
107
|
+
"advanced_example": "from runbooks.cloudops import SecurityEnforcer; enforcer = SecurityEnforcer(); enforcer.enforce_s3_encryption()"
|
108
|
+
},
|
109
|
+
"governance_campaign": {
|
110
|
+
"description": "Multi-account governance and cleanup operations",
|
111
|
+
"simple_example": "from runbooks.cloudops import governance_campaign; result = governance_campaign(management_profile='org-management', scope='organization')",
|
112
|
+
"advanced_example": "from runbooks.cloudops import ResourceLifecycleManager; manager = ResourceLifecycleManager(); manager.enforce_tagging_standards()"
|
113
|
+
},
|
114
|
+
"infrastructure_optimization": {
|
115
|
+
"description": "Infrastructure optimization and performance recovery",
|
116
|
+
"simple_example": "from runbooks.cloudops import optimize_infrastructure; result = optimize_infrastructure(profile='operations', cost_reduction_target=25)",
|
117
|
+
"advanced_example": "from runbooks.cloudops import InfrastructureOptimizer; optimizer = InfrastructureOptimizer(); optimizer.optimize_load_balancers()"
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
def get_business_scenarios():
|
122
|
+
"""Get available business scenarios with examples."""
|
123
|
+
return BUSINESS_SCENARIO_EXAMPLES
|
@@ -0,0 +1,385 @@
|
|
1
|
+
"""
|
2
|
+
Base CloudOps Class with Enterprise Patterns
|
3
|
+
|
4
|
+
Provides common functionality for all CloudOps automation classes including:
|
5
|
+
- Rich CLI integration with enterprise UX standards
|
6
|
+
- Performance monitoring and benchmarking
|
7
|
+
- AWS profile management with multi-account support
|
8
|
+
- Error handling and logging
|
9
|
+
- Business metrics collection
|
10
|
+
|
11
|
+
Strategic Alignment:
|
12
|
+
- Integrates with existing runbooks architecture
|
13
|
+
- Follows Rich CLI standards from rich_utils.py
|
14
|
+
- Supports multi-profile enterprise configurations
|
15
|
+
"""
|
16
|
+
|
17
|
+
import asyncio
|
18
|
+
import time
|
19
|
+
from typing import Dict, List, Optional, Any, Union
|
20
|
+
import boto3
|
21
|
+
from botocore.exceptions import ClientError, NoCredentialsError, ProfileNotFound
|
22
|
+
from dataclasses import dataclass
|
23
|
+
from datetime import datetime
|
24
|
+
|
25
|
+
from runbooks.common.rich_utils import (
|
26
|
+
console, print_header, print_success, print_error, print_warning, print_info,
|
27
|
+
create_table, create_progress_bar, format_cost, create_panel, STATUS_INDICATORS
|
28
|
+
)
|
29
|
+
from .models import (
|
30
|
+
BusinessScenario, ExecutionMode, RiskLevel,
|
31
|
+
ProfileConfiguration, CloudOpsExecutionResult, BusinessMetrics, ResourceImpact
|
32
|
+
)
|
33
|
+
|
34
|
+
@dataclass
|
35
|
+
class PerformanceBenchmark:
|
36
|
+
"""Performance benchmarking for enterprise operations."""
|
37
|
+
operation_name: str
|
38
|
+
start_time: float
|
39
|
+
end_time: Optional[float] = None
|
40
|
+
success: bool = True
|
41
|
+
error_message: Optional[str] = None
|
42
|
+
|
43
|
+
@property
|
44
|
+
def duration(self) -> float:
|
45
|
+
"""Calculate operation duration."""
|
46
|
+
if self.end_time:
|
47
|
+
return self.end_time - self.start_time
|
48
|
+
return time.time() - self.start_time
|
49
|
+
|
50
|
+
class CloudOpsBase:
|
51
|
+
"""
|
52
|
+
Base class for all CloudOps automation scenarios.
|
53
|
+
|
54
|
+
Provides enterprise-grade functionality including:
|
55
|
+
- Rich CLI integration with consistent UX
|
56
|
+
- Performance monitoring and benchmarking
|
57
|
+
- Multi-account AWS profile management
|
58
|
+
- Error handling with business-focused messaging
|
59
|
+
- Audit trail and logging
|
60
|
+
"""
|
61
|
+
|
62
|
+
def __init__(
|
63
|
+
self,
|
64
|
+
profile: str = "default",
|
65
|
+
dry_run: bool = True,
|
66
|
+
execution_mode: ExecutionMode = ExecutionMode.DRY_RUN
|
67
|
+
):
|
68
|
+
"""
|
69
|
+
Initialize CloudOps base class.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
profile: AWS profile name for operations
|
73
|
+
dry_run: Enable dry-run mode (safe analysis only)
|
74
|
+
execution_mode: Execution mode (dry_run/execute/validate_only)
|
75
|
+
"""
|
76
|
+
self.profile = profile
|
77
|
+
self.dry_run = dry_run
|
78
|
+
self.execution_mode = execution_mode
|
79
|
+
|
80
|
+
# Performance monitoring
|
81
|
+
self.benchmarks: List[PerformanceBenchmark] = []
|
82
|
+
self.session_start_time = time.time()
|
83
|
+
|
84
|
+
# AWS session management
|
85
|
+
self.session: Optional[boto3.Session] = None
|
86
|
+
self.available_regions: List[str] = []
|
87
|
+
|
88
|
+
# Business metrics collection
|
89
|
+
self.resources_analyzed = 0
|
90
|
+
self.resources_impacted: List[ResourceImpact] = []
|
91
|
+
|
92
|
+
# Initialize AWS session
|
93
|
+
self._initialize_aws_session()
|
94
|
+
|
95
|
+
def _initialize_aws_session(self) -> None:
|
96
|
+
"""Initialize AWS session with profile validation."""
|
97
|
+
try:
|
98
|
+
self.session = boto3.Session(profile_name=self.profile)
|
99
|
+
|
100
|
+
# Validate session by getting caller identity
|
101
|
+
sts = self.session.client('sts')
|
102
|
+
identity = sts.get_caller_identity()
|
103
|
+
|
104
|
+
self.account_id = identity.get('Account', 'unknown')
|
105
|
+
self.user_arn = identity.get('Arn', 'unknown')
|
106
|
+
|
107
|
+
print_success(f"AWS session initialized for profile: {self.profile}")
|
108
|
+
print_info(f"Account ID: {self.account_id}")
|
109
|
+
|
110
|
+
except ProfileNotFound:
|
111
|
+
error_msg = f"AWS profile '{self.profile}' not found in local configuration"
|
112
|
+
print_error(error_msg)
|
113
|
+
raise ValueError(error_msg)
|
114
|
+
|
115
|
+
except NoCredentialsError:
|
116
|
+
error_msg = f"No valid credentials found for profile '{self.profile}'"
|
117
|
+
print_error(error_msg)
|
118
|
+
raise ValueError(error_msg)
|
119
|
+
|
120
|
+
except ClientError as e:
|
121
|
+
error_msg = f"AWS authentication failed for profile '{self.profile}': {str(e)}"
|
122
|
+
print_error(error_msg)
|
123
|
+
raise ValueError(error_msg)
|
124
|
+
|
125
|
+
def _get_available_regions(self, service_name: str = 'ec2') -> List[str]:
|
126
|
+
"""Get available AWS regions for a service."""
|
127
|
+
if not self.available_regions:
|
128
|
+
try:
|
129
|
+
client = self.session.client(service_name, region_name='us-east-1')
|
130
|
+
response = client.describe_regions()
|
131
|
+
self.available_regions = [region['RegionName'] for region in response['Regions']]
|
132
|
+
except Exception as e:
|
133
|
+
print_warning(f"Could not fetch available regions: {str(e)}")
|
134
|
+
# Fallback to common regions
|
135
|
+
self.available_regions = [
|
136
|
+
'us-east-1', 'us-west-2', 'eu-west-1', 'ap-southeast-1'
|
137
|
+
]
|
138
|
+
return self.available_regions
|
139
|
+
|
140
|
+
def start_benchmark(self, operation_name: str) -> PerformanceBenchmark:
|
141
|
+
"""Start performance benchmarking for an operation."""
|
142
|
+
benchmark = PerformanceBenchmark(
|
143
|
+
operation_name=operation_name,
|
144
|
+
start_time=time.time()
|
145
|
+
)
|
146
|
+
self.benchmarks.append(benchmark)
|
147
|
+
return benchmark
|
148
|
+
|
149
|
+
def complete_benchmark(
|
150
|
+
self,
|
151
|
+
benchmark: PerformanceBenchmark,
|
152
|
+
success: bool = True,
|
153
|
+
error_message: Optional[str] = None
|
154
|
+
) -> None:
|
155
|
+
"""Complete performance benchmarking."""
|
156
|
+
benchmark.end_time = time.time()
|
157
|
+
benchmark.success = success
|
158
|
+
benchmark.error_message = error_message
|
159
|
+
|
160
|
+
duration = benchmark.duration
|
161
|
+
|
162
|
+
# Rich CLI performance feedback
|
163
|
+
if success:
|
164
|
+
if duration < 30: # < 30s target for single account
|
165
|
+
print_success(f"✅ {benchmark.operation_name} completed ({duration:.1f}s)")
|
166
|
+
elif duration < 120: # < 120s target for multi-account
|
167
|
+
print_warning(f"⚠️ {benchmark.operation_name} completed ({duration:.1f}s) - approaching time limit")
|
168
|
+
else:
|
169
|
+
print_error(f"⏰ {benchmark.operation_name} completed ({duration:.1f}s) - exceeds performance target")
|
170
|
+
else:
|
171
|
+
print_error(f"❌ {benchmark.operation_name} failed ({duration:.1f}s): {error_message}")
|
172
|
+
|
173
|
+
async def execute_with_monitoring(
|
174
|
+
self,
|
175
|
+
operation_name: str,
|
176
|
+
operation_func,
|
177
|
+
*args,
|
178
|
+
**kwargs
|
179
|
+
) -> Any:
|
180
|
+
"""
|
181
|
+
Execute an operation with comprehensive monitoring.
|
182
|
+
|
183
|
+
Args:
|
184
|
+
operation_name: Human-readable operation name
|
185
|
+
operation_func: Async function to execute
|
186
|
+
*args, **kwargs: Arguments to pass to operation_func
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
Result of operation_func execution
|
190
|
+
"""
|
191
|
+
benchmark = self.start_benchmark(operation_name)
|
192
|
+
|
193
|
+
try:
|
194
|
+
with console.status(f"[cyan]Executing {operation_name}..."):
|
195
|
+
if asyncio.iscoroutinefunction(operation_func):
|
196
|
+
result = await operation_func(*args, **kwargs)
|
197
|
+
else:
|
198
|
+
result = operation_func(*args, **kwargs)
|
199
|
+
|
200
|
+
self.complete_benchmark(benchmark, success=True)
|
201
|
+
return result
|
202
|
+
|
203
|
+
except Exception as e:
|
204
|
+
error_message = str(e)
|
205
|
+
self.complete_benchmark(benchmark, success=False, error_message=error_message)
|
206
|
+
|
207
|
+
# Rich CLI error display
|
208
|
+
print_error(f"Operation failed: {operation_name}")
|
209
|
+
print_error(f"Error details: {error_message}")
|
210
|
+
|
211
|
+
raise
|
212
|
+
|
213
|
+
def create_resource_impact(
|
214
|
+
self,
|
215
|
+
resource_type: str,
|
216
|
+
resource_id: str,
|
217
|
+
region: str,
|
218
|
+
estimated_cost: Optional[float] = None,
|
219
|
+
projected_savings: Optional[float] = None,
|
220
|
+
risk_level: RiskLevel = RiskLevel.LOW,
|
221
|
+
modification_required: bool = False,
|
222
|
+
**kwargs
|
223
|
+
) -> ResourceImpact:
|
224
|
+
"""
|
225
|
+
Create a standardized ResourceImpact object.
|
226
|
+
|
227
|
+
Args:
|
228
|
+
resource_type: AWS resource type (e.g., 'nat-gateway', 'ec2-instance')
|
229
|
+
resource_id: Unique resource identifier
|
230
|
+
region: AWS region
|
231
|
+
estimated_cost: Current monthly cost estimate
|
232
|
+
projected_savings: Projected monthly savings
|
233
|
+
risk_level: Risk level for modification
|
234
|
+
modification_required: Whether resource needs modification
|
235
|
+
**kwargs: Additional ResourceImpact fields
|
236
|
+
|
237
|
+
Returns:
|
238
|
+
ResourceImpact object with standardized business metrics
|
239
|
+
"""
|
240
|
+
impact = ResourceImpact(
|
241
|
+
resource_type=resource_type,
|
242
|
+
resource_id=resource_id,
|
243
|
+
region=region,
|
244
|
+
account_id=self.account_id,
|
245
|
+
estimated_monthly_cost=estimated_cost,
|
246
|
+
projected_savings=projected_savings,
|
247
|
+
risk_level=risk_level,
|
248
|
+
modification_required=modification_required,
|
249
|
+
**kwargs
|
250
|
+
)
|
251
|
+
|
252
|
+
self.resources_impacted.append(impact)
|
253
|
+
self.resources_analyzed += 1
|
254
|
+
|
255
|
+
return impact
|
256
|
+
|
257
|
+
def display_execution_summary(self, result: CloudOpsExecutionResult) -> None:
|
258
|
+
"""
|
259
|
+
Display Rich CLI execution summary for business stakeholders.
|
260
|
+
|
261
|
+
Args:
|
262
|
+
result: CloudOpsExecutionResult with business metrics
|
263
|
+
"""
|
264
|
+
# Executive Summary Panel
|
265
|
+
summary_content = (
|
266
|
+
f"📊 Resources Analyzed: {result.resources_analyzed:,}\n"
|
267
|
+
f"🎯 Resources Impacted: {len(result.resources_impacted):,}\n"
|
268
|
+
f"💰 Monthly Savings: {format_cost(result.business_metrics.total_monthly_savings)}\n"
|
269
|
+
f"⏱️ Execution Time: {result.execution_time:.1f}s\n"
|
270
|
+
f"🛡️ Risk Level: {result.business_metrics.overall_risk_level.value.title()}"
|
271
|
+
)
|
272
|
+
|
273
|
+
if result.business_metrics.roi_percentage:
|
274
|
+
summary_content += f"\n📈 ROI: {result.business_metrics.roi_percentage:.1f}%"
|
275
|
+
|
276
|
+
summary_panel = create_panel(
|
277
|
+
summary_content,
|
278
|
+
title="Executive Business Impact Summary",
|
279
|
+
border_style="green" if result.success else "red"
|
280
|
+
)
|
281
|
+
console.print(summary_panel)
|
282
|
+
|
283
|
+
# Performance Benchmarks Table
|
284
|
+
if self.benchmarks:
|
285
|
+
perf_table = create_table(
|
286
|
+
title="Performance Benchmarks",
|
287
|
+
columns=[
|
288
|
+
{"name": "Operation", "style": "cyan"},
|
289
|
+
{"name": "Duration", "style": "yellow"},
|
290
|
+
{"name": "Status", "style": "green"}
|
291
|
+
]
|
292
|
+
)
|
293
|
+
|
294
|
+
for benchmark in self.benchmarks:
|
295
|
+
status_icon = "✅" if benchmark.success else "❌"
|
296
|
+
duration_str = f"{benchmark.duration:.1f}s"
|
297
|
+
|
298
|
+
# Color code performance
|
299
|
+
if benchmark.duration < 30:
|
300
|
+
duration_style = "green"
|
301
|
+
elif benchmark.duration < 120:
|
302
|
+
duration_style = "yellow"
|
303
|
+
else:
|
304
|
+
duration_style = "red"
|
305
|
+
|
306
|
+
perf_table.add_row(
|
307
|
+
benchmark.operation_name,
|
308
|
+
f"[{duration_style}]{duration_str}[/{duration_style}]",
|
309
|
+
status_icon
|
310
|
+
)
|
311
|
+
|
312
|
+
console.print(perf_table)
|
313
|
+
|
314
|
+
# Recommendations Display
|
315
|
+
if result.recommendations:
|
316
|
+
recommendations_text = "\n".join([f"• {rec}" for rec in result.recommendations])
|
317
|
+
rec_panel = create_panel(
|
318
|
+
recommendations_text,
|
319
|
+
title="Strategic Recommendations",
|
320
|
+
border_style="blue"
|
321
|
+
)
|
322
|
+
console.print(rec_panel)
|
323
|
+
|
324
|
+
def create_business_metrics(
|
325
|
+
self,
|
326
|
+
total_savings: float = 0.0,
|
327
|
+
implementation_cost: Optional[float] = None,
|
328
|
+
overall_risk: RiskLevel = RiskLevel.LOW
|
329
|
+
) -> BusinessMetrics:
|
330
|
+
"""
|
331
|
+
Create standardized business metrics for executive reporting.
|
332
|
+
|
333
|
+
Args:
|
334
|
+
total_savings: Total projected monthly savings
|
335
|
+
implementation_cost: One-time implementation cost
|
336
|
+
overall_risk: Overall risk level for the operation
|
337
|
+
|
338
|
+
Returns:
|
339
|
+
BusinessMetrics object with calculated ROI and business impact
|
340
|
+
"""
|
341
|
+
# Calculate ROI if implementation cost is provided
|
342
|
+
roi_percentage = None
|
343
|
+
payback_period = None
|
344
|
+
|
345
|
+
if implementation_cost and implementation_cost > 0 and total_savings > 0:
|
346
|
+
annual_savings = total_savings * 12
|
347
|
+
roi_percentage = (annual_savings / implementation_cost - 1) * 100
|
348
|
+
payback_period = int(implementation_cost / total_savings)
|
349
|
+
|
350
|
+
return BusinessMetrics(
|
351
|
+
total_monthly_savings=total_savings,
|
352
|
+
implementation_cost=implementation_cost,
|
353
|
+
roi_percentage=roi_percentage,
|
354
|
+
payback_period_months=payback_period,
|
355
|
+
overall_risk_level=overall_risk,
|
356
|
+
operational_efficiency_gain=80.0 if total_savings > 1000 else 50.0, # Estimate based on savings
|
357
|
+
manual_effort_reduction=90.0, # High automation benefit
|
358
|
+
business_continuity_impact="minimal"
|
359
|
+
)
|
360
|
+
|
361
|
+
def get_session_summary(self) -> Dict[str, Any]:
|
362
|
+
"""Get comprehensive session summary for audit trail."""
|
363
|
+
total_duration = time.time() - self.session_start_time
|
364
|
+
successful_ops = sum(1 for b in self.benchmarks if b.success)
|
365
|
+
failed_ops = len(self.benchmarks) - successful_ops
|
366
|
+
|
367
|
+
return {
|
368
|
+
"profile_used": self.profile,
|
369
|
+
"account_id": getattr(self, 'account_id', 'unknown'),
|
370
|
+
"execution_mode": self.execution_mode.value,
|
371
|
+
"total_session_duration": total_duration,
|
372
|
+
"resources_analyzed": self.resources_analyzed,
|
373
|
+
"resources_impacted": len(self.resources_impacted),
|
374
|
+
"successful_operations": successful_ops,
|
375
|
+
"failed_operations": failed_ops,
|
376
|
+
"performance_benchmarks": [
|
377
|
+
{
|
378
|
+
"operation": b.operation_name,
|
379
|
+
"duration": b.duration,
|
380
|
+
"success": b.success,
|
381
|
+
"error": b.error_message
|
382
|
+
}
|
383
|
+
for b in self.benchmarks
|
384
|
+
]
|
385
|
+
}
|