runbooks 0.9.0__py3-none-any.whl → 0.9.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 (46) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/cfat/assessment/compliance.py +4 -1
  3. runbooks/cloudops/__init__.py +123 -0
  4. runbooks/cloudops/base.py +385 -0
  5. runbooks/cloudops/cost_optimizer.py +811 -0
  6. runbooks/cloudops/infrastructure_optimizer.py +29 -0
  7. runbooks/cloudops/interfaces.py +828 -0
  8. runbooks/cloudops/lifecycle_manager.py +29 -0
  9. runbooks/cloudops/mcp_cost_validation.py +678 -0
  10. runbooks/cloudops/models.py +251 -0
  11. runbooks/cloudops/monitoring_automation.py +29 -0
  12. runbooks/cloudops/notebook_framework.py +676 -0
  13. runbooks/cloudops/security_enforcer.py +449 -0
  14. runbooks/common/mcp_cost_explorer_integration.py +900 -0
  15. runbooks/common/mcp_integration.py +19 -10
  16. runbooks/common/rich_utils.py +1 -1
  17. runbooks/finops/README.md +31 -0
  18. runbooks/finops/cost_optimizer.py +1340 -0
  19. runbooks/finops/finops_dashboard.py +211 -5
  20. runbooks/finops/schemas.py +589 -0
  21. runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
  22. runbooks/inventory/runbooks.security.security_export.log +0 -0
  23. runbooks/main.py +525 -0
  24. runbooks/operate/ec2_operations.py +428 -0
  25. runbooks/operate/iam_operations.py +598 -3
  26. runbooks/operate/rds_operations.py +508 -0
  27. runbooks/operate/s3_operations.py +508 -0
  28. runbooks/remediation/base.py +5 -3
  29. runbooks/security/__init__.py +101 -0
  30. runbooks/security/cloudops_automation_security_validator.py +1164 -0
  31. runbooks/security/compliance_automation_engine.py +4 -4
  32. runbooks/security/enterprise_security_framework.py +4 -5
  33. runbooks/security/executive_security_dashboard.py +1247 -0
  34. runbooks/security/multi_account_security_controls.py +2254 -0
  35. runbooks/security/real_time_security_monitor.py +1196 -0
  36. runbooks/security/security_baseline_tester.py +3 -3
  37. runbooks/sre/production_monitoring_framework.py +584 -0
  38. runbooks/validation/mcp_validator.py +29 -15
  39. runbooks/vpc/networking_wrapper.py +6 -3
  40. runbooks-0.9.2.dist-info/METADATA +525 -0
  41. {runbooks-0.9.0.dist-info → runbooks-0.9.2.dist-info}/RECORD +45 -23
  42. runbooks-0.9.0.dist-info/METADATA +0 -718
  43. {runbooks-0.9.0.dist-info → runbooks-0.9.2.dist-info}/WHEEL +0 -0
  44. {runbooks-0.9.0.dist-info → runbooks-0.9.2.dist-info}/entry_points.txt +0 -0
  45. {runbooks-0.9.0.dist-info → runbooks-0.9.2.dist-info}/licenses/LICENSE +0 -0
  46. {runbooks-0.9.0.dist-info → runbooks-0.9.2.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.9.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
- self.session = boto3.Session(profile_name=profile) if profile else boto3.Session()
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
+ }