runbooks 1.0.3__py3-none-any.whl → 1.1.0__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 +10 -5
- runbooks/__init__.py.backup +134 -0
- runbooks/__init___optimized.py +110 -0
- runbooks/cloudops/base.py +56 -3
- runbooks/cloudops/cost_optimizer.py +496 -42
- runbooks/common/aws_pricing.py +236 -80
- runbooks/common/business_logic.py +485 -0
- runbooks/common/cli_decorators.py +219 -0
- runbooks/common/error_handling.py +424 -0
- runbooks/common/lazy_loader.py +186 -0
- runbooks/common/module_cli_base.py +378 -0
- runbooks/common/performance_monitoring.py +512 -0
- runbooks/common/profile_utils.py +133 -6
- runbooks/enterprise/logging.py +30 -2
- runbooks/enterprise/validation.py +177 -0
- runbooks/finops/README.md +311 -236
- runbooks/finops/aws_client.py +1 -1
- runbooks/finops/business_case_config.py +723 -19
- runbooks/finops/cli.py +136 -0
- runbooks/finops/commvault_ec2_analysis.py +25 -9
- runbooks/finops/config.py +272 -0
- runbooks/finops/dashboard_runner.py +136 -23
- runbooks/finops/ebs_cost_optimizer.py +39 -40
- runbooks/finops/enhanced_trend_visualization.py +7 -2
- runbooks/finops/enterprise_wrappers.py +45 -18
- runbooks/finops/finops_dashboard.py +50 -25
- runbooks/finops/finops_scenarios.py +22 -7
- runbooks/finops/helpers.py +115 -2
- runbooks/finops/multi_dashboard.py +7 -5
- runbooks/finops/optimizer.py +97 -6
- runbooks/finops/scenario_cli_integration.py +247 -0
- runbooks/finops/scenarios.py +12 -1
- runbooks/finops/unlimited_scenarios.py +393 -0
- runbooks/finops/validation_framework.py +19 -7
- runbooks/finops/workspaces_analyzer.py +1 -5
- runbooks/inventory/mcp_inventory_validator.py +2 -1
- runbooks/main.py +132 -94
- runbooks/main_final.py +358 -0
- runbooks/main_minimal.py +84 -0
- runbooks/main_optimized.py +493 -0
- runbooks/main_ultra_minimal.py +47 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/METADATA +1 -1
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/RECORD +47 -31
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/WHEEL +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/entry_points.txt +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/top_level.txt +0 -0
runbooks/main.py
CHANGED
@@ -104,7 +104,18 @@ from runbooks.common.rich_utils import console, create_table, print_banner, prin
|
|
104
104
|
from runbooks.config import load_config, save_config
|
105
105
|
from runbooks.inventory.core.collector import InventoryCollector
|
106
106
|
from runbooks.utils import setup_logging, setup_enhanced_logging
|
107
|
-
|
107
|
+
# PERFORMANCE FIX: Lazy load business case config to avoid MCP initialization
|
108
|
+
# from runbooks.finops.business_case_config import get_business_case_config, format_business_achievement
|
109
|
+
|
110
|
+
def lazy_get_business_case_config():
|
111
|
+
"""Lazy load business case config only when needed."""
|
112
|
+
from runbooks.finops.business_case_config import get_business_case_config
|
113
|
+
return get_business_case_config
|
114
|
+
|
115
|
+
def lazy_format_business_achievement():
|
116
|
+
"""Lazy load business achievement formatter only when needed."""
|
117
|
+
from runbooks.finops.business_case_config import format_business_achievement
|
118
|
+
return format_business_achievement
|
108
119
|
|
109
120
|
console = Console()
|
110
121
|
|
@@ -6093,7 +6104,7 @@ def comprehensive_analysis(profile, region, dry_run, all_scenarios, output_dir):
|
|
6093
6104
|
console.print(f"\n[blue]📊 Scenario 3: Commvault EC2 Investigation (FinOps-25)[/blue]")
|
6094
6105
|
ctx.invoke(commvault_ec2,
|
6095
6106
|
profile=profile, region=region, dry_run=dry_run,
|
6096
|
-
account=
|
6107
|
+
account=get_account_id_for_context(profile), investigate_utilization=True,
|
6097
6108
|
output_file=f"{output_dir}/commvault_ec2_analysis.csv")
|
6098
6109
|
|
6099
6110
|
# Summary report
|
@@ -6110,7 +6121,7 @@ def comprehensive_analysis(profile, region, dry_run, all_scenarios, output_dir):
|
|
6110
6121
|
)
|
6111
6122
|
|
6112
6123
|
# Use dynamic configuration for summary table
|
6113
|
-
config =
|
6124
|
+
config = lazy_get_business_case_config()()
|
6114
6125
|
workspaces_scenario = config.get_scenario('workspaces')
|
6115
6126
|
rds_scenario = config.get_scenario('rds-snapshots')
|
6116
6127
|
backup_scenario = config.get_scenario('backup-investigation')
|
@@ -6198,43 +6209,22 @@ def _parse_profiles_parameter(profiles_tuple):
|
|
6198
6209
|
@click.option(
|
6199
6210
|
"--export-markdown", "--markdown", is_flag=True, help="Generate Rich-styled markdown export with 10-column format"
|
6200
6211
|
)
|
6201
|
-
@click.option(
|
6202
|
-
"--profile-display-length",
|
6203
|
-
type=int,
|
6204
|
-
help="Maximum characters for profile name display (optional, no truncation if not specified)",
|
6205
|
-
)
|
6206
|
-
@click.option(
|
6207
|
-
"--service-name-length",
|
6208
|
-
type=int,
|
6209
|
-
help="Maximum characters for service name display (optional, no truncation if not specified)",
|
6210
|
-
)
|
6211
|
-
@click.option(
|
6212
|
-
"--max-services-text",
|
6213
|
-
type=int,
|
6214
|
-
help="Maximum number of services in text summaries (optional, no limit if not specified)",
|
6215
|
-
)
|
6216
|
-
@click.option(
|
6217
|
-
"--high-cost-threshold", type=float, default=5000, help="High cost threshold for highlighting (default: 5000)"
|
6218
|
-
)
|
6219
|
-
@click.option(
|
6220
|
-
"--medium-cost-threshold", type=float, default=1000, help="Medium cost threshold for highlighting (default: 1000)"
|
6221
|
-
)
|
6222
6212
|
@click.option(
|
6223
6213
|
"--validate", is_flag=True, help="Enable MCP cross-validation with real-time AWS API comparison for enterprise accuracy verification"
|
6224
6214
|
)
|
6225
6215
|
@click.option(
|
6226
|
-
"--
|
6216
|
+
"--unblended", is_flag=True, help="AWS Cost Explorer UnblendedCost analysis for technical teams (DevOps/SRE focus)"
|
6227
6217
|
)
|
6228
6218
|
@click.option(
|
6229
|
-
"--
|
6219
|
+
"--amortized", is_flag=True, help="AWS Cost Explorer AmortizedCost analysis for financial teams (Finance/Executive focus)"
|
6230
6220
|
)
|
6231
6221
|
@click.option(
|
6232
|
-
"--dual-metrics", is_flag=True, default=True, help="Show both
|
6222
|
+
"--dual-metrics", is_flag=True, default=True, help="Show both UnblendedCost and AmortizedCost metrics (comprehensive analysis, default)"
|
6233
6223
|
)
|
6234
6224
|
@click.option(
|
6235
|
-
"--scenario",
|
6236
|
-
type=
|
6237
|
-
help="Business scenario
|
6225
|
+
"--scenario",
|
6226
|
+
type=str,
|
6227
|
+
help="Business scenario: workspaces, snapshots, commvault, nat-gateway, elastic-ip, ebs, vpc-cleanup"
|
6238
6228
|
)
|
6239
6229
|
@click.pass_context
|
6240
6230
|
def finops(
|
@@ -6257,41 +6247,41 @@ def finops(
|
|
6257
6247
|
json,
|
6258
6248
|
pdf,
|
6259
6249
|
export_markdown,
|
6260
|
-
profile_display_length,
|
6261
|
-
service_name_length,
|
6262
|
-
max_services_text,
|
6263
|
-
high_cost_threshold,
|
6264
|
-
medium_cost_threshold,
|
6265
6250
|
validate,
|
6266
|
-
|
6267
|
-
|
6251
|
+
unblended,
|
6252
|
+
amortized,
|
6268
6253
|
dual_metrics,
|
6269
6254
|
scenario,
|
6270
6255
|
):
|
6271
6256
|
"""
|
6272
|
-
AWS FinOps - Cost and usage analytics
|
6273
|
-
|
6274
|
-
|
6275
|
-
|
6276
|
-
|
6277
|
-
BUSINESS SCENARIOS
|
6278
|
-
runbooks finops --scenario workspaces # WorkSpaces
|
6279
|
-
runbooks finops --scenario snapshots # RDS
|
6280
|
-
runbooks finops --scenario commvault # Backup
|
6281
|
-
runbooks finops --scenario nat-gateway #
|
6282
|
-
runbooks finops --scenario elastic-ip # IP
|
6283
|
-
runbooks finops --scenario ebs #
|
6284
|
-
runbooks finops --scenario vpc-cleanup #
|
6285
|
-
|
6286
|
-
|
6287
|
-
|
6288
|
-
|
6289
|
-
runbooks finops --
|
6290
|
-
runbooks finops --
|
6291
|
-
|
6292
|
-
|
6293
|
-
runbooks finops --
|
6294
|
-
runbooks finops --
|
6257
|
+
AWS FinOps - Cost and usage analytics.
|
6258
|
+
|
6259
|
+
📊 DEFAULT DASHBOARD:
|
6260
|
+
runbooks finops --profile BILLING_PROFILE
|
6261
|
+
|
6262
|
+
🎯 BUSINESS SCENARIOS:
|
6263
|
+
runbooks finops --scenario workspaces --profile PROFILE # WorkSpaces optimization
|
6264
|
+
runbooks finops --scenario snapshots --profile PROFILE # RDS snapshots cleanup
|
6265
|
+
runbooks finops --scenario commvault --profile PROFILE # Backup analysis
|
6266
|
+
runbooks finops --scenario nat-gateway --profile PROFILE # NAT Gateway optimization
|
6267
|
+
runbooks finops --scenario elastic-ip --profile PROFILE # Elastic IP management
|
6268
|
+
runbooks finops --scenario ebs --profile PROFILE # EBS optimization
|
6269
|
+
runbooks finops --scenario vpc-cleanup --profile PROFILE # VPC cleanup
|
6270
|
+
|
6271
|
+
📊 ANALYTICS MODES:
|
6272
|
+
runbooks finops --audit --profile PROFILE # Cost anomaly analysis
|
6273
|
+
runbooks finops --trend --profile PROFILE # 6-month trend analysis
|
6274
|
+
runbooks finops --unblended --profile PROFILE # Technical cost view (DevOps/SRE)
|
6275
|
+
runbooks finops --amortized --profile PROFILE # Financial cost view (Finance)
|
6276
|
+
|
6277
|
+
📄 EXPORTS:
|
6278
|
+
runbooks finops --csv --json --pdf --profile PROFILE # Multiple formats
|
6279
|
+
runbooks finops --report-name monthly --pdf --profile PROFILE
|
6280
|
+
|
6281
|
+
🌍 MULTIPLE PROFILES/REGIONS:
|
6282
|
+
runbooks finops --profiles PROF1 PROF2 --regions us-east-1 eu-west-1
|
6283
|
+
|
6284
|
+
⚠️ STATUS: Some business scenarios may require additional CloudOps dependencies.
|
6295
6285
|
"""
|
6296
6286
|
|
6297
6287
|
# Handle group behavior: if no subcommand invoked, execute main functionality
|
@@ -6302,14 +6292,54 @@ def finops(
|
|
6302
6292
|
# Subcommand will handle execution
|
6303
6293
|
return
|
6304
6294
|
|
6295
|
+
# Removed broken --help-scenarios logic - use main --help instead
|
6296
|
+
|
6305
6297
|
# Business Scenario Dispatch Logic (Strategic Objective #1: Unified CLI)
|
6306
6298
|
if scenario:
|
6307
|
-
from runbooks.common.rich_utils import console, print_header, print_success, print_info
|
6299
|
+
from runbooks.common.rich_utils import console, print_header, print_success, print_info, print_error
|
6308
6300
|
|
6301
|
+
# PHASE 2 PRIORITY 1: Unlimited Scenario Expansion Framework
|
6302
|
+
# Dynamic scenario validation (replaces hardcoded choice list)
|
6303
|
+
from runbooks.finops.unlimited_scenarios import get_dynamic_scenario_choices
|
6304
|
+
valid_scenarios = get_dynamic_scenario_choices()
|
6305
|
+
|
6306
|
+
if scenario not in valid_scenarios:
|
6307
|
+
print_error(f"Unknown scenario: '{scenario}'")
|
6308
|
+
print_info("Available scenarios:")
|
6309
|
+
for valid_scenario in valid_scenarios:
|
6310
|
+
config = lazy_get_business_case_config()()
|
6311
|
+
scenario_obj = config.get_scenario(valid_scenario)
|
6312
|
+
if scenario_obj:
|
6313
|
+
print_info(f" {valid_scenario} - {scenario_obj.display_name} ({scenario_obj.savings_range_display})")
|
6314
|
+
else:
|
6315
|
+
print_info(f" {valid_scenario}")
|
6316
|
+
print_info("\nUse 'runbooks finops --help-scenarios' for comprehensive scenario information")
|
6317
|
+
return
|
6318
|
+
|
6309
6319
|
# Unified scenario dispatcher with enterprise Rich CLI formatting
|
6310
6320
|
print_header("FinOps Business Scenarios", "Manager Priority Cost Optimization")
|
6311
|
-
|
6312
|
-
|
6321
|
+
print_success(f"✅ Scenario validated: {scenario.upper()}")
|
6322
|
+
|
6323
|
+
# Display unlimited expansion capability info
|
6324
|
+
from runbooks.finops.unlimited_scenarios import discover_scenarios_summary
|
6325
|
+
summary = discover_scenarios_summary()
|
6326
|
+
if summary["scenario_discovery"]["environment_discovered"] > 0:
|
6327
|
+
print_info(f"🚀 Unlimited expansion: {summary['scenario_discovery']['environment_discovered']} environment-discovered scenarios active")
|
6328
|
+
|
6329
|
+
# Validate and suggest optimal parameters for scenario
|
6330
|
+
from runbooks.finops.scenario_cli_integration import validate_and_suggest_parameters
|
6331
|
+
cli_params = {
|
6332
|
+
'time_range': time_range,
|
6333
|
+
'unblended': unblended,
|
6334
|
+
'amortized': amortized,
|
6335
|
+
'dual_metrics': dual_metrics,
|
6336
|
+
'pdf': pdf,
|
6337
|
+
'csv': csv,
|
6338
|
+
'json': json,
|
6339
|
+
'export_markdown': export_markdown
|
6340
|
+
}
|
6341
|
+
validate_and_suggest_parameters(scenario, cli_params)
|
6342
|
+
|
6313
6343
|
try:
|
6314
6344
|
# Import CloudOps cost optimizer for enhanced JIRA scenario integration
|
6315
6345
|
from runbooks.cloudops.cost_optimizer import CostOptimizer
|
@@ -6327,7 +6357,7 @@ def finops(
|
|
6327
6357
|
)
|
6328
6358
|
|
6329
6359
|
if scenario.lower() == "workspaces":
|
6330
|
-
config =
|
6360
|
+
config = lazy_get_business_case_config()()
|
6331
6361
|
workspaces_scenario = config.get_scenario('workspaces')
|
6332
6362
|
scenario_info = f"{workspaces_scenario.display_name} ({workspaces_scenario.savings_range_display})" if workspaces_scenario else "WorkSpaces Resource Optimization"
|
6333
6363
|
print_info(f"{scenario_info}")
|
@@ -6352,7 +6382,7 @@ def finops(
|
|
6352
6382
|
}
|
6353
6383
|
|
6354
6384
|
elif scenario.lower() == "snapshots":
|
6355
|
-
config =
|
6385
|
+
config = lazy_get_business_case_config()()
|
6356
6386
|
rds_scenario = config.get_scenario('rds-snapshots')
|
6357
6387
|
scenario_info = f"{rds_scenario.display_name} ({rds_scenario.savings_range_display})" if rds_scenario else "RDS Storage Optimization"
|
6358
6388
|
print_info(f"{scenario_info}")
|
@@ -6377,15 +6407,17 @@ def finops(
|
|
6377
6407
|
}
|
6378
6408
|
|
6379
6409
|
elif scenario.lower() == "commvault":
|
6380
|
-
config =
|
6410
|
+
config = lazy_get_business_case_config()()
|
6381
6411
|
backup_scenario = config.get_scenario('backup-investigation')
|
6382
6412
|
scenario_info = f"{backup_scenario.display_name}" if backup_scenario else "Backup Infrastructure Analysis"
|
6383
6413
|
print_info(f"{scenario_info} (Real AWS integration)")
|
6384
6414
|
print_info("🚀 Enhanced with CloudOps enterprise integration")
|
6385
6415
|
|
6386
6416
|
# Use CloudOps cost optimizer for enterprise-grade investigation
|
6417
|
+
# Dynamically resolve account ID from current AWS profile context
|
6418
|
+
current_account_id = get_account_id_for_context(profile if profile != "default" else "default")
|
6387
6419
|
commvault_result = asyncio.run(cost_optimizer.investigate_commvault_ec2(
|
6388
|
-
account_id=
|
6420
|
+
account_id=current_account_id, # Dynamic account resolution
|
6389
6421
|
dry_run=True # Always dry-run for investigations
|
6390
6422
|
))
|
6391
6423
|
|
@@ -6403,7 +6435,7 @@ def finops(
|
|
6403
6435
|
}
|
6404
6436
|
|
6405
6437
|
elif scenario.lower() == "nat-gateway":
|
6406
|
-
config =
|
6438
|
+
config = lazy_get_business_case_config()()
|
6407
6439
|
nat_scenario = config.get_scenario('nat-gateway')
|
6408
6440
|
scenario_info = f"{nat_scenario.display_name} ({nat_scenario.savings_range_display})" if nat_scenario else "Network Gateway Optimization"
|
6409
6441
|
print_info(f"{scenario_info}")
|
@@ -6441,7 +6473,7 @@ def finops(
|
|
6441
6473
|
}
|
6442
6474
|
|
6443
6475
|
elif scenario.lower() == "elastic-ip":
|
6444
|
-
config =
|
6476
|
+
config = lazy_get_business_case_config()()
|
6445
6477
|
eip_scenario = config.get_scenario('elastic-ip')
|
6446
6478
|
scenario_info = f"{eip_scenario.display_name} ({eip_scenario.savings_range_display})" if eip_scenario else "IP Address Resource Management"
|
6447
6479
|
print_info(f"{scenario_info}")
|
@@ -6481,7 +6513,7 @@ def finops(
|
|
6481
6513
|
}
|
6482
6514
|
|
6483
6515
|
elif scenario.lower() == "ebs":
|
6484
|
-
config =
|
6516
|
+
config = lazy_get_business_case_config()()
|
6485
6517
|
ebs_scenario = config.get_scenario('ebs-optimization')
|
6486
6518
|
scenario_info = f"{ebs_scenario.display_name}" if ebs_scenario else "Storage Volume Optimization (15-20% cost reduction potential)"
|
6487
6519
|
print_info(f"{scenario_info}")
|
@@ -6529,7 +6561,7 @@ def finops(
|
|
6529
6561
|
}
|
6530
6562
|
|
6531
6563
|
elif scenario.lower() == "vpc-cleanup":
|
6532
|
-
config =
|
6564
|
+
config = lazy_get_business_case_config()()
|
6533
6565
|
vpc_scenario = config.get_scenario('vpc-cleanup')
|
6534
6566
|
scenario_info = f"{vpc_scenario.display_name} ({vpc_scenario.savings_range_display})" if vpc_scenario else "Network Infrastructure Cleanup"
|
6535
6567
|
print_info(f"{scenario_info}")
|
@@ -6671,16 +6703,19 @@ def finops(
|
|
6671
6703
|
report_name = f"finops_multi_format_export"
|
6672
6704
|
click.echo(click.style(f"📝 Auto-generated report name: {report_name}", fg="blue"))
|
6673
6705
|
|
6674
|
-
# Dual-Metric Configuration Logic (Enterprise
|
6706
|
+
# AWS Terminology Alignment: Dual-Metric Configuration Logic (Enhanced Enterprise Implementation)
|
6675
6707
|
metric_config = "dual" # Default comprehensive analysis
|
6676
|
-
|
6708
|
+
|
6709
|
+
|
6710
|
+
# AWS native parameter processing
|
6711
|
+
if unblended:
|
6677
6712
|
metric_config = "technical"
|
6678
|
-
click.echo(click.style("🔧
|
6679
|
-
elif
|
6680
|
-
metric_config = "financial"
|
6681
|
-
click.echo(click.style("📊
|
6713
|
+
click.echo(click.style("🔧 AWS UnblendedCost Analysis: Technical cost view for DevOps/SRE teams", fg="bright_blue", bold=True))
|
6714
|
+
elif amortized:
|
6715
|
+
metric_config = "financial"
|
6716
|
+
click.echo(click.style("📊 AWS AmortizedCost Analysis: Financial reporting view for Finance/Executive teams", fg="bright_green", bold=True))
|
6682
6717
|
else:
|
6683
|
-
click.echo(click.style("💰 Dual-Metrics: Both
|
6718
|
+
click.echo(click.style("💰 Dual-Metrics: Both AWS UnblendedCost and AmortizedCost analysis (comprehensive, default)", fg="bright_cyan", bold=True))
|
6684
6719
|
|
6685
6720
|
# Report name logic (separate from metric config)
|
6686
6721
|
if report_types and not report_name:
|
@@ -6746,17 +6781,12 @@ def finops(
|
|
6746
6781
|
audit=audit,
|
6747
6782
|
export_markdown=export_markdown, # Add export_markdown parameter
|
6748
6783
|
config_file=None, # Not exposed in Click interface yet
|
6749
|
-
# Display configuration parameters
|
6750
|
-
profile_display_length=profile_display_length,
|
6751
|
-
service_name_length=service_name_length,
|
6752
|
-
max_services_text=max_services_text,
|
6753
|
-
high_cost_threshold=high_cost_threshold,
|
6754
|
-
medium_cost_threshold=medium_cost_threshold,
|
6784
|
+
# Display configuration parameters now managed via API-only config
|
6755
6785
|
validate=validate,
|
6756
|
-
# Dual-Metric Configuration (Enterprise Enhancement)
|
6786
|
+
# AWS Terminology Alignment: Dual-Metric Configuration (Enterprise Enhancement)
|
6757
6787
|
metric_config=metric_config,
|
6758
|
-
|
6759
|
-
|
6788
|
+
unblended=unblended,
|
6789
|
+
amortized=amortized,
|
6760
6790
|
dual_metrics=dual_metrics,
|
6761
6791
|
)
|
6762
6792
|
# Route to appropriate dashboard implementation
|
@@ -6777,8 +6807,11 @@ def finops(
|
|
6777
6807
|
@click.option("--output", type=click.Choice(["json", "csv", "pdf", "html"]), help="Output format")
|
6778
6808
|
def dashboard(profile, region, dry_run, output):
|
6779
6809
|
"""
|
6780
|
-
FinOps cost analytics dashboard.
|
6781
|
-
|
6810
|
+
FinOps cost analytics dashboard (same as 'runbooks finops' default).
|
6811
|
+
|
6812
|
+
📊 This command provides identical functionality to running 'runbooks finops' without parameters.
|
6813
|
+
Both commands launch the interactive cost dashboard with business scenario overview.
|
6814
|
+
|
6782
6815
|
Interactive cost analysis with Rich CLI formatting and enterprise-grade reporting.
|
6783
6816
|
"""
|
6784
6817
|
from runbooks.common.rich_utils import console, print_header
|
@@ -6885,21 +6918,26 @@ def finops_23_rds_snapshots(profile, output_file):
|
|
6885
6918
|
|
6886
6919
|
@main.command("finops-25")
|
6887
6920
|
@click.option('--profile', help='AWS profile name')
|
6888
|
-
@click.option('--account-id',
|
6921
|
+
@click.option('--account-id', help='Account ID for analysis (uses current AWS account if not specified)')
|
6889
6922
|
@click.option('--output-file', help='Save results to file')
|
6890
6923
|
def finops_25_commvault(profile, account_id, output_file):
|
6891
6924
|
"""FinOps-25: Commvault EC2 investigation framework (Real AWS integration).
|
6892
|
-
|
6925
|
+
|
6893
6926
|
UNIFIED CLI: Use 'runbooks finops --scenario commvault' for new unified interface.
|
6894
6927
|
"""
|
6895
6928
|
from runbooks.common.rich_utils import console, print_warning, print_info
|
6896
|
-
|
6929
|
+
|
6897
6930
|
print_warning("Legacy command detected! Consider using unified interface:")
|
6898
6931
|
print_info("runbooks finops --scenario commvault --profile [PROFILE]")
|
6899
|
-
|
6932
|
+
|
6933
|
+
# Resolve account ID dynamically if not provided
|
6934
|
+
if not account_id:
|
6935
|
+
account_id = get_account_id_for_context(profile or "default")
|
6936
|
+
console.print(f"[dim]Using current AWS account: {account_id}[/dim]")
|
6937
|
+
|
6900
6938
|
try:
|
6901
6939
|
from runbooks.finops.finops_scenarios import investigate_finops_25_commvault
|
6902
|
-
results = investigate_finops_25_commvault(profile)
|
6940
|
+
results = investigate_finops_25_commvault(profile, account_id=account_id)
|
6903
6941
|
|
6904
6942
|
if output_file:
|
6905
6943
|
import json
|