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
runbooks/vpc/config.py
CHANGED
@@ -13,6 +13,7 @@ from typing import Any, Dict, List, Optional
|
|
13
13
|
# Import AWS Pricing API for zero hardcoded values
|
14
14
|
try:
|
15
15
|
from runbooks.common.aws_pricing_api import pricing_api
|
16
|
+
|
16
17
|
AWS_PRICING_AVAILABLE = True
|
17
18
|
except ImportError:
|
18
19
|
AWS_PRICING_AVAILABLE = False
|
@@ -25,20 +26,12 @@ class AWSCostModel:
|
|
25
26
|
# NAT Gateway Pricing - Real-time from AWS Pricing API (NO hardcoded defaults)
|
26
27
|
nat_gateway_hourly: float = field(default_factory=lambda: AWSCostModel._get_nat_gateway_hourly())
|
27
28
|
nat_gateway_monthly: float = field(default_factory=lambda: AWSCostModel._get_nat_gateway_monthly())
|
28
|
-
nat_gateway_data_processing: float = field(
|
29
|
-
default_factory=lambda: AWSCostModel._get_nat_gateway_data_processing()
|
30
|
-
)
|
29
|
+
nat_gateway_data_processing: float = field(default_factory=lambda: AWSCostModel._get_nat_gateway_data_processing())
|
31
30
|
|
32
31
|
# Transit Gateway Pricing - Real-time from AWS Pricing API (NO hardcoded defaults)
|
33
|
-
transit_gateway_hourly: float = field(
|
34
|
-
|
35
|
-
)
|
36
|
-
transit_gateway_monthly: float = field(
|
37
|
-
default_factory=lambda: AWSCostModel._get_transit_gateway_monthly()
|
38
|
-
)
|
39
|
-
transit_gateway_attachment: float = field(
|
40
|
-
default_factory=lambda: AWSCostModel._get_transit_gateway_attachment()
|
41
|
-
)
|
32
|
+
transit_gateway_hourly: float = field(default_factory=lambda: AWSCostModel._get_transit_gateway_hourly())
|
33
|
+
transit_gateway_monthly: float = field(default_factory=lambda: AWSCostModel._get_transit_gateway_monthly())
|
34
|
+
transit_gateway_attachment: float = field(default_factory=lambda: AWSCostModel._get_transit_gateway_attachment())
|
42
35
|
transit_gateway_data_processing: float = field(
|
43
36
|
default_factory=lambda: AWSCostModel._get_transit_gateway_data_processing()
|
44
37
|
)
|
@@ -56,60 +49,48 @@ class AWSCostModel:
|
|
56
49
|
)
|
57
50
|
|
58
51
|
# Elastic IP Pricing - ENTERPRISE COMPLIANCE: Real-time AWS Pricing API ONLY
|
59
|
-
elastic_ip_idle_hourly: float = field(
|
60
|
-
|
61
|
-
)
|
62
|
-
elastic_ip_idle_monthly: float = field(
|
63
|
-
default_factory=lambda: AWSCostModel._get_elastic_ip_idle_monthly()
|
64
|
-
)
|
52
|
+
elastic_ip_idle_hourly: float = field(default_factory=lambda: AWSCostModel._get_elastic_ip_idle_hourly())
|
53
|
+
elastic_ip_idle_monthly: float = field(default_factory=lambda: AWSCostModel._get_elastic_ip_idle_monthly())
|
65
54
|
elastic_ip_attached: float = 0.0 # Always free when attached (AWS confirmed)
|
66
|
-
elastic_ip_remap: float = field(
|
67
|
-
default_factory=lambda: AWSCostModel._get_elastic_ip_remap()
|
68
|
-
)
|
55
|
+
elastic_ip_remap: float = field(default_factory=lambda: AWSCostModel._get_elastic_ip_remap())
|
69
56
|
|
70
57
|
# Data Transfer Pricing - ENTERPRISE COMPLIANCE: Real-time AWS Pricing API ONLY
|
71
|
-
data_transfer_inter_az: float = field(
|
72
|
-
|
73
|
-
)
|
74
|
-
data_transfer_inter_region: float = field(
|
75
|
-
default_factory=lambda: AWSCostModel._get_data_transfer_inter_region()
|
76
|
-
)
|
77
|
-
data_transfer_internet_out: float = field(
|
78
|
-
default_factory=lambda: AWSCostModel._get_data_transfer_internet_out()
|
79
|
-
)
|
58
|
+
data_transfer_inter_az: float = field(default_factory=lambda: AWSCostModel._get_data_transfer_inter_az())
|
59
|
+
data_transfer_inter_region: float = field(default_factory=lambda: AWSCostModel._get_data_transfer_inter_region())
|
60
|
+
data_transfer_internet_out: float = field(default_factory=lambda: AWSCostModel._get_data_transfer_internet_out())
|
80
61
|
data_transfer_s3_same_region: float = 0.0 # Always free
|
81
|
-
|
62
|
+
|
82
63
|
@staticmethod
|
83
64
|
def _get_nat_gateway_hourly() -> float:
|
84
65
|
"""Get NAT Gateway hourly cost from AWS Pricing API with enhanced enterprise fallback."""
|
85
66
|
if AWS_PRICING_AVAILABLE:
|
86
67
|
try:
|
87
68
|
# Use enhanced pricing API with regional fallback and graceful degradation
|
88
|
-
current_region = os.getenv(
|
69
|
+
current_region = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
|
89
70
|
monthly_cost = pricing_api.get_nat_gateway_monthly_cost(current_region)
|
90
71
|
return monthly_cost / (24 * 30)
|
91
72
|
except Exception as e:
|
92
73
|
print(f"⚠️ NAT Gateway pricing API fallback: {e}")
|
93
|
-
|
74
|
+
|
94
75
|
# Universal compatibility: standard AWS pricing when API unavailable
|
95
76
|
print("ℹ️ Using universal compatibility NAT Gateway rate")
|
96
77
|
return 0.045 # AWS standard NAT Gateway hourly rate
|
97
|
-
|
78
|
+
|
98
79
|
@staticmethod
|
99
80
|
def _get_nat_gateway_monthly() -> float:
|
100
81
|
"""Get NAT Gateway monthly cost from AWS Pricing API with enhanced enterprise fallback."""
|
101
82
|
if AWS_PRICING_AVAILABLE:
|
102
83
|
try:
|
103
84
|
# Use enhanced pricing API with regional fallback and graceful degradation
|
104
|
-
current_region = os.getenv(
|
85
|
+
current_region = os.getenv("AWS_DEFAULT_REGION", "us-east-1")
|
105
86
|
return pricing_api.get_nat_gateway_monthly_cost(current_region)
|
106
87
|
except Exception as e:
|
107
88
|
print(f"⚠️ NAT Gateway monthly pricing API fallback: {e}")
|
108
|
-
|
89
|
+
|
109
90
|
# Universal compatibility: calculate from hourly rate
|
110
91
|
print("ℹ️ Calculating monthly cost from universal compatibility hourly rate")
|
111
92
|
return AWSCostModel._get_nat_gateway_hourly() * 24 * 30
|
112
|
-
|
93
|
+
|
113
94
|
@staticmethod
|
114
95
|
def _get_nat_gateway_data_processing() -> float:
|
115
96
|
"""Get NAT Gateway data processing cost from AWS Pricing API."""
|
@@ -121,7 +102,7 @@ class AWSCostModel:
|
|
121
102
|
pass
|
122
103
|
# Universal compatibility: standard AWS pricing
|
123
104
|
return 0.045 # AWS standard NAT Gateway data processing rate
|
124
|
-
|
105
|
+
|
125
106
|
@staticmethod
|
126
107
|
def _get_transit_gateway_hourly() -> float:
|
127
108
|
"""Get Transit Gateway hourly cost from AWS Pricing API."""
|
@@ -133,12 +114,12 @@ class AWSCostModel:
|
|
133
114
|
pass
|
134
115
|
# Universal compatibility: standard AWS pricing
|
135
116
|
return 0.05 # AWS standard Transit Gateway hourly rate
|
136
|
-
|
117
|
+
|
137
118
|
@staticmethod
|
138
119
|
def _get_transit_gateway_monthly() -> float:
|
139
120
|
"""Get Transit Gateway monthly cost from AWS Pricing API."""
|
140
121
|
return AWSCostModel._get_transit_gateway_hourly() * 24 * 30
|
141
|
-
|
122
|
+
|
142
123
|
@staticmethod
|
143
124
|
def _get_transit_gateway_attachment() -> float:
|
144
125
|
"""Get Transit Gateway attachment cost from AWS Pricing API."""
|
@@ -150,7 +131,7 @@ class AWSCostModel:
|
|
150
131
|
pass
|
151
132
|
# Universal compatibility: standard AWS pricing
|
152
133
|
return 0.05 # AWS standard TGW attachment rate
|
153
|
-
|
134
|
+
|
154
135
|
@staticmethod
|
155
136
|
def _get_transit_gateway_data_processing() -> float:
|
156
137
|
"""Get Transit Gateway data processing cost from AWS Pricing API."""
|
@@ -162,7 +143,7 @@ class AWSCostModel:
|
|
162
143
|
pass
|
163
144
|
# Universal compatibility: standard AWS pricing
|
164
145
|
return 0.02 # AWS standard TGW data processing rate
|
165
|
-
|
146
|
+
|
166
147
|
# VPC Endpoint Pricing Methods
|
167
148
|
@staticmethod
|
168
149
|
def _get_vpc_endpoint_interface_hourly() -> float:
|
@@ -172,7 +153,7 @@ class AWSCostModel:
|
|
172
153
|
# Universal compatibility: standard AWS pricing
|
173
154
|
return 0.01 # AWS standard VPC Interface Endpoint hourly rate
|
174
155
|
return float(value)
|
175
|
-
|
156
|
+
|
176
157
|
@staticmethod
|
177
158
|
def _get_vpc_endpoint_interface_monthly() -> float:
|
178
159
|
"""Get VPC Endpoint Interface monthly cost from AWS Pricing API."""
|
@@ -181,7 +162,7 @@ class AWSCostModel:
|
|
181
162
|
# Universal compatibility: calculate from hourly rate
|
182
163
|
return AWSCostModel._get_vpc_endpoint_interface_hourly() * 24 * 30
|
183
164
|
return float(value)
|
184
|
-
|
165
|
+
|
185
166
|
@staticmethod
|
186
167
|
def _get_vpc_endpoint_data_processing() -> float:
|
187
168
|
"""Get VPC Endpoint data processing cost from AWS Pricing API."""
|
@@ -190,7 +171,7 @@ class AWSCostModel:
|
|
190
171
|
# Universal compatibility: standard AWS pricing
|
191
172
|
return 0.01 # AWS standard VPC Endpoint data processing rate
|
192
173
|
return float(value)
|
193
|
-
|
174
|
+
|
194
175
|
# Elastic IP Pricing Methods
|
195
176
|
@staticmethod
|
196
177
|
def _get_elastic_ip_idle_hourly() -> float:
|
@@ -200,7 +181,7 @@ class AWSCostModel:
|
|
200
181
|
# Universal compatibility: standard AWS pricing
|
201
182
|
return 0.005 # AWS standard Elastic IP idle hourly rate
|
202
183
|
return float(value)
|
203
|
-
|
184
|
+
|
204
185
|
@staticmethod
|
205
186
|
def _get_elastic_ip_idle_monthly() -> float:
|
206
187
|
"""Get Elastic IP idle monthly cost from AWS Pricing API."""
|
@@ -209,7 +190,7 @@ class AWSCostModel:
|
|
209
190
|
# Universal compatibility: calculate from hourly rate
|
210
191
|
return AWSCostModel._get_elastic_ip_idle_hourly() * 24 * 30
|
211
192
|
return float(value)
|
212
|
-
|
193
|
+
|
213
194
|
@staticmethod
|
214
195
|
def _get_elastic_ip_remap() -> float:
|
215
196
|
"""Get Elastic IP remap cost from AWS Pricing API."""
|
@@ -218,7 +199,7 @@ class AWSCostModel:
|
|
218
199
|
# Universal compatibility: standard AWS pricing
|
219
200
|
return 0.10 # AWS standard Elastic IP remap cost
|
220
201
|
return float(value)
|
221
|
-
|
202
|
+
|
222
203
|
# Data Transfer Pricing Methods
|
223
204
|
@staticmethod
|
224
205
|
def _get_data_transfer_inter_az() -> float:
|
@@ -228,7 +209,7 @@ class AWSCostModel:
|
|
228
209
|
# Universal compatibility: standard AWS pricing
|
229
210
|
return 0.01 # AWS standard Inter-AZ data transfer rate per GB
|
230
211
|
return float(value)
|
231
|
-
|
212
|
+
|
232
213
|
@staticmethod
|
233
214
|
def _get_data_transfer_inter_region() -> float:
|
234
215
|
"""Get Inter-region data transfer cost from AWS Pricing API."""
|
@@ -237,7 +218,7 @@ class AWSCostModel:
|
|
237
218
|
# Universal compatibility: standard AWS pricing
|
238
219
|
return 0.02 # AWS standard Inter-region data transfer rate per GB
|
239
220
|
return float(value)
|
240
|
-
|
221
|
+
|
241
222
|
@staticmethod
|
242
223
|
def _get_data_transfer_internet_out() -> float:
|
243
224
|
"""Get Internet outbound data transfer cost from AWS Pricing API."""
|
@@ -253,13 +234,23 @@ class OptimizationThresholds:
|
|
253
234
|
"""Configurable thresholds for optimization recommendations - NO hardcoded defaults"""
|
254
235
|
|
255
236
|
# Usage thresholds - Dynamic from environment or raise error
|
256
|
-
idle_connection_threshold: int = field(
|
257
|
-
|
258
|
-
|
237
|
+
idle_connection_threshold: int = field(
|
238
|
+
default_factory=lambda: OptimizationThresholds._get_env_int("IDLE_CONNECTION_THRESHOLD")
|
239
|
+
)
|
240
|
+
low_usage_gb_threshold: float = field(
|
241
|
+
default_factory=lambda: OptimizationThresholds._get_env_float("LOW_USAGE_GB_THRESHOLD")
|
242
|
+
)
|
243
|
+
low_connection_threshold: int = field(
|
244
|
+
default_factory=lambda: OptimizationThresholds._get_env_int("LOW_CONNECTION_THRESHOLD")
|
245
|
+
)
|
259
246
|
|
260
247
|
# Cost thresholds - Dynamic from environment or raise error
|
261
|
-
high_cost_threshold: float = field(
|
262
|
-
|
248
|
+
high_cost_threshold: float = field(
|
249
|
+
default_factory=lambda: OptimizationThresholds._get_env_float("HIGH_COST_THRESHOLD")
|
250
|
+
)
|
251
|
+
critical_cost_threshold: float = field(
|
252
|
+
default_factory=lambda: OptimizationThresholds._get_env_float("CRITICAL_COST_THRESHOLD")
|
253
|
+
)
|
263
254
|
|
264
255
|
# Optimization targets - Dynamic from environment or raise error
|
265
256
|
target_reduction_percent: float = field(
|
@@ -270,23 +261,20 @@ class OptimizationThresholds:
|
|
270
261
|
cost_approval_threshold: float = field(
|
271
262
|
default_factory=lambda: OptimizationThresholds._get_env_float("COST_APPROVAL_THRESHOLD")
|
272
263
|
)
|
273
|
-
|
264
|
+
|
274
265
|
@staticmethod
|
275
266
|
def _get_env_int(var_name: str) -> int:
|
276
267
|
"""Get integer from environment with universal compatibility defaults."""
|
277
268
|
value = os.getenv(var_name)
|
278
269
|
if value is None:
|
279
270
|
# Universal compatibility defaults for optimization thresholds
|
280
|
-
defaults = {
|
281
|
-
"IDLE_CONNECTION_THRESHOLD": 1,
|
282
|
-
"LOW_CONNECTION_THRESHOLD": 5
|
283
|
-
}
|
271
|
+
defaults = {"IDLE_CONNECTION_THRESHOLD": 1, "LOW_CONNECTION_THRESHOLD": 5}
|
284
272
|
default_value = defaults.get(var_name)
|
285
273
|
if default_value is None:
|
286
274
|
raise ValueError(f"Environment variable {var_name} required and no universal default available")
|
287
275
|
return default_value
|
288
276
|
return int(value)
|
289
|
-
|
277
|
+
|
290
278
|
@staticmethod
|
291
279
|
def _get_env_float(var_name: str) -> float:
|
292
280
|
"""Get float from environment with universal compatibility defaults."""
|
@@ -299,13 +287,14 @@ class OptimizationThresholds:
|
|
299
287
|
"CRITICAL_COST_THRESHOLD": 1000.0,
|
300
288
|
"TARGET_REDUCTION_PERCENT": 0.30,
|
301
289
|
"COST_APPROVAL_THRESHOLD": 500.0,
|
302
|
-
"PERFORMANCE_BASELINE_THRESHOLD": 30.0
|
290
|
+
"PERFORMANCE_BASELINE_THRESHOLD": 30.0,
|
303
291
|
}
|
304
292
|
default_value = defaults.get(var_name)
|
305
293
|
if default_value is None:
|
306
294
|
raise ValueError(f"Environment variable {var_name} required and no universal default available")
|
307
295
|
return default_value
|
308
296
|
return float(value)
|
297
|
+
|
309
298
|
performance_baseline_threshold: float = field(
|
310
299
|
default_factory=lambda: OptimizationThresholds._get_env_float("PERFORMANCE_BASELINE_THRESHOLD")
|
311
300
|
)
|
@@ -334,14 +323,20 @@ class RegionalConfiguration:
|
|
334
323
|
regional_multipliers: Dict[str, float] = field(
|
335
324
|
default_factory=lambda: RegionalConfiguration._get_regional_multipliers()
|
336
325
|
)
|
337
|
-
|
326
|
+
|
338
327
|
@staticmethod
|
339
328
|
def _get_regional_multipliers() -> Dict[str, float]:
|
340
329
|
"""Get regional cost multipliers - NO hardcoded defaults."""
|
341
330
|
regions = [
|
342
|
-
"us-east-1",
|
343
|
-
"
|
344
|
-
"
|
331
|
+
"us-east-1",
|
332
|
+
"us-west-2",
|
333
|
+
"us-west-1",
|
334
|
+
"eu-west-1",
|
335
|
+
"eu-central-1",
|
336
|
+
"eu-west-2",
|
337
|
+
"ap-southeast-1",
|
338
|
+
"ap-southeast-2",
|
339
|
+
"ap-northeast-1",
|
345
340
|
]
|
346
341
|
multipliers = {}
|
347
342
|
for region in regions:
|
@@ -361,7 +356,7 @@ class VPCNetworkingConfig:
|
|
361
356
|
|
362
357
|
# AWS Configuration - NO hardcoded defaults
|
363
358
|
default_region: str = field(default_factory=lambda: VPCNetworkingConfig._get_required_env("AWS_DEFAULT_REGION"))
|
364
|
-
|
359
|
+
|
365
360
|
@staticmethod
|
366
361
|
def _get_required_env(var_name: str) -> str:
|
367
362
|
"""Get environment variable with universal compatibility defaults."""
|
@@ -373,24 +368,21 @@ class VPCNetworkingConfig:
|
|
373
368
|
"OUTPUT_FORMAT": "json",
|
374
369
|
"OUTPUT_DIR": "./tmp",
|
375
370
|
"ENABLE_COST_APPROVAL_WORKFLOW": "false",
|
376
|
-
"ENABLE_MCP_VALIDATION": "false"
|
371
|
+
"ENABLE_MCP_VALIDATION": "false",
|
377
372
|
}
|
378
373
|
default_value = defaults.get(var_name)
|
379
374
|
if default_value is None:
|
380
375
|
raise ValueError(f"Environment variable {var_name} required and no universal default available")
|
381
376
|
return default_value
|
382
377
|
return value
|
383
|
-
|
378
|
+
|
384
379
|
@staticmethod
|
385
380
|
def _get_required_env_int(var_name: str) -> int:
|
386
381
|
"""Get integer environment variable with universal compatibility defaults."""
|
387
382
|
value = os.getenv(var_name)
|
388
383
|
if value is None:
|
389
384
|
# Universal compatibility defaults for any AWS environment
|
390
|
-
defaults = {
|
391
|
-
"DEFAULT_ANALYSIS_DAYS": 30,
|
392
|
-
"FORECAST_DAYS": 30
|
393
|
-
}
|
385
|
+
defaults = {"DEFAULT_ANALYSIS_DAYS": 30, "FORECAST_DAYS": 30}
|
394
386
|
default_value = defaults.get(var_name)
|
395
387
|
if default_value is None:
|
396
388
|
raise ValueError(f"Environment variable {var_name} required and no universal default available")
|
@@ -398,31 +390,33 @@ class VPCNetworkingConfig:
|
|
398
390
|
return int(value)
|
399
391
|
|
400
392
|
# AWS Profiles - Universal compatibility with fallback to AWS_PROFILE or 'default'
|
401
|
-
billing_profile: Optional[str] = field(
|
402
|
-
os.getenv("BILLING_PROFILE") or
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
)
|
412
|
-
single_account_profile: Optional[str] = field(
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
"default"
|
422
|
-
)
|
393
|
+
billing_profile: Optional[str] = field(
|
394
|
+
default_factory=lambda: (os.getenv("BILLING_PROFILE") or os.getenv("AWS_PROFILE") or "default")
|
395
|
+
)
|
396
|
+
centralized_ops_profile: Optional[str] = field(
|
397
|
+
default_factory=lambda: (
|
398
|
+
os.getenv("CENTRALIZED_OPS_PROFILE")
|
399
|
+
or os.getenv("CENTRALISED_OPS_PROFILE") # Alternative spelling
|
400
|
+
or os.getenv("AWS_PROFILE")
|
401
|
+
or "default"
|
402
|
+
)
|
403
|
+
)
|
404
|
+
single_account_profile: Optional[str] = field(
|
405
|
+
default_factory=lambda: (
|
406
|
+
os.getenv("SINGLE_ACCOUNT_PROFILE")
|
407
|
+
or os.getenv("SINGLE_AWS_PROFILE") # Alternative naming
|
408
|
+
or os.getenv("AWS_PROFILE")
|
409
|
+
or "default"
|
410
|
+
)
|
411
|
+
)
|
412
|
+
management_profile: Optional[str] = field(
|
413
|
+
default_factory=lambda: (os.getenv("MANAGEMENT_PROFILE") or os.getenv("AWS_PROFILE") or "default")
|
414
|
+
)
|
423
415
|
|
424
416
|
# Analysis Configuration - ENTERPRISE COMPLIANCE: No hardcoded defaults
|
425
|
-
default_analysis_days: int = field(
|
417
|
+
default_analysis_days: int = field(
|
418
|
+
default_factory=lambda: VPCNetworkingConfig._get_required_env_int("DEFAULT_ANALYSIS_DAYS")
|
419
|
+
)
|
426
420
|
forecast_days: int = field(default_factory=lambda: VPCNetworkingConfig._get_required_env_int("FORECAST_DAYS"))
|
427
421
|
|
428
422
|
# Output Configuration - ENTERPRISE COMPLIANCE: No hardcoded defaults
|
@@ -476,10 +470,11 @@ def load_config(config_file: Optional[str] = None) -> VPCNetworkingConfig:
|
|
476
470
|
# Universal compatibility - warn instead of failing
|
477
471
|
if not config.billing_profile or config.billing_profile == "default":
|
478
472
|
import warnings
|
473
|
+
|
479
474
|
warnings.warn(
|
480
475
|
"Cost approval workflow enabled but no specific BILLING_PROFILE set. "
|
481
476
|
"Using default profile. Set BILLING_PROFILE for enterprise multi-account setup.",
|
482
|
-
UserWarning
|
477
|
+
UserWarning,
|
483
478
|
)
|
484
479
|
|
485
480
|
return config
|