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
@@ -0,0 +1,358 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
VPC Test Data Loader - AWS-25 Integration Framework
|
4
|
+
=====================================================
|
5
|
+
|
6
|
+
Enterprise test data integration for VPC cleanup validation using comprehensive
|
7
|
+
production test data with 27 VPCs across 10 regions.
|
8
|
+
|
9
|
+
Author: python-runbooks-engineer [1]
|
10
|
+
Strategic Coordination: enterprise-product-owner [0]
|
11
|
+
Epic: AWS-25 VPC Infrastructure Cleanup
|
12
|
+
"""
|
13
|
+
|
14
|
+
import yaml
|
15
|
+
import logging
|
16
|
+
from pathlib import Path
|
17
|
+
from typing import Dict, List, Any, Optional
|
18
|
+
from datetime import datetime, timezone
|
19
|
+
|
20
|
+
from runbooks.common.rich_utils import console, print_success, print_warning, print_error
|
21
|
+
|
22
|
+
logger = logging.getLogger(__name__)
|
23
|
+
|
24
|
+
|
25
|
+
class VPCTestDataLoader:
|
26
|
+
"""
|
27
|
+
Enterprise VPC test data loader for AWS-25 validation framework.
|
28
|
+
|
29
|
+
Integrates comprehensive test data with 27 VPCs across 10 regions for
|
30
|
+
validation against multi-region discovery implementation.
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(self, test_data_path: Optional[str] = None):
|
34
|
+
"""
|
35
|
+
Initialize test data loader with production test dataset.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
test_data_path: Path to test data file (optional, uses default if None)
|
39
|
+
"""
|
40
|
+
self.test_data_path = test_data_path or self._get_default_test_data_path()
|
41
|
+
self.test_data = None
|
42
|
+
self._load_test_data()
|
43
|
+
|
44
|
+
def _get_default_test_data_path(self) -> str:
|
45
|
+
"""Get default path to VPC test data file."""
|
46
|
+
# Navigate to .claude/config/environment-data/vpc-test-data-production.yaml
|
47
|
+
current_dir = Path(__file__).parent
|
48
|
+
project_root = current_dir.parent.parent.parent # Go up to project root
|
49
|
+
test_data_path = project_root / ".claude" / "config" / "environment-data" / "vpc-test-data-production.yaml"
|
50
|
+
return str(test_data_path)
|
51
|
+
|
52
|
+
def _load_test_data(self):
|
53
|
+
"""Load VPC test data from YAML configuration."""
|
54
|
+
try:
|
55
|
+
with open(self.test_data_path, "r") as f:
|
56
|
+
self.test_data = yaml.safe_load(f)
|
57
|
+
|
58
|
+
print_success(f"✅ Test data loaded: {self.test_data_path}")
|
59
|
+
|
60
|
+
# Validate test data structure
|
61
|
+
if not self._validate_test_data_structure():
|
62
|
+
print_error("❌ Test data validation failed")
|
63
|
+
self.test_data = None
|
64
|
+
return
|
65
|
+
|
66
|
+
# Log test data summary
|
67
|
+
active_count = len(self.test_data["vpc_test_data"]["active_vpcs"])
|
68
|
+
deleted_count = len(self.test_data["vpc_test_data"]["deleted_vpcs"])
|
69
|
+
total_savings = self.test_data["business_metrics"]["annual_savings"]
|
70
|
+
|
71
|
+
print_success(f"📊 Test Data Summary: {active_count} active VPCs, {deleted_count} deleted VPCs")
|
72
|
+
print_success(f"💰 Business Case: ${total_savings:,} annual savings target")
|
73
|
+
|
74
|
+
except FileNotFoundError:
|
75
|
+
print_error(f"❌ Test data file not found: {self.test_data_path}")
|
76
|
+
self.test_data = None
|
77
|
+
except yaml.YAMLError as e:
|
78
|
+
print_error(f"❌ YAML parsing error: {e}")
|
79
|
+
self.test_data = None
|
80
|
+
except Exception as e:
|
81
|
+
print_error(f"❌ Test data loading failed: {e}")
|
82
|
+
self.test_data = None
|
83
|
+
|
84
|
+
def _validate_test_data_structure(self) -> bool:
|
85
|
+
"""Validate test data has required structure."""
|
86
|
+
required_keys = ["vpc_test_data", "business_metrics", "aws_profiles"]
|
87
|
+
|
88
|
+
if not all(key in self.test_data for key in required_keys):
|
89
|
+
print_error("❌ Missing required test data sections")
|
90
|
+
return False
|
91
|
+
|
92
|
+
# Validate VPC data structure
|
93
|
+
vpc_data = self.test_data["vpc_test_data"]
|
94
|
+
if "active_vpcs" not in vpc_data or "deleted_vpcs" not in vpc_data:
|
95
|
+
print_error("❌ Missing VPC data sections")
|
96
|
+
return False
|
97
|
+
|
98
|
+
return True
|
99
|
+
|
100
|
+
def get_active_vpcs(self) -> List[Dict[str, Any]]:
|
101
|
+
"""Get list of active VPCs for discovery testing."""
|
102
|
+
if not self.test_data:
|
103
|
+
return []
|
104
|
+
|
105
|
+
return self.test_data["vpc_test_data"]["active_vpcs"]
|
106
|
+
|
107
|
+
def get_deleted_vpcs(self) -> List[Dict[str, Any]]:
|
108
|
+
"""Get list of deleted VPCs for historical validation."""
|
109
|
+
if not self.test_data:
|
110
|
+
return []
|
111
|
+
|
112
|
+
return self.test_data["vpc_test_data"]["deleted_vpcs"]
|
113
|
+
|
114
|
+
def get_vpc_by_id(self, vpc_id: str) -> Optional[Dict[str, Any]]:
|
115
|
+
"""Get specific VPC data by ID."""
|
116
|
+
active_vpcs = self.get_active_vpcs()
|
117
|
+
for vpc in active_vpcs:
|
118
|
+
if vpc.get("vpc_id") == vpc_id:
|
119
|
+
return vpc
|
120
|
+
|
121
|
+
return None
|
122
|
+
|
123
|
+
def get_vpcs_by_region(self, region: str) -> List[Dict[str, Any]]:
|
124
|
+
"""Get all VPCs in a specific region."""
|
125
|
+
active_vpcs = self.get_active_vpcs()
|
126
|
+
return [vpc for vpc in active_vpcs if vpc.get("region") == region]
|
127
|
+
|
128
|
+
def get_zero_eni_vpcs(self) -> List[Dict[str, Any]]:
|
129
|
+
"""Get VPCs with 0 ENIs (immediate cleanup candidates)."""
|
130
|
+
active_vpcs = self.get_active_vpcs()
|
131
|
+
return [vpc for vpc in active_vpcs if vpc.get("enis", 0) == 0]
|
132
|
+
|
133
|
+
def get_test_regions(self) -> List[str]:
|
134
|
+
"""Get list of all regions in test data."""
|
135
|
+
active_vpcs = self.get_active_vpcs()
|
136
|
+
regions = list(set(vpc.get("region", "unknown") for vpc in active_vpcs))
|
137
|
+
return sorted(regions)
|
138
|
+
|
139
|
+
def get_business_metrics(self) -> Dict[str, Any]:
|
140
|
+
"""Get business metrics for validation."""
|
141
|
+
if not self.test_data:
|
142
|
+
return {}
|
143
|
+
|
144
|
+
return self.test_data.get("business_metrics", {})
|
145
|
+
|
146
|
+
def get_aws_profiles(self) -> Dict[str, str]:
|
147
|
+
"""Get AWS profiles configuration."""
|
148
|
+
if not self.test_data:
|
149
|
+
return {}
|
150
|
+
|
151
|
+
return self.test_data.get("aws_profiles", {})
|
152
|
+
|
153
|
+
def simulate_vpc_discovery_response(self, region: str) -> Dict[str, Any]:
|
154
|
+
"""
|
155
|
+
Simulate AWS VPC discovery response for testing.
|
156
|
+
|
157
|
+
Returns mock VPC data in AWS API response format for the specified region.
|
158
|
+
"""
|
159
|
+
region_vpcs = self.get_vpcs_by_region(region)
|
160
|
+
|
161
|
+
# Convert test data to AWS API response format
|
162
|
+
aws_vpcs = []
|
163
|
+
for vpc_data in region_vpcs:
|
164
|
+
aws_vpc = {
|
165
|
+
"VpcId": vpc_data["vpc_id"],
|
166
|
+
"CidrBlock": vpc_data["cidr"],
|
167
|
+
"State": "available",
|
168
|
+
"IsDefault": vpc_data.get("name", "").startswith("default"),
|
169
|
+
"Tags": [{"Key": "Name", "Value": vpc_data["name"]}],
|
170
|
+
}
|
171
|
+
aws_vpcs.append(aws_vpc)
|
172
|
+
|
173
|
+
return {
|
174
|
+
"Vpcs": aws_vpcs,
|
175
|
+
"ResponseMetadata": {
|
176
|
+
"HTTPStatusCode": 200,
|
177
|
+
"RequestId": f"test-request-{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
178
|
+
"HTTPHeaders": {"date": datetime.now(timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")},
|
179
|
+
},
|
180
|
+
}
|
181
|
+
|
182
|
+
def simulate_eni_response(self, vpc_id: str) -> Dict[str, Any]:
|
183
|
+
"""
|
184
|
+
Simulate AWS ENI response for testing ENI Gate validation.
|
185
|
+
|
186
|
+
Returns mock ENI data based on test data ENI counts.
|
187
|
+
"""
|
188
|
+
vpc_data = self.get_vpc_by_id(vpc_id)
|
189
|
+
if not vpc_data:
|
190
|
+
return {"NetworkInterfaces": []}
|
191
|
+
|
192
|
+
eni_count = vpc_data.get("enis", 0)
|
193
|
+
|
194
|
+
# Generate mock ENI data
|
195
|
+
network_interfaces = []
|
196
|
+
for i in range(eni_count):
|
197
|
+
eni = {
|
198
|
+
"NetworkInterfaceId": f"eni-{vpc_id[-8:]}{i:02d}",
|
199
|
+
"VpcId": vpc_id,
|
200
|
+
"Status": "in-use",
|
201
|
+
"PrivateIpAddress": f"10.0.{i}.{i + 10}",
|
202
|
+
"Description": f"Test ENI {i + 1} for {vpc_data['name']}",
|
203
|
+
}
|
204
|
+
network_interfaces.append(eni)
|
205
|
+
|
206
|
+
return {
|
207
|
+
"NetworkInterfaces": network_interfaces,
|
208
|
+
"ResponseMetadata": {
|
209
|
+
"HTTPStatusCode": 200,
|
210
|
+
"RequestId": f"test-eni-{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
211
|
+
"HTTPHeaders": {"date": datetime.now(timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")},
|
212
|
+
},
|
213
|
+
}
|
214
|
+
|
215
|
+
def validate_discovery_results(self, discovered_vpcs: List[Dict], expected_region: str) -> Dict[str, Any]:
|
216
|
+
"""
|
217
|
+
Validate VPC discovery results against test data.
|
218
|
+
|
219
|
+
Args:
|
220
|
+
discovered_vpcs: VPCs discovered by the implementation
|
221
|
+
expected_region: Region that was scanned
|
222
|
+
|
223
|
+
Returns:
|
224
|
+
Validation results with accuracy metrics
|
225
|
+
"""
|
226
|
+
expected_vpcs = self.get_vpcs_by_region(expected_region)
|
227
|
+
expected_vpc_ids = [vpc["vpc_id"] for vpc in expected_vpcs]
|
228
|
+
discovered_vpc_ids = [vpc.get("vpc_id", "") for vpc in discovered_vpcs]
|
229
|
+
|
230
|
+
# Calculate accuracy metrics
|
231
|
+
correctly_found = len(set(discovered_vpc_ids) & set(expected_vpc_ids))
|
232
|
+
total_expected = len(expected_vpc_ids)
|
233
|
+
total_discovered = len(discovered_vpc_ids)
|
234
|
+
|
235
|
+
accuracy = (correctly_found / total_expected * 100) if total_expected > 0 else 0
|
236
|
+
precision = (correctly_found / total_discovered * 100) if total_discovered > 0 else 0
|
237
|
+
|
238
|
+
# Identify missing and extra VPCs
|
239
|
+
missing_vpcs = set(expected_vpc_ids) - set(discovered_vpc_ids)
|
240
|
+
extra_vpcs = set(discovered_vpc_ids) - set(expected_vpc_ids)
|
241
|
+
|
242
|
+
return {
|
243
|
+
"region": expected_region,
|
244
|
+
"expected_count": total_expected,
|
245
|
+
"discovered_count": total_discovered,
|
246
|
+
"correctly_found": correctly_found,
|
247
|
+
"accuracy_percentage": round(accuracy, 1),
|
248
|
+
"precision_percentage": round(precision, 1),
|
249
|
+
"missing_vpcs": list(missing_vpcs),
|
250
|
+
"extra_vpcs": list(extra_vpcs),
|
251
|
+
"validation_passed": accuracy >= 90.0, # 90% accuracy threshold
|
252
|
+
"validation_timestamp": datetime.now(timezone.utc).isoformat(),
|
253
|
+
}
|
254
|
+
|
255
|
+
def generate_test_summary(self) -> Dict[str, Any]:
|
256
|
+
"""Generate comprehensive test data summary."""
|
257
|
+
if not self.test_data:
|
258
|
+
return {"error": "No test data available"}
|
259
|
+
|
260
|
+
active_vpcs = self.get_active_vpcs()
|
261
|
+
deleted_vpcs = self.get_deleted_vpcs()
|
262
|
+
regions = self.get_test_regions()
|
263
|
+
zero_eni_vpcs = self.get_zero_eni_vpcs()
|
264
|
+
business_metrics = self.get_business_metrics()
|
265
|
+
|
266
|
+
# Calculate region distribution
|
267
|
+
region_distribution = {}
|
268
|
+
for vpc in active_vpcs:
|
269
|
+
region = vpc.get("region", "unknown")
|
270
|
+
region_distribution[region] = region_distribution.get(region, 0) + 1
|
271
|
+
|
272
|
+
# Calculate ENI distribution
|
273
|
+
eni_distribution = {}
|
274
|
+
for vpc in active_vpcs:
|
275
|
+
eni_count = vpc.get("enis", 0)
|
276
|
+
eni_key = f"{eni_count}_enis"
|
277
|
+
eni_distribution[eni_key] = eni_distribution.get(eni_key, 0) + 1
|
278
|
+
|
279
|
+
return {
|
280
|
+
"test_data_source": self.test_data_path,
|
281
|
+
"total_active_vpcs": len(active_vpcs),
|
282
|
+
"total_deleted_vpcs": len(deleted_vpcs),
|
283
|
+
"total_regions": len(regions),
|
284
|
+
"regions": regions,
|
285
|
+
"region_distribution": region_distribution,
|
286
|
+
"eni_distribution": eni_distribution,
|
287
|
+
"zero_eni_candidates": len(zero_eni_vpcs),
|
288
|
+
"business_metrics": business_metrics,
|
289
|
+
"annual_savings_target": business_metrics.get("annual_savings", 0),
|
290
|
+
"immediate_cleanup_ready": len(zero_eni_vpcs),
|
291
|
+
"data_quality": {
|
292
|
+
"complete_vpc_records": len(
|
293
|
+
[
|
294
|
+
vpc
|
295
|
+
for vpc in active_vpcs
|
296
|
+
if all(key in vpc for key in ["vpc_id", "name", "region", "enis", "cost_annual"])
|
297
|
+
]
|
298
|
+
),
|
299
|
+
"data_completeness": round(
|
300
|
+
len(
|
301
|
+
[
|
302
|
+
vpc
|
303
|
+
for vpc in active_vpcs
|
304
|
+
if all(key in vpc for key in ["vpc_id", "name", "region", "enis", "cost_annual"])
|
305
|
+
]
|
306
|
+
)
|
307
|
+
/ len(active_vpcs)
|
308
|
+
* 100,
|
309
|
+
1,
|
310
|
+
)
|
311
|
+
if active_vpcs
|
312
|
+
else 0,
|
313
|
+
},
|
314
|
+
"generated_at": datetime.now(timezone.utc).isoformat(),
|
315
|
+
}
|
316
|
+
|
317
|
+
|
318
|
+
def load_test_data() -> VPCTestDataLoader:
|
319
|
+
"""Convenience function to load VPC test data."""
|
320
|
+
return VPCTestDataLoader()
|
321
|
+
|
322
|
+
|
323
|
+
def validate_test_data_integration() -> bool:
|
324
|
+
"""Validate test data integration is working properly."""
|
325
|
+
try:
|
326
|
+
loader = VPCTestDataLoader()
|
327
|
+
if not loader.test_data:
|
328
|
+
print_error("❌ Test data integration failed")
|
329
|
+
return False
|
330
|
+
|
331
|
+
summary = loader.generate_test_summary()
|
332
|
+
print_success(f"✅ Test data integration validated: {summary['total_active_vpcs']} VPCs ready")
|
333
|
+
return True
|
334
|
+
|
335
|
+
except Exception as e:
|
336
|
+
print_error(f"❌ Test data validation failed: {e}")
|
337
|
+
return False
|
338
|
+
|
339
|
+
|
340
|
+
if __name__ == "__main__":
|
341
|
+
# Standalone validation
|
342
|
+
console.print("[bold green]VPC Test Data Loader - AWS-25 Integration[/bold green]")
|
343
|
+
|
344
|
+
loader = VPCTestDataLoader()
|
345
|
+
if loader.test_data:
|
346
|
+
summary = loader.generate_test_summary()
|
347
|
+
|
348
|
+
console.print(f"[green]✅ Active VPCs:[/green] {summary['total_active_vpcs']}")
|
349
|
+
console.print(f"[green]✅ Regions:[/green] {summary['total_regions']}")
|
350
|
+
console.print(f"[green]✅ Zero ENI candidates:[/green] {summary['zero_eni_candidates']}")
|
351
|
+
console.print(f"[green]✅ Annual savings target:[/green] ${summary['annual_savings_target']:,}")
|
352
|
+
|
353
|
+
# Test region-specific discovery
|
354
|
+
for region in summary["regions"][:3]: # Test first 3 regions
|
355
|
+
region_vpcs = loader.get_vpcs_by_region(region)
|
356
|
+
console.print(f"[cyan]📍 {region}:[/cyan] {len(region_vpcs)} VPCs")
|
357
|
+
else:
|
358
|
+
print_error("❌ Test data loading failed")
|