runbooks 1.1.3__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/WEIGHT_CONFIG_README.md +1 -1
- runbooks/cfat/assessment/compliance.py +8 -8
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cfat/models.py +6 -2
- runbooks/cfat/tests/__init__.py +6 -1
- runbooks/cli/__init__.py +13 -0
- runbooks/cli/commands/cfat.py +274 -0
- runbooks/cli/commands/finops.py +1164 -0
- runbooks/cli/commands/inventory.py +379 -0
- runbooks/cli/commands/operate.py +239 -0
- runbooks/cli/commands/security.py +248 -0
- runbooks/cli/commands/validation.py +825 -0
- runbooks/cli/commands/vpc.py +310 -0
- runbooks/cli/registry.py +107 -0
- runbooks/cloudops/__init__.py +23 -30
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +549 -547
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +226 -227
- 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 +179 -215
- 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 +341 -0
- runbooks/common/aws_utils.py +75 -80
- runbooks/common/business_logic.py +127 -105
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +456 -464
- runbooks/common/cross_account_manager.py +198 -205
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +235 -0
- 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 +478 -495
- 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 +176 -194
- runbooks/common/patterns.py +204 -0
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +248 -39
- runbooks/common/rich_utils.py +643 -92
- 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 +29 -33
- 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 +488 -622
- 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 +40 -37
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +230 -292
- 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 +338 -175
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1513 -482
- 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 +25 -29
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +77 -78
- runbooks/finops/scenarios.py +1278 -439
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- 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/types.py +3 -3
- runbooks/finops/validation_framework.py +263 -269
- runbooks/finops/vpc_cleanup_exporter.py +191 -146
- runbooks/finops/vpc_cleanup_optimizer.py +593 -575
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/hitl/enhanced_workflow_engine.py +1 -1
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/README.md +3 -3
- runbooks/inventory/Tests/common_test_data.py +30 -30
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +28 -11
- runbooks/inventory/collectors/aws_networking.py +111 -101
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/discovery.md +2 -2
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/find_ec2_security_groups.py +1 -1
- 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 +56 -52
- runbooks/inventory/rich_inventory_display.py +33 -32
- runbooks/inventory/unified_validation_engine.py +278 -251
- runbooks/inventory/vpc_analyzer.py +733 -696
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +382 -378
- runbooks/inventory/vpc_flow_analyzer.py +3 -3
- runbooks/main.py +152 -9147
- 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/metrics/dora_metrics_engine.py +2 -2
- 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/mcp_integration.py +1 -1
- runbooks/operate/networking_cost_heatmap.py +33 -10
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/operate/vpc_operations.py +648 -618
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +71 -67
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +91 -65
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +49 -44
- 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/integration_test_enterprise_security.py +5 -3
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/run_script.py +1 -1
- 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/mcp_reliability_engine.py +6 -6
- 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 +51 -48
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +754 -708
- 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 +190 -162
- runbooks/vpc/mcp_no_eni_validator.py +681 -640
- 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 +1302 -1129
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.5.dist-info/METADATA +328 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/RECORD +233 -200
- 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 -956
- 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.3.dist-info/METADATA +0 -799
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.3.dist-info → runbooks-1.1.5.dist-info}/top_level.txt +0 -0
runbooks/common/date_utils.py
CHANGED
@@ -22,94 +22,82 @@ def get_current_year() -> int:
|
|
22
22
|
def get_current_month_period() -> Dict[str, str]:
|
23
23
|
"""
|
24
24
|
Generate current month's start and end dates for AWS API calls.
|
25
|
-
|
25
|
+
|
26
26
|
Returns:
|
27
27
|
Dict with 'Start' and 'End' keys in YYYY-MM-DD format
|
28
28
|
"""
|
29
29
|
now = datetime.now()
|
30
|
-
start_date = now.replace(day=1).strftime(
|
31
|
-
|
30
|
+
start_date = now.replace(day=1).strftime("%Y-%m-%d")
|
31
|
+
|
32
32
|
# Get last day of current month
|
33
33
|
if now.month == 12:
|
34
34
|
next_month = now.replace(year=now.year + 1, month=1, day=1)
|
35
35
|
else:
|
36
36
|
next_month = now.replace(month=now.month + 1, day=1)
|
37
|
-
|
38
|
-
end_date = (next_month - timedelta(days=1)).strftime(
|
39
|
-
|
40
|
-
return {
|
41
|
-
'Start': start_date,
|
42
|
-
'End': end_date
|
43
|
-
}
|
37
|
+
|
38
|
+
end_date = (next_month - timedelta(days=1)).strftime("%Y-%m-%d")
|
39
|
+
|
40
|
+
return {"Start": start_date, "End": end_date}
|
44
41
|
|
45
42
|
|
46
43
|
def get_previous_month_period() -> Dict[str, str]:
|
47
44
|
"""
|
48
45
|
Generate previous month's start and end dates for AWS API calls.
|
49
|
-
|
46
|
+
|
50
47
|
Returns:
|
51
48
|
Dict with 'Start' and 'End' keys in YYYY-MM-DD format
|
52
49
|
"""
|
53
50
|
now = datetime.now()
|
54
|
-
|
51
|
+
|
55
52
|
# Get first day of previous month
|
56
53
|
if now.month == 1:
|
57
54
|
prev_month = now.replace(year=now.year - 1, month=12, day=1)
|
58
55
|
else:
|
59
56
|
prev_month = now.replace(month=now.month - 1, day=1)
|
60
|
-
|
61
|
-
start_date = prev_month.strftime(
|
62
|
-
|
63
|
-
# Get last day of previous month
|
64
|
-
end_date = (now.replace(day=1) - timedelta(days=1)).strftime(
|
65
|
-
|
66
|
-
return {
|
67
|
-
'Start': start_date,
|
68
|
-
'End': end_date
|
69
|
-
}
|
57
|
+
|
58
|
+
start_date = prev_month.strftime("%Y-%m-%d")
|
59
|
+
|
60
|
+
# Get last day of previous month
|
61
|
+
end_date = (now.replace(day=1) - timedelta(days=1)).strftime("%Y-%m-%d")
|
62
|
+
|
63
|
+
return {"Start": start_date, "End": end_date}
|
70
64
|
|
71
65
|
|
72
66
|
def get_test_date_period(days_back: int = 30) -> Dict[str, str]:
|
73
67
|
"""
|
74
68
|
Generate test date periods for consistent test data.
|
75
|
-
|
69
|
+
|
76
70
|
Args:
|
77
71
|
days_back: Number of days back from today for start date
|
78
|
-
|
72
|
+
|
79
73
|
Returns:
|
80
74
|
Dict with 'Start' and 'End' keys in YYYY-MM-DD format
|
81
75
|
"""
|
82
|
-
end_date = datetime.now().strftime(
|
83
|
-
start_date = (datetime.now() - timedelta(days=days_back)).strftime(
|
84
|
-
|
85
|
-
return {
|
86
|
-
'Start': start_date,
|
87
|
-
'End': end_date
|
88
|
-
}
|
76
|
+
end_date = datetime.now().strftime("%Y-%m-%d")
|
77
|
+
start_date = (datetime.now() - timedelta(days=days_back)).strftime("%Y-%m-%d")
|
78
|
+
|
79
|
+
return {"Start": start_date, "End": end_date}
|
89
80
|
|
90
81
|
|
91
82
|
def get_aws_cli_example_period() -> Tuple[str, str]:
|
92
83
|
"""
|
93
84
|
Generate example date period for AWS CLI documentation.
|
94
85
|
Uses yesterday and today to ensure valid time range.
|
95
|
-
|
86
|
+
|
96
87
|
Returns:
|
97
88
|
Tuple of (start_date, end_date) in YYYY-MM-DD format
|
98
89
|
"""
|
99
90
|
today = datetime.now()
|
100
91
|
yesterday = today - timedelta(days=1)
|
101
|
-
|
102
|
-
return (
|
103
|
-
yesterday.strftime('%Y-%m-%d'),
|
104
|
-
today.strftime('%Y-%m-%d')
|
105
|
-
)
|
92
|
+
|
93
|
+
return (yesterday.strftime("%Y-%m-%d"), today.strftime("%Y-%m-%d"))
|
106
94
|
|
107
95
|
|
108
96
|
def get_collection_timestamp() -> str:
|
109
97
|
"""
|
110
98
|
Generate collection timestamp for test data.
|
111
|
-
|
99
|
+
|
112
100
|
Returns:
|
113
101
|
ISO format timestamp string
|
114
102
|
"""
|
115
|
-
return datetime.now().isoformat()
|
103
|
+
return datetime.now().isoformat()
|
@@ -0,0 +1,235 @@
|
|
1
|
+
"""
|
2
|
+
Common CLI Decorators for Modular Commands
|
3
|
+
|
4
|
+
KISS Principle: Simple, reusable decorators for consistent CLI patterns
|
5
|
+
DRY Principle: No duplicated decorator logic across command modules
|
6
|
+
|
7
|
+
This module provides consistent decorators used across all modular command
|
8
|
+
files, enabling the DRY principle while maintaining enterprise standards.
|
9
|
+
"""
|
10
|
+
|
11
|
+
import functools
|
12
|
+
import time
|
13
|
+
from typing import Any, Callable
|
14
|
+
|
15
|
+
import click
|
16
|
+
from rich.console import Console
|
17
|
+
|
18
|
+
console = Console()
|
19
|
+
|
20
|
+
|
21
|
+
def common_aws_options(f):
|
22
|
+
"""
|
23
|
+
Common AWS options for all commands.
|
24
|
+
|
25
|
+
Provides consistent AWS configuration options across all command modules:
|
26
|
+
- --profile: AWS profile selection
|
27
|
+
- --region: AWS region targeting
|
28
|
+
- --dry-run: Safety mode for testing
|
29
|
+
"""
|
30
|
+
f = click.option("--profile", default="default", help="AWS profile to use")(f)
|
31
|
+
f = click.option("--region", help="AWS region (overrides profile default)")(f)
|
32
|
+
f = click.option("--dry-run", is_flag=True, help="Perform a dry run without making changes")(f)
|
33
|
+
return f
|
34
|
+
|
35
|
+
|
36
|
+
def common_output_options(f):
|
37
|
+
"""
|
38
|
+
Common output options for commands that generate reports.
|
39
|
+
|
40
|
+
Provides consistent output formatting options:
|
41
|
+
- --format: Output format selection (table, csv, json, markdown, pdf)
|
42
|
+
- --output-file: File output destination
|
43
|
+
"""
|
44
|
+
f = click.option(
|
45
|
+
"--format",
|
46
|
+
"output_format",
|
47
|
+
type=click.Choice(["table", "csv", "json", "markdown", "pdf"]),
|
48
|
+
default="table",
|
49
|
+
help="Output format",
|
50
|
+
)(f)
|
51
|
+
f = click.option("--output-file", type=click.Path(), help="Output file path")(f)
|
52
|
+
return f
|
53
|
+
|
54
|
+
|
55
|
+
def common_filter_options(f):
|
56
|
+
"""
|
57
|
+
Common filtering options for resource discovery commands.
|
58
|
+
|
59
|
+
Provides consistent filtering capabilities:
|
60
|
+
- --tags: Resource tag filtering
|
61
|
+
- --accounts: Account ID filtering
|
62
|
+
- --regions: Region filtering
|
63
|
+
"""
|
64
|
+
f = click.option("--tags", multiple=True, help="Filter by tags (key=value format)")(f)
|
65
|
+
f = click.option("--accounts", multiple=True, help="Filter by account IDs")(f)
|
66
|
+
f = click.option("--regions", multiple=True, help="Filter by regions")(f)
|
67
|
+
return f
|
68
|
+
|
69
|
+
|
70
|
+
def performance_timing(f):
|
71
|
+
"""
|
72
|
+
Performance timing decorator for measuring command execution time.
|
73
|
+
|
74
|
+
Automatically tracks and reports command execution time for performance
|
75
|
+
monitoring and optimization analysis.
|
76
|
+
"""
|
77
|
+
|
78
|
+
@functools.wraps(f)
|
79
|
+
def wrapper(*args, **kwargs):
|
80
|
+
start_time = time.time()
|
81
|
+
try:
|
82
|
+
result = f(*args, **kwargs)
|
83
|
+
execution_time = time.time() - start_time
|
84
|
+
|
85
|
+
# Only show timing in debug mode or for slow operations
|
86
|
+
if execution_time > 1.0: # Show for operations > 1 second
|
87
|
+
console.print(f"[dim]⏱️ Completed in {execution_time:.2f}s[/dim]")
|
88
|
+
|
89
|
+
return result
|
90
|
+
except Exception as e:
|
91
|
+
execution_time = time.time() - start_time
|
92
|
+
console.print(f"[red]❌ Failed after {execution_time:.2f}s: {e}[/red]")
|
93
|
+
raise
|
94
|
+
|
95
|
+
return wrapper
|
96
|
+
|
97
|
+
|
98
|
+
def error_handler(f):
|
99
|
+
"""
|
100
|
+
Common error handling decorator for consistent error reporting.
|
101
|
+
|
102
|
+
Provides enterprise-grade error handling with:
|
103
|
+
- Rich formatting for better UX
|
104
|
+
- Consistent error message structure
|
105
|
+
- Debug information when enabled
|
106
|
+
"""
|
107
|
+
|
108
|
+
@functools.wraps(f)
|
109
|
+
def wrapper(*args, **kwargs):
|
110
|
+
try:
|
111
|
+
return f(*args, **kwargs)
|
112
|
+
except click.ClickException:
|
113
|
+
# Re-raise Click exceptions as-is
|
114
|
+
raise
|
115
|
+
except ImportError as e:
|
116
|
+
console.print(f"[red]❌ Module not available: {e}[/red]")
|
117
|
+
console.print(f"[yellow]💡 This functionality may require additional dependencies[/yellow]")
|
118
|
+
raise click.ClickException("Required module not available")
|
119
|
+
except Exception as e:
|
120
|
+
console.print(f"[red]❌ Unexpected error: {e}[/red]")
|
121
|
+
console.print(f"[yellow]💡 Run with --debug for detailed error information[/yellow]")
|
122
|
+
raise click.ClickException(str(e))
|
123
|
+
|
124
|
+
return wrapper
|
125
|
+
|
126
|
+
|
127
|
+
def require_aws_profile(f):
|
128
|
+
"""
|
129
|
+
Decorator to ensure AWS profile is properly configured.
|
130
|
+
|
131
|
+
Validates that the AWS profile exists and is accessible before
|
132
|
+
executing commands that require AWS API access.
|
133
|
+
"""
|
134
|
+
|
135
|
+
@functools.wraps(f)
|
136
|
+
def wrapper(*args, **kwargs):
|
137
|
+
# Get profile from context or kwargs
|
138
|
+
ctx = click.get_current_context()
|
139
|
+
profile = ctx.obj.get("profile", "default")
|
140
|
+
|
141
|
+
try:
|
142
|
+
import boto3
|
143
|
+
|
144
|
+
# Test profile access
|
145
|
+
session = boto3.Session(profile_name=profile)
|
146
|
+
session.get_credentials()
|
147
|
+
|
148
|
+
return f(*args, **kwargs)
|
149
|
+
except Exception as e:
|
150
|
+
console.print(f"[red]❌ AWS profile '{profile}' not accessible: {e}[/red]")
|
151
|
+
console.print(f"[yellow]💡 Run 'aws configure list-profiles' to see available profiles[/yellow]")
|
152
|
+
raise click.ClickException(f"AWS profile '{profile}' not accessible")
|
153
|
+
|
154
|
+
return wrapper
|
155
|
+
|
156
|
+
|
157
|
+
def enterprise_audit_trail(f):
|
158
|
+
"""
|
159
|
+
Enterprise audit trail decorator for compliance and governance.
|
160
|
+
|
161
|
+
Automatically logs command execution for audit purposes with:
|
162
|
+
- Command name and parameters
|
163
|
+
- User context and timestamp
|
164
|
+
- Execution results and duration
|
165
|
+
"""
|
166
|
+
|
167
|
+
@functools.wraps(f)
|
168
|
+
def wrapper(*args, **kwargs):
|
169
|
+
ctx = click.get_current_context()
|
170
|
+
|
171
|
+
# Log command execution start
|
172
|
+
audit_data = {
|
173
|
+
"command": ctx.command.name,
|
174
|
+
"profile": ctx.obj.get("profile", "default"),
|
175
|
+
"region": ctx.obj.get("region", "default"),
|
176
|
+
"dry_run": ctx.obj.get("dry_run", False),
|
177
|
+
"timestamp": time.time(),
|
178
|
+
}
|
179
|
+
|
180
|
+
try:
|
181
|
+
result = f(*args, **kwargs)
|
182
|
+
audit_data["status"] = "success"
|
183
|
+
audit_data["duration"] = time.time() - audit_data["timestamp"]
|
184
|
+
|
185
|
+
# Log successful execution
|
186
|
+
if ctx.obj.get("debug"):
|
187
|
+
console.print(f"[dim]📋 Audit: {audit_data}[/dim]")
|
188
|
+
|
189
|
+
return result
|
190
|
+
except Exception as e:
|
191
|
+
audit_data["status"] = "error"
|
192
|
+
audit_data["error"] = str(e)
|
193
|
+
audit_data["duration"] = time.time() - audit_data["timestamp"]
|
194
|
+
|
195
|
+
# Log failed execution
|
196
|
+
if ctx.obj.get("debug"):
|
197
|
+
console.print(f"[dim]📋 Audit: {audit_data}[/dim]")
|
198
|
+
|
199
|
+
raise
|
200
|
+
|
201
|
+
return wrapper
|
202
|
+
|
203
|
+
|
204
|
+
def rich_progress(description: str = "Processing"):
|
205
|
+
"""
|
206
|
+
Rich progress indicator decorator for long-running operations.
|
207
|
+
|
208
|
+
Args:
|
209
|
+
description: Description text for the progress indicator
|
210
|
+
|
211
|
+
Automatically shows a progress spinner for operations that take time,
|
212
|
+
improving user experience for long-running commands.
|
213
|
+
"""
|
214
|
+
|
215
|
+
def decorator(f):
|
216
|
+
@functools.wraps(f)
|
217
|
+
def wrapper(*args, **kwargs):
|
218
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
219
|
+
|
220
|
+
with Progress(
|
221
|
+
SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console
|
222
|
+
) as progress:
|
223
|
+
task = progress.add_task(description, total=None)
|
224
|
+
|
225
|
+
try:
|
226
|
+
result = f(*args, **kwargs)
|
227
|
+
progress.update(task, description=f"✅ {description} completed")
|
228
|
+
return result
|
229
|
+
except Exception as e:
|
230
|
+
progress.update(task, description=f"❌ {description} failed")
|
231
|
+
raise
|
232
|
+
|
233
|
+
return wrapper
|
234
|
+
|
235
|
+
return decorator
|