runbooks 1.1.3__py3-none-any.whl → 1.1.5__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 +31 -2
- runbooks/__init___optimized.py +18 -4
- runbooks/_platform/__init__.py +1 -5
- runbooks/_platform/core/runbooks_wrapper.py +141 -138
- runbooks/aws2/accuracy_validator.py +812 -0
- runbooks/base.py +7 -0
- runbooks/cfat/WEIGHT_CONFIG_README.md +1 -1
- runbooks/cfat/assessment/compliance.py +8 -8
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cfat/models.py +6 -2
- runbooks/cfat/tests/__init__.py +6 -1
- runbooks/cli/__init__.py +13 -0
- runbooks/cli/commands/cfat.py +274 -0
- runbooks/cli/commands/finops.py +1164 -0
- runbooks/cli/commands/inventory.py +379 -0
- runbooks/cli/commands/operate.py +239 -0
- runbooks/cli/commands/security.py +248 -0
- runbooks/cli/commands/validation.py +825 -0
- runbooks/cli/commands/vpc.py +310 -0
- runbooks/cli/registry.py +107 -0
- runbooks/cloudops/__init__.py +23 -30
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +549 -547
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +226 -227
- runbooks/cloudops/lifecycle_manager.py +5 -4
- runbooks/cloudops/mcp_cost_validation.py +252 -235
- runbooks/cloudops/models.py +78 -53
- runbooks/cloudops/monitoring_automation.py +5 -4
- runbooks/cloudops/notebook_framework.py +179 -215
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +11 -0
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +341 -0
- runbooks/common/aws_utils.py +75 -80
- runbooks/common/business_logic.py +127 -105
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
- runbooks/common/cross_account_manager.py +198 -205
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +235 -0
- runbooks/common/dry_run_examples.py +173 -208
- runbooks/common/dry_run_framework.py +157 -155
- runbooks/common/enhanced_exception_handler.py +15 -4
- runbooks/common/enhanced_logging_example.py +50 -64
- runbooks/common/enhanced_logging_integration_example.py +65 -37
- runbooks/common/env_utils.py +16 -16
- runbooks/common/error_handling.py +40 -38
- runbooks/common/lazy_loader.py +41 -23
- runbooks/common/logging_integration_helper.py +79 -86
- runbooks/common/mcp_cost_explorer_integration.py +478 -495
- runbooks/common/mcp_integration.py +63 -74
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +176 -194
- runbooks/common/patterns.py +204 -0
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +248 -39
- runbooks/common/rich_utils.py +643 -92
- runbooks/common/sre_performance_suite.py +177 -186
- runbooks/enterprise/__init__.py +1 -1
- runbooks/enterprise/logging.py +144 -106
- runbooks/enterprise/security.py +187 -204
- runbooks/enterprise/validation.py +43 -56
- runbooks/finops/__init__.py +29 -33
- runbooks/finops/account_resolver.py +1 -1
- runbooks/finops/advanced_optimization_engine.py +980 -0
- runbooks/finops/automation_core.py +268 -231
- runbooks/finops/business_case_config.py +184 -179
- runbooks/finops/cli.py +660 -139
- runbooks/finops/commvault_ec2_analysis.py +157 -164
- runbooks/finops/compute_cost_optimizer.py +336 -320
- runbooks/finops/config.py +20 -20
- runbooks/finops/cost_optimizer.py +488 -622
- runbooks/finops/cost_processor.py +332 -214
- runbooks/finops/dashboard_runner.py +1006 -172
- runbooks/finops/ebs_cost_optimizer.py +991 -657
- runbooks/finops/elastic_ip_optimizer.py +317 -257
- runbooks/finops/enhanced_mcp_integration.py +340 -0
- runbooks/finops/enhanced_progress.py +40 -37
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +230 -292
- runbooks/finops/executive_export.py +203 -160
- runbooks/finops/helpers.py +130 -288
- runbooks/finops/iam_guidance.py +1 -1
- runbooks/finops/infrastructure/__init__.py +80 -0
- runbooks/finops/infrastructure/commands.py +506 -0
- runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
- runbooks/finops/markdown_exporter.py +338 -175
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1513 -482
- runbooks/finops/network_cost_optimizer.py +657 -587
- runbooks/finops/notebook_utils.py +226 -188
- runbooks/finops/optimization_engine.py +1136 -0
- runbooks/finops/optimizer.py +25 -29
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +77 -78
- runbooks/finops/scenarios.py +1278 -439
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/tests/test_finops_dashboard.py +3 -3
- runbooks/finops/tests/test_reference_images_validation.py +2 -2
- runbooks/finops/tests/test_single_account_features.py +17 -17
- runbooks/finops/tests/validate_test_suite.py +1 -1
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +263 -269
- runbooks/finops/vpc_cleanup_exporter.py +191 -146
- runbooks/finops/vpc_cleanup_optimizer.py +593 -575
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/hitl/enhanced_workflow_engine.py +1 -1
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/README.md +3 -3
- runbooks/inventory/Tests/common_test_data.py +30 -30
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +28 -11
- runbooks/inventory/collectors/aws_networking.py +111 -101
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/discovery.md +2 -2
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/find_ec2_security_groups.py +1 -1
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/mcp_inventory_validator.py +549 -465
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +56 -52
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +733 -696
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +3 -3
- runbooks/main.py +152 -9147
- runbooks/main_final.py +91 -60
- runbooks/main_minimal.py +22 -10
- runbooks/main_optimized.py +131 -100
- runbooks/main_ultra_minimal.py +7 -2
- runbooks/mcp/__init__.py +36 -0
- runbooks/mcp/integration.py +679 -0
- runbooks/metrics/dora_metrics_engine.py +2 -2
- runbooks/monitoring/performance_monitor.py +9 -4
- runbooks/operate/dynamodb_operations.py +3 -1
- runbooks/operate/ec2_operations.py +145 -137
- runbooks/operate/iam_operations.py +146 -152
- runbooks/operate/mcp_integration.py +1 -1
- runbooks/operate/networking_cost_heatmap.py +33 -10
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/operate/vpc_operations.py +648 -618
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +71 -67
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +91 -65
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +49 -44
- runbooks/security/__init__.py +19 -0
- runbooks/security/assessment_runner.py +1150 -0
- runbooks/security/baseline_checker.py +812 -0
- runbooks/security/cloudops_automation_security_validator.py +509 -535
- runbooks/security/compliance_automation_engine.py +17 -17
- runbooks/security/config/__init__.py +2 -2
- runbooks/security/config/compliance_config.py +50 -50
- runbooks/security/config_template_generator.py +63 -76
- runbooks/security/enterprise_security_framework.py +1 -1
- runbooks/security/executive_security_dashboard.py +519 -508
- runbooks/security/integration_test_enterprise_security.py +5 -3
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/run_script.py +1 -1
- runbooks/security/security_baseline_tester.py +1 -1
- runbooks/security/security_cli.py +143 -112
- runbooks/security/test_2way_validation.py +439 -0
- runbooks/security/two_way_validation_framework.py +852 -0
- runbooks/sre/mcp_reliability_engine.py +6 -6
- runbooks/sre/production_monitoring_framework.py +167 -177
- runbooks/tdd/__init__.py +15 -0
- runbooks/tdd/cli.py +1071 -0
- runbooks/utils/__init__.py +14 -17
- runbooks/utils/logger.py +7 -2
- runbooks/utils/version_validator.py +51 -48
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +754 -708
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +447 -451
- runbooks/vpc/README.md +617 -0
- runbooks/vpc/__init__.py +8 -1
- runbooks/vpc/analyzer.py +577 -0
- runbooks/vpc/cleanup_wrapper.py +476 -413
- runbooks/vpc/cli_cloudtrail_commands.py +339 -0
- runbooks/vpc/cli_mcp_validation_commands.py +480 -0
- runbooks/vpc/cloudtrail_audit_integration.py +717 -0
- runbooks/vpc/config.py +92 -97
- runbooks/vpc/cost_engine.py +411 -148
- runbooks/vpc/cost_explorer_integration.py +553 -0
- runbooks/vpc/cross_account_session.py +101 -106
- runbooks/vpc/enhanced_mcp_validation.py +917 -0
- runbooks/vpc/eni_gate_validator.py +961 -0
- runbooks/vpc/heatmap_engine.py +190 -162
- runbooks/vpc/mcp_no_eni_validator.py +681 -640
- runbooks/vpc/nat_gateway_optimizer.py +358 -0
- runbooks/vpc/networking_wrapper.py +15 -8
- runbooks/vpc/pdca_remediation_planner.py +528 -0
- runbooks/vpc/performance_optimized_analyzer.py +219 -231
- runbooks/vpc/runbooks_adapter.py +1167 -241
- runbooks/vpc/tdd_red_phase_stubs.py +601 -0
- runbooks/vpc/test_data_loader.py +358 -0
- runbooks/vpc/tests/conftest.py +314 -4
- runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
- runbooks/vpc/tests/test_cost_engine.py +0 -2
- runbooks/vpc/topology_generator.py +326 -0
- runbooks/vpc/unified_scenarios.py +1302 -1129
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
- runbooks/finops/README.md +0 -414
- runbooks/finops/accuracy_cross_validator.py +0 -647
- runbooks/finops/business_cases.py +0 -950
- runbooks/finops/dashboard_router.py +0 -922
- runbooks/finops/ebs_optimizer.py +0 -956
- runbooks/finops/embedded_mcp_validator.py +0 -1629
- runbooks/finops/enhanced_dashboard_runner.py +0 -527
- runbooks/finops/finops_dashboard.py +0 -584
- runbooks/finops/finops_scenarios.py +0 -1218
- runbooks/finops/legacy_migration.py +0 -730
- runbooks/finops/multi_dashboard.py +0 -1519
- runbooks/finops/single_dashboard.py +0 -1113
- runbooks/finops/unlimited_scenarios.py +0 -393
- runbooks-1.1.3.dist-info/METADATA +0 -799
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -13,22 +13,31 @@ from dataclasses import dataclass, field
|
|
13
13
|
from enum import Enum
|
14
14
|
|
15
15
|
from .rich_utils import (
|
16
|
-
create_table,
|
17
|
-
|
16
|
+
create_table,
|
17
|
+
console,
|
18
|
+
print_header,
|
19
|
+
print_success,
|
20
|
+
print_info,
|
21
|
+
print_warning,
|
22
|
+
format_cost,
|
23
|
+
create_panel,
|
24
|
+
create_progress_bar,
|
18
25
|
)
|
19
26
|
from .profile_utils import get_profile_for_operation
|
20
27
|
|
21
28
|
|
22
29
|
class BusinessImpactLevel(Enum):
|
23
30
|
"""Business impact classification for operations and optimizations."""
|
31
|
+
|
24
32
|
CRITICAL = "CRITICAL" # >$100K annual impact
|
25
|
-
HIGH = "HIGH"
|
26
|
-
MEDIUM = "MEDIUM"
|
27
|
-
LOW = "LOW"
|
33
|
+
HIGH = "HIGH" # measurable range annual impact
|
34
|
+
MEDIUM = "MEDIUM" # measurable range annual impact
|
35
|
+
LOW = "LOW" # <$5K annual impact
|
28
36
|
|
29
37
|
|
30
38
|
class OptimizationType(Enum):
|
31
39
|
"""Types of optimization operations supported."""
|
40
|
+
|
32
41
|
COST_REDUCTION = "COST_REDUCTION"
|
33
42
|
RESOURCE_EFFICIENCY = "RESOURCE_EFFICIENCY"
|
34
43
|
SECURITY_COMPLIANCE = "SECURITY_COMPLIANCE"
|
@@ -39,6 +48,7 @@ class OptimizationType(Enum):
|
|
39
48
|
@dataclass
|
40
49
|
class BusinessMetrics:
|
41
50
|
"""Universal business metrics for operations and optimizations."""
|
51
|
+
|
42
52
|
annual_savings: float = 0.0
|
43
53
|
monthly_cost_current: float = 0.0
|
44
54
|
monthly_cost_optimized: float = 0.0
|
@@ -70,6 +80,7 @@ class BusinessMetrics:
|
|
70
80
|
@dataclass
|
71
81
|
class OptimizationResult:
|
72
82
|
"""Universal optimization result structure."""
|
83
|
+
|
73
84
|
resource_type: str
|
74
85
|
operation_type: OptimizationType
|
75
86
|
business_metrics: BusinessMetrics
|
@@ -101,8 +112,9 @@ class UniversalBusinessLogic:
|
|
101
112
|
self.module_name = module_name
|
102
113
|
self.session_metrics = []
|
103
114
|
|
104
|
-
def create_cost_analysis_table(
|
105
|
-
|
115
|
+
def create_cost_analysis_table(
|
116
|
+
self, cost_data: Dict[str, Any], title: str, include_quarterly: bool = False
|
117
|
+
) -> None:
|
106
118
|
"""
|
107
119
|
Standardized cost analysis table creation following FinOps patterns.
|
108
120
|
|
@@ -111,10 +123,7 @@ class UniversalBusinessLogic:
|
|
111
123
|
title: Table title for display
|
112
124
|
include_quarterly: Include quarterly intelligence columns
|
113
125
|
"""
|
114
|
-
table = create_table(
|
115
|
-
title=title,
|
116
|
-
caption="Enterprise cost analysis with MCP validation"
|
117
|
-
)
|
126
|
+
table = create_table(title=title, caption="Enterprise cost analysis with MCP validation")
|
118
127
|
|
119
128
|
# Standard columns based on successful FinOps patterns
|
120
129
|
table.add_column("Resource", style="cyan", no_wrap=True)
|
@@ -129,21 +138,16 @@ class UniversalBusinessLogic:
|
|
129
138
|
# Add rows with consistent formatting
|
130
139
|
total_savings = 0.0
|
131
140
|
for resource, data in cost_data.items():
|
132
|
-
current_cost = data.get(
|
133
|
-
optimization_pct = data.get(
|
134
|
-
annual_savings = data.get(
|
141
|
+
current_cost = data.get("current", 0.0)
|
142
|
+
optimization_pct = data.get("optimization_percentage", 0.0)
|
143
|
+
annual_savings = data.get("annual_savings", 0.0)
|
135
144
|
total_savings += annual_savings
|
136
145
|
|
137
|
-
row_data = [
|
138
|
-
resource,
|
139
|
-
format_cost(current_cost),
|
140
|
-
f"{optimization_pct:.1f}%",
|
141
|
-
format_cost(annual_savings)
|
142
|
-
]
|
146
|
+
row_data = [resource, format_cost(current_cost), f"{optimization_pct:.1f}%", format_cost(annual_savings)]
|
143
147
|
|
144
148
|
if include_quarterly:
|
145
|
-
quarterly_trend = data.get(
|
146
|
-
strategic_context = data.get(
|
149
|
+
quarterly_trend = data.get("quarterly_trend", "Stable")
|
150
|
+
strategic_context = data.get("strategic_context", "Monitor")
|
147
151
|
row_data.extend([quarterly_trend, strategic_context])
|
148
152
|
|
149
153
|
table.add_row(*row_data)
|
@@ -163,17 +167,14 @@ class UniversalBusinessLogic:
|
|
163
167
|
[bold bright_green]Total Annual Savings: {format_cost(total_savings)}[/]
|
164
168
|
[yellow]Business Impact: {impact_level.value}[/]
|
165
169
|
[cyan]Resources Analyzed: {len(cost_data)}[/]
|
166
|
-
[dim]Analysis Timestamp: {datetime.now().strftime(
|
170
|
+
[dim]Analysis Timestamp: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}[/]
|
167
171
|
"""
|
168
|
-
summary_panel = create_panel(
|
169
|
-
summary_text.strip(),
|
170
|
-
title="💰 Executive Summary",
|
171
|
-
border_style="green"
|
172
|
-
)
|
172
|
+
summary_panel = create_panel(summary_text.strip(), title="💰 Executive Summary", border_style="green")
|
173
173
|
console.print(summary_panel)
|
174
174
|
|
175
|
-
def standardize_resource_operations(
|
176
|
-
|
175
|
+
def standardize_resource_operations(
|
176
|
+
self, resource_type: str, operation: str, profile: Optional[str] = None, **kwargs
|
177
|
+
) -> Dict[str, Any]:
|
177
178
|
"""
|
178
179
|
Standardized resource operation pattern following proven CLI patterns.
|
179
180
|
|
@@ -189,7 +190,7 @@ class UniversalBusinessLogic:
|
|
189
190
|
# Apply proven profile management patterns
|
190
191
|
selected_profile = get_profile_for_operation("operational", profile)
|
191
192
|
|
192
|
-
print_header(f"{resource_type.title()} {operation.title()}", f"
|
193
|
+
print_header(f"{resource_type.title()} {operation.title()}", f"latest version - {self.module_name}")
|
193
194
|
print_info(f"Using profile: {selected_profile}")
|
194
195
|
|
195
196
|
# Standard operation tracking
|
@@ -197,19 +198,16 @@ class UniversalBusinessLogic:
|
|
197
198
|
|
198
199
|
# Standard result format following successful patterns
|
199
200
|
result = {
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
'start_time': operation_start.isoformat(),
|
211
|
-
'execution_time_seconds': 0.0
|
212
|
-
}
|
201
|
+
"module": self.module_name,
|
202
|
+
"resource_type": resource_type,
|
203
|
+
"operation": operation,
|
204
|
+
"profile_used": selected_profile,
|
205
|
+
"timestamp": operation_start.isoformat(),
|
206
|
+
"success": True,
|
207
|
+
"results": {},
|
208
|
+
"business_metrics": BusinessMetrics(),
|
209
|
+
"recommendations": [],
|
210
|
+
"performance_data": {"start_time": operation_start.isoformat(), "execution_time_seconds": 0.0},
|
213
211
|
}
|
214
212
|
|
215
213
|
return result
|
@@ -230,30 +228,38 @@ class UniversalBusinessLogic:
|
|
230
228
|
|
231
229
|
# Impact-based recommendations
|
232
230
|
if impact == BusinessImpactLevel.CRITICAL:
|
233
|
-
recommendations.extend(
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
231
|
+
recommendations.extend(
|
232
|
+
[
|
233
|
+
f"🚨 CRITICAL: Immediate action required - ${metrics.annual_savings:,.0f} annual savings opportunity",
|
234
|
+
"📋 Executive approval recommended for implementation",
|
235
|
+
"⏰ Target implementation: Within 30 days",
|
236
|
+
"📊 Monthly progress tracking recommended",
|
237
|
+
]
|
238
|
+
)
|
239
239
|
elif impact == BusinessImpactLevel.HIGH:
|
240
|
-
recommendations.extend(
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
240
|
+
recommendations.extend(
|
241
|
+
[
|
242
|
+
f"🔴 HIGH PRIORITY: ${metrics.annual_savings:,.0f} annual savings available",
|
243
|
+
"📋 Business case development recommended",
|
244
|
+
"⏰ Target implementation: Within 90 days",
|
245
|
+
"📊 Quarterly progress review recommended",
|
246
|
+
]
|
247
|
+
)
|
246
248
|
elif impact == BusinessImpactLevel.MEDIUM:
|
247
|
-
recommendations.extend(
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
249
|
+
recommendations.extend(
|
250
|
+
[
|
251
|
+
f"🟡 MEDIUM PRIORITY: ${metrics.annual_savings:,.0f} annual savings potential",
|
252
|
+
"📋 Consider in next planning cycle",
|
253
|
+
"⏰ Target implementation: Within 6 months",
|
254
|
+
]
|
255
|
+
)
|
252
256
|
else:
|
253
|
-
recommendations.extend(
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
+
recommendations.extend(
|
258
|
+
[
|
259
|
+
f"🟢 LOW PRIORITY: ${metrics.annual_savings:,.0f} annual savings",
|
260
|
+
"📋 Include in routine optimization reviews",
|
261
|
+
]
|
262
|
+
)
|
257
263
|
|
258
264
|
# ROI-based recommendations
|
259
265
|
if metrics.roi_percentage > 200:
|
@@ -271,8 +277,9 @@ class UniversalBusinessLogic:
|
|
271
277
|
|
272
278
|
return recommendations
|
273
279
|
|
274
|
-
def create_executive_dashboard(
|
275
|
-
|
280
|
+
def create_executive_dashboard(
|
281
|
+
self, results: List[OptimizationResult], dashboard_title: str = "Executive Dashboard"
|
282
|
+
) -> None:
|
276
283
|
"""
|
277
284
|
Create executive dashboard following successful FinOps patterns.
|
278
285
|
|
@@ -288,7 +295,14 @@ class UniversalBusinessLogic:
|
|
288
295
|
|
289
296
|
# Summary metrics
|
290
297
|
total_savings = sum(r.business_metrics.annual_savings for r in results)
|
291
|
-
high_impact_count = len(
|
298
|
+
high_impact_count = len(
|
299
|
+
[
|
300
|
+
r
|
301
|
+
for r in results
|
302
|
+
if r.business_metrics.determine_impact_level()
|
303
|
+
in [BusinessImpactLevel.CRITICAL, BusinessImpactLevel.HIGH]
|
304
|
+
]
|
305
|
+
)
|
292
306
|
|
293
307
|
# Executive summary table
|
294
308
|
summary_table = create_table(
|
@@ -296,13 +310,17 @@ class UniversalBusinessLogic:
|
|
296
310
|
columns=[
|
297
311
|
{"name": "Metric", "style": "cyan", "justify": "left"},
|
298
312
|
{"name": "Value", "style": "bright_green", "justify": "right"},
|
299
|
-
{"name": "Impact", "style": "yellow", "justify": "left"}
|
300
|
-
]
|
313
|
+
{"name": "Impact", "style": "yellow", "justify": "left"},
|
314
|
+
],
|
301
315
|
)
|
302
316
|
|
303
317
|
summary_table.add_row("Total Annual Savings", format_cost(total_savings), f"{len(results)} opportunities")
|
304
318
|
summary_table.add_row("High Priority Items", str(high_impact_count), "Immediate attention required")
|
305
|
-
summary_table.add_row(
|
319
|
+
summary_table.add_row(
|
320
|
+
"Average Confidence",
|
321
|
+
f"{sum(r.business_metrics.confidence_level for r in results) / len(results):.1f}%",
|
322
|
+
"Validation accuracy",
|
323
|
+
)
|
306
324
|
|
307
325
|
console.print(summary_table)
|
308
326
|
|
@@ -318,8 +336,8 @@ class UniversalBusinessLogic:
|
|
318
336
|
{"name": "Annual Savings", "style": "bright_green", "justify": "right"},
|
319
337
|
{"name": "Impact", "style": "yellow", "justify": "center"},
|
320
338
|
{"name": "Confidence", "style": "blue", "justify": "right"},
|
321
|
-
{"name": "Next Action", "style": "white", "justify": "left"}
|
322
|
-
]
|
339
|
+
{"name": "Next Action", "style": "white", "justify": "left"},
|
340
|
+
],
|
323
341
|
)
|
324
342
|
|
325
343
|
for result in top_results:
|
@@ -331,7 +349,7 @@ class UniversalBusinessLogic:
|
|
331
349
|
format_cost(result.business_metrics.annual_savings),
|
332
350
|
impact.value,
|
333
351
|
f"{result.business_metrics.confidence_level:.1f}%",
|
334
|
-
next_action
|
352
|
+
next_action,
|
335
353
|
)
|
336
354
|
|
337
355
|
console.print(opportunities_table)
|
@@ -350,8 +368,8 @@ class UniversalBusinessLogic:
|
|
350
368
|
metrics = BusinessMetrics()
|
351
369
|
|
352
370
|
# Extract costs
|
353
|
-
current_monthly = usage_data.get(
|
354
|
-
optimized_monthly = usage_data.get(
|
371
|
+
current_monthly = usage_data.get("monthly_cost_current", 0.0)
|
372
|
+
optimized_monthly = usage_data.get("monthly_cost_optimized", current_monthly * 0.7) # Default 30% optimization
|
355
373
|
|
356
374
|
metrics.monthly_cost_current = current_monthly
|
357
375
|
metrics.monthly_cost_optimized = optimized_monthly
|
@@ -362,12 +380,12 @@ class UniversalBusinessLogic:
|
|
362
380
|
|
363
381
|
# Set confidence based on resource type (following successful patterns)
|
364
382
|
confidence_levels = {
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
383
|
+
"NAT Gateway": 95.0, # High confidence from proven results
|
384
|
+
"Elastic IP": 90.0,
|
385
|
+
"EBS Volume": 85.0,
|
386
|
+
"EC2 Instance": 80.0,
|
387
|
+
"RDS Instance": 75.0,
|
388
|
+
"Generic": 70.0,
|
371
389
|
}
|
372
390
|
metrics.confidence_level = confidence_levels.get(resource_type, 70.0)
|
373
391
|
|
@@ -384,8 +402,9 @@ class UniversalBusinessLogic:
|
|
384
402
|
|
385
403
|
return metrics
|
386
404
|
|
387
|
-
def export_business_results(
|
388
|
-
|
405
|
+
def export_business_results(
|
406
|
+
self, results: List[OptimizationResult], export_formats: List[str] = None
|
407
|
+
) -> Dict[str, str]:
|
389
408
|
"""
|
390
409
|
Export business results in multiple formats following successful patterns.
|
391
410
|
|
@@ -397,9 +416,9 @@ class UniversalBusinessLogic:
|
|
397
416
|
Dictionary with export file paths
|
398
417
|
"""
|
399
418
|
if export_formats is None:
|
400
|
-
export_formats = [
|
419
|
+
export_formats = ["csv", "json", "markdown"]
|
401
420
|
|
402
|
-
timestamp = datetime.now().strftime(
|
421
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
403
422
|
base_filename = f"{self.module_name}_optimization_results_{timestamp}"
|
404
423
|
|
405
424
|
exported_files = {}
|
@@ -409,41 +428,44 @@ class UniversalBusinessLogic:
|
|
409
428
|
for fmt in export_formats:
|
410
429
|
filename = f"./awso_evidence/{base_filename}.{fmt}"
|
411
430
|
|
412
|
-
if fmt ==
|
431
|
+
if fmt == "csv":
|
413
432
|
# CSV export for analysis
|
414
433
|
csv_content = "Resource,Annual_Savings,Impact_Level,Confidence,ROI_Percentage\n"
|
415
434
|
for result in results:
|
416
435
|
csv_content += f"{result.resource_type},{result.business_metrics.annual_savings},"
|
417
436
|
csv_content += f"{result.business_metrics.determine_impact_level().value},"
|
418
|
-
csv_content +=
|
437
|
+
csv_content += (
|
438
|
+
f"{result.business_metrics.confidence_level},{result.business_metrics.roi_percentage}\n"
|
439
|
+
)
|
419
440
|
|
420
|
-
with open(filename,
|
441
|
+
with open(filename, "w") as f:
|
421
442
|
f.write(csv_content)
|
422
443
|
|
423
|
-
elif fmt ==
|
444
|
+
elif fmt == "json":
|
424
445
|
# JSON export for systems integration
|
425
446
|
import json
|
447
|
+
|
426
448
|
json_data = {
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
449
|
+
"module": self.module_name,
|
450
|
+
"timestamp": timestamp,
|
451
|
+
"total_results": len(results),
|
452
|
+
"total_annual_savings": sum(r.business_metrics.annual_savings for r in results),
|
453
|
+
"results": [
|
432
454
|
{
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
455
|
+
"resource_type": r.resource_type,
|
456
|
+
"annual_savings": r.business_metrics.annual_savings,
|
457
|
+
"impact_level": r.business_metrics.determine_impact_level().value,
|
458
|
+
"confidence_level": r.business_metrics.confidence_level,
|
459
|
+
"executive_summary": r.get_executive_summary(),
|
438
460
|
}
|
439
461
|
for r in results
|
440
|
-
]
|
462
|
+
],
|
441
463
|
}
|
442
464
|
|
443
|
-
with open(filename,
|
465
|
+
with open(filename, "w") as f:
|
444
466
|
json.dump(json_data, f, indent=2)
|
445
467
|
|
446
|
-
elif fmt ==
|
468
|
+
elif fmt == "markdown":
|
447
469
|
# Markdown export for documentation and reports
|
448
470
|
md_content = f"# {self.module_name.title()} Optimization Results\n\n"
|
449
471
|
md_content += f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
@@ -462,7 +484,7 @@ class UniversalBusinessLogic:
|
|
462
484
|
md_content += f"- **Confidence**: {result.business_metrics.confidence_level:.1f}%\n"
|
463
485
|
md_content += f"- **ROI**: {result.business_metrics.roi_percentage:.1f}%\n\n"
|
464
486
|
|
465
|
-
with open(filename,
|
487
|
+
with open(filename, "w") as f:
|
466
488
|
f.write(md_content)
|
467
489
|
|
468
490
|
exported_files[fmt] = filename
|
@@ -482,4 +504,4 @@ def create_business_logic_handler(module_name: str) -> UniversalBusinessLogic:
|
|
482
504
|
Returns:
|
483
505
|
UniversalBusinessLogic instance configured for the module
|
484
506
|
"""
|
485
|
-
return UniversalBusinessLogic(module_name)
|
507
|
+
return UniversalBusinessLogic(module_name)
|
@@ -27,26 +27,19 @@ def common_aws_options(f: Callable) -> Callable:
|
|
27
27
|
def my_command(profile, region, dry_run, **kwargs):
|
28
28
|
# Your command logic here
|
29
29
|
"""
|
30
|
+
|
31
|
+
@click.option("--profile", help="AWS profile override (highest priority over environment variables)", type=str)
|
32
|
+
@click.option("--region", help="AWS region override (default: us-east-1)", type=str, default="us-east-1")
|
30
33
|
@click.option(
|
31
|
-
|
32
|
-
help='AWS profile override (highest priority over environment variables)',
|
33
|
-
type=str
|
34
|
-
)
|
35
|
-
@click.option(
|
36
|
-
'--region',
|
37
|
-
help='AWS region override (default: us-east-1)',
|
38
|
-
type=str,
|
39
|
-
default='us-east-1'
|
40
|
-
)
|
41
|
-
@click.option(
|
42
|
-
'--dry-run',
|
34
|
+
"--dry-run",
|
43
35
|
is_flag=True,
|
44
36
|
default=True,
|
45
|
-
help=
|
37
|
+
help="Safe analysis mode - no resource modifications (enterprise default)",
|
46
38
|
)
|
47
39
|
@wraps(f)
|
48
40
|
def wrapper(*args, **kwargs):
|
49
41
|
return f(*args, **kwargs)
|
42
|
+
|
50
43
|
return wrapper
|
51
44
|
|
52
45
|
|
@@ -65,26 +58,24 @@ def common_output_options(f: Callable) -> Callable:
|
|
65
58
|
def my_command(output_format, output_dir, export, **kwargs):
|
66
59
|
# Your command logic here
|
67
60
|
"""
|
61
|
+
|
68
62
|
@click.option(
|
69
|
-
|
70
|
-
type=click.Choice([
|
71
|
-
default=
|
72
|
-
help=
|
73
|
-
)
|
74
|
-
@click.option(
|
75
|
-
'--output-dir',
|
76
|
-
default='./awso_evidence',
|
77
|
-
help='Directory for generated files and evidence packages',
|
78
|
-
type=click.Path()
|
63
|
+
"--output-format",
|
64
|
+
type=click.Choice(["json", "csv", "table", "pdf", "markdown"], case_sensitive=False),
|
65
|
+
default="table",
|
66
|
+
help="Output format for results display",
|
79
67
|
)
|
80
68
|
@click.option(
|
81
|
-
|
82
|
-
|
83
|
-
help=
|
69
|
+
"--output-dir",
|
70
|
+
default="./awso_evidence",
|
71
|
+
help="Directory for generated files and evidence packages",
|
72
|
+
type=click.Path(),
|
84
73
|
)
|
74
|
+
@click.option("--export", is_flag=True, help="Enable multi-format export (CSV, JSON, PDF, HTML)")
|
85
75
|
@wraps(f)
|
86
76
|
def wrapper(*args, **kwargs):
|
87
77
|
return f(*args, **kwargs)
|
78
|
+
|
88
79
|
return wrapper
|
89
80
|
|
90
81
|
|
@@ -102,20 +93,18 @@ def mcp_validation_option(f: Callable) -> Callable:
|
|
102
93
|
def my_command(validate, confidence_threshold, **kwargs):
|
103
94
|
# Your command logic with MCP validation
|
104
95
|
"""
|
96
|
+
|
97
|
+
@click.option("--validate", is_flag=True, help="Enable MCP validation for enhanced accuracy (≥99.5% target)")
|
105
98
|
@click.option(
|
106
|
-
|
107
|
-
is_flag=True,
|
108
|
-
help='Enable MCP validation for enhanced accuracy (≥99.5% target)'
|
109
|
-
)
|
110
|
-
@click.option(
|
111
|
-
'--confidence-threshold',
|
99
|
+
"--confidence-threshold",
|
112
100
|
type=float,
|
113
101
|
default=99.5,
|
114
|
-
help=
|
102
|
+
help="Minimum confidence threshold for validation (default: 99.5%%)",
|
115
103
|
)
|
116
104
|
@wraps(f)
|
117
105
|
def wrapper(*args, **kwargs):
|
118
106
|
return f(*args, **kwargs)
|
107
|
+
|
119
108
|
return wrapper
|
120
109
|
|
121
110
|
|
@@ -134,26 +123,21 @@ def enterprise_options(f: Callable) -> Callable:
|
|
134
123
|
def my_command(all_profiles, combine, approval_required, **kwargs):
|
135
124
|
# Your enterprise command logic
|
136
125
|
"""
|
126
|
+
|
137
127
|
@click.option(
|
138
|
-
|
139
|
-
'all_profiles',
|
140
|
-
is_flag=True,
|
141
|
-
help='Use all available AWS profiles for multi-account operations'
|
142
|
-
)
|
143
|
-
@click.option(
|
144
|
-
'--combine',
|
145
|
-
is_flag=True,
|
146
|
-
help='Combine profiles from the same AWS account for unified reporting'
|
128
|
+
"--all", "all_profiles", is_flag=True, help="Use all available AWS profiles for multi-account operations"
|
147
129
|
)
|
130
|
+
@click.option("--combine", is_flag=True, help="Combine profiles from the same AWS account for unified reporting")
|
148
131
|
@click.option(
|
149
|
-
|
132
|
+
"--approval-required",
|
150
133
|
is_flag=True,
|
151
134
|
default=True,
|
152
|
-
help=
|
135
|
+
help="Require human approval for state-changing operations (enterprise default)",
|
153
136
|
)
|
154
137
|
@wraps(f)
|
155
138
|
def wrapper(*args, **kwargs):
|
156
139
|
return f(*args, **kwargs)
|
140
|
+
|
157
141
|
return wrapper
|
158
142
|
|
159
143
|
|
@@ -172,26 +156,16 @@ def performance_options(f: Callable) -> Callable:
|
|
172
156
|
def my_command(performance_target, timeout, parallel, **kwargs):
|
173
157
|
# Your performance-monitored command
|
174
158
|
"""
|
159
|
+
|
175
160
|
@click.option(
|
176
|
-
|
177
|
-
type=int,
|
178
|
-
default=30,
|
179
|
-
help='Target execution time in seconds (enterprise default: 30s)'
|
180
|
-
)
|
181
|
-
@click.option(
|
182
|
-
'--timeout',
|
183
|
-
type=int,
|
184
|
-
default=300,
|
185
|
-
help='Maximum execution timeout in seconds (default: 5 minutes)'
|
186
|
-
)
|
187
|
-
@click.option(
|
188
|
-
'--parallel',
|
189
|
-
is_flag=True,
|
190
|
-
help='Enable parallel processing for multi-resource operations'
|
161
|
+
"--performance-target", type=int, default=30, help="Target execution time in seconds (enterprise default: 30s)"
|
191
162
|
)
|
163
|
+
@click.option("--timeout", type=int, default=300, help="Maximum execution timeout in seconds (default: 5 minutes)")
|
164
|
+
@click.option("--parallel", is_flag=True, help="Enable parallel processing for multi-resource operations")
|
192
165
|
@wraps(f)
|
193
166
|
def wrapper(*args, **kwargs):
|
194
167
|
return f(*args, **kwargs)
|
168
|
+
|
195
169
|
return wrapper
|
196
170
|
|
197
171
|
|
@@ -208,6 +182,7 @@ def all_standard_options(f: Callable) -> Callable:
|
|
208
182
|
def comprehensive_command(**kwargs):
|
209
183
|
# Command with all standard options available
|
210
184
|
"""
|
185
|
+
|
211
186
|
@performance_options
|
212
187
|
@enterprise_options
|
213
188
|
@mcp_validation_option
|
@@ -216,4 +191,5 @@ def all_standard_options(f: Callable) -> Callable:
|
|
216
191
|
@wraps(f)
|
217
192
|
def wrapper(*args, **kwargs):
|
218
193
|
return f(*args, **kwargs)
|
219
|
-
|
194
|
+
|
195
|
+
return wrapper
|