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
@@ -1,7 +1,7 @@
|
|
1
1
|
"""
|
2
2
|
Dynamic Business Case Configuration - Enterprise Template System
|
3
3
|
|
4
|
-
Strategic Achievement: Replace hardcoded
|
4
|
+
Strategic Achievement: Replace hardcoded references with dynamic business case templates
|
5
5
|
- Enterprise naming conventions with configurable business scenarios
|
6
6
|
- Dynamic financial targets and achievement tracking
|
7
7
|
- Reusable template system for unlimited business case scaling
|
@@ -14,12 +14,13 @@ This module provides configurable business case templates following enterprise s
|
|
14
14
|
|
15
15
|
import os
|
16
16
|
from dataclasses import dataclass
|
17
|
-
from typing import Dict, List, Optional, Any, Union, NamedTuple
|
18
17
|
from enum import Enum
|
18
|
+
from typing import Any, Dict, List, NamedTuple, Optional, Union
|
19
19
|
|
20
20
|
|
21
21
|
class BusinessCaseType(Enum):
|
22
22
|
"""Standard business case types for enterprise scenarios."""
|
23
|
+
|
23
24
|
COST_OPTIMIZATION = "cost_optimization"
|
24
25
|
RESOURCE_CLEANUP = "resource_cleanup"
|
25
26
|
COMPLIANCE_FRAMEWORK = "compliance_framework"
|
@@ -30,6 +31,7 @@ class BusinessCaseType(Enum):
|
|
30
31
|
@dataclass
|
31
32
|
class BusinessScenario:
|
32
33
|
"""Dynamic business scenario configuration."""
|
34
|
+
|
33
35
|
scenario_id: str
|
34
36
|
display_name: str
|
35
37
|
business_case_type: BusinessCaseType
|
@@ -40,12 +42,12 @@ class BusinessScenario:
|
|
40
42
|
risk_level: str = "Medium"
|
41
43
|
implementation_status: str = "Analysis"
|
42
44
|
cli_command_suffix: str = ""
|
43
|
-
|
45
|
+
|
44
46
|
@property
|
45
47
|
def scenario_display_id(self) -> str:
|
46
48
|
"""Generate enterprise-friendly scenario display ID."""
|
47
49
|
return f"{self.business_case_type.value.replace('_', '-').title()}-{self.scenario_id}"
|
48
|
-
|
50
|
+
|
49
51
|
@property
|
50
52
|
def savings_range_display(self) -> str:
|
51
53
|
"""Generate savings range display for business presentations."""
|
@@ -62,18 +64,18 @@ class BusinessScenario:
|
|
62
64
|
|
63
65
|
class BusinessCaseConfigManager:
|
64
66
|
"""Enterprise business case configuration manager."""
|
65
|
-
|
67
|
+
|
66
68
|
def __init__(self, config_source: Optional[str] = None):
|
67
69
|
"""
|
68
70
|
Initialize business case configuration manager.
|
69
|
-
|
71
|
+
|
70
72
|
Args:
|
71
73
|
config_source: Optional path to configuration file or environment variable prefix
|
72
74
|
"""
|
73
75
|
self.config_source = config_source or "RUNBOOKS_BUSINESS_CASE"
|
74
76
|
self.scenarios = self._load_default_scenarios()
|
75
77
|
self._load_environment_overrides()
|
76
|
-
|
78
|
+
|
77
79
|
def _load_default_scenarios(self) -> Dict[str, BusinessScenario]:
|
78
80
|
"""Load default enterprise business scenarios."""
|
79
81
|
return {
|
@@ -86,7 +88,7 @@ class BusinessCaseConfigManager:
|
|
86
88
|
business_description="Identify and optimize unused Amazon WorkSpaces for cost efficiency",
|
87
89
|
technical_focus="Zero-usage WorkSpaces detection and cost analysis",
|
88
90
|
risk_level="Low",
|
89
|
-
cli_command_suffix="workspaces"
|
91
|
+
cli_command_suffix="workspaces",
|
90
92
|
),
|
91
93
|
"rds-snapshots": BusinessScenario(
|
92
94
|
scenario_id="rds-snapshots",
|
@@ -97,7 +99,7 @@ class BusinessCaseConfigManager:
|
|
97
99
|
business_description="Optimize manual RDS snapshots to reduce storage costs",
|
98
100
|
technical_focus="Manual RDS snapshot lifecycle management",
|
99
101
|
risk_level="Medium",
|
100
|
-
cli_command_suffix="rds-snapshots"
|
102
|
+
cli_command_suffix="rds-snapshots",
|
101
103
|
),
|
102
104
|
"backup-investigation": BusinessScenario(
|
103
105
|
scenario_id="backup-investigation",
|
@@ -107,7 +109,7 @@ class BusinessCaseConfigManager:
|
|
107
109
|
technical_focus="Backup infrastructure resource utilization analysis",
|
108
110
|
risk_level="Medium",
|
109
111
|
implementation_status="Framework",
|
110
|
-
cli_command_suffix="backup-investigation"
|
112
|
+
cli_command_suffix="backup-investigation",
|
111
113
|
),
|
112
114
|
"nat-gateway": BusinessScenario(
|
113
115
|
scenario_id="nat-gateway",
|
@@ -117,7 +119,7 @@ class BusinessCaseConfigManager:
|
|
117
119
|
target_savings_max=12000,
|
118
120
|
business_description="Optimize NAT Gateway configurations for cost efficiency",
|
119
121
|
technical_focus="NAT Gateway usage analysis and rightsizing",
|
120
|
-
cli_command_suffix="nat-gateway"
|
122
|
+
cli_command_suffix="nat-gateway",
|
121
123
|
),
|
122
124
|
"elastic-ip": BusinessScenario(
|
123
125
|
scenario_id="elastic-ip",
|
@@ -127,7 +129,7 @@ class BusinessCaseConfigManager:
|
|
127
129
|
business_description="Optimize unattached Elastic IP addresses",
|
128
130
|
technical_focus="Elastic IP attachment analysis and cleanup recommendations",
|
129
131
|
risk_level="Low",
|
130
|
-
cli_command_suffix="elastic-ip"
|
132
|
+
cli_command_suffix="elastic-ip",
|
131
133
|
),
|
132
134
|
"ebs-optimization": BusinessScenario(
|
133
135
|
scenario_id="ebs-optimization",
|
@@ -135,7 +137,7 @@ class BusinessCaseConfigManager:
|
|
135
137
|
business_case_type=BusinessCaseType.COST_OPTIMIZATION,
|
136
138
|
business_description="Optimize EBS volume types and utilization for cost efficiency",
|
137
139
|
technical_focus="EBS volume rightsizing and type optimization (15-20% potential)",
|
138
|
-
cli_command_suffix="ebs-optimization"
|
140
|
+
cli_command_suffix="ebs-optimization",
|
139
141
|
),
|
140
142
|
"vpc-cleanup": BusinessScenario(
|
141
143
|
scenario_id="vpc-cleanup",
|
@@ -144,10 +146,10 @@ class BusinessCaseConfigManager:
|
|
144
146
|
target_savings_min=5869,
|
145
147
|
business_description="Clean up unused VPC resources and infrastructure",
|
146
148
|
technical_focus="VPC resource utilization analysis and cleanup recommendations",
|
147
|
-
cli_command_suffix="vpc-cleanup"
|
148
|
-
)
|
149
|
+
cli_command_suffix="vpc-cleanup",
|
150
|
+
),
|
149
151
|
}
|
150
|
-
|
152
|
+
|
151
153
|
def _load_environment_overrides(self) -> None:
|
152
154
|
"""
|
153
155
|
Load configuration overrides and discover new scenarios from environment variables.
|
@@ -206,7 +208,7 @@ class BusinessCaseConfigManager:
|
|
206
208
|
if env_var.startswith(prefix) and "_DISPLAY_NAME" in env_var:
|
207
209
|
# Extract scenario key from pattern: RUNBOOKS_BUSINESS_CASE_[SCENARIO]_DISPLAY_NAME
|
208
210
|
scenario_part = env_var.replace(prefix, "").replace("_DISPLAY_NAME", "")
|
209
|
-
scenario_key = scenario_part.lower().replace(
|
211
|
+
scenario_key = scenario_part.lower().replace("_", "-")
|
210
212
|
discovered_scenarios.add((scenario_key, scenario_part))
|
211
213
|
|
212
214
|
# Create new scenarios for discovered patterns
|
@@ -216,7 +218,9 @@ class BusinessCaseConfigManager:
|
|
216
218
|
if new_scenario:
|
217
219
|
self.scenarios[scenario_key] = new_scenario
|
218
220
|
|
219
|
-
def _create_scenario_from_environment(
|
221
|
+
def _create_scenario_from_environment(
|
222
|
+
self, scenario_key: str, env_scenario_key: str, prefix: str
|
223
|
+
) -> Optional[BusinessScenario]:
|
220
224
|
"""
|
221
225
|
Create a new BusinessScenario from environment variables.
|
222
226
|
|
@@ -266,21 +270,21 @@ class BusinessCaseConfigManager:
|
|
266
270
|
technical_focus=technical_focus,
|
267
271
|
risk_level=risk_level,
|
268
272
|
implementation_status=implementation_status,
|
269
|
-
cli_command_suffix=cli_suffix
|
273
|
+
cli_command_suffix=cli_suffix,
|
270
274
|
)
|
271
|
-
|
275
|
+
|
272
276
|
def get_scenario(self, scenario_key: str) -> Optional[BusinessScenario]:
|
273
277
|
"""Get business scenario by key."""
|
274
278
|
return self.scenarios.get(scenario_key)
|
275
|
-
|
279
|
+
|
276
280
|
def get_all_scenarios(self) -> Dict[str, BusinessScenario]:
|
277
281
|
"""Get all configured business scenarios."""
|
278
282
|
return self.scenarios
|
279
|
-
|
283
|
+
|
280
284
|
def get_scenario_choices(self) -> List[str]:
|
281
285
|
"""Get list of valid scenario keys for CLI choice options."""
|
282
286
|
return list(self.scenarios.keys())
|
283
|
-
|
287
|
+
|
284
288
|
def get_scenario_help_text(self) -> str:
|
285
289
|
"""Generate help text for CLI scenario option."""
|
286
290
|
help_parts = []
|
@@ -288,25 +292,28 @@ class BusinessCaseConfigManager:
|
|
288
292
|
savings_display = scenario.savings_range_display
|
289
293
|
help_parts.append(f"{key} ({scenario.display_name}: {savings_display})")
|
290
294
|
return "Business scenario analysis: " + ", ".join(help_parts)
|
291
|
-
|
292
|
-
def format_scenario_for_display(
|
293
|
-
|
294
|
-
|
295
|
+
|
296
|
+
def format_scenario_for_display(
|
297
|
+
self,
|
298
|
+
scenario_key: str,
|
299
|
+
achieved_savings: Optional[float] = None,
|
300
|
+
achievement_percentage: Optional[float] = None,
|
301
|
+
) -> str:
|
295
302
|
"""Format scenario for display in tables and reports."""
|
296
303
|
scenario = self.get_scenario(scenario_key)
|
297
304
|
if not scenario:
|
298
305
|
return f"Unknown scenario: {scenario_key}"
|
299
|
-
|
306
|
+
|
300
307
|
base_info = f"{scenario.display_name} ({scenario.savings_range_display})"
|
301
|
-
|
308
|
+
|
302
309
|
if achieved_savings:
|
303
310
|
base_info += f" - Achieved: ${achieved_savings:,.0f}"
|
304
|
-
|
311
|
+
|
305
312
|
if achievement_percentage:
|
306
313
|
base_info += f" ({achievement_percentage:.0f}% of target)"
|
307
|
-
|
314
|
+
|
308
315
|
return base_info
|
309
|
-
|
316
|
+
|
310
317
|
def add_dynamic_scenario(self, scenario: BusinessScenario) -> None:
|
311
318
|
"""
|
312
319
|
Add a new business scenario dynamically.
|
@@ -316,7 +323,9 @@ class BusinessCaseConfigManager:
|
|
316
323
|
"""
|
317
324
|
self.scenarios[scenario.scenario_id] = scenario
|
318
325
|
|
319
|
-
def create_scenario_from_template(
|
326
|
+
def create_scenario_from_template(
|
327
|
+
self, scenario_id: str, template_type: str = "aws_resource_optimization"
|
328
|
+
) -> BusinessScenario:
|
320
329
|
"""
|
321
330
|
Create a business scenario from predefined templates.
|
322
331
|
|
@@ -344,7 +353,7 @@ class BusinessCaseConfigManager:
|
|
344
353
|
technical_focus=f"{scenario_id.title().replace('-', ' ')} resource analysis with automated recommendations",
|
345
354
|
risk_level="Medium",
|
346
355
|
implementation_status="Template Ready",
|
347
|
-
cli_command_suffix=scenario_id
|
356
|
+
cli_command_suffix=scenario_id,
|
348
357
|
),
|
349
358
|
"lambda_rightsizing": BusinessScenario(
|
350
359
|
scenario_id=scenario_id,
|
@@ -353,7 +362,7 @@ class BusinessCaseConfigManager:
|
|
353
362
|
business_description="Optimize Lambda function memory allocation and timeout settings",
|
354
363
|
technical_focus="CloudWatch metrics analysis for memory and duration optimization",
|
355
364
|
risk_level="Low",
|
356
|
-
cli_command_suffix=scenario_id
|
365
|
+
cli_command_suffix=scenario_id,
|
357
366
|
),
|
358
367
|
"s3_storage_optimization": BusinessScenario(
|
359
368
|
scenario_id=scenario_id,
|
@@ -362,7 +371,7 @@ class BusinessCaseConfigManager:
|
|
362
371
|
business_description="Optimize S3 storage classes based on access patterns",
|
363
372
|
technical_focus="S3 access pattern analysis with intelligent storage class recommendations",
|
364
373
|
risk_level="Low",
|
365
|
-
cli_command_suffix=scenario_id
|
374
|
+
cli_command_suffix=scenario_id,
|
366
375
|
),
|
367
376
|
"healthcare_compliance": BusinessScenario(
|
368
377
|
scenario_id=scenario_id,
|
@@ -371,7 +380,7 @@ class BusinessCaseConfigManager:
|
|
371
380
|
business_description="HIPAA compliance optimization with cost considerations",
|
372
381
|
technical_focus="Healthcare data security analysis with cost-effective compliance solutions",
|
373
382
|
risk_level="High",
|
374
|
-
cli_command_suffix=scenario_id
|
383
|
+
cli_command_suffix=scenario_id,
|
375
384
|
),
|
376
385
|
"finance_cost_governance": BusinessScenario(
|
377
386
|
scenario_id=scenario_id,
|
@@ -380,7 +389,7 @@ class BusinessCaseConfigManager:
|
|
380
389
|
business_description="Financial industry cost governance and audit readiness",
|
381
390
|
technical_focus="SOX compliance cost optimization with audit trail requirements",
|
382
391
|
risk_level="High",
|
383
|
-
cli_command_suffix=scenario_id
|
392
|
+
cli_command_suffix=scenario_id,
|
384
393
|
),
|
385
394
|
"manufacturing_automation": BusinessScenario(
|
386
395
|
scenario_id=scenario_id,
|
@@ -389,8 +398,8 @@ class BusinessCaseConfigManager:
|
|
389
398
|
business_description="Manufacturing workflow automation with cost optimization",
|
390
399
|
technical_focus="IoT and automation pipeline cost optimization analysis",
|
391
400
|
risk_level="Medium",
|
392
|
-
cli_command_suffix=scenario_id
|
393
|
-
)
|
401
|
+
cli_command_suffix=scenario_id,
|
402
|
+
),
|
394
403
|
}
|
395
404
|
|
396
405
|
template = templates.get(template_type, templates["aws_resource_optimization"])
|
@@ -405,7 +414,7 @@ class BusinessCaseConfigManager:
|
|
405
414
|
technical_focus=template.technical_focus,
|
406
415
|
risk_level=template.risk_level,
|
407
416
|
implementation_status=template.implementation_status,
|
408
|
-
cli_command_suffix=template.cli_command_suffix
|
417
|
+
cli_command_suffix=template.cli_command_suffix,
|
409
418
|
)
|
410
419
|
|
411
420
|
def get_template_types(self) -> List[str]:
|
@@ -416,11 +425,12 @@ class BusinessCaseConfigManager:
|
|
416
425
|
"s3_storage_optimization",
|
417
426
|
"healthcare_compliance",
|
418
427
|
"finance_cost_governance",
|
419
|
-
"manufacturing_automation"
|
428
|
+
"manufacturing_automation",
|
420
429
|
]
|
421
430
|
|
422
|
-
def calculate_roi_projection(
|
423
|
-
|
431
|
+
def calculate_roi_projection(
|
432
|
+
self, scenario_key: str, current_monthly_cost: float, optimization_percentage: float = 0.20
|
433
|
+
) -> Dict[str, float]:
|
424
434
|
"""
|
425
435
|
Calculate ROI projection for a business scenario.
|
426
436
|
|
@@ -440,20 +450,15 @@ class BusinessCaseConfigManager:
|
|
440
450
|
"monthly_savings": monthly_savings,
|
441
451
|
"annual_savings": annual_savings,
|
442
452
|
"optimization_percentage": optimization_percentage * 100,
|
443
|
-
"roi_12_month": annual_savings # Assuming minimal implementation cost for analysis
|
453
|
+
"roi_12_month": annual_savings, # Assuming minimal implementation cost for analysis
|
444
454
|
}
|
445
455
|
|
446
456
|
def create_business_case_summary(self) -> Dict[str, Any]:
|
447
457
|
"""Create executive summary of all business cases."""
|
448
|
-
total_min_savings = sum(
|
449
|
-
scenario.target_savings_min or 0
|
450
|
-
for scenario in self.scenarios.values()
|
451
|
-
)
|
458
|
+
total_min_savings = sum(scenario.target_savings_min or 0 for scenario in self.scenarios.values())
|
452
459
|
|
453
460
|
total_max_savings = sum(
|
454
|
-
scenario.target_savings_max or 0
|
455
|
-
for scenario in self.scenarios.values()
|
456
|
-
if scenario.target_savings_max
|
461
|
+
scenario.target_savings_max or 0 for scenario in self.scenarios.values() if scenario.target_savings_max
|
457
462
|
)
|
458
463
|
|
459
464
|
return {
|
@@ -462,24 +467,22 @@ class BusinessCaseConfigManager:
|
|
462
467
|
"total_potential_max": total_max_savings,
|
463
468
|
"potential_range": f"${total_min_savings:,.0f}-${total_max_savings:,.0f}",
|
464
469
|
"scenarios_by_type": {
|
465
|
-
case_type.value: [
|
466
|
-
s.display_name for s in self.scenarios.values()
|
467
|
-
if s.business_case_type == case_type
|
468
|
-
]
|
470
|
+
case_type.value: [s.display_name for s in self.scenarios.values() if s.business_case_type == case_type]
|
469
471
|
for case_type in BusinessCaseType
|
470
472
|
},
|
471
473
|
"scenario_discovery": {
|
472
474
|
"default_scenarios": 7,
|
473
475
|
"environment_discovered": len(self.scenarios) - 7,
|
474
476
|
"total_active": len(self.scenarios),
|
475
|
-
"unlimited_expansion": True
|
476
|
-
}
|
477
|
+
"unlimited_expansion": True,
|
478
|
+
},
|
477
479
|
}
|
478
480
|
|
479
481
|
|
480
482
|
# Global configuration manager instance
|
481
483
|
_config_manager = None
|
482
484
|
|
485
|
+
|
483
486
|
def get_business_case_config() -> BusinessCaseConfigManager:
|
484
487
|
"""Get global business case configuration manager."""
|
485
488
|
global _config_manager
|
@@ -506,17 +509,17 @@ def format_business_achievement(scenario_key: str, achieved_savings: float) -> s
|
|
506
509
|
"""Format business achievement for executive reporting."""
|
507
510
|
config = get_business_case_config()
|
508
511
|
scenario = config.get_scenario(scenario_key)
|
509
|
-
|
512
|
+
|
510
513
|
if not scenario:
|
511
514
|
return f"{scenario_key}: ${achieved_savings:,.0f} annual savings"
|
512
|
-
|
515
|
+
|
513
516
|
# Calculate achievement percentage if target is available
|
514
517
|
achievement_text = f"{scenario.display_name}: ${achieved_savings:,.0f} annual savings"
|
515
|
-
|
518
|
+
|
516
519
|
if scenario.target_savings_min:
|
517
520
|
percentage = (achieved_savings / scenario.target_savings_min) * 100
|
518
521
|
achievement_text += f" ({percentage:.0f}% of target)"
|
519
|
-
|
522
|
+
|
520
523
|
return achievement_text
|
521
524
|
|
522
525
|
|
@@ -539,12 +542,10 @@ def create_scenario_from_environment_variables(scenario_id: str) -> Optional[Bus
|
|
539
542
|
BusinessScenario object or None if required fields missing
|
540
543
|
"""
|
541
544
|
config_manager = get_business_case_config()
|
542
|
-
env_key = scenario_id.upper().replace(
|
545
|
+
env_key = scenario_id.upper().replace("-", "_")
|
543
546
|
|
544
547
|
return config_manager._create_scenario_from_environment(
|
545
|
-
scenario_id.lower().replace(
|
546
|
-
env_key,
|
547
|
-
"RUNBOOKS_BUSINESS_CASE_"
|
548
|
+
scenario_id.lower().replace("_", "-"), env_key, "RUNBOOKS_BUSINESS_CASE_"
|
548
549
|
)
|
549
550
|
|
550
551
|
|
@@ -571,8 +572,9 @@ def get_available_templates() -> List[str]:
|
|
571
572
|
return config_manager.get_template_types()
|
572
573
|
|
573
574
|
|
574
|
-
def calculate_scenario_roi(
|
575
|
-
|
575
|
+
def calculate_scenario_roi(
|
576
|
+
scenario_id: str, current_monthly_cost: float, optimization_percentage: float = 0.20
|
577
|
+
) -> Dict[str, float]:
|
576
578
|
"""
|
577
579
|
Calculate ROI projection for any business scenario.
|
578
580
|
|
@@ -622,7 +624,7 @@ def discover_scenarios_summary() -> Dict[str, Any]:
|
|
622
624
|
# Migration helper functions for existing hardcoded patterns
|
623
625
|
def migrate_legacy_scenario_reference(legacy_ref: str) -> str:
|
624
626
|
"""
|
625
|
-
Migrate legacy
|
627
|
+
Migrate legacy references to dynamic business case keys.
|
626
628
|
|
627
629
|
Args:
|
628
630
|
legacy_ref: Legacy reference like "FinOps-24", "finops-23", etc.
|
@@ -644,7 +646,7 @@ def migrate_legacy_scenario_reference(legacy_ref: str) -> str:
|
|
644
646
|
"finops-ebs": "ebs-optimization",
|
645
647
|
"FinOps-EBS": "ebs-optimization",
|
646
648
|
"awso-05": "vpc-cleanup",
|
647
|
-
"AWSO-05": "vpc-cleanup"
|
649
|
+
"AWSO-05": "vpc-cleanup",
|
648
650
|
}
|
649
651
|
|
650
652
|
return legacy_mapping.get(legacy_ref, legacy_ref.lower())
|
@@ -654,8 +656,10 @@ def migrate_legacy_scenario_reference(legacy_ref: str) -> str:
|
|
654
656
|
# Business Scenario Matrix - Phase 1 Priority 2 Implementation
|
655
657
|
# ============================================================================
|
656
658
|
|
659
|
+
|
657
660
|
class ScenarioParameter(NamedTuple):
|
658
661
|
"""Parameter recommendation for business scenarios."""
|
662
|
+
|
659
663
|
name: str
|
660
664
|
optimal_value: Union[str, int, float]
|
661
665
|
business_justification: str
|
@@ -665,6 +669,7 @@ class ScenarioParameter(NamedTuple):
|
|
665
669
|
@dataclass
|
666
670
|
class ScenarioParameterMatrix:
|
667
671
|
"""Intelligent parameter defaults for business scenarios."""
|
672
|
+
|
668
673
|
timerange_days: Optional[int] = None
|
669
674
|
regional_scope: Optional[str] = None # single, multi, global
|
670
675
|
cost_focus: Optional[str] = None # unblended, amortized, dual-metrics
|
@@ -678,40 +683,40 @@ class ScenarioParameterMatrix:
|
|
678
683
|
recommendations = {}
|
679
684
|
|
680
685
|
if self.timerange_days:
|
681
|
-
recommendations[
|
682
|
-
name=
|
686
|
+
recommendations["timerange"] = ScenarioParameter(
|
687
|
+
name="--time-range",
|
683
688
|
optimal_value=self.timerange_days,
|
684
689
|
business_justification=f"Optimal analysis period: {self.timerange_days} days. {self.business_justification}",
|
685
|
-
alternative_values=[7, 30, 60, 90, 180] if self.timerange_days not in [7, 30, 60, 90, 180] else None
|
690
|
+
alternative_values=[7, 30, 60, 90, 180] if self.timerange_days not in [7, 30, 60, 90, 180] else None,
|
686
691
|
)
|
687
692
|
|
688
693
|
if self.regional_scope:
|
689
694
|
scope_mapping = {
|
690
|
-
|
691
|
-
|
692
|
-
|
695
|
+
"single": ["--region", "us-east-1"],
|
696
|
+
"multi": ["--all-regions", True],
|
697
|
+
"global": ["--global-scope", True],
|
693
698
|
}
|
694
699
|
if self.regional_scope in scope_mapping:
|
695
700
|
param_name, param_value = scope_mapping[self.regional_scope]
|
696
|
-
recommendations[
|
701
|
+
recommendations["regional_scope"] = ScenarioParameter(
|
697
702
|
name=param_name,
|
698
703
|
optimal_value=param_value,
|
699
|
-
business_justification=f"Regional scope: {self.regional_scope} - {self.business_justification}"
|
704
|
+
business_justification=f"Regional scope: {self.regional_scope} - {self.business_justification}",
|
700
705
|
)
|
701
706
|
|
702
707
|
if self.cost_focus:
|
703
|
-
recommendations[
|
704
|
-
name=f
|
708
|
+
recommendations["cost_focus"] = ScenarioParameter(
|
709
|
+
name=f"--{self.cost_focus}",
|
705
710
|
optimal_value=True,
|
706
|
-
business_justification=f"Cost perspective: {self.cost_focus} - {self.business_justification}"
|
711
|
+
business_justification=f"Cost perspective: {self.cost_focus} - {self.business_justification}",
|
707
712
|
)
|
708
713
|
|
709
714
|
if self.export_priority:
|
710
|
-
recommendations[
|
711
|
-
name=
|
715
|
+
recommendations["export_format"] = ScenarioParameter(
|
716
|
+
name="--" + self.export_priority.replace("_", "-"),
|
712
717
|
optimal_value=True,
|
713
718
|
business_justification=f"Export format: {self.export_priority} - {self.business_justification}",
|
714
|
-
alternative_values=[
|
719
|
+
alternative_values=["csv", "json", "pdf", "markdown"] if self.export_priority else None,
|
715
720
|
)
|
716
721
|
|
717
722
|
return recommendations
|
@@ -737,70 +742,64 @@ class BusinessScenarioMatrix:
|
|
737
742
|
"""Build the complete business scenario parameter matrix."""
|
738
743
|
return {
|
739
744
|
# TIER 1 HIGH-VALUE SCENARIOS
|
740
|
-
|
745
|
+
"workspaces": ScenarioParameterMatrix(
|
741
746
|
timerange_days=90,
|
742
|
-
regional_scope=
|
743
|
-
cost_focus=
|
744
|
-
export_priority=
|
745
|
-
validation_level=
|
746
|
-
business_justification="WorkSpaces require quarterly analysis for usage pattern detection. Single-region focus optimizes analysis speed. Unblended costs show true resource utilization. PDF format ideal for management review."
|
747
|
+
regional_scope="single",
|
748
|
+
cost_focus="unblended",
|
749
|
+
export_priority="pdf",
|
750
|
+
validation_level="comprehensive",
|
751
|
+
business_justification="WorkSpaces require quarterly analysis for usage pattern detection. Single-region focus optimizes analysis speed. Unblended costs show true resource utilization. PDF format ideal for management review.",
|
747
752
|
),
|
748
|
-
|
749
|
-
'nat-gateway': ScenarioParameterMatrix(
|
753
|
+
"nat-gateway": ScenarioParameterMatrix(
|
750
754
|
timerange_days=30,
|
751
|
-
regional_scope=
|
752
|
-
cost_focus=
|
753
|
-
export_priority=
|
754
|
-
validation_level=
|
755
|
-
business_justification="NAT Gateways require monthly analysis for traffic optimization. Multi-region analysis essential for comprehensive network cost optimization. Amortized costs account for data transfer pricing. JSON format enables automation integration."
|
755
|
+
regional_scope="multi",
|
756
|
+
cost_focus="amortized",
|
757
|
+
export_priority="json",
|
758
|
+
validation_level="enhanced",
|
759
|
+
business_justification="NAT Gateways require monthly analysis for traffic optimization. Multi-region analysis essential for comprehensive network cost optimization. Amortized costs account for data transfer pricing. JSON format enables automation integration.",
|
756
760
|
),
|
757
|
-
|
758
|
-
'rds-snapshots': ScenarioParameterMatrix(
|
761
|
+
"rds-snapshots": ScenarioParameterMatrix(
|
759
762
|
timerange_days=90,
|
760
|
-
regional_scope=
|
761
|
-
cost_focus=
|
762
|
-
export_priority=
|
763
|
-
validation_level=
|
764
|
-
business_justification="RDS snapshots require quarterly analysis for retention policy optimization. Multi-region scope captures all backup strategies. Dual metrics provide complete cost visibility. CSV format enables spreadsheet analysis."
|
763
|
+
regional_scope="multi",
|
764
|
+
cost_focus="dual-metrics",
|
765
|
+
export_priority="csv",
|
766
|
+
validation_level="comprehensive",
|
767
|
+
business_justification="RDS snapshots require quarterly analysis for retention policy optimization. Multi-region scope captures all backup strategies. Dual metrics provide complete cost visibility. CSV format enables spreadsheet analysis.",
|
765
768
|
),
|
766
|
-
|
767
769
|
# TIER 2 STRATEGIC SCENARIOS
|
768
|
-
|
770
|
+
"ebs-optimization": ScenarioParameterMatrix(
|
769
771
|
timerange_days=180,
|
770
|
-
regional_scope=
|
771
|
-
cost_focus=
|
772
|
-
export_priority=
|
773
|
-
validation_level=
|
774
|
-
business_justification="EBS optimization requires extended analysis to identify usage patterns. Multi-region scope captures all storage. Dual metrics show both immediate and amortized costs. PDF format suitable for capacity planning presentations."
|
772
|
+
regional_scope="multi",
|
773
|
+
cost_focus="dual-metrics",
|
774
|
+
export_priority="pdf",
|
775
|
+
validation_level="comprehensive",
|
776
|
+
business_justification="EBS optimization requires extended analysis to identify usage patterns. Multi-region scope captures all storage. Dual metrics show both immediate and amortized costs. PDF format suitable for capacity planning presentations.",
|
775
777
|
),
|
776
|
-
|
777
|
-
'vpc-cleanup': ScenarioParameterMatrix(
|
778
|
+
"vpc-cleanup": ScenarioParameterMatrix(
|
778
779
|
timerange_days=30,
|
779
|
-
regional_scope=
|
780
|
-
cost_focus=
|
781
|
-
export_priority=
|
782
|
-
validation_level=
|
783
|
-
business_justification="VPC cleanup requires recent data for active resource identification. Multi-region analysis captures all network resources. Unblended costs show direct infrastructure impact. CSV enables detailed resource tracking."
|
780
|
+
regional_scope="multi",
|
781
|
+
cost_focus="unblended",
|
782
|
+
export_priority="csv",
|
783
|
+
validation_level="enhanced",
|
784
|
+
business_justification="VPC cleanup requires recent data for active resource identification. Multi-region analysis captures all network resources. Unblended costs show direct infrastructure impact. CSV enables detailed resource tracking.",
|
784
785
|
),
|
785
|
-
|
786
|
-
'elastic-ip': ScenarioParameterMatrix(
|
786
|
+
"elastic-ip": ScenarioParameterMatrix(
|
787
787
|
timerange_days=7,
|
788
|
-
regional_scope=
|
789
|
-
cost_focus=
|
790
|
-
export_priority=
|
791
|
-
validation_level=
|
792
|
-
business_justification="Elastic IP analysis requires recent data for attachment status. Multi-region scope captures all IP allocations. Unblended costs show direct charges. JSON format enables automated cleanup workflows."
|
788
|
+
regional_scope="multi",
|
789
|
+
cost_focus="unblended",
|
790
|
+
export_priority="json",
|
791
|
+
validation_level="basic",
|
792
|
+
business_justification="Elastic IP analysis requires recent data for attachment status. Multi-region scope captures all IP allocations. Unblended costs show direct charges. JSON format enables automated cleanup workflows.",
|
793
793
|
),
|
794
|
-
|
795
794
|
# TIER 3 FRAMEWORK SCENARIOS
|
796
|
-
|
795
|
+
"backup-investigation": ScenarioParameterMatrix(
|
797
796
|
timerange_days=None, # Framework-based
|
798
|
-
regional_scope=
|
799
|
-
cost_focus=
|
800
|
-
export_priority=
|
801
|
-
validation_level=
|
802
|
-
business_justification="Backup investigation uses framework-based timerange analysis. Multi-region scope for comprehensive backup strategy. Amortized costs for long-term planning. Markdown format for documentation and reporting."
|
803
|
-
)
|
797
|
+
regional_scope="multi",
|
798
|
+
cost_focus="amortized",
|
799
|
+
export_priority="markdown",
|
800
|
+
validation_level="basic",
|
801
|
+
business_justification="Backup investigation uses framework-based timerange analysis. Multi-region scope for comprehensive backup strategy. Amortized costs for long-term planning. Markdown format for documentation and reporting.",
|
802
|
+
),
|
804
803
|
}
|
805
804
|
|
806
805
|
def _extend_matrix_with_discovered_scenarios(self) -> None:
|
@@ -833,59 +832,60 @@ class BusinessScenarioMatrix:
|
|
833
832
|
type_defaults = {
|
834
833
|
BusinessCaseType.COST_OPTIMIZATION: ScenarioParameterMatrix(
|
835
834
|
timerange_days=30,
|
836
|
-
regional_scope=
|
837
|
-
cost_focus=
|
838
|
-
export_priority=
|
839
|
-
validation_level=
|
840
|
-
business_justification=f"Cost optimization requires comprehensive analysis with dual cost perspectives for {scenario.display_name}"
|
835
|
+
regional_scope="multi",
|
836
|
+
cost_focus="dual-metrics",
|
837
|
+
export_priority="pdf",
|
838
|
+
validation_level="enhanced",
|
839
|
+
business_justification=f"Cost optimization requires comprehensive analysis with dual cost perspectives for {scenario.display_name}",
|
841
840
|
),
|
842
841
|
BusinessCaseType.RESOURCE_CLEANUP: ScenarioParameterMatrix(
|
843
842
|
timerange_days=7,
|
844
|
-
regional_scope=
|
845
|
-
cost_focus=
|
846
|
-
export_priority=
|
847
|
-
validation_level=
|
848
|
-
business_justification=f"Resource cleanup requires recent data for active resource identification in {scenario.display_name}"
|
843
|
+
regional_scope="multi",
|
844
|
+
cost_focus="unblended",
|
845
|
+
export_priority="csv",
|
846
|
+
validation_level="basic",
|
847
|
+
business_justification=f"Resource cleanup requires recent data for active resource identification in {scenario.display_name}",
|
849
848
|
),
|
850
849
|
BusinessCaseType.COMPLIANCE_FRAMEWORK: ScenarioParameterMatrix(
|
851
850
|
timerange_days=90,
|
852
|
-
regional_scope=
|
853
|
-
cost_focus=
|
854
|
-
export_priority=
|
855
|
-
validation_level=
|
856
|
-
business_justification=f"Compliance frameworks require extended analysis with comprehensive reporting for {scenario.display_name}"
|
851
|
+
regional_scope="global",
|
852
|
+
cost_focus="amortized",
|
853
|
+
export_priority="pdf",
|
854
|
+
validation_level="comprehensive",
|
855
|
+
business_justification=f"Compliance frameworks require extended analysis with comprehensive reporting for {scenario.display_name}",
|
857
856
|
),
|
858
857
|
BusinessCaseType.SECURITY_ENHANCEMENT: ScenarioParameterMatrix(
|
859
858
|
timerange_days=30,
|
860
|
-
regional_scope=
|
861
|
-
cost_focus=
|
862
|
-
export_priority=
|
863
|
-
validation_level=
|
864
|
-
business_justification=f"Security enhancements require thorough analysis with documentation focus for {scenario.display_name}"
|
859
|
+
regional_scope="global",
|
860
|
+
cost_focus="unblended",
|
861
|
+
export_priority="markdown",
|
862
|
+
validation_level="comprehensive",
|
863
|
+
business_justification=f"Security enhancements require thorough analysis with documentation focus for {scenario.display_name}",
|
865
864
|
),
|
866
865
|
BusinessCaseType.AUTOMATION_DEPLOYMENT: ScenarioParameterMatrix(
|
867
866
|
timerange_days=60,
|
868
|
-
regional_scope=
|
869
|
-
cost_focus=
|
870
|
-
export_priority=
|
871
|
-
validation_level=
|
872
|
-
business_justification=f"Automation deployment requires extended analysis with machine-readable output for {scenario.display_name}"
|
873
|
-
)
|
867
|
+
regional_scope="multi",
|
868
|
+
cost_focus="amortized",
|
869
|
+
export_priority="json",
|
870
|
+
validation_level="enhanced",
|
871
|
+
business_justification=f"Automation deployment requires extended analysis with machine-readable output for {scenario.display_name}",
|
872
|
+
),
|
874
873
|
}
|
875
874
|
|
876
875
|
# Use type-based defaults or fallback to generic cost optimization pattern
|
877
|
-
default_matrix = type_defaults.get(
|
878
|
-
|
876
|
+
default_matrix = type_defaults.get(
|
877
|
+
scenario.business_case_type, type_defaults[BusinessCaseType.COST_OPTIMIZATION]
|
878
|
+
)
|
879
879
|
|
880
880
|
# Override with scenario-specific intelligence where available
|
881
|
-
if scenario.risk_level.lower() ==
|
881
|
+
if scenario.risk_level.lower() == "high":
|
882
882
|
# High risk scenarios need more comprehensive validation
|
883
|
-
default_matrix.validation_level =
|
883
|
+
default_matrix.validation_level = "comprehensive"
|
884
884
|
default_matrix.timerange_days = max(default_matrix.timerange_days or 30, 90)
|
885
885
|
|
886
|
-
if scenario.risk_level.lower() ==
|
886
|
+
if scenario.risk_level.lower() == "low":
|
887
887
|
# Low risk scenarios can use basic validation
|
888
|
-
default_matrix.validation_level =
|
888
|
+
default_matrix.validation_level = "basic"
|
889
889
|
default_matrix.timerange_days = min(default_matrix.timerange_days or 30, 14)
|
890
890
|
|
891
891
|
return default_matrix
|
@@ -932,7 +932,7 @@ class BusinessScenarioMatrix:
|
|
932
932
|
help_lines.append(f" → {param.business_justification}")
|
933
933
|
|
934
934
|
if param.alternative_values:
|
935
|
-
alternatives =
|
935
|
+
alternatives = ", ".join(str(v) for v in param.alternative_values)
|
936
936
|
help_lines.append(f" Alternatives: {alternatives}")
|
937
937
|
help_lines.append("")
|
938
938
|
|
@@ -951,25 +951,29 @@ class BusinessScenarioMatrix:
|
|
951
951
|
suggestions = {}
|
952
952
|
|
953
953
|
# Check timerange optimization
|
954
|
-
if
|
955
|
-
optimal_timerange = recommendations[
|
956
|
-
provided_timerange = provided_params.get(
|
954
|
+
if "timerange" in recommendations:
|
955
|
+
optimal_timerange = recommendations["timerange"].optimal_value
|
956
|
+
provided_timerange = provided_params.get("time_range")
|
957
957
|
|
958
958
|
if provided_timerange and provided_timerange != optimal_timerange:
|
959
|
-
suggestions[
|
959
|
+
suggestions["timerange"] = (
|
960
|
+
f"Consider --time-range {optimal_timerange} for optimal {scenario_key} analysis (current: {provided_timerange})"
|
961
|
+
)
|
960
962
|
|
961
963
|
# Check export format optimization
|
962
|
-
if
|
963
|
-
optimal_export = recommendations[
|
964
|
-
export_formats = provided_params.get(
|
964
|
+
if "export_format" in recommendations:
|
965
|
+
optimal_export = recommendations["export_format"].name.replace("--", "")
|
966
|
+
export_formats = provided_params.get("export_formats", [])
|
965
967
|
|
966
968
|
if export_formats and optimal_export not in export_formats:
|
967
|
-
suggestions[
|
969
|
+
suggestions["export_format"] = (
|
970
|
+
f"Consider {optimal_export} export format for {scenario_key} analysis (optimal for business case)"
|
971
|
+
)
|
968
972
|
|
969
973
|
# Check cost focus optimization
|
970
|
-
if
|
971
|
-
optimal_focus = recommendations[
|
972
|
-
cost_focus_params = [
|
974
|
+
if "cost_focus" in recommendations:
|
975
|
+
optimal_focus = recommendations["cost_focus"].name.replace("--", "")
|
976
|
+
cost_focus_params = ["unblended", "amortized", "dual_metrics"]
|
973
977
|
provided_focus = None
|
974
978
|
|
975
979
|
for focus_type in cost_focus_params:
|
@@ -978,7 +982,7 @@ class BusinessScenarioMatrix:
|
|
978
982
|
break
|
979
983
|
|
980
984
|
if not provided_focus:
|
981
|
-
suggestions[
|
985
|
+
suggestions["cost_focus"] = f"Consider {optimal_focus} cost perspective for {scenario_key} analysis"
|
982
986
|
|
983
987
|
return suggestions
|
984
988
|
|
@@ -1010,9 +1014,10 @@ class BusinessScenarioMatrix:
|
|
1010
1014
|
# Global scenario matrix instance
|
1011
1015
|
_scenario_matrix = None
|
1012
1016
|
|
1017
|
+
|
1013
1018
|
def get_business_scenario_matrix() -> BusinessScenarioMatrix:
|
1014
1019
|
"""Get global business scenario matrix instance."""
|
1015
1020
|
global _scenario_matrix
|
1016
1021
|
if _scenario_matrix is None:
|
1017
1022
|
_scenario_matrix = BusinessScenarioMatrix()
|
1018
|
-
return _scenario_matrix
|
1023
|
+
return _scenario_matrix
|