runbooks 1.1.4__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/assessment/compliance.py +1 -1
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cli/__init__.py +1 -1
- runbooks/cli/commands/cfat.py +64 -23
- runbooks/cli/commands/finops.py +1005 -54
- runbooks/cli/commands/inventory.py +138 -35
- runbooks/cli/commands/operate.py +9 -36
- runbooks/cli/commands/security.py +42 -18
- runbooks/cli/commands/validation.py +432 -18
- runbooks/cli/commands/vpc.py +81 -17
- runbooks/cli/registry.py +22 -10
- runbooks/cloudops/__init__.py +20 -27
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +544 -542
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +224 -225
- 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 +177 -213
- 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 +40 -36
- runbooks/common/aws_utils.py +74 -79
- runbooks/common/business_logic.py +126 -104
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
- runbooks/common/cross_account_manager.py +197 -204
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +29 -19
- 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 +476 -493
- 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 +175 -193
- runbooks/common/patterns.py +23 -25
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +111 -37
- runbooks/common/rich_utils.py +201 -141
- 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 +26 -30
- 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 +484 -618
- 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 +32 -29
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +223 -285
- 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 +337 -174
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1512 -481
- 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 +19 -23
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +64 -65
- runbooks/finops/scenarios.py +1277 -438
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +259 -265
- runbooks/finops/vpc_cleanup_exporter.py +189 -144
- runbooks/finops/vpc_cleanup_optimizer.py +591 -573
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +1 -1
- runbooks/inventory/collectors/aws_networking.py +109 -99
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/drift_detection_cli.py +69 -96
- 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 +55 -51
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +732 -695
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +1 -1
- runbooks/main.py +49 -34
- 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/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/networking_cost_heatmap.py +29 -8
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_operations.py +646 -616
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +70 -66
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +86 -60
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +46 -41
- 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/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- 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/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 +50 -47
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +745 -704
- 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 +185 -160
- runbooks/vpc/mcp_no_eni_validator.py +680 -639
- 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 +1297 -1124
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/RECORD +214 -193
- 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 -973
- 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.4.dist-info/METADATA +0 -800
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -46,8 +46,17 @@ from botocore.exceptions import ClientError, NoCredentialsError
|
|
46
46
|
|
47
47
|
# Internal imports
|
48
48
|
from runbooks.common.rich_utils import (
|
49
|
-
console,
|
50
|
-
|
49
|
+
console,
|
50
|
+
print_header,
|
51
|
+
print_success,
|
52
|
+
print_error,
|
53
|
+
print_warning,
|
54
|
+
print_info,
|
55
|
+
create_table,
|
56
|
+
create_panel,
|
57
|
+
format_cost,
|
58
|
+
create_progress_bar,
|
59
|
+
STATUS_INDICATORS,
|
51
60
|
)
|
52
61
|
|
53
62
|
# Profile and pricing integration
|
@@ -55,6 +64,7 @@ try:
|
|
55
64
|
from runbooks.common.profile_utils import get_profile_for_operation
|
56
65
|
from runbooks.common.aws_pricing import get_aws_pricing_engine, calculate_annual_cost
|
57
66
|
from runbooks.common.mcp_cost_explorer_integration import MCPCostExplorerIntegration
|
67
|
+
|
58
68
|
INTEGRATIONS_AVAILABLE = True
|
59
69
|
except ImportError as e:
|
60
70
|
print_warning(f"Integration modules not fully available: {e}")
|
@@ -63,6 +73,7 @@ except ImportError as e:
|
|
63
73
|
# Terraform drift detection integration
|
64
74
|
try:
|
65
75
|
from runbooks.validation.terraform_drift_detector import TerraformDriftDetector
|
76
|
+
|
66
77
|
TERRAFORM_INTEGRATION_AVAILABLE = True
|
67
78
|
except ImportError:
|
68
79
|
print_warning("Terraform drift detection not available")
|
@@ -74,6 +85,7 @@ logger = logging.getLogger(__name__)
|
|
74
85
|
@dataclass
|
75
86
|
class CostExplorerResult:
|
76
87
|
"""Comprehensive Cost Explorer API result."""
|
88
|
+
|
77
89
|
service_name: str
|
78
90
|
account_id: str
|
79
91
|
region: str
|
@@ -90,6 +102,7 @@ class CostExplorerResult:
|
|
90
102
|
@dataclass
|
91
103
|
class TerraformCostAlignment:
|
92
104
|
"""Terraform infrastructure cost alignment."""
|
105
|
+
|
93
106
|
terraform_resource_id: str
|
94
107
|
terraform_resource_type: str
|
95
108
|
cost_explorer_attribution: Decimal
|
@@ -101,27 +114,28 @@ class TerraformCostAlignment:
|
|
101
114
|
@dataclass
|
102
115
|
class ComprehensiveCostAnalysis:
|
103
116
|
"""Complete cost analysis with infrastructure alignment."""
|
117
|
+
|
104
118
|
analysis_id: str
|
105
119
|
analysis_timestamp: datetime
|
106
|
-
|
120
|
+
|
107
121
|
# Cost Explorer data
|
108
122
|
cost_explorer_results: List[CostExplorerResult]
|
109
123
|
total_monthly_cost: Decimal
|
110
124
|
total_annual_projection: Decimal
|
111
|
-
|
125
|
+
|
112
126
|
# MCP validation
|
113
127
|
mcp_validation_accuracy: float
|
114
128
|
mcp_cross_validation_results: Dict[str, Any]
|
115
|
-
|
129
|
+
|
116
130
|
# Terraform alignment
|
117
131
|
terraform_cost_alignment: List[TerraformCostAlignment]
|
118
132
|
infrastructure_drift_summary: Dict[str, Any]
|
119
|
-
|
133
|
+
|
120
134
|
# Business impact
|
121
135
|
optimization_opportunities: List[Dict[str, Any]]
|
122
136
|
annual_savings_potential: Decimal
|
123
137
|
roi_projection: float
|
124
|
-
|
138
|
+
|
125
139
|
# Compliance and governance
|
126
140
|
compliance_status: str
|
127
141
|
audit_trail: Dict[str, Any]
|
@@ -131,21 +145,23 @@ class ComprehensiveCostAnalysis:
|
|
131
145
|
class ComprehensiveCostExplorerIntegration:
|
132
146
|
"""
|
133
147
|
Comprehensive AWS Cost Explorer integration with MCP validation and terraform alignment.
|
134
|
-
|
148
|
+
|
135
149
|
Provides enterprise-grade cost analysis with real-time API integration,
|
136
150
|
comprehensive validation, and infrastructure governance alignment.
|
137
151
|
"""
|
138
|
-
|
139
|
-
def __init__(
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
152
|
+
|
153
|
+
def __init__(
|
154
|
+
self,
|
155
|
+
billing_profile: Optional[str] = None,
|
156
|
+
management_profile: Optional[str] = None,
|
157
|
+
single_account_profile: Optional[str] = None,
|
158
|
+
terraform_state_dir: Optional[str] = None,
|
159
|
+
validation_tolerance_percent: float = 5.0,
|
160
|
+
performance_target_seconds: float = 30.0,
|
161
|
+
):
|
146
162
|
"""
|
147
163
|
Initialize comprehensive Cost Explorer integration.
|
148
|
-
|
164
|
+
|
149
165
|
Args:
|
150
166
|
billing_profile: AWS profile for Cost Explorer access
|
151
167
|
management_profile: AWS profile for Organizations access
|
@@ -160,33 +176,33 @@ class ComprehensiveCostExplorerIntegration:
|
|
160
176
|
self.terraform_state_dir = terraform_state_dir
|
161
177
|
self.validation_tolerance = validation_tolerance_percent
|
162
178
|
self.performance_target = performance_target_seconds
|
163
|
-
|
179
|
+
|
164
180
|
# Component integrations
|
165
181
|
self.mcp_integration = None
|
166
182
|
self.terraform_detector = None
|
167
183
|
self.pricing_engine = None
|
168
|
-
|
184
|
+
|
169
185
|
# Results and caching
|
170
186
|
self.analysis_cache = {}
|
171
187
|
self.evidence_dir = Path("validation-evidence") / "comprehensive-cost-analysis"
|
172
188
|
self.evidence_dir.mkdir(parents=True, exist_ok=True)
|
173
|
-
|
189
|
+
|
174
190
|
print_header("Comprehensive Cost Explorer Integration", "1.0.0")
|
175
191
|
print_info("🏗️ Initializing enterprise cost analysis with infrastructure alignment...")
|
176
|
-
|
192
|
+
|
177
193
|
async def initialize_integrations(self, user_profile_override: Optional[str] = None) -> Dict[str, Any]:
|
178
194
|
"""Initialize all component integrations."""
|
179
|
-
|
195
|
+
|
180
196
|
initialization_results = {
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
197
|
+
"timestamp": datetime.now().isoformat(),
|
198
|
+
"user_profile_override": user_profile_override,
|
199
|
+
"integrations": {},
|
200
|
+
"overall_status": "unknown",
|
185
201
|
}
|
186
|
-
|
202
|
+
|
187
203
|
with create_progress_bar() as progress:
|
188
204
|
task = progress.add_task("Initializing integrations...", total=100)
|
189
|
-
|
205
|
+
|
190
206
|
# Initialize MCP Cost Explorer integration
|
191
207
|
progress.update(task, advance=25, description="Initializing MCP integration...")
|
192
208
|
if INTEGRATIONS_AVAILABLE:
|
@@ -196,126 +212,125 @@ class ComprehensiveCostExplorerIntegration:
|
|
196
212
|
management_profile=self.management_profile,
|
197
213
|
single_account_profile=self.single_account_profile,
|
198
214
|
tolerance_percent=self.validation_tolerance,
|
199
|
-
performance_target_seconds=self.performance_target
|
215
|
+
performance_target_seconds=self.performance_target,
|
200
216
|
)
|
201
|
-
|
217
|
+
|
202
218
|
# Initialize profiles
|
203
219
|
mcp_results = await self.mcp_integration.initialize_profiles(user_profile_override)
|
204
|
-
initialization_results[
|
205
|
-
|
206
|
-
|
207
|
-
|
220
|
+
initialization_results["integrations"]["mcp"] = {
|
221
|
+
"status": "initialized",
|
222
|
+
"profiles_successful": len(mcp_results.get("profiles_successful", [])),
|
223
|
+
"validation_capability": "available",
|
208
224
|
}
|
209
|
-
|
225
|
+
|
210
226
|
except Exception as e:
|
211
|
-
initialization_results[
|
212
|
-
|
213
|
-
|
214
|
-
|
227
|
+
initialization_results["integrations"]["mcp"] = {
|
228
|
+
"status": "error",
|
229
|
+
"error": str(e),
|
230
|
+
"validation_capability": "limited",
|
215
231
|
}
|
216
232
|
else:
|
217
|
-
initialization_results[
|
218
|
-
|
219
|
-
|
233
|
+
initialization_results["integrations"]["mcp"] = {
|
234
|
+
"status": "not_available",
|
235
|
+
"reason": "Integration modules not installed",
|
220
236
|
}
|
221
|
-
|
237
|
+
|
222
238
|
# Initialize pricing engine
|
223
239
|
progress.update(task, advance=25, description="Initializing pricing engine...")
|
224
240
|
if INTEGRATIONS_AVAILABLE:
|
225
241
|
try:
|
226
|
-
self.pricing_engine = get_aws_pricing_engine(
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
'status': 'initialized',
|
232
|
-
'cache_ttl_hours': 24,
|
233
|
-
'fallback_enabled': True
|
242
|
+
self.pricing_engine = get_aws_pricing_engine(cache_ttl_hours=24, enable_fallback=True)
|
243
|
+
initialization_results["integrations"]["pricing"] = {
|
244
|
+
"status": "initialized",
|
245
|
+
"cache_ttl_hours": 24,
|
246
|
+
"fallback_enabled": True,
|
234
247
|
}
|
235
248
|
except Exception as e:
|
236
|
-
initialization_results[
|
237
|
-
|
238
|
-
'error': str(e)
|
239
|
-
}
|
240
|
-
|
249
|
+
initialization_results["integrations"]["pricing"] = {"status": "error", "error": str(e)}
|
250
|
+
|
241
251
|
# Initialize terraform drift detector
|
242
252
|
progress.update(task, advance=25, description="Initializing terraform detector...")
|
243
253
|
if TERRAFORM_INTEGRATION_AVAILABLE:
|
244
254
|
try:
|
245
|
-
self.terraform_detector = TerraformDriftDetector(
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
'state_dir': self.terraform_state_dir,
|
251
|
-
'drift_detection': 'available'
|
255
|
+
self.terraform_detector = TerraformDriftDetector(terraform_state_dir=self.terraform_state_dir)
|
256
|
+
initialization_results["integrations"]["terraform"] = {
|
257
|
+
"status": "initialized",
|
258
|
+
"state_dir": self.terraform_state_dir,
|
259
|
+
"drift_detection": "available",
|
252
260
|
}
|
253
261
|
except Exception as e:
|
254
|
-
initialization_results[
|
255
|
-
|
256
|
-
|
257
|
-
|
262
|
+
initialization_results["integrations"]["terraform"] = {
|
263
|
+
"status": "error",
|
264
|
+
"error": str(e),
|
265
|
+
"drift_detection": "unavailable",
|
258
266
|
}
|
259
267
|
else:
|
260
|
-
initialization_results[
|
261
|
-
|
262
|
-
|
268
|
+
initialization_results["integrations"]["terraform"] = {
|
269
|
+
"status": "not_available",
|
270
|
+
"reason": "Terraform integration module not installed",
|
263
271
|
}
|
264
|
-
|
272
|
+
|
265
273
|
progress.update(task, advance=25, description="Finalizing initialization...")
|
266
|
-
|
274
|
+
|
267
275
|
# Determine overall status
|
268
|
-
successful_integrations = sum(
|
269
|
-
|
270
|
-
|
271
|
-
|
276
|
+
successful_integrations = sum(
|
277
|
+
1
|
278
|
+
for integration in initialization_results["integrations"].values()
|
279
|
+
if integration.get("status") == "initialized"
|
280
|
+
)
|
281
|
+
total_integrations = len(initialization_results["integrations"])
|
282
|
+
|
272
283
|
if successful_integrations == total_integrations:
|
273
|
-
initialization_results[
|
284
|
+
initialization_results["overall_status"] = "fully_operational"
|
274
285
|
elif successful_integrations > 0:
|
275
|
-
initialization_results[
|
286
|
+
initialization_results["overall_status"] = "partially_operational"
|
276
287
|
else:
|
277
|
-
initialization_results[
|
278
|
-
|
288
|
+
initialization_results["overall_status"] = "initialization_failed"
|
289
|
+
|
279
290
|
progress.update(task, completed=100)
|
280
|
-
|
291
|
+
|
281
292
|
# Display initialization results
|
282
293
|
self._display_initialization_results(initialization_results)
|
283
|
-
|
294
|
+
|
284
295
|
return initialization_results
|
285
|
-
|
286
|
-
async def perform_comprehensive_cost_analysis(
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
296
|
+
|
297
|
+
async def perform_comprehensive_cost_analysis(
|
298
|
+
self,
|
299
|
+
account_filter: Optional[str] = None,
|
300
|
+
analysis_days: int = 90,
|
301
|
+
include_terraform_alignment: bool = True,
|
302
|
+
runbooks_evidence_file: Optional[str] = None,
|
303
|
+
) -> ComprehensiveCostAnalysis:
|
291
304
|
"""
|
292
305
|
Perform comprehensive cost analysis with all integrations.
|
293
|
-
|
306
|
+
|
294
307
|
Args:
|
295
308
|
account_filter: Specific account ID for analysis
|
296
309
|
analysis_days: Number of days for cost analysis
|
297
310
|
include_terraform_alignment: Include terraform drift detection
|
298
311
|
runbooks_evidence_file: Path to runbooks evidence for terraform alignment
|
299
|
-
|
312
|
+
|
300
313
|
Returns:
|
301
314
|
Complete comprehensive cost analysis
|
302
315
|
"""
|
303
316
|
analysis_start = datetime.now()
|
304
317
|
analysis_id = f"comprehensive_cost_{analysis_start.strftime('%Y%m%d_%H%M%S')}"
|
305
|
-
|
318
|
+
|
306
319
|
print_header("Comprehensive Cost Analysis")
|
307
320
|
print_info(f"🎯 Analysis ID: {analysis_id}")
|
308
321
|
print_info(f"📊 Account Filter: {account_filter or 'All accounts'}")
|
309
322
|
print_info(f"📅 Analysis Period: {analysis_days} days")
|
310
|
-
|
323
|
+
|
311
324
|
# Phase 1: Cost Explorer API integration
|
312
325
|
print_info("💰 Phase 1: Cost Explorer API integration...")
|
313
326
|
cost_explorer_results = await self._perform_cost_explorer_analysis(account_filter, analysis_days)
|
314
|
-
|
327
|
+
|
315
328
|
# Phase 2: MCP validation
|
316
329
|
print_info("🔍 Phase 2: MCP cross-validation...")
|
317
|
-
mcp_validation_results = await self._perform_mcp_validation(
|
318
|
-
|
330
|
+
mcp_validation_results = await self._perform_mcp_validation(
|
331
|
+
cost_explorer_results, account_filter, analysis_days
|
332
|
+
)
|
333
|
+
|
319
334
|
# Phase 3: Terraform alignment (if enabled)
|
320
335
|
terraform_alignment = []
|
321
336
|
infrastructure_drift = {}
|
@@ -326,13 +341,13 @@ class ComprehensiveCostExplorerIntegration:
|
|
326
341
|
)
|
327
342
|
else:
|
328
343
|
print_info("⏭️ Phase 3: Skipped - terraform alignment not requested")
|
329
|
-
|
344
|
+
|
330
345
|
# Phase 4: Business impact analysis
|
331
346
|
print_info("💼 Phase 4: Business impact analysis...")
|
332
347
|
optimization_opportunities, savings_potential, roi_projection = await self._analyze_business_impact(
|
333
348
|
cost_explorer_results, terraform_alignment
|
334
349
|
)
|
335
|
-
|
350
|
+
|
336
351
|
# Phase 5: Generate comprehensive analysis
|
337
352
|
print_info("📋 Phase 5: Generating comprehensive analysis...")
|
338
353
|
comprehensive_analysis = ComprehensiveCostAnalysis(
|
@@ -341,381 +356,401 @@ class ComprehensiveCostExplorerIntegration:
|
|
341
356
|
cost_explorer_results=cost_explorer_results,
|
342
357
|
total_monthly_cost=sum(result.monthly_cost for result in cost_explorer_results),
|
343
358
|
total_annual_projection=sum(result.annual_projection for result in cost_explorer_results),
|
344
|
-
mcp_validation_accuracy=mcp_validation_results.get(
|
359
|
+
mcp_validation_accuracy=mcp_validation_results.get("overall_accuracy", 0.0),
|
345
360
|
mcp_cross_validation_results=mcp_validation_results,
|
346
361
|
terraform_cost_alignment=terraform_alignment,
|
347
362
|
infrastructure_drift_summary=infrastructure_drift,
|
348
363
|
optimization_opportunities=optimization_opportunities,
|
349
364
|
annual_savings_potential=savings_potential,
|
350
365
|
roi_projection=roi_projection,
|
351
|
-
compliance_status=
|
366
|
+
compliance_status="compliant"
|
367
|
+
if mcp_validation_results.get("overall_accuracy", 0) >= 99.5
|
368
|
+
else "needs_review",
|
352
369
|
audit_trail={
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
370
|
+
"analysis_methodology": "comprehensive_cost_explorer_with_mcp_terraform_validation",
|
371
|
+
"accuracy_standards": "≥99.5% MCP validation required",
|
372
|
+
"infrastructure_alignment": "terraform_drift_detection_integrated",
|
373
|
+
"evidence_generation": "complete_audit_trail",
|
357
374
|
},
|
358
|
-
evidence_files=[]
|
375
|
+
evidence_files=[],
|
359
376
|
)
|
360
|
-
|
377
|
+
|
361
378
|
# Generate evidence files
|
362
379
|
evidence_files = await self._generate_comprehensive_evidence(comprehensive_analysis)
|
363
380
|
comprehensive_analysis.evidence_files = evidence_files
|
364
|
-
|
381
|
+
|
365
382
|
# Display results
|
366
383
|
self._display_comprehensive_results(comprehensive_analysis)
|
367
|
-
|
384
|
+
|
368
385
|
return comprehensive_analysis
|
369
|
-
|
370
|
-
async def _perform_cost_explorer_analysis(
|
386
|
+
|
387
|
+
async def _perform_cost_explorer_analysis(
|
388
|
+
self, account_filter: Optional[str], analysis_days: int
|
389
|
+
) -> List[CostExplorerResult]:
|
371
390
|
"""Perform Cost Explorer API analysis."""
|
372
|
-
|
391
|
+
|
373
392
|
cost_explorer_results = []
|
374
|
-
|
393
|
+
|
375
394
|
if not self.mcp_integration:
|
376
395
|
print_warning("⚠️ MCP integration not available - using fallback pricing")
|
377
|
-
|
396
|
+
|
378
397
|
# Fallback to pricing engine if available
|
379
398
|
if self.pricing_engine:
|
380
|
-
services = [
|
399
|
+
services = ["nat_gateway", "elastic_ip", "vpc_endpoint", "ebs_gp3", "s3_standard"]
|
381
400
|
for service in services:
|
382
|
-
pricing_result = self.pricing_engine.get_service_pricing(service,
|
383
|
-
|
384
|
-
cost_explorer_results.append(
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
401
|
+
pricing_result = self.pricing_engine.get_service_pricing(service, "us-east-1")
|
402
|
+
|
403
|
+
cost_explorer_results.append(
|
404
|
+
CostExplorerResult(
|
405
|
+
service_name=service,
|
406
|
+
account_id=account_filter or "fallback",
|
407
|
+
region="us-east-1",
|
408
|
+
monthly_cost=Decimal(str(pricing_result.monthly_cost)),
|
409
|
+
annual_projection=Decimal(str(pricing_result.monthly_cost * 12)),
|
410
|
+
cost_trend="stable",
|
411
|
+
optimization_potential=Decimal(str(pricing_result.monthly_cost * 0.3)),
|
412
|
+
last_updated=pricing_result.last_updated,
|
413
|
+
data_source=pricing_result.pricing_source,
|
414
|
+
validation_accuracy=90.0, # Fallback accuracy
|
415
|
+
confidence_level=75.0,
|
416
|
+
)
|
417
|
+
)
|
418
|
+
|
398
419
|
return cost_explorer_results
|
399
|
-
|
420
|
+
|
400
421
|
try:
|
401
422
|
# Use MCP integration for Cost Explorer data
|
402
423
|
cost_data = await self.mcp_integration._retrieve_cost_explorer_data(account_filter, analysis_days)
|
403
|
-
|
424
|
+
|
404
425
|
# Process cost data into CostExplorerResult format
|
405
|
-
if cost_data.get(
|
406
|
-
for service_name, service_cost in cost_data[
|
426
|
+
if cost_data.get("service_breakdown"):
|
427
|
+
for service_name, service_cost in cost_data["service_breakdown"].items():
|
407
428
|
annual_cost = Decimal(str(service_cost)) * 12
|
408
|
-
|
409
|
-
cost_explorer_results.append(
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
429
|
+
|
430
|
+
cost_explorer_results.append(
|
431
|
+
CostExplorerResult(
|
432
|
+
service_name=service_name,
|
433
|
+
account_id=account_filter or "organization",
|
434
|
+
region="us-east-1", # Cost Explorer aggregated
|
435
|
+
monthly_cost=Decimal(str(service_cost)),
|
436
|
+
annual_projection=annual_cost,
|
437
|
+
cost_trend=self._determine_cost_trend(service_cost),
|
438
|
+
optimization_potential=Decimal(str(service_cost * 0.25)), # 25% optimization potential
|
439
|
+
last_updated=datetime.now(),
|
440
|
+
data_source="cost_explorer_api",
|
441
|
+
validation_accuracy=95.0, # High accuracy from API
|
442
|
+
confidence_level=90.0,
|
443
|
+
)
|
444
|
+
)
|
445
|
+
|
446
|
+
elif cost_data.get("account_breakdown"):
|
447
|
+
for account_id, account_cost in cost_data["account_breakdown"].items():
|
425
448
|
annual_cost = Decimal(str(account_cost)) * 12
|
426
|
-
|
427
|
-
cost_explorer_results.append(
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
449
|
+
|
450
|
+
cost_explorer_results.append(
|
451
|
+
CostExplorerResult(
|
452
|
+
service_name="account_total",
|
453
|
+
account_id=account_id,
|
454
|
+
region="all_regions",
|
455
|
+
monthly_cost=Decimal(str(account_cost)),
|
456
|
+
annual_projection=annual_cost,
|
457
|
+
cost_trend=self._determine_cost_trend(account_cost),
|
458
|
+
optimization_potential=Decimal(str(account_cost * 0.20)), # 20% optimization potential
|
459
|
+
last_updated=datetime.now(),
|
460
|
+
data_source="cost_explorer_api",
|
461
|
+
validation_accuracy=95.0,
|
462
|
+
confidence_level=90.0,
|
463
|
+
)
|
464
|
+
)
|
465
|
+
|
441
466
|
except Exception as e:
|
442
467
|
print_error(f"Cost Explorer analysis error: {e}")
|
443
468
|
logger.error(f"Cost Explorer analysis failed: {e}")
|
444
|
-
|
469
|
+
|
445
470
|
return cost_explorer_results
|
446
|
-
|
447
|
-
async def _perform_mcp_validation(
|
448
|
-
|
471
|
+
|
472
|
+
async def _perform_mcp_validation(
|
473
|
+
self, cost_explorer_results: List[CostExplorerResult], account_filter: Optional[str], analysis_days: int
|
474
|
+
) -> Dict[str, Any]:
|
449
475
|
"""Perform MCP cross-validation."""
|
450
|
-
|
476
|
+
|
451
477
|
mcp_validation_results = {
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
478
|
+
"validation_timestamp": datetime.now().isoformat(),
|
479
|
+
"validation_method": "comprehensive_mcp_cost_explorer",
|
480
|
+
"overall_accuracy": 0.0,
|
481
|
+
"validations": [],
|
482
|
+
"enterprise_compliance": False,
|
457
483
|
}
|
458
|
-
|
484
|
+
|
459
485
|
if not self.mcp_integration:
|
460
|
-
mcp_validation_results.update(
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
486
|
+
mcp_validation_results.update(
|
487
|
+
{
|
488
|
+
"status": "mcp_integration_unavailable",
|
489
|
+
"overall_accuracy": 85.0, # Fallback accuracy
|
490
|
+
"enterprise_compliance": False,
|
491
|
+
"note": "MCP validation requires full integration availability",
|
492
|
+
}
|
493
|
+
)
|
466
494
|
return mcp_validation_results
|
467
|
-
|
495
|
+
|
468
496
|
try:
|
469
497
|
# Prepare notebook-style results for cross-validation
|
470
498
|
notebook_results = {
|
471
|
-
|
472
|
-
|
473
|
-
|
499
|
+
"cost_trends": {
|
500
|
+
"total_monthly_spend": float(sum(result.monthly_cost for result in cost_explorer_results)),
|
501
|
+
"analysis_period_days": analysis_days,
|
474
502
|
},
|
475
|
-
|
476
|
-
result.service_name: float(result.monthly_cost)
|
477
|
-
for result in cost_explorer_results
|
503
|
+
"service_breakdown": {
|
504
|
+
result.service_name: float(result.monthly_cost) for result in cost_explorer_results
|
478
505
|
},
|
479
|
-
|
506
|
+
"optimization_potential": float(sum(result.optimization_potential for result in cost_explorer_results)),
|
480
507
|
}
|
481
|
-
|
508
|
+
|
482
509
|
# Perform MCP validation
|
483
510
|
validation_results = await self.mcp_integration.validate_cost_data_with_cross_validation(
|
484
|
-
notebook_results=notebook_results,
|
485
|
-
account_filter=account_filter,
|
486
|
-
analysis_days=analysis_days
|
511
|
+
notebook_results=notebook_results, account_filter=account_filter, analysis_days=analysis_days
|
487
512
|
)
|
488
|
-
|
513
|
+
|
489
514
|
# Extract validation accuracy
|
490
|
-
cross_validation = validation_results.get(
|
491
|
-
validations = cross_validation.get(
|
492
|
-
|
515
|
+
cross_validation = validation_results.get("cross_validation", {})
|
516
|
+
validations = cross_validation.get("validations", [])
|
517
|
+
|
493
518
|
if validations:
|
494
519
|
# Calculate overall accuracy from validations
|
495
|
-
validated_count = sum(1 for v in validations if v.get(
|
520
|
+
validated_count = sum(1 for v in validations if v.get("status") == "validated")
|
496
521
|
total_count = len(validations)
|
497
|
-
|
522
|
+
|
498
523
|
overall_accuracy = (validated_count / total_count * 100) if total_count > 0 else 0
|
499
|
-
|
500
|
-
mcp_validation_results.update(
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
524
|
+
|
525
|
+
mcp_validation_results.update(
|
526
|
+
{
|
527
|
+
"overall_accuracy": overall_accuracy,
|
528
|
+
"validations": validations,
|
529
|
+
"enterprise_compliance": overall_accuracy >= 99.5,
|
530
|
+
"manager_priorities_assessment": validation_results.get("manager_priorities_assessment", {}),
|
531
|
+
"performance_metrics": validation_results.get("performance_metrics", {}),
|
532
|
+
}
|
533
|
+
)
|
507
534
|
else:
|
508
|
-
mcp_validation_results.update(
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
535
|
+
mcp_validation_results.update(
|
536
|
+
{
|
537
|
+
"overall_accuracy": 75.0, # Default when validation fails
|
538
|
+
"enterprise_compliance": False,
|
539
|
+
"status": "validation_incomplete",
|
540
|
+
}
|
541
|
+
)
|
542
|
+
|
514
543
|
except Exception as e:
|
515
544
|
print_error(f"MCP validation error: {e}")
|
516
|
-
mcp_validation_results.update(
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
545
|
+
mcp_validation_results.update(
|
546
|
+
{
|
547
|
+
"status": "validation_error",
|
548
|
+
"error": str(e),
|
549
|
+
"overall_accuracy": 70.0, # Conservative accuracy on error
|
550
|
+
"enterprise_compliance": False,
|
551
|
+
}
|
552
|
+
)
|
553
|
+
|
523
554
|
return mcp_validation_results
|
524
|
-
|
525
|
-
async def _perform_terraform_alignment(
|
526
|
-
|
555
|
+
|
556
|
+
async def _perform_terraform_alignment(
|
557
|
+
self, cost_explorer_results: List[CostExplorerResult], runbooks_evidence_file: str
|
558
|
+
) -> Tuple[List[TerraformCostAlignment], Dict[str, Any]]:
|
527
559
|
"""Perform terraform infrastructure cost alignment."""
|
528
|
-
|
560
|
+
|
529
561
|
terraform_alignments = []
|
530
562
|
infrastructure_drift = {}
|
531
|
-
|
563
|
+
|
532
564
|
if not self.terraform_detector:
|
533
565
|
print_warning("⚠️ Terraform integration not available")
|
534
|
-
return terraform_alignments, {
|
535
|
-
|
566
|
+
return terraform_alignments, {"status": "terraform_integration_unavailable"}
|
567
|
+
|
536
568
|
try:
|
537
569
|
# Perform terraform drift detection
|
538
570
|
drift_result = self.terraform_detector.detect_infrastructure_drift(
|
539
571
|
runbooks_evidence_file=runbooks_evidence_file,
|
540
|
-
resource_types=[
|
572
|
+
resource_types=["aws_vpc", "aws_subnet", "aws_nat_gateway", "aws_eip"],
|
541
573
|
)
|
542
|
-
|
574
|
+
|
543
575
|
# Process drift results for cost alignment
|
544
576
|
for drift_analysis in drift_result.drift_analysis:
|
545
577
|
# Try to correlate with cost data
|
546
578
|
related_cost = self._correlate_cost_with_resource(
|
547
|
-
drift_analysis.resource_type,
|
548
|
-
drift_analysis.resource_id,
|
549
|
-
cost_explorer_results
|
579
|
+
drift_analysis.resource_type, drift_analysis.resource_id, cost_explorer_results
|
550
580
|
)
|
551
|
-
|
581
|
+
|
552
582
|
terraform_alignment = TerraformCostAlignment(
|
553
583
|
terraform_resource_id=drift_analysis.resource_id,
|
554
584
|
terraform_resource_type=drift_analysis.resource_type,
|
555
585
|
cost_explorer_attribution=related_cost,
|
556
586
|
alignment_status=drift_analysis.drift_type,
|
557
587
|
drift_details=drift_analysis.drift_details,
|
558
|
-
remediation_recommendation=drift_analysis.remediation_recommendation
|
588
|
+
remediation_recommendation=drift_analysis.remediation_recommendation,
|
559
589
|
)
|
560
|
-
|
590
|
+
|
561
591
|
terraform_alignments.append(terraform_alignment)
|
562
|
-
|
592
|
+
|
563
593
|
# Summarize infrastructure drift
|
564
594
|
infrastructure_drift = {
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
595
|
+
"drift_detection_id": drift_result.drift_detection_id,
|
596
|
+
"total_resources_terraform": drift_result.total_resources_terraform,
|
597
|
+
"total_resources_runbooks": drift_result.total_resources_runbooks,
|
598
|
+
"drift_percentage": drift_result.drift_percentage,
|
599
|
+
"overall_risk_level": drift_result.overall_risk_level,
|
600
|
+
"compliance_impact": drift_result.compliance_impact,
|
601
|
+
"remediation_priority": drift_result.remediation_priority,
|
572
602
|
}
|
573
|
-
|
603
|
+
|
574
604
|
except Exception as e:
|
575
605
|
print_error(f"Terraform alignment error: {e}")
|
576
|
-
infrastructure_drift = {
|
577
|
-
|
578
|
-
'error': str(e)
|
579
|
-
}
|
580
|
-
|
606
|
+
infrastructure_drift = {"status": "alignment_error", "error": str(e)}
|
607
|
+
|
581
608
|
return terraform_alignments, infrastructure_drift
|
582
|
-
|
583
|
-
async def _analyze_business_impact(
|
584
|
-
|
609
|
+
|
610
|
+
async def _analyze_business_impact(
|
611
|
+
self, cost_explorer_results: List[CostExplorerResult], terraform_alignments: List[TerraformCostAlignment]
|
612
|
+
) -> Tuple[List[Dict[str, Any]], Decimal, float]:
|
585
613
|
"""Analyze business impact and optimization opportunities."""
|
586
|
-
|
614
|
+
|
587
615
|
optimization_opportunities = []
|
588
|
-
total_savings_potential = Decimal(
|
589
|
-
|
616
|
+
total_savings_potential = Decimal("0")
|
617
|
+
|
590
618
|
# Analyze cost optimization opportunities
|
591
619
|
for result in cost_explorer_results:
|
592
620
|
if result.optimization_potential > 0:
|
593
|
-
optimization_opportunities.append(
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
621
|
+
optimization_opportunities.append(
|
622
|
+
{
|
623
|
+
"type": "cost_optimization",
|
624
|
+
"service": result.service_name,
|
625
|
+
"account": result.account_id,
|
626
|
+
"current_monthly_cost": float(result.monthly_cost),
|
627
|
+
"potential_monthly_savings": float(result.optimization_potential),
|
628
|
+
"annual_savings_potential": float(result.optimization_potential * 12),
|
629
|
+
"confidence_level": result.confidence_level,
|
630
|
+
"recommendation": f"Optimize {result.service_name} configuration to reduce costs",
|
631
|
+
"implementation_effort": "medium",
|
632
|
+
"risk_level": "low",
|
633
|
+
}
|
634
|
+
)
|
635
|
+
|
606
636
|
total_savings_potential += result.optimization_potential * 12
|
607
|
-
|
637
|
+
|
608
638
|
# Analyze terraform alignment opportunities
|
609
639
|
for alignment in terraform_alignments:
|
610
|
-
if alignment.alignment_status in [
|
611
|
-
optimization_opportunities.append(
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
640
|
+
if alignment.alignment_status in ["missing_from_terraform", "configuration_drift"]:
|
641
|
+
optimization_opportunities.append(
|
642
|
+
{
|
643
|
+
"type": "infrastructure_governance",
|
644
|
+
"resource_type": alignment.terraform_resource_type,
|
645
|
+
"resource_id": alignment.terraform_resource_id,
|
646
|
+
"alignment_status": alignment.alignment_status,
|
647
|
+
"cost_attribution": float(alignment.cost_explorer_attribution),
|
648
|
+
"recommendation": alignment.remediation_recommendation,
|
649
|
+
"implementation_effort": "high"
|
650
|
+
if alignment.alignment_status == "missing_from_terraform"
|
651
|
+
else "medium",
|
652
|
+
"risk_level": "medium",
|
653
|
+
"governance_impact": "high",
|
654
|
+
}
|
655
|
+
)
|
656
|
+
|
623
657
|
# Calculate ROI projection
|
624
658
|
total_current_cost = sum(result.annual_projection for result in cost_explorer_results)
|
625
659
|
roi_projection = float((total_savings_potential / total_current_cost) * 100) if total_current_cost > 0 else 0.0
|
626
|
-
|
660
|
+
|
627
661
|
return optimization_opportunities, total_savings_potential, roi_projection
|
628
|
-
|
629
|
-
def _correlate_cost_with_resource(
|
630
|
-
|
662
|
+
|
663
|
+
def _correlate_cost_with_resource(
|
664
|
+
self, resource_type: str, resource_id: str, cost_results: List[CostExplorerResult]
|
665
|
+
) -> Decimal:
|
631
666
|
"""Correlate terraform resource with cost data."""
|
632
|
-
|
667
|
+
|
633
668
|
# Simple correlation based on resource type
|
634
669
|
service_mapping = {
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
670
|
+
"aws_vpc": "Amazon Virtual Private Cloud",
|
671
|
+
"aws_nat_gateway": "Amazon VPC",
|
672
|
+
"aws_subnet": "Amazon Virtual Private Cloud",
|
673
|
+
"aws_eip": "Amazon Elastic Compute Cloud - Compute",
|
639
674
|
}
|
640
|
-
|
641
|
-
service_name = service_mapping.get(resource_type,
|
642
|
-
|
675
|
+
|
676
|
+
service_name = service_mapping.get(resource_type, "")
|
677
|
+
|
643
678
|
for result in cost_results:
|
644
679
|
if service_name in result.service_name or result.service_name in service_name:
|
645
680
|
# Rough attribution - could be enhanced with detailed resource tagging
|
646
|
-
return result.monthly_cost * Decimal(
|
647
|
-
|
648
|
-
return Decimal(
|
649
|
-
|
681
|
+
return result.monthly_cost * Decimal("0.1") # 10% attribution estimate
|
682
|
+
|
683
|
+
return Decimal("0")
|
684
|
+
|
650
685
|
def _determine_cost_trend(self, current_cost: float) -> str:
|
651
686
|
"""Determine cost trend (simplified)."""
|
652
687
|
# In real implementation, this would compare historical data
|
653
688
|
if current_cost > 1000:
|
654
|
-
return
|
689
|
+
return "increasing"
|
655
690
|
elif current_cost < 100:
|
656
|
-
return
|
691
|
+
return "decreasing"
|
657
692
|
else:
|
658
|
-
return
|
659
|
-
|
693
|
+
return "stable"
|
694
|
+
|
660
695
|
async def _generate_comprehensive_evidence(self, analysis: ComprehensiveCostAnalysis) -> List[str]:
|
661
696
|
"""Generate comprehensive evidence files."""
|
662
|
-
|
697
|
+
|
663
698
|
evidence_files = []
|
664
699
|
timestamp = analysis.analysis_timestamp.strftime("%Y%m%d_%H%M%S")
|
665
|
-
|
700
|
+
|
666
701
|
# Main analysis evidence
|
667
702
|
main_evidence_file = self.evidence_dir / f"comprehensive_cost_analysis_{timestamp}.json"
|
668
|
-
|
703
|
+
|
669
704
|
evidence_data = {
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
705
|
+
"comprehensive_cost_analysis": asdict(analysis),
|
706
|
+
"enterprise_metadata": {
|
707
|
+
"framework_version": "1.0.0",
|
708
|
+
"strategic_coordination": "python-runbooks-engineer → qa-testing-specialist → cloud-architect",
|
709
|
+
"compliance_standards": ["DoD", "Enterprise", "FAANG SDLC"],
|
710
|
+
"validation_methodology": "aws_cost_explorer_api + mcp_cross_validation + terraform_alignment",
|
676
711
|
},
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
712
|
+
"business_intelligence": {
|
713
|
+
"total_annual_cost_projection": float(analysis.total_annual_projection),
|
714
|
+
"annual_savings_potential": float(analysis.annual_savings_potential),
|
715
|
+
"roi_projection_percent": analysis.roi_projection,
|
716
|
+
"mcp_validation_accuracy": analysis.mcp_validation_accuracy,
|
717
|
+
"enterprise_compliance_status": analysis.compliance_status,
|
718
|
+
},
|
719
|
+
"executive_summary": self._generate_executive_summary(analysis),
|
720
|
+
"audit_compliance": {
|
721
|
+
"data_source": "real_aws_cost_explorer_api",
|
722
|
+
"validation_methodology": "mcp_cross_validation",
|
723
|
+
"infrastructure_alignment": "terraform_drift_detection",
|
724
|
+
"evidence_integrity": "cryptographic_hash_validation",
|
725
|
+
"audit_trail": "comprehensive",
|
683
726
|
},
|
684
|
-
'executive_summary': self._generate_executive_summary(analysis),
|
685
|
-
'audit_compliance': {
|
686
|
-
'data_source': 'real_aws_cost_explorer_api',
|
687
|
-
'validation_methodology': 'mcp_cross_validation',
|
688
|
-
'infrastructure_alignment': 'terraform_drift_detection',
|
689
|
-
'evidence_integrity': 'cryptographic_hash_validation',
|
690
|
-
'audit_trail': 'comprehensive'
|
691
|
-
}
|
692
727
|
}
|
693
|
-
|
694
|
-
with open(main_evidence_file,
|
728
|
+
|
729
|
+
with open(main_evidence_file, "w") as f:
|
695
730
|
json.dump(evidence_data, f, indent=2, default=str)
|
696
|
-
|
731
|
+
|
697
732
|
evidence_files.append(str(main_evidence_file))
|
698
|
-
|
733
|
+
|
699
734
|
# Executive summary file
|
700
735
|
exec_summary_file = self.evidence_dir / f"executive_summary_{timestamp}.md"
|
701
736
|
exec_summary = self._generate_executive_summary(analysis)
|
702
|
-
|
703
|
-
with open(exec_summary_file,
|
737
|
+
|
738
|
+
with open(exec_summary_file, "w") as f:
|
704
739
|
f.write(exec_summary)
|
705
|
-
|
740
|
+
|
706
741
|
evidence_files.append(str(exec_summary_file))
|
707
|
-
|
742
|
+
|
708
743
|
print_success(f"📄 Evidence files generated: {len(evidence_files)} files")
|
709
|
-
|
744
|
+
|
710
745
|
return evidence_files
|
711
|
-
|
746
|
+
|
712
747
|
def _generate_executive_summary(self, analysis: ComprehensiveCostAnalysis) -> str:
|
713
748
|
"""Generate executive summary."""
|
714
|
-
|
749
|
+
|
715
750
|
return f"""# Comprehensive Cost Analysis Executive Summary
|
716
751
|
|
717
752
|
**Analysis ID**: {analysis.analysis_id}
|
718
|
-
**Date**: {analysis.analysis_timestamp.strftime(
|
753
|
+
**Date**: {analysis.analysis_timestamp.strftime("%Y-%m-%d %H:%M:%S")}
|
719
754
|
|
720
755
|
## Financial Overview
|
721
756
|
|
@@ -727,19 +762,19 @@ class ComprehensiveCostExplorerIntegration:
|
|
727
762
|
|
728
763
|
- **MCP Validation Accuracy**: {analysis.mcp_validation_accuracy:.1f}%
|
729
764
|
- **Enterprise Compliance**: {analysis.compliance_status.upper()}
|
730
|
-
- **Infrastructure Alignment**: {
|
765
|
+
- **Infrastructure Alignment**: {"Validated" if analysis.terraform_cost_alignment else "Not Assessed"}
|
731
766
|
|
732
767
|
## Key Findings
|
733
768
|
|
734
769
|
- **Cost Explorer Results**: {len(analysis.cost_explorer_results)} services analyzed
|
735
770
|
- **Optimization Opportunities**: {len(analysis.optimization_opportunities)} identified
|
736
|
-
- **Infrastructure Drift**: {
|
771
|
+
- **Infrastructure Drift**: {"Detected" if analysis.infrastructure_drift_summary.get("drift_percentage", 0) > 0 else "None detected"}
|
737
772
|
|
738
773
|
## Recommendations
|
739
774
|
|
740
775
|
1. **Cost Optimization**: Implement identified optimization opportunities for ${analysis.annual_savings_potential:,.2f} annual savings
|
741
|
-
2. **Infrastructure Governance**: {
|
742
|
-
3. **Validation Framework**: {
|
776
|
+
2. **Infrastructure Governance**: {"Address infrastructure drift detected" if analysis.infrastructure_drift_summary.get("drift_percentage", 0) > 0 else "Maintain current infrastructure alignment"}
|
777
|
+
3. **Validation Framework**: {"Continue MCP validation excellence" if analysis.mcp_validation_accuracy >= 99.5 else "Enhance MCP validation accuracy"}
|
743
778
|
|
744
779
|
## Strategic Alignment
|
745
780
|
|
@@ -752,106 +787,91 @@ class ComprehensiveCostExplorerIntegration:
|
|
752
787
|
*Generated by Comprehensive Cost Explorer Integration latest version*
|
753
788
|
*Strategic Coordination: Enterprise Agile Team with systematic delegation*
|
754
789
|
"""
|
755
|
-
|
790
|
+
|
756
791
|
def _display_initialization_results(self, results: Dict[str, Any]) -> None:
|
757
792
|
"""Display initialization results."""
|
758
|
-
|
793
|
+
|
759
794
|
init_table = create_table(
|
760
795
|
title="Integration Initialization Results",
|
761
796
|
columns=[
|
762
797
|
{"name": "Integration", "style": "bold cyan"},
|
763
798
|
{"name": "Status", "style": "white"},
|
764
799
|
{"name": "Capability", "style": "yellow"},
|
765
|
-
{"name": "Notes", "style": "dim"}
|
766
|
-
]
|
800
|
+
{"name": "Notes", "style": "dim"},
|
801
|
+
],
|
767
802
|
)
|
768
|
-
|
769
|
-
for integration_name, integration_data in results[
|
770
|
-
status = integration_data.get(
|
803
|
+
|
804
|
+
for integration_name, integration_data in results["integrations"].items():
|
805
|
+
status = integration_data.get("status", "unknown")
|
771
806
|
status_display = {
|
772
|
-
|
773
|
-
|
774
|
-
|
807
|
+
"initialized": "✅ Operational",
|
808
|
+
"error": "❌ Error",
|
809
|
+
"not_available": "⚠️ Unavailable",
|
775
810
|
}.get(status, status)
|
776
|
-
|
777
|
-
capability =
|
778
|
-
notes = integration_data.get(
|
779
|
-
|
780
|
-
init_table.add_row(
|
781
|
-
|
782
|
-
status_display,
|
783
|
-
capability,
|
784
|
-
notes
|
785
|
-
)
|
786
|
-
|
811
|
+
|
812
|
+
capability = "Available" if status == "initialized" else "Limited"
|
813
|
+
notes = integration_data.get("error", integration_data.get("reason", "Ready"))[:50]
|
814
|
+
|
815
|
+
init_table.add_row(integration_name.upper(), status_display, capability, notes)
|
816
|
+
|
787
817
|
console.print(init_table)
|
788
|
-
|
789
|
-
overall_status = results[
|
818
|
+
|
819
|
+
overall_status = results["overall_status"]
|
790
820
|
status_panel = create_panel(
|
791
|
-
f"""🏗️ Comprehensive Integration Status: {overall_status.upper().replace(
|
821
|
+
f"""🏗️ Comprehensive Integration Status: {overall_status.upper().replace("_", " ")}
|
792
822
|
|
793
823
|
Integration Readiness:
|
794
|
-
• Real-time Cost Explorer API: {
|
795
|
-
• MCP Validation (≥99.5%): {
|
796
|
-
• Terraform Drift Detection: {
|
797
|
-
• Dynamic Pricing Engine: {
|
824
|
+
• Real-time Cost Explorer API: {"✅ Ready" if "mcp" in results["integrations"] and results["integrations"]["mcp"].get("status") == "initialized" else "⚠️ Limited"}
|
825
|
+
• MCP Validation (≥99.5%): {"✅ Ready" if "mcp" in results["integrations"] and results["integrations"]["mcp"].get("status") == "initialized" else "⚠️ Limited"}
|
826
|
+
• Terraform Drift Detection: {"✅ Ready" if "terraform" in results["integrations"] and results["integrations"]["terraform"].get("status") == "initialized" else "⚠️ Limited"}
|
827
|
+
• Dynamic Pricing Engine: {"✅ Ready" if "pricing" in results["integrations"] and results["integrations"]["pricing"].get("status") == "initialized" else "⚠️ Limited"}
|
798
828
|
|
799
|
-
Enterprise Compliance: {
|
829
|
+
Enterprise Compliance: {"✅ All systems operational" if overall_status == "fully_operational" else "⚠️ Partial capability - some features may be limited"}""",
|
800
830
|
title="Enterprise Integration Status",
|
801
|
-
border_style="green" if overall_status ==
|
831
|
+
border_style="green" if overall_status == "fully_operational" else "yellow",
|
802
832
|
)
|
803
|
-
|
833
|
+
|
804
834
|
console.print(status_panel)
|
805
|
-
|
835
|
+
|
806
836
|
def _display_comprehensive_results(self, analysis: ComprehensiveCostAnalysis) -> None:
|
807
837
|
"""Display comprehensive analysis results."""
|
808
|
-
|
838
|
+
|
809
839
|
print_header("Comprehensive Cost Analysis Results")
|
810
|
-
|
840
|
+
|
811
841
|
# Financial summary
|
812
842
|
financial_table = create_table(
|
813
843
|
title="💰 Financial Analysis Summary",
|
814
844
|
columns=[
|
815
845
|
{"name": "Metric", "style": "bold cyan"},
|
816
846
|
{"name": "Value", "style": "bright_green", "justify": "right"},
|
817
|
-
{"name": "Assessment", "style": "yellow", "justify": "center"}
|
818
|
-
]
|
819
|
-
)
|
820
|
-
|
821
|
-
financial_table.add_row(
|
822
|
-
"Current Annual Cost",
|
823
|
-
f"${analysis.total_annual_projection:,.2f}",
|
824
|
-
"📊"
|
825
|
-
)
|
826
|
-
|
827
|
-
financial_table.add_row(
|
828
|
-
"Annual Savings Potential",
|
829
|
-
f"${analysis.annual_savings_potential:,.2f}",
|
830
|
-
"💰"
|
847
|
+
{"name": "Assessment", "style": "yellow", "justify": "center"},
|
848
|
+
],
|
831
849
|
)
|
832
|
-
|
850
|
+
|
851
|
+
financial_table.add_row("Current Annual Cost", f"${analysis.total_annual_projection:,.2f}", "📊")
|
852
|
+
|
853
|
+
financial_table.add_row("Annual Savings Potential", f"${analysis.annual_savings_potential:,.2f}", "💰")
|
854
|
+
|
833
855
|
financial_table.add_row(
|
834
|
-
"ROI Projection",
|
835
|
-
f"{analysis.roi_projection:.1f}%",
|
836
|
-
"📈" if analysis.roi_projection > 10 else "📊"
|
856
|
+
"ROI Projection", f"{analysis.roi_projection:.1f}%", "📈" if analysis.roi_projection > 10 else "📊"
|
837
857
|
)
|
838
|
-
|
858
|
+
|
839
859
|
financial_table.add_row(
|
840
860
|
"MCP Validation Accuracy",
|
841
861
|
f"{analysis.mcp_validation_accuracy:.1f}%",
|
842
|
-
"✅" if analysis.mcp_validation_accuracy >= 99.5 else "⚠️"
|
862
|
+
"✅" if analysis.mcp_validation_accuracy >= 99.5 else "⚠️",
|
843
863
|
)
|
844
|
-
|
864
|
+
|
845
865
|
console.print(financial_table)
|
846
|
-
|
866
|
+
|
847
867
|
# Compliance status panel
|
848
|
-
compliance_color = "green" if analysis.compliance_status ==
|
868
|
+
compliance_color = "green" if analysis.compliance_status == "compliant" else "yellow"
|
849
869
|
compliance_text = f"""🏛️ Enterprise Compliance Assessment
|
850
870
|
|
851
871
|
Compliance Status: {analysis.compliance_status.upper()}
|
852
|
-
MCP Validation: {analysis.mcp_validation_accuracy:.1f}% ({
|
853
|
-
Infrastructure Alignment: {
|
854
|
-
Audit Trail: {
|
872
|
+
MCP Validation: {analysis.mcp_validation_accuracy:.1f}% ({"✅ EXCEEDS" if analysis.mcp_validation_accuracy >= 99.5 else "⚠️ BELOW"} 99.5% requirement)
|
873
|
+
Infrastructure Alignment: {"✅ Terraform validated" if analysis.terraform_cost_alignment else "📊 Assessment available"}
|
874
|
+
Audit Trail: {"✅ Complete" if analysis.evidence_files else "⚠️ Generating"}
|
855
875
|
|
856
876
|
🎯 Strategic Objectives:
|
857
877
|
• runbooks package: ✅ Enhanced with real-time Cost Explorer API
|
@@ -865,19 +885,17 @@ Audit Trail: {'✅ Complete' if analysis.evidence_files else '⚠️ Generating'
|
|
865
885
|
• Executive-ready reporting with quantified ROI"""
|
866
886
|
|
867
887
|
compliance_panel = create_panel(
|
868
|
-
compliance_text,
|
869
|
-
title="Enterprise Compliance & Strategic Alignment",
|
870
|
-
border_style=compliance_color
|
888
|
+
compliance_text, title="Enterprise Compliance & Strategic Alignment", border_style=compliance_color
|
871
889
|
)
|
872
|
-
|
890
|
+
|
873
891
|
console.print(compliance_panel)
|
874
|
-
|
892
|
+
|
875
893
|
# Optimization opportunities summary
|
876
894
|
if analysis.optimization_opportunities:
|
877
895
|
print_info(f"🔧 {len(analysis.optimization_opportunities)} optimization opportunities identified")
|
878
896
|
print_info(f"💰 Total annual savings potential: ${analysis.annual_savings_potential:,.2f}")
|
879
897
|
print_info(f"📈 ROI projection: {analysis.roi_projection:.1f}%")
|
880
|
-
|
898
|
+
|
881
899
|
# Evidence files
|
882
900
|
if analysis.evidence_files:
|
883
901
|
print_success(f"📄 Evidence files generated: {len(analysis.evidence_files)} files")
|
@@ -889,91 +907,65 @@ Audit Trail: {'✅ Complete' if analysis.evidence_files else '⚠️ Generating'
|
|
889
907
|
async def main():
|
890
908
|
"""Main CLI interface for comprehensive cost analysis."""
|
891
909
|
import argparse
|
892
|
-
|
910
|
+
|
893
911
|
parser = argparse.ArgumentParser(
|
894
912
|
description="Comprehensive AWS Cost Explorer Integration with MCP Validation and Terraform Alignment"
|
895
913
|
)
|
914
|
+
parser.add_argument("--account-filter", help="Specific AWS account ID to analyze")
|
915
|
+
parser.add_argument("--analysis-days", type=int, default=90, help="Number of days for cost analysis (default: 90)")
|
916
|
+
parser.add_argument("--billing-profile", help="AWS profile for Cost Explorer access")
|
917
|
+
parser.add_argument("--management-profile", help="AWS profile for Organizations access")
|
918
|
+
parser.add_argument("--single-account-profile", help="AWS profile for single account operations")
|
919
|
+
parser.add_argument("--terraform-state-dir", help="Directory containing terraform state files")
|
920
|
+
parser.add_argument("--runbooks-evidence", help="Path to runbooks evidence file for terraform alignment")
|
921
|
+
parser.add_argument("--skip-terraform", action="store_true", help="Skip terraform alignment validation")
|
896
922
|
parser.add_argument(
|
897
|
-
"--
|
898
|
-
help="Specific AWS account ID to analyze"
|
923
|
+
"--validation-tolerance", type=float, default=5.0, help="MCP validation tolerance percentage (default: 5.0)"
|
899
924
|
)
|
900
|
-
|
901
|
-
"--analysis-days",
|
902
|
-
type=int,
|
903
|
-
default=90,
|
904
|
-
help="Number of days for cost analysis (default: 90)"
|
905
|
-
)
|
906
|
-
parser.add_argument(
|
907
|
-
"--billing-profile",
|
908
|
-
help="AWS profile for Cost Explorer access"
|
909
|
-
)
|
910
|
-
parser.add_argument(
|
911
|
-
"--management-profile",
|
912
|
-
help="AWS profile for Organizations access"
|
913
|
-
)
|
914
|
-
parser.add_argument(
|
915
|
-
"--single-account-profile",
|
916
|
-
help="AWS profile for single account operations"
|
917
|
-
)
|
918
|
-
parser.add_argument(
|
919
|
-
"--terraform-state-dir",
|
920
|
-
help="Directory containing terraform state files"
|
921
|
-
)
|
922
|
-
parser.add_argument(
|
923
|
-
"--runbooks-evidence",
|
924
|
-
help="Path to runbooks evidence file for terraform alignment"
|
925
|
-
)
|
926
|
-
parser.add_argument(
|
927
|
-
"--skip-terraform",
|
928
|
-
action="store_true",
|
929
|
-
help="Skip terraform alignment validation"
|
930
|
-
)
|
931
|
-
parser.add_argument(
|
932
|
-
"--validation-tolerance",
|
933
|
-
type=float,
|
934
|
-
default=5.0,
|
935
|
-
help="MCP validation tolerance percentage (default: 5.0)"
|
936
|
-
)
|
937
|
-
|
925
|
+
|
938
926
|
args = parser.parse_args()
|
939
|
-
|
927
|
+
|
940
928
|
# Initialize comprehensive integration
|
941
929
|
integration = ComprehensiveCostExplorerIntegration(
|
942
930
|
billing_profile=args.billing_profile,
|
943
931
|
management_profile=args.management_profile,
|
944
932
|
single_account_profile=args.single_account_profile,
|
945
933
|
terraform_state_dir=args.terraform_state_dir,
|
946
|
-
validation_tolerance_percent=args.validation_tolerance
|
934
|
+
validation_tolerance_percent=args.validation_tolerance,
|
947
935
|
)
|
948
|
-
|
936
|
+
|
949
937
|
try:
|
950
938
|
# Initialize all integrations
|
951
939
|
init_results = await integration.initialize_integrations()
|
952
|
-
|
953
|
-
if init_results[
|
940
|
+
|
941
|
+
if init_results["overall_status"] == "initialization_failed":
|
954
942
|
print_error("❌ Integration initialization failed - limited functionality available")
|
955
|
-
|
943
|
+
|
956
944
|
# Perform comprehensive cost analysis
|
957
945
|
analysis = await integration.perform_comprehensive_cost_analysis(
|
958
946
|
account_filter=args.account_filter,
|
959
947
|
analysis_days=args.analysis_days,
|
960
948
|
include_terraform_alignment=not args.skip_terraform and bool(args.runbooks_evidence),
|
961
|
-
runbooks_evidence_file=args.runbooks_evidence
|
949
|
+
runbooks_evidence_file=args.runbooks_evidence,
|
962
950
|
)
|
963
|
-
|
951
|
+
|
964
952
|
# Final summary
|
965
|
-
if analysis.compliance_status ==
|
966
|
-
print_success(
|
953
|
+
if analysis.compliance_status == "compliant":
|
954
|
+
print_success(
|
955
|
+
"✅ ENTERPRISE COMPLIANCE ACHIEVED: ≥99.5% MCP validation with complete infrastructure alignment"
|
956
|
+
)
|
967
957
|
else:
|
968
958
|
print_warning("⚠️ COMPLIANCE REVIEW REQUIRED: Enhance MCP validation accuracy to meet enterprise standards")
|
969
|
-
|
970
|
-
print_info(
|
959
|
+
|
960
|
+
print_info(
|
961
|
+
f"💰 Annual savings potential: ${analysis.annual_savings_potential:,.2f} ({analysis.roi_projection:.1f}% ROI)"
|
962
|
+
)
|
971
963
|
print_info(f"📊 Analysis evidence: {len(analysis.evidence_files)} files generated")
|
972
|
-
|
964
|
+
|
973
965
|
except Exception as e:
|
974
966
|
print_error(f"❌ Comprehensive cost analysis failed: {str(e)}")
|
975
967
|
raise
|
976
968
|
|
977
969
|
|
978
970
|
if __name__ == "__main__":
|
979
|
-
asyncio.run(main())
|
971
|
+
asyncio.run(main())
|