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.
Files changed (228) hide show
  1. runbooks/__init__.py +31 -2
  2. runbooks/__init___optimized.py +18 -4
  3. runbooks/_platform/__init__.py +1 -5
  4. runbooks/_platform/core/runbooks_wrapper.py +141 -138
  5. runbooks/aws2/accuracy_validator.py +812 -0
  6. runbooks/base.py +7 -0
  7. runbooks/cfat/assessment/compliance.py +1 -1
  8. runbooks/cfat/assessment/runner.py +1 -0
  9. runbooks/cfat/cloud_foundations_assessment.py +227 -239
  10. runbooks/cli/__init__.py +1 -1
  11. runbooks/cli/commands/cfat.py +64 -23
  12. runbooks/cli/commands/finops.py +1005 -54
  13. runbooks/cli/commands/inventory.py +138 -35
  14. runbooks/cli/commands/operate.py +9 -36
  15. runbooks/cli/commands/security.py +42 -18
  16. runbooks/cli/commands/validation.py +432 -18
  17. runbooks/cli/commands/vpc.py +81 -17
  18. runbooks/cli/registry.py +22 -10
  19. runbooks/cloudops/__init__.py +20 -27
  20. runbooks/cloudops/base.py +96 -107
  21. runbooks/cloudops/cost_optimizer.py +544 -542
  22. runbooks/cloudops/infrastructure_optimizer.py +5 -4
  23. runbooks/cloudops/interfaces.py +224 -225
  24. runbooks/cloudops/lifecycle_manager.py +5 -4
  25. runbooks/cloudops/mcp_cost_validation.py +252 -235
  26. runbooks/cloudops/models.py +78 -53
  27. runbooks/cloudops/monitoring_automation.py +5 -4
  28. runbooks/cloudops/notebook_framework.py +177 -213
  29. runbooks/cloudops/security_enforcer.py +125 -159
  30. runbooks/common/accuracy_validator.py +11 -0
  31. runbooks/common/aws_pricing.py +349 -326
  32. runbooks/common/aws_pricing_api.py +211 -212
  33. runbooks/common/aws_profile_manager.py +40 -36
  34. runbooks/common/aws_utils.py +74 -79
  35. runbooks/common/business_logic.py +126 -104
  36. runbooks/common/cli_decorators.py +36 -60
  37. runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
  38. runbooks/common/cross_account_manager.py +197 -204
  39. runbooks/common/date_utils.py +27 -39
  40. runbooks/common/decorators.py +29 -19
  41. runbooks/common/dry_run_examples.py +173 -208
  42. runbooks/common/dry_run_framework.py +157 -155
  43. runbooks/common/enhanced_exception_handler.py +15 -4
  44. runbooks/common/enhanced_logging_example.py +50 -64
  45. runbooks/common/enhanced_logging_integration_example.py +65 -37
  46. runbooks/common/env_utils.py +16 -16
  47. runbooks/common/error_handling.py +40 -38
  48. runbooks/common/lazy_loader.py +41 -23
  49. runbooks/common/logging_integration_helper.py +79 -86
  50. runbooks/common/mcp_cost_explorer_integration.py +476 -493
  51. runbooks/common/mcp_integration.py +63 -74
  52. runbooks/common/memory_optimization.py +140 -118
  53. runbooks/common/module_cli_base.py +37 -58
  54. runbooks/common/organizations_client.py +175 -193
  55. runbooks/common/patterns.py +23 -25
  56. runbooks/common/performance_monitoring.py +67 -71
  57. runbooks/common/performance_optimization_engine.py +283 -274
  58. runbooks/common/profile_utils.py +111 -37
  59. runbooks/common/rich_utils.py +201 -141
  60. runbooks/common/sre_performance_suite.py +177 -186
  61. runbooks/enterprise/__init__.py +1 -1
  62. runbooks/enterprise/logging.py +144 -106
  63. runbooks/enterprise/security.py +187 -204
  64. runbooks/enterprise/validation.py +43 -56
  65. runbooks/finops/__init__.py +26 -30
  66. runbooks/finops/account_resolver.py +1 -1
  67. runbooks/finops/advanced_optimization_engine.py +980 -0
  68. runbooks/finops/automation_core.py +268 -231
  69. runbooks/finops/business_case_config.py +184 -179
  70. runbooks/finops/cli.py +660 -139
  71. runbooks/finops/commvault_ec2_analysis.py +157 -164
  72. runbooks/finops/compute_cost_optimizer.py +336 -320
  73. runbooks/finops/config.py +20 -20
  74. runbooks/finops/cost_optimizer.py +484 -618
  75. runbooks/finops/cost_processor.py +332 -214
  76. runbooks/finops/dashboard_runner.py +1006 -172
  77. runbooks/finops/ebs_cost_optimizer.py +991 -657
  78. runbooks/finops/elastic_ip_optimizer.py +317 -257
  79. runbooks/finops/enhanced_mcp_integration.py +340 -0
  80. runbooks/finops/enhanced_progress.py +32 -29
  81. runbooks/finops/enhanced_trend_visualization.py +3 -2
  82. runbooks/finops/enterprise_wrappers.py +223 -285
  83. runbooks/finops/executive_export.py +203 -160
  84. runbooks/finops/helpers.py +130 -288
  85. runbooks/finops/iam_guidance.py +1 -1
  86. runbooks/finops/infrastructure/__init__.py +80 -0
  87. runbooks/finops/infrastructure/commands.py +506 -0
  88. runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
  89. runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
  90. runbooks/finops/markdown_exporter.py +337 -174
  91. runbooks/finops/mcp_validator.py +1952 -0
  92. runbooks/finops/nat_gateway_optimizer.py +1512 -481
  93. runbooks/finops/network_cost_optimizer.py +657 -587
  94. runbooks/finops/notebook_utils.py +226 -188
  95. runbooks/finops/optimization_engine.py +1136 -0
  96. runbooks/finops/optimizer.py +19 -23
  97. runbooks/finops/rds_snapshot_optimizer.py +367 -411
  98. runbooks/finops/reservation_optimizer.py +427 -363
  99. runbooks/finops/scenario_cli_integration.py +64 -65
  100. runbooks/finops/scenarios.py +1277 -438
  101. runbooks/finops/schemas.py +218 -182
  102. runbooks/finops/snapshot_manager.py +2289 -0
  103. runbooks/finops/types.py +3 -3
  104. runbooks/finops/validation_framework.py +259 -265
  105. runbooks/finops/vpc_cleanup_exporter.py +189 -144
  106. runbooks/finops/vpc_cleanup_optimizer.py +591 -573
  107. runbooks/finops/workspaces_analyzer.py +171 -182
  108. runbooks/integration/__init__.py +89 -0
  109. runbooks/integration/mcp_integration.py +1920 -0
  110. runbooks/inventory/CLAUDE.md +816 -0
  111. runbooks/inventory/__init__.py +2 -2
  112. runbooks/inventory/cloud_foundations_integration.py +144 -149
  113. runbooks/inventory/collectors/aws_comprehensive.py +1 -1
  114. runbooks/inventory/collectors/aws_networking.py +109 -99
  115. runbooks/inventory/collectors/base.py +4 -0
  116. runbooks/inventory/core/collector.py +495 -313
  117. runbooks/inventory/drift_detection_cli.py +69 -96
  118. runbooks/inventory/inventory_mcp_cli.py +48 -46
  119. runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
  120. runbooks/inventory/mcp_inventory_validator.py +549 -465
  121. runbooks/inventory/mcp_vpc_validator.py +359 -442
  122. runbooks/inventory/organizations_discovery.py +55 -51
  123. runbooks/inventory/rich_inventory_display.py +33 -32
  124. runbooks/inventory/unified_validation_engine.py +278 -251
  125. runbooks/inventory/vpc_analyzer.py +732 -695
  126. runbooks/inventory/vpc_architecture_validator.py +293 -348
  127. runbooks/inventory/vpc_dependency_analyzer.py +382 -378
  128. runbooks/inventory/vpc_flow_analyzer.py +1 -1
  129. runbooks/main.py +49 -34
  130. runbooks/main_final.py +91 -60
  131. runbooks/main_minimal.py +22 -10
  132. runbooks/main_optimized.py +131 -100
  133. runbooks/main_ultra_minimal.py +7 -2
  134. runbooks/mcp/__init__.py +36 -0
  135. runbooks/mcp/integration.py +679 -0
  136. runbooks/monitoring/performance_monitor.py +9 -4
  137. runbooks/operate/dynamodb_operations.py +3 -1
  138. runbooks/operate/ec2_operations.py +145 -137
  139. runbooks/operate/iam_operations.py +146 -152
  140. runbooks/operate/networking_cost_heatmap.py +29 -8
  141. runbooks/operate/rds_operations.py +223 -254
  142. runbooks/operate/s3_operations.py +107 -118
  143. runbooks/operate/vpc_operations.py +646 -616
  144. runbooks/remediation/base.py +1 -1
  145. runbooks/remediation/commons.py +10 -7
  146. runbooks/remediation/commvault_ec2_analysis.py +70 -66
  147. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
  148. runbooks/remediation/multi_account.py +24 -21
  149. runbooks/remediation/rds_snapshot_list.py +86 -60
  150. runbooks/remediation/remediation_cli.py +92 -146
  151. runbooks/remediation/universal_account_discovery.py +83 -79
  152. runbooks/remediation/workspaces_list.py +46 -41
  153. runbooks/security/__init__.py +19 -0
  154. runbooks/security/assessment_runner.py +1150 -0
  155. runbooks/security/baseline_checker.py +812 -0
  156. runbooks/security/cloudops_automation_security_validator.py +509 -535
  157. runbooks/security/compliance_automation_engine.py +17 -17
  158. runbooks/security/config/__init__.py +2 -2
  159. runbooks/security/config/compliance_config.py +50 -50
  160. runbooks/security/config_template_generator.py +63 -76
  161. runbooks/security/enterprise_security_framework.py +1 -1
  162. runbooks/security/executive_security_dashboard.py +519 -508
  163. runbooks/security/multi_account_security_controls.py +959 -1210
  164. runbooks/security/real_time_security_monitor.py +422 -444
  165. runbooks/security/security_baseline_tester.py +1 -1
  166. runbooks/security/security_cli.py +143 -112
  167. runbooks/security/test_2way_validation.py +439 -0
  168. runbooks/security/two_way_validation_framework.py +852 -0
  169. runbooks/sre/production_monitoring_framework.py +167 -177
  170. runbooks/tdd/__init__.py +15 -0
  171. runbooks/tdd/cli.py +1071 -0
  172. runbooks/utils/__init__.py +14 -17
  173. runbooks/utils/logger.py +7 -2
  174. runbooks/utils/version_validator.py +50 -47
  175. runbooks/validation/__init__.py +6 -6
  176. runbooks/validation/cli.py +9 -3
  177. runbooks/validation/comprehensive_2way_validator.py +745 -704
  178. runbooks/validation/mcp_validator.py +906 -228
  179. runbooks/validation/terraform_citations_validator.py +104 -115
  180. runbooks/validation/terraform_drift_detector.py +447 -451
  181. runbooks/vpc/README.md +617 -0
  182. runbooks/vpc/__init__.py +8 -1
  183. runbooks/vpc/analyzer.py +577 -0
  184. runbooks/vpc/cleanup_wrapper.py +476 -413
  185. runbooks/vpc/cli_cloudtrail_commands.py +339 -0
  186. runbooks/vpc/cli_mcp_validation_commands.py +480 -0
  187. runbooks/vpc/cloudtrail_audit_integration.py +717 -0
  188. runbooks/vpc/config.py +92 -97
  189. runbooks/vpc/cost_engine.py +411 -148
  190. runbooks/vpc/cost_explorer_integration.py +553 -0
  191. runbooks/vpc/cross_account_session.py +101 -106
  192. runbooks/vpc/enhanced_mcp_validation.py +917 -0
  193. runbooks/vpc/eni_gate_validator.py +961 -0
  194. runbooks/vpc/heatmap_engine.py +185 -160
  195. runbooks/vpc/mcp_no_eni_validator.py +680 -639
  196. runbooks/vpc/nat_gateway_optimizer.py +358 -0
  197. runbooks/vpc/networking_wrapper.py +15 -8
  198. runbooks/vpc/pdca_remediation_planner.py +528 -0
  199. runbooks/vpc/performance_optimized_analyzer.py +219 -231
  200. runbooks/vpc/runbooks_adapter.py +1167 -241
  201. runbooks/vpc/tdd_red_phase_stubs.py +601 -0
  202. runbooks/vpc/test_data_loader.py +358 -0
  203. runbooks/vpc/tests/conftest.py +314 -4
  204. runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
  205. runbooks/vpc/tests/test_cost_engine.py +0 -2
  206. runbooks/vpc/topology_generator.py +326 -0
  207. runbooks/vpc/unified_scenarios.py +1297 -1124
  208. runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
  209. runbooks-1.1.5.dist-info/METADATA +328 -0
  210. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/RECORD +214 -193
  211. runbooks/finops/README.md +0 -414
  212. runbooks/finops/accuracy_cross_validator.py +0 -647
  213. runbooks/finops/business_cases.py +0 -950
  214. runbooks/finops/dashboard_router.py +0 -922
  215. runbooks/finops/ebs_optimizer.py +0 -973
  216. runbooks/finops/embedded_mcp_validator.py +0 -1629
  217. runbooks/finops/enhanced_dashboard_runner.py +0 -527
  218. runbooks/finops/finops_dashboard.py +0 -584
  219. runbooks/finops/finops_scenarios.py +0 -1218
  220. runbooks/finops/legacy_migration.py +0 -730
  221. runbooks/finops/multi_dashboard.py +0 -1519
  222. runbooks/finops/single_dashboard.py +0 -1113
  223. runbooks/finops/unlimited_scenarios.py +0 -393
  224. runbooks-1.1.4.dist-info/METADATA +0 -800
  225. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
  226. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
  227. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
  228. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,7 @@ Strategic Enhancement: Migrated VPC discovery capabilities from vpc module follo
8
8
  Maintains 100% compatibility with AWS Cloud Foundations inventory-scripts:
9
9
  - all_my_vpcs.py -> Enhanced VPCCollector with topology mapping
10
10
  - all_my_subnets.py -> SubnetCollector
11
- - all_my_elbs.py -> ELBCollector
11
+ - all_my_elbs.py -> ELBCollector
12
12
  - all_my_enis.py -> ENICollector
13
13
  - all_my_phzs.py -> Route53Collector
14
14
 
@@ -293,32 +293,33 @@ if __name__ == "__main__":
293
293
  # NEW VPC MODULE MIGRATION - Network Topology Discovery
294
294
  # ============================================================================
295
295
 
296
+
296
297
  class NetworkTopologyCollector(BaseResourceCollector):
297
298
  """
298
299
  Network Topology Collector - Migrated from vpc module networking_wrapper.py
299
-
300
+
300
301
  Provides comprehensive VPC topology mapping and cross-region relationships
301
302
  following enterprise discovery patterns with Rich CLI integration.
302
303
  """
303
-
304
+
304
305
  def __init__(self, session: Optional[boto3.Session] = None):
305
306
  super().__init__(resource_type=ResourceType.VPC, session=session) # Using VPC as base type
306
-
307
+
307
308
  @aws_api_retry
308
309
  def collect_network_topology(self, account: AWSAccount, regions: List[str] = None) -> Dict[str, Any]:
309
310
  """
310
311
  Collect comprehensive network topology across regions.
311
-
312
+
312
313
  Args:
313
314
  account: AWS account to analyze
314
315
  regions: List of regions to analyze (default: all available)
315
-
316
+
316
317
  Returns:
317
318
  Dictionary with complete network topology mapping
318
319
  """
319
320
  if not regions:
320
321
  regions = ["us-east-1", "us-west-2", "eu-west-1"] # Default enterprise regions
321
-
322
+
322
323
  print_header("Network Topology Discovery", "latest version")
323
324
  topology = {
324
325
  "account_id": account.account_id,
@@ -331,9 +332,9 @@ class NetworkTopologyCollector(BaseResourceCollector):
331
332
  "vpc_peering": [],
332
333
  "total_vpcs": 0,
333
334
  "total_subnets": 0,
334
- "recommendations": []
335
+ "recommendations": [],
335
336
  }
336
-
337
+
337
338
  for region in regions:
338
339
  try:
339
340
  print_info(f"Analyzing network topology in {region}")
@@ -341,22 +342,24 @@ class NetworkTopologyCollector(BaseResourceCollector):
341
342
  topology["vpc_topology"][region] = region_topology
342
343
  topology["total_vpcs"] += len(region_topology["vpcs"])
343
344
  topology["total_subnets"] += len(region_topology["subnets"])
344
-
345
+
345
346
  except Exception as e:
346
347
  self.logger.error(f"Failed to collect topology from {region}: {e}")
347
348
  continue
348
-
349
+
349
350
  # Analyze cross-region connections
350
351
  topology["cross_region_connections"] = self._analyze_cross_region_connections(topology["vpc_topology"])
351
352
  topology["recommendations"] = self._generate_topology_recommendations(topology)
352
-
353
- print_success(f"Network topology discovery completed: {topology['total_vpcs']} VPCs, {topology['total_subnets']} subnets")
353
+
354
+ print_success(
355
+ f"Network topology discovery completed: {topology['total_vpcs']} VPCs, {topology['total_subnets']} subnets"
356
+ )
354
357
  return topology
355
-
358
+
356
359
  def _collect_region_topology(self, region: str, account: AWSAccount) -> Dict[str, Any]:
357
360
  """Collect detailed network topology for a specific region."""
358
361
  ec2 = self.session.client("ec2", region_name=region)
359
-
362
+
360
363
  region_topology = {
361
364
  "region": region,
362
365
  "vpcs": [],
@@ -365,38 +368,38 @@ class NetworkTopologyCollector(BaseResourceCollector):
365
368
  "internet_gateways": [],
366
369
  "nat_gateways": [],
367
370
  "vpc_endpoints": [],
368
- "network_interfaces": []
371
+ "network_interfaces": [],
369
372
  }
370
-
373
+
371
374
  try:
372
375
  # Collect VPCs with enhanced metadata
373
376
  vpcs_response = ec2.describe_vpcs()
374
377
  for vpc in vpcs_response["Vpcs"]:
375
378
  vpc_data = self._enhance_vpc_data(ec2, vpc, region, account)
376
379
  region_topology["vpcs"].append(vpc_data)
377
-
380
+
378
381
  # Collect NAT Gateways
379
382
  nat_response = ec2.describe_nat_gateways()
380
383
  for nat in nat_response["NatGateways"]:
381
384
  if nat["State"] != "deleted":
382
385
  nat_data = self._enhance_nat_gateway_data(ec2, nat, region)
383
386
  region_topology["nat_gateways"].append(nat_data)
384
-
387
+
385
388
  # Collect VPC Endpoints
386
389
  endpoints_response = ec2.describe_vpc_endpoints()
387
390
  for endpoint in endpoints_response["VpcEndpoints"]:
388
391
  endpoint_data = self._enhance_vpc_endpoint_data(endpoint, region)
389
392
  region_topology["vpc_endpoints"].append(endpoint_data)
390
-
393
+
391
394
  except ClientError as e:
392
395
  self.logger.error(f"AWS API error in {region}: {e}")
393
-
396
+
394
397
  return region_topology
395
-
398
+
396
399
  def _enhance_vpc_data(self, ec2_client, vpc: Dict[str, Any], region: str, account: AWSAccount) -> Dict[str, Any]:
397
400
  """Enhance VPC data with topology relationships."""
398
401
  tags = {tag["Key"]: tag["Value"] for tag in vpc.get("Tags", [])}
399
-
402
+
400
403
  enhanced_vpc = {
401
404
  "vpc_id": vpc["VpcId"],
402
405
  "cidr_block": vpc["CidrBlock"],
@@ -412,35 +415,35 @@ class NetworkTopologyCollector(BaseResourceCollector):
412
415
  "route_tables": [],
413
416
  "internet_gateways": [],
414
417
  "security_groups": [],
415
- "network_acls": []
418
+ "network_acls": [],
416
419
  }
417
-
420
+
418
421
  # Get associated subnets
419
422
  try:
420
- subnets_response = ec2_client.describe_subnets(
421
- Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}]
422
- )
423
+ subnets_response = ec2_client.describe_subnets(Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}])
423
424
  for subnet in subnets_response["Subnets"]:
424
425
  subnet_tags = {tag["Key"]: tag["Value"] for tag in subnet.get("Tags", [])}
425
- enhanced_vpc["subnets"].append({
426
- "subnet_id": subnet["SubnetId"],
427
- "cidr_block": subnet["CidrBlock"],
428
- "availability_zone": subnet["AvailabilityZone"],
429
- "available_ip_address_count": subnet["AvailableIpAddressCount"],
430
- "map_public_ip_on_launch": subnet.get("MapPublicIpOnLaunch", False),
431
- "state": subnet["State"],
432
- "tags": subnet_tags,
433
- "name": subnet_tags.get("Name", subnet["SubnetId"])
434
- })
426
+ enhanced_vpc["subnets"].append(
427
+ {
428
+ "subnet_id": subnet["SubnetId"],
429
+ "cidr_block": subnet["CidrBlock"],
430
+ "availability_zone": subnet["AvailabilityZone"],
431
+ "available_ip_address_count": subnet["AvailableIpAddressCount"],
432
+ "map_public_ip_on_launch": subnet.get("MapPublicIpOnLaunch", False),
433
+ "state": subnet["State"],
434
+ "tags": subnet_tags,
435
+ "name": subnet_tags.get("Name", subnet["SubnetId"]),
436
+ }
437
+ )
435
438
  except ClientError as e:
436
439
  self.logger.warning(f"Failed to get subnets for VPC {vpc['VpcId']}: {e}")
437
-
440
+
438
441
  return enhanced_vpc
439
-
442
+
440
443
  def _enhance_nat_gateway_data(self, ec2_client, nat: Dict[str, Any], region: str) -> Dict[str, Any]:
441
444
  """Enhance NAT Gateway data with usage and cost implications."""
442
445
  tags = {tag["Key"]: tag["Value"] for tag in nat.get("Tags", [])}
443
-
446
+
444
447
  return {
445
448
  "nat_gateway_id": nat["NatGatewayId"],
446
449
  "state": nat["State"],
@@ -454,13 +457,13 @@ class NetworkTopologyCollector(BaseResourceCollector):
454
457
  # Enhanced with network interface information
455
458
  "network_interface_id": nat.get("NatGatewayAddresses", [{}])[0].get("NetworkInterfaceId"),
456
459
  "public_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PublicIp"),
457
- "private_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PrivateIp")
460
+ "private_ip": nat.get("NatGatewayAddresses", [{}])[0].get("PrivateIp"),
458
461
  }
459
-
462
+
460
463
  def _enhance_vpc_endpoint_data(self, endpoint: Dict[str, Any], region: str) -> Dict[str, Any]:
461
464
  """Enhance VPC Endpoint data with service and cost information."""
462
465
  tags = {tag["Key"]: tag["Value"] for tag in endpoint.get("Tags", [])}
463
-
466
+
464
467
  return {
465
468
  "vpc_endpoint_id": endpoint["VpcEndpointId"],
466
469
  "vpc_id": endpoint.get("VpcId"),
@@ -473,64 +476,65 @@ class NetworkTopologyCollector(BaseResourceCollector):
473
476
  "name": tags.get("Name", endpoint["VpcEndpointId"]),
474
477
  "route_table_ids": endpoint.get("RouteTableIds", []),
475
478
  "subnet_ids": endpoint.get("SubnetIds", []),
476
- "policy_document": endpoint.get("PolicyDocument")
479
+ "policy_document": endpoint.get("PolicyDocument"),
477
480
  }
478
-
481
+
479
482
  def _analyze_cross_region_connections(self, vpc_topology: Dict[str, Any]) -> List[Dict[str, Any]]:
480
483
  """Analyze potential cross-region network connections."""
481
484
  connections = []
482
485
  # This would be enhanced to detect VPC peering, Transit Gateway, etc.
483
486
  # For now, return empty list as foundation
484
487
  return connections
485
-
488
+
486
489
  def _generate_topology_recommendations(self, topology: Dict[str, Any]) -> List[Dict[str, Any]]:
487
490
  """Generate network topology optimization recommendations."""
488
491
  recommendations = []
489
-
492
+
490
493
  # Basic recommendations based on topology analysis
491
494
  total_nat_gateways = sum(
492
- len(region_data.get("nat_gateways", []))
493
- for region_data in topology["vpc_topology"].values()
495
+ len(region_data.get("nat_gateways", [])) for region_data in topology["vpc_topology"].values()
494
496
  )
495
-
497
+
496
498
  if total_nat_gateways > topology["total_vpcs"]:
497
- recommendations.append({
498
- "type": "cost_optimization",
499
- "priority": "high",
500
- "description": f"Multiple NAT Gateways detected ({total_nat_gateways}) across {topology['total_vpcs']} VPCs",
501
- "recommendation": "Consider consolidating NAT Gateways to reduce monthly costs",
502
- "estimated_savings": f"${(total_nat_gateways - topology['total_vpcs']) * 45:.2f}/month"
503
- })
504
-
499
+ recommendations.append(
500
+ {
501
+ "type": "cost_optimization",
502
+ "priority": "high",
503
+ "description": f"Multiple NAT Gateways detected ({total_nat_gateways}) across {topology['total_vpcs']} VPCs",
504
+ "recommendation": "Consider consolidating NAT Gateways to reduce monthly costs",
505
+ "estimated_savings": f"${(total_nat_gateways - topology['total_vpcs']) * 45:.2f}/month",
506
+ }
507
+ )
508
+
505
509
  return recommendations
506
510
 
507
511
 
508
512
  class TransitGatewayCollector(BaseResourceCollector):
509
513
  """
510
514
  Transit Gateway Collector - Enhanced discovery from vpc module
511
-
515
+
512
516
  Provides comprehensive Transit Gateway and VPC peering discovery
513
517
  with enterprise cost analysis integration.
514
518
  """
515
-
519
+
516
520
  def __init__(self, session: Optional[boto3.Session] = None):
517
521
  super().__init__(resource_type=ResourceType.VPC, session=session)
518
-
522
+
519
523
  @aws_api_retry
520
524
  def collect_transit_gateways(self, account: AWSAccount, regions: List[str] = None) -> Dict[str, Any]:
521
525
  """
522
526
  Collect Transit Gateway configurations and attachments.
523
-
527
+
524
528
  Args:
525
529
  account: AWS account to analyze
526
530
  regions: List of regions to analyze
527
-
531
+
528
532
  Returns:
529
533
  Dictionary with Transit Gateway analysis
530
534
  """
531
535
  if not regions:
532
536
  regions = ["us-east-1", "us-west-2", "eu-west-1"]
533
-
537
+
534
538
  print_header("Transit Gateway Discovery", "latest version")
535
539
  tgw_analysis = {
536
540
  "account_id": account.account_id,
@@ -540,18 +544,18 @@ class TransitGatewayCollector(BaseResourceCollector):
540
544
  "total_tgw": 0,
541
545
  "total_attachments": 0,
542
546
  "monthly_cost_estimate": 0,
543
- "recommendations": []
547
+ "recommendations": [],
544
548
  }
545
-
549
+
546
550
  for region in regions:
547
551
  try:
548
552
  print_info(f"Analyzing Transit Gateways in {region}")
549
553
  ec2 = self.session.client("ec2", region_name=region)
550
-
554
+
551
555
  # Get Transit Gateways
552
556
  tgw_response = ec2.describe_transit_gateways()
553
557
  region_tgws = []
554
-
558
+
555
559
  for tgw in tgw_response["TransitGateways"]:
556
560
  if tgw["State"] not in ["deleted", "deleting"]:
557
561
  tgw_data = self._enhance_transit_gateway_data(ec2, tgw, region)
@@ -559,22 +563,24 @@ class TransitGatewayCollector(BaseResourceCollector):
559
563
  tgw_analysis["total_tgw"] += 1
560
564
  tgw_analysis["total_attachments"] += len(tgw_data["attachments"])
561
565
  tgw_analysis["monthly_cost_estimate"] += 36.50 # Base TGW cost per month
562
-
566
+
563
567
  tgw_analysis["transit_gateways"][region] = region_tgws
564
-
568
+
565
569
  except ClientError as e:
566
570
  self.logger.error(f"Failed to collect Transit Gateways from {region}: {e}")
567
571
  continue
568
-
572
+
569
573
  tgw_analysis["recommendations"] = self._generate_tgw_recommendations(tgw_analysis)
570
-
571
- print_success(f"Transit Gateway discovery completed: {tgw_analysis['total_tgw']} TGWs, {tgw_analysis['total_attachments']} attachments")
574
+
575
+ print_success(
576
+ f"Transit Gateway discovery completed: {tgw_analysis['total_tgw']} TGWs, {tgw_analysis['total_attachments']} attachments"
577
+ )
572
578
  return tgw_analysis
573
-
579
+
574
580
  def _enhance_transit_gateway_data(self, ec2_client, tgw: Dict[str, Any], region: str) -> Dict[str, Any]:
575
581
  """Enhance Transit Gateway data with attachments and routing information."""
576
582
  tags = {tag["Key"]: tag["Value"] for tag in tgw.get("Tags", [])}
577
-
583
+
578
584
  tgw_data = {
579
585
  "transit_gateway_id": tgw["TransitGatewayId"],
580
586
  "state": tgw["State"],
@@ -585,42 +591,46 @@ class TransitGatewayCollector(BaseResourceCollector):
585
591
  "tags": tags,
586
592
  "name": tags.get("Name", tgw["TransitGatewayId"]),
587
593
  "attachments": [],
588
- "route_tables": []
594
+ "route_tables": [],
589
595
  }
590
-
596
+
591
597
  # Get Transit Gateway Attachments
592
598
  try:
593
599
  attachments_response = ec2_client.describe_transit_gateway_attachments(
594
600
  Filters=[{"Name": "transit-gateway-id", "Values": [tgw["TransitGatewayId"]]}]
595
601
  )
596
-
602
+
597
603
  for attachment in attachments_response["TransitGatewayAttachments"]:
598
604
  attachment_tags = {tag["Key"]: tag["Value"] for tag in attachment.get("Tags", [])}
599
- tgw_data["attachments"].append({
600
- "attachment_id": attachment["TransitGatewayAttachmentId"],
601
- "resource_type": attachment["ResourceType"],
602
- "resource_id": attachment.get("ResourceId"),
603
- "state": attachment["State"],
604
- "tags": attachment_tags,
605
- "name": attachment_tags.get("Name", attachment["TransitGatewayAttachmentId"])
606
- })
607
-
605
+ tgw_data["attachments"].append(
606
+ {
607
+ "attachment_id": attachment["TransitGatewayAttachmentId"],
608
+ "resource_type": attachment["ResourceType"],
609
+ "resource_id": attachment.get("ResourceId"),
610
+ "state": attachment["State"],
611
+ "tags": attachment_tags,
612
+ "name": attachment_tags.get("Name", attachment["TransitGatewayAttachmentId"]),
613
+ }
614
+ )
615
+
608
616
  except ClientError as e:
609
617
  self.logger.warning(f"Failed to get attachments for TGW {tgw['TransitGatewayId']}: {e}")
610
-
618
+
611
619
  return tgw_data
612
-
620
+
613
621
  def _generate_tgw_recommendations(self, tgw_analysis: Dict[str, Any]) -> List[Dict[str, Any]]:
614
622
  """Generate Transit Gateway optimization recommendations."""
615
623
  recommendations = []
616
-
624
+
617
625
  if tgw_analysis["total_tgw"] > 1:
618
- recommendations.append({
619
- "type": "cost_optimization",
620
- "priority": "medium",
621
- "description": f"Multiple Transit Gateways detected ({tgw_analysis['total_tgw']})",
622
- "recommendation": "Consider consolidating Transit Gateways to reduce base costs",
623
- "estimated_savings": f"${(tgw_analysis['total_tgw'] - 1) * 36.50:.2f}/month"
624
- })
625
-
626
+ recommendations.append(
627
+ {
628
+ "type": "cost_optimization",
629
+ "priority": "medium",
630
+ "description": f"Multiple Transit Gateways detected ({tgw_analysis['total_tgw']})",
631
+ "recommendation": "Consider consolidating Transit Gateways to reduce base costs",
632
+ "estimated_savings": f"${(tgw_analysis['total_tgw'] - 1) * 36.50:.2f}/month",
633
+ }
634
+ )
635
+
626
636
  return recommendations
@@ -220,3 +220,7 @@ class BaseResourceCollector(ABC):
220
220
  return (
221
221
  f"{self.__class__.__name__}(category='{self.service_category}', resources={len(self.supported_resources)})"
222
222
  )
223
+
224
+
225
+ # Alias for backward compatibility
226
+ BaseCollector = BaseResourceCollector