runbooks 1.1.2__py3-none-any.whl → 1.1.4__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 +1 -1
- runbooks/cfat/WEIGHT_CONFIG_README.md +1 -1
- runbooks/cfat/assessment/compliance.py +7 -7
- runbooks/cfat/models.py +6 -2
- runbooks/cfat/tests/__init__.py +6 -1
- runbooks/cli/__init__.py +13 -0
- runbooks/cli/commands/cfat.py +233 -0
- runbooks/cli/commands/finops.py +213 -0
- runbooks/cli/commands/inventory.py +276 -0
- runbooks/cli/commands/operate.py +266 -0
- runbooks/cli/commands/security.py +224 -0
- runbooks/cli/commands/validation.py +411 -0
- runbooks/cli/commands/vpc.py +246 -0
- runbooks/cli/registry.py +95 -0
- runbooks/cloudops/__init__.py +3 -3
- runbooks/cloudops/cost_optimizer.py +164 -28
- runbooks/cloudops/interfaces.py +2 -2
- runbooks/cloudops/mcp_cost_validation.py +3 -3
- runbooks/cloudops/notebook_framework.py +2 -2
- runbooks/common/aws_profile_manager.py +337 -0
- runbooks/common/aws_utils.py +1 -1
- runbooks/common/business_logic.py +3 -3
- runbooks/common/comprehensive_cost_explorer_integration.py +1 -1
- runbooks/common/cross_account_manager.py +1 -1
- runbooks/common/decorators.py +225 -0
- runbooks/common/mcp_cost_explorer_integration.py +2 -2
- runbooks/common/organizations_client.py +1 -1
- runbooks/common/patterns.py +206 -0
- runbooks/common/profile_utils.py +149 -14
- runbooks/common/rich_utils.py +507 -16
- runbooks/finops/README.md +11 -11
- runbooks/finops/__init__.py +4 -4
- runbooks/finops/business_cases.py +3 -3
- runbooks/finops/cli.py +169 -103
- runbooks/finops/cost_optimizer.py +4 -4
- runbooks/finops/dashboard_router.py +2 -2
- runbooks/finops/ebs_cost_optimizer.py +4 -4
- runbooks/finops/ebs_optimizer.py +19 -2
- runbooks/finops/embedded_mcp_validator.py +101 -23
- runbooks/finops/enhanced_progress.py +8 -8
- runbooks/finops/enterprise_wrappers.py +7 -7
- runbooks/finops/finops_scenarios.py +101 -27
- runbooks/finops/legacy_migration.py +8 -8
- runbooks/finops/markdown_exporter.py +2 -2
- runbooks/finops/multi_dashboard.py +1 -1
- runbooks/finops/nat_gateway_optimizer.py +1 -1
- runbooks/finops/optimizer.py +6 -6
- runbooks/finops/rds_snapshot_optimizer.py +1389 -0
- runbooks/finops/scenario_cli_integration.py +13 -13
- runbooks/finops/scenarios.py +16 -16
- runbooks/finops/single_dashboard.py +10 -10
- runbooks/finops/tests/test_finops_dashboard.py +3 -3
- runbooks/finops/tests/test_reference_images_validation.py +2 -2
- runbooks/finops/tests/test_single_account_features.py +17 -17
- runbooks/finops/tests/validate_test_suite.py +1 -1
- runbooks/finops/validation_framework.py +5 -5
- runbooks/finops/vpc_cleanup_exporter.py +3 -3
- runbooks/finops/vpc_cleanup_optimizer.py +3 -3
- runbooks/finops/workspaces_analyzer.py +31 -13
- runbooks/hitl/enhanced_workflow_engine.py +1 -1
- runbooks/inventory/README.md +3 -3
- runbooks/inventory/Tests/common_test_data.py +30 -30
- runbooks/inventory/collectors/aws_comprehensive.py +28 -11
- runbooks/inventory/collectors/aws_networking.py +2 -2
- runbooks/inventory/discovery.md +2 -2
- runbooks/inventory/find_ec2_security_groups.py +1 -1
- runbooks/inventory/list_rds_snapshots_aggregator.py +745 -0
- runbooks/inventory/organizations_discovery.py +1 -1
- runbooks/inventory/vpc_analyzer.py +1 -1
- runbooks/inventory/vpc_flow_analyzer.py +2 -2
- runbooks/main.py +143 -8882
- runbooks/metrics/dora_metrics_engine.py +2 -2
- runbooks/operate/mcp_integration.py +1 -1
- runbooks/operate/networking_cost_heatmap.py +4 -2
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/operate/vpc_operations.py +2 -2
- runbooks/remediation/commvault_ec2_analysis.py +1 -1
- runbooks/remediation/rds_snapshot_list.py +5 -5
- runbooks/remediation/workspaces_list.py +5 -5
- runbooks/security/integration_test_enterprise_security.py +5 -3
- runbooks/security/run_script.py +1 -1
- runbooks/sre/mcp_reliability_engine.py +6 -6
- runbooks/utils/version_validator.py +1 -1
- runbooks/validation/comprehensive_2way_validator.py +9 -4
- runbooks/vpc/heatmap_engine.py +7 -4
- runbooks/vpc/mcp_no_eni_validator.py +1 -1
- runbooks/vpc/unified_scenarios.py +7 -7
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/METADATA +53 -52
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/RECORD +94 -80
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/WHEEL +0 -0
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.2.dist-info → runbooks-1.1.4.dist-info}/top_level.txt +0 -0
runbooks/finops/__init__.py
CHANGED
@@ -67,7 +67,7 @@ from runbooks.finops.finops_scenarios import (
|
|
67
67
|
FinOpsBusinessScenarios,
|
68
68
|
)
|
69
69
|
|
70
|
-
# NEW
|
70
|
+
# NEW latest version: Clean API wrapper for notebook consumption
|
71
71
|
from runbooks.finops.scenarios import (
|
72
72
|
finops_workspaces,
|
73
73
|
finops_snapshots,
|
@@ -99,12 +99,12 @@ __all__ = [
|
|
99
99
|
"_run_executive_dashboard",
|
100
100
|
# Enterprise Dashboard Classes - backward compatibility
|
101
101
|
"FinOpsConfig",
|
102
|
-
# Business scenarios with notebook integration (
|
102
|
+
# Business scenarios with notebook integration (latest version)
|
103
103
|
"create_business_scenarios_validated",
|
104
104
|
"format_for_business_audience",
|
105
105
|
"format_for_technical_audience",
|
106
106
|
"FinOpsBusinessScenarios",
|
107
|
-
# NEW
|
107
|
+
# NEW latest version: Clean API wrapper functions (cleaned naming)
|
108
108
|
"finops_workspaces",
|
109
109
|
"finops_snapshots",
|
110
110
|
"finops_commvault",
|
@@ -140,7 +140,7 @@ __all__ = [
|
|
140
140
|
"export_audit_report_to_json",
|
141
141
|
"export_trend_data_to_json",
|
142
142
|
"load_config_file",
|
143
|
-
# NOTEBOOK INTEGRATION FUNCTIONS (
|
143
|
+
# NOTEBOOK INTEGRATION FUNCTIONS (latest version)
|
144
144
|
"format_currency",
|
145
145
|
"create_business_summary_table",
|
146
146
|
"export_scenarios_to_notebook_html",
|
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
🏢 CloudOps-Automation Business Cases Module (Enhanced
|
2
|
+
🏢 CloudOps-Automation Business Cases Module (Enhanced latest version)
|
3
3
|
Enterprise Business Logic Extraction from 67+ Notebooks
|
4
4
|
|
5
5
|
Strategic Achievement: Business logic consolidation enabling $78,500+ annual savings
|
@@ -17,7 +17,7 @@ Enhanced Features:
|
|
17
17
|
- Executive dashboard integration
|
18
18
|
|
19
19
|
Author: Enterprise Agile Team (6-Agent Coordination)
|
20
|
-
Version:
|
20
|
+
Version: latest version - Distributed Architecture Framework
|
21
21
|
"""
|
22
22
|
|
23
23
|
import os
|
@@ -758,7 +758,7 @@ class EnhancedBusinessCaseDashboard:
|
|
758
758
|
|
759
759
|
Strategic Output: Complete business case portfolio for C-suite presentation
|
760
760
|
"""
|
761
|
-
print_header("Enterprise Business Case Portfolio Analysis", "
|
761
|
+
print_header("Enterprise Business Case Portfolio Analysis", "latest version")
|
762
762
|
|
763
763
|
# Get FinOps business cases (Universal $132K methodology)
|
764
764
|
finops_cases = self.finops_analyzer.get_all_business_cases()
|
runbooks/finops/cli.py
CHANGED
@@ -228,7 +228,7 @@ def main() -> int:
|
|
228
228
|
parser.add_argument(
|
229
229
|
"--scenario",
|
230
230
|
type=str,
|
231
|
-
help="Business scenario analysis (workspaces, snapshots,
|
231
|
+
help="Business scenario analysis (workspaces, rds-snapshots, backup-investigation, nat-gateway, elastic-ip, ebs-optimization, vpc-cleanup)",
|
232
232
|
)
|
233
233
|
parser.add_argument(
|
234
234
|
"--help-scenario",
|
@@ -272,93 +272,58 @@ def main() -> int:
|
|
272
272
|
|
273
273
|
console.print(f"[bold cyan]🎯 Executing Business Scenario: {args.scenario}[/bold cyan]")
|
274
274
|
|
275
|
-
#
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
from runbooks.finops.
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
def execute_elastic_ip_scenario():
|
328
|
-
# Create a simplified elastic IP scenario execution
|
329
|
-
print_info("Elastic IP optimization scenario analysis")
|
330
|
-
# Use enterprise profile resolution: User > Environment > Default
|
331
|
-
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
332
|
-
return {"scenario": "elastic-ip", "status": "completed", "profile": profile_param}
|
333
|
-
|
334
|
-
# Map scenarios to execution functions
|
335
|
-
scenario_map = {
|
336
|
-
'workspaces': execute_workspaces_scenario,
|
337
|
-
'snapshots': execute_snapshots_scenario,
|
338
|
-
'commvault': execute_commvault_scenario,
|
339
|
-
'nat-gateway': execute_nat_gateway_scenario,
|
340
|
-
'ebs': execute_ebs_scenario,
|
341
|
-
'vpc-cleanup': execute_vpc_cleanup_scenario,
|
342
|
-
'elastic-ip': execute_elastic_ip_scenario,
|
343
|
-
}
|
344
|
-
|
345
|
-
if args.scenario not in scenario_map:
|
346
|
-
print_error(f"Unknown scenario: '{args.scenario}'")
|
347
|
-
print_info("Available scenarios: " + ", ".join(scenario_map.keys()))
|
348
|
-
return 1
|
349
|
-
|
350
|
-
# Execute scenario
|
351
|
-
scenario_func = scenario_map[args.scenario]
|
352
|
-
result = scenario_func()
|
353
|
-
|
354
|
-
print_success(f"✅ Scenario '{args.scenario}' completed successfully")
|
355
|
-
|
356
|
-
# Export results if requested
|
357
|
-
if args.report_type and result:
|
358
|
-
from runbooks.finops.helpers import export_scenario_results
|
359
|
-
export_scenario_results(result, args.scenario, args.report_type, args.dir)
|
360
|
-
|
361
|
-
return 0
|
275
|
+
# CRITICAL FIX: Handle --all flag for scenarios by using dashboard router logic
|
276
|
+
if hasattr(args, "all") and args.all:
|
277
|
+
print_info("🔍 --all flag detected: Integrating with dashboard router for organization discovery")
|
278
|
+
|
279
|
+
# Use dashboard router to handle --all flag and get profiles
|
280
|
+
from runbooks.finops.dashboard_router import create_dashboard_router
|
281
|
+
router = create_dashboard_router()
|
282
|
+
use_case, routing_config = router.detect_use_case(args)
|
283
|
+
|
284
|
+
# Extract profiles from routing config
|
285
|
+
profiles_to_use = routing_config.get("profiles_to_analyze", [])
|
286
|
+
if not profiles_to_use:
|
287
|
+
print_error("--all flag failed to discover any profiles")
|
288
|
+
return 1
|
289
|
+
|
290
|
+
print_success(f"Discovered {len(profiles_to_use)} profiles for scenario execution")
|
291
|
+
|
292
|
+
# Execute scenario across all discovered profiles
|
293
|
+
all_results = []
|
294
|
+
for profile in profiles_to_use:
|
295
|
+
print_info(f"Executing scenario '{args.scenario}' for profile: {profile}")
|
296
|
+
|
297
|
+
# Create a copy of args with single profile for execution
|
298
|
+
single_profile_args = argparse.Namespace(**vars(args))
|
299
|
+
single_profile_args.profiles = [profile]
|
300
|
+
single_profile_args.all = False # Disable --all for individual execution
|
301
|
+
|
302
|
+
# Execute scenario with single profile (recursive call but with all=False)
|
303
|
+
result = _execute_single_scenario(single_profile_args)
|
304
|
+
if result:
|
305
|
+
all_results.append(result)
|
306
|
+
|
307
|
+
# Combine results and export if requested
|
308
|
+
combined_result = {
|
309
|
+
"scenario": args.scenario,
|
310
|
+
"status": "completed",
|
311
|
+
"profiles_analyzed": len(profiles_to_use),
|
312
|
+
"individual_results": all_results,
|
313
|
+
"organization_scope": use_case == "organization_wide"
|
314
|
+
}
|
315
|
+
|
316
|
+
print_success(f"✅ Scenario '{args.scenario}' completed for {len(profiles_to_use)} profiles")
|
317
|
+
|
318
|
+
# Export results if requested
|
319
|
+
if args.report_type and combined_result:
|
320
|
+
from runbooks.finops.helpers import export_scenario_results
|
321
|
+
export_scenario_results(combined_result, args.scenario, args.report_type, args.dir)
|
322
|
+
|
323
|
+
return 0
|
324
|
+
else:
|
325
|
+
# Handle single profile execution (existing logic)
|
326
|
+
return _execute_single_scenario(args)
|
362
327
|
|
363
328
|
except ImportError as e:
|
364
329
|
console.print(f"[red]❌ Scenario '{args.scenario}' not available: {e}[/red]")
|
@@ -367,26 +332,127 @@ def main() -> int:
|
|
367
332
|
console.print(f"[red]❌ Scenario execution failed: {e}[/red]")
|
368
333
|
return 1
|
369
334
|
|
335
|
+
|
336
|
+
def _execute_single_scenario(args: argparse.Namespace) -> int:
|
337
|
+
"""Execute a scenario for a single profile (internal helper function)."""
|
338
|
+
import argparse
|
339
|
+
from runbooks.common.rich_utils import print_header, print_success, print_error, print_info
|
340
|
+
from runbooks.common.profile_utils import get_profile_for_operation
|
341
|
+
|
342
|
+
def execute_workspaces_scenario():
|
343
|
+
from runbooks.finops.scenarios import finops_workspaces
|
344
|
+
# Use enterprise profile resolution: User > Environment > Default
|
345
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
346
|
+
return finops_workspaces(profile=profile_param)
|
347
|
+
|
348
|
+
def execute_snapshots_scenario():
|
349
|
+
from runbooks.finops.scenarios import finops_snapshots
|
350
|
+
# Use enterprise profile resolution: User > Environment > Default
|
351
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
352
|
+
return finops_snapshots(profile=profile_param)
|
353
|
+
|
354
|
+
def execute_commvault_scenario():
|
355
|
+
from runbooks.finops.scenarios import finops_commvault
|
356
|
+
# Use enterprise profile resolution: User > Environment > Default
|
357
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
358
|
+
return finops_commvault(profile=profile_param)
|
359
|
+
|
360
|
+
def execute_nat_gateway_scenario():
|
361
|
+
from runbooks.finops.nat_gateway_optimizer import nat_gateway_optimizer
|
362
|
+
# Use enterprise profile resolution: User > Environment > Default
|
363
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
364
|
+
regions = args.regions if args.regions else ['us-east-1']
|
365
|
+
# Call the CLI function with default parameters
|
366
|
+
nat_gateway_optimizer(
|
367
|
+
profile=profile_param,
|
368
|
+
regions=regions,
|
369
|
+
dry_run=True,
|
370
|
+
export_format='json',
|
371
|
+
output_file=None,
|
372
|
+
usage_threshold_days=7
|
373
|
+
)
|
374
|
+
return {"scenario": "nat-gateway", "status": "completed", "profile": profile_param}
|
375
|
+
|
376
|
+
def execute_ebs_scenario():
|
377
|
+
# Create a simplified EBS scenario execution
|
378
|
+
print_info("EBS optimization scenario analysis")
|
379
|
+
# Use enterprise profile resolution: User > Environment > Default
|
380
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
381
|
+
return {"scenario": "ebs", "status": "completed", "profile": profile_param}
|
382
|
+
|
383
|
+
def execute_vpc_cleanup_scenario():
|
384
|
+
# Create a simplified VPC cleanup scenario execution
|
385
|
+
print_info("VPC cleanup scenario analysis")
|
386
|
+
# Use enterprise profile resolution: User > Environment > Default
|
387
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
388
|
+
return {"scenario": "vpc-cleanup", "status": "completed", "profile": profile_param}
|
389
|
+
|
390
|
+
def execute_elastic_ip_scenario():
|
391
|
+
# Create a simplified elastic IP scenario execution
|
392
|
+
print_info("Elastic IP optimization scenario analysis")
|
393
|
+
# Use enterprise profile resolution: User > Environment > Default
|
394
|
+
profile_param = get_profile_for_operation("billing", args.profiles[0] if args.profiles else None)
|
395
|
+
return {"scenario": "elastic-ip", "status": "completed", "profile": profile_param}
|
396
|
+
|
397
|
+
# Map scenarios to execution functions
|
398
|
+
scenario_map = {
|
399
|
+
'workspaces': execute_workspaces_scenario,
|
400
|
+
'rds-snapshots': execute_snapshots_scenario,
|
401
|
+
'backup-investigation': execute_commvault_scenario,
|
402
|
+
'nat-gateway': execute_nat_gateway_scenario,
|
403
|
+
'ebs-optimization': execute_ebs_scenario,
|
404
|
+
'vpc-cleanup': execute_vpc_cleanup_scenario,
|
405
|
+
'elastic-ip': execute_elastic_ip_scenario,
|
406
|
+
}
|
407
|
+
|
408
|
+
if args.scenario not in scenario_map:
|
409
|
+
print_error(f"Unknown scenario: '{args.scenario}'")
|
410
|
+
print_info("Available scenarios: " + ", ".join(scenario_map.keys()))
|
411
|
+
return 1
|
412
|
+
|
413
|
+
# Execute scenario
|
414
|
+
scenario_func = scenario_map[args.scenario]
|
415
|
+
result = scenario_func()
|
416
|
+
|
417
|
+
print_success(f"✅ Scenario '{args.scenario}' completed successfully")
|
418
|
+
|
419
|
+
# Export results if requested
|
420
|
+
if args.report_type and result:
|
421
|
+
from runbooks.finops.helpers import export_scenario_results
|
422
|
+
export_scenario_results(result, args.scenario, args.report_type, args.dir)
|
423
|
+
|
424
|
+
return 0
|
425
|
+
|
426
|
+
|
370
427
|
# Handle PDCA mode
|
371
428
|
if args.pdca or args.pdca_continuous:
|
372
|
-
|
373
|
-
|
374
|
-
|
429
|
+
try:
|
430
|
+
import asyncio
|
431
|
+
from runbooks.finops.pdca_engine import AutonomousPDCAEngine, PDCAThresholds
|
432
|
+
|
433
|
+
console.print("[bold bright_cyan]🤖 Launching Autonomous PDCA Engine...[/]")
|
434
|
+
|
435
|
+
# Configure PDCA thresholds
|
436
|
+
thresholds = PDCAThresholds(
|
437
|
+
max_risk_score=25,
|
438
|
+
max_cost_increase=10.0,
|
439
|
+
max_untagged_resources=50,
|
440
|
+
max_unused_eips=5,
|
441
|
+
max_budget_overruns=1,
|
442
|
+
)
|
375
443
|
|
376
|
-
|
444
|
+
# Initialize PDCA engine
|
445
|
+
artifacts_dir = args.dir or "artifacts"
|
377
446
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
max_cost_increase=10.0,
|
382
|
-
max_untagged_resources=50,
|
383
|
-
max_unused_eips=5,
|
384
|
-
max_budget_overruns=1,
|
385
|
-
)
|
447
|
+
# Ensure artifacts directory exists
|
448
|
+
import os
|
449
|
+
os.makedirs(artifacts_dir, exist_ok=True)
|
386
450
|
|
387
|
-
|
388
|
-
|
389
|
-
|
451
|
+
engine = AutonomousPDCAEngine(thresholds=thresholds, artifacts_dir=artifacts_dir)
|
452
|
+
except ImportError as e:
|
453
|
+
console.print(f"[red]❌ PDCA Engine not available: {e}[/]")
|
454
|
+
console.print("[yellow]💡 PDCA functionality requires additional setup[/]")
|
455
|
+
return 1
|
390
456
|
|
391
457
|
try:
|
392
458
|
# Determine execution mode
|
@@ -100,7 +100,7 @@ class AWSCostOptimizer:
|
|
100
100
|
Returns:
|
101
101
|
Tuple (success, list_of_idle_instances)
|
102
102
|
"""
|
103
|
-
print_header("Cost Optimizer - Idle Instance Detection", "
|
103
|
+
print_header("Cost Optimizer - Idle Instance Detection", "latest version")
|
104
104
|
|
105
105
|
result = []
|
106
106
|
regions_to_check = [region] if region else self._get_all_regions()
|
@@ -409,7 +409,7 @@ class AWSCostOptimizer:
|
|
409
409
|
Returns:
|
410
410
|
Tuple (success, list_of_low_usage_volumes)
|
411
411
|
"""
|
412
|
-
print_header("Cost Optimizer - Low Usage EBS Volume Detection", "
|
412
|
+
print_header("Cost Optimizer - Low Usage EBS Volume Detection", "latest version")
|
413
413
|
|
414
414
|
result = []
|
415
415
|
regions_to_check = [region] if region else self._get_all_regions()
|
@@ -739,7 +739,7 @@ class AWSCostOptimizer:
|
|
739
739
|
Returns:
|
740
740
|
Tuple (success, list_of_unused_nat_gateways)
|
741
741
|
"""
|
742
|
-
print_header("Cost Optimizer - Unused NAT Gateway Detection", "
|
742
|
+
print_header("Cost Optimizer - Unused NAT Gateway Detection", "latest version")
|
743
743
|
|
744
744
|
result = []
|
745
745
|
regions_to_check = [region] if region else self._get_all_regions()
|
@@ -1206,7 +1206,7 @@ def comprehensive_cost_optimization(
|
|
1206
1206
|
- AWS_Delete_EBS_Volumes_With_Low_Usage.ipynb
|
1207
1207
|
"""
|
1208
1208
|
|
1209
|
-
print_header("Comprehensive AWS Cost Optimization", "
|
1209
|
+
print_header("Comprehensive AWS Cost Optimization", "latest version")
|
1210
1210
|
|
1211
1211
|
total_monthly_savings = 0.0
|
1212
1212
|
total_annual_savings = 0.0
|
@@ -283,7 +283,7 @@ class DashboardRouter:
|
|
283
283
|
int: Exit code (0 for success, 1 for failure)
|
284
284
|
"""
|
285
285
|
try:
|
286
|
-
print_header("FinOps Dashboard Router", "
|
286
|
+
print_header("FinOps Dashboard Router", "latest version")
|
287
287
|
|
288
288
|
# Detect use-case and route appropriately
|
289
289
|
use_case, routing_config = self.detect_use_case(args)
|
@@ -551,7 +551,7 @@ class DashboardRouter:
|
|
551
551
|
- Smooth progress tracking (no 0%→100% jumps)
|
552
552
|
"""
|
553
553
|
try:
|
554
|
-
print_header("Service-Per-Row Dashboard", "
|
554
|
+
print_header("Service-Per-Row Dashboard", "latest version")
|
555
555
|
print_info("🎯 Focus: TOP 10 Services with optimization insights")
|
556
556
|
|
557
557
|
# Get profile for analysis
|
@@ -16,7 +16,7 @@ Business Focus: CFO/Financial stakeholder optimization with quantified ROI analy
|
|
16
16
|
and enterprise-grade safety controls for multi-account EBS portfolio management.
|
17
17
|
|
18
18
|
Author: Enterprise Agile Team (6-Agent Coordination)
|
19
|
-
Version:
|
19
|
+
Version: latest version - Cost Optimization Portfolio
|
20
20
|
"""
|
21
21
|
|
22
22
|
import os
|
@@ -154,7 +154,7 @@ class EBSCostOptimizer:
|
|
154
154
|
Strategic Focus: Complete EBS portfolio analysis with quantified business impact
|
155
155
|
for enterprise financial decision making.
|
156
156
|
"""
|
157
|
-
print_header("EBS Volume Cost Optimization Engine", "Comprehensive Analysis
|
157
|
+
print_header("EBS Volume Cost Optimization Engine", "Comprehensive Analysis latest version")
|
158
158
|
|
159
159
|
regions = regions or ["us-east-1", "us-west-2", "eu-west-1"]
|
160
160
|
|
@@ -254,7 +254,7 @@ class EBSCostOptimizer:
|
|
254
254
|
Business Focus: 20% cost reduction with enhanced performance for GP2 volumes
|
255
255
|
Enterprise Value: $1.5M-$9.3M savings potential across large environments
|
256
256
|
"""
|
257
|
-
print_header("GP2 to GP3 Conversion Analysis", "Cost Optimization Engine
|
257
|
+
print_header("GP2 to GP3 Conversion Analysis", "Cost Optimization Engine latest version")
|
258
258
|
|
259
259
|
regions = regions or ["us-east-1", "us-west-2"]
|
260
260
|
|
@@ -329,7 +329,7 @@ EBS GP2 to GP3 Conversion Analysis Summary:
|
|
329
329
|
Business Focus: Eliminate ongoing costs for unused storage resources
|
330
330
|
Safety Focus: Comprehensive safety checks before cleanup recommendations
|
331
331
|
"""
|
332
|
-
print_header("Unattached EBS Volume Cleanup Analysis", "Resource Cleanup
|
332
|
+
print_header("Unattached EBS Volume Cleanup Analysis", "Resource Cleanup latest version")
|
333
333
|
|
334
334
|
regions = regions or ["us-east-1", "us-west-2"]
|
335
335
|
|
runbooks/finops/ebs_optimizer.py
CHANGED
@@ -513,8 +513,25 @@ class EBSOptimizer:
|
|
513
513
|
metrics = usage_metrics.get(volume.volume_id)
|
514
514
|
instance_state = getattr(volume, 'instance_state', None)
|
515
515
|
|
516
|
-
# Calculate current monthly cost
|
517
|
-
|
516
|
+
# Calculate current monthly cost using dynamic pricing (enterprise compliance)
|
517
|
+
volume_pricing = self.ebs_pricing.get(volume.volume_type)
|
518
|
+
if volume_pricing is None:
|
519
|
+
# Dynamic fallback for unknown volume types - no hardcoded values
|
520
|
+
try:
|
521
|
+
from ..common.aws_pricing import get_aws_pricing_engine
|
522
|
+
pricing_engine = get_aws_pricing_engine(profile=self.profile_name, enable_fallback=True)
|
523
|
+
volume_pricing_result = pricing_engine.get_ebs_pricing(volume.volume_type, "us-east-1")
|
524
|
+
volume_pricing = volume_pricing_result.monthly_cost_per_gb
|
525
|
+
print_info(f"Dynamic pricing resolved for {volume.volume_type}: ${volume_pricing:.4f}/GB/month")
|
526
|
+
except Exception as e:
|
527
|
+
print_error(f"ENTERPRISE COMPLIANCE VIOLATION: Cannot determine pricing for {volume.volume_type}: {e}")
|
528
|
+
print_warning("Universal compatibility requires dynamic pricing - hardcoded values not permitted")
|
529
|
+
raise RuntimeError(
|
530
|
+
f"Universal compatibility mode requires dynamic AWS pricing for volume type '{volume.volume_type}'. "
|
531
|
+
f"Please ensure your AWS profile has pricing:GetProducts permissions."
|
532
|
+
)
|
533
|
+
|
534
|
+
monthly_cost = volume.size * volume_pricing
|
518
535
|
annual_cost = monthly_cost * 12
|
519
536
|
|
520
537
|
# Initialize optimization analysis
|