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.
Files changed (47) hide show
  1. runbooks/__init__.py +10 -5
  2. runbooks/__init__.py.backup +134 -0
  3. runbooks/__init___optimized.py +110 -0
  4. runbooks/cloudops/base.py +56 -3
  5. runbooks/cloudops/cost_optimizer.py +496 -42
  6. runbooks/common/aws_pricing.py +236 -80
  7. runbooks/common/business_logic.py +485 -0
  8. runbooks/common/cli_decorators.py +219 -0
  9. runbooks/common/error_handling.py +424 -0
  10. runbooks/common/lazy_loader.py +186 -0
  11. runbooks/common/module_cli_base.py +378 -0
  12. runbooks/common/performance_monitoring.py +512 -0
  13. runbooks/common/profile_utils.py +133 -6
  14. runbooks/enterprise/logging.py +30 -2
  15. runbooks/enterprise/validation.py +177 -0
  16. runbooks/finops/README.md +311 -236
  17. runbooks/finops/aws_client.py +1 -1
  18. runbooks/finops/business_case_config.py +723 -19
  19. runbooks/finops/cli.py +136 -0
  20. runbooks/finops/commvault_ec2_analysis.py +25 -9
  21. runbooks/finops/config.py +272 -0
  22. runbooks/finops/dashboard_runner.py +136 -23
  23. runbooks/finops/ebs_cost_optimizer.py +39 -40
  24. runbooks/finops/enhanced_trend_visualization.py +7 -2
  25. runbooks/finops/enterprise_wrappers.py +45 -18
  26. runbooks/finops/finops_dashboard.py +50 -25
  27. runbooks/finops/finops_scenarios.py +22 -7
  28. runbooks/finops/helpers.py +115 -2
  29. runbooks/finops/multi_dashboard.py +7 -5
  30. runbooks/finops/optimizer.py +97 -6
  31. runbooks/finops/scenario_cli_integration.py +247 -0
  32. runbooks/finops/scenarios.py +12 -1
  33. runbooks/finops/unlimited_scenarios.py +393 -0
  34. runbooks/finops/validation_framework.py +19 -7
  35. runbooks/finops/workspaces_analyzer.py +1 -5
  36. runbooks/inventory/mcp_inventory_validator.py +2 -1
  37. runbooks/main.py +132 -94
  38. runbooks/main_final.py +358 -0
  39. runbooks/main_minimal.py +84 -0
  40. runbooks/main_optimized.py +493 -0
  41. runbooks/main_ultra_minimal.py +47 -0
  42. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/METADATA +1 -1
  43. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/RECORD +47 -31
  44. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/WHEEL +0 -0
  45. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/entry_points.txt +0 -0
  46. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/licenses/LICENSE +0 -0
  47. {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,219 @@
1
+ """
2
+ CLI Decorators for runbooks package - Enterprise CLI Standardization
3
+
4
+ Provides standard decorators for common CLI options, eliminating code duplication
5
+ and ensuring consistent user experience across all runbooks modules.
6
+
7
+ Following KISS & DRY principles - enhance existing structure without creating complexity.
8
+ """
9
+
10
+ import click
11
+ from functools import wraps
12
+ from typing import Callable, Any
13
+
14
+
15
+ def common_aws_options(f: Callable) -> Callable:
16
+ """
17
+ Standard AWS options for all runbooks commands.
18
+
19
+ Provides consistent AWS configuration options across all modules:
20
+ - --profile: AWS profile override (highest priority in 3-tier system)
21
+ - --region: AWS region override
22
+ - --dry-run: Safe analysis mode (enterprise default)
23
+
24
+ Usage:
25
+ @common_aws_options
26
+ @click.command()
27
+ def my_command(profile, region, dry_run, **kwargs):
28
+ # Your command logic here
29
+ """
30
+ @click.option(
31
+ '--profile',
32
+ help='AWS profile override (highest priority over environment variables)',
33
+ type=str
34
+ )
35
+ @click.option(
36
+ '--region',
37
+ help='AWS region override (default: us-east-1)',
38
+ type=str,
39
+ default='us-east-1'
40
+ )
41
+ @click.option(
42
+ '--dry-run',
43
+ is_flag=True,
44
+ default=True,
45
+ help='Safe analysis mode - no resource modifications (enterprise default)'
46
+ )
47
+ @wraps(f)
48
+ def wrapper(*args, **kwargs):
49
+ return f(*args, **kwargs)
50
+ return wrapper
51
+
52
+
53
+ def common_output_options(f: Callable) -> Callable:
54
+ """
55
+ Standard output options for all runbooks commands.
56
+
57
+ Provides consistent output formatting and export options:
58
+ - --output-format: JSON, CSV, table, PDF output formats
59
+ - --output-dir: Output directory for generated files
60
+ - --export: Enable multi-format export capability
61
+
62
+ Usage:
63
+ @common_output_options
64
+ @click.command()
65
+ def my_command(output_format, output_dir, export, **kwargs):
66
+ # Your command logic here
67
+ """
68
+ @click.option(
69
+ '--output-format',
70
+ type=click.Choice(['json', 'csv', 'table', 'pdf', 'markdown'], case_sensitive=False),
71
+ default='table',
72
+ help='Output format for results display'
73
+ )
74
+ @click.option(
75
+ '--output-dir',
76
+ default='./awso_evidence',
77
+ help='Directory for generated files and evidence packages',
78
+ type=click.Path()
79
+ )
80
+ @click.option(
81
+ '--export',
82
+ is_flag=True,
83
+ help='Enable multi-format export (CSV, JSON, PDF, HTML)'
84
+ )
85
+ @wraps(f)
86
+ def wrapper(*args, **kwargs):
87
+ return f(*args, **kwargs)
88
+ return wrapper
89
+
90
+
91
+ def mcp_validation_option(f: Callable) -> Callable:
92
+ """
93
+ MCP validation option for cost optimization and inventory modules.
94
+
95
+ Provides MCP (Model Context Protocol) validation capability for enhanced accuracy:
96
+ - --validate: Enable MCP validation with ≥99.5% accuracy target
97
+ - --confidence-threshold: Minimum confidence threshold (default: 99.5%)
98
+
99
+ Usage:
100
+ @mcp_validation_option
101
+ @click.command()
102
+ def my_command(validate, confidence_threshold, **kwargs):
103
+ # Your command logic with MCP validation
104
+ """
105
+ @click.option(
106
+ '--validate',
107
+ is_flag=True,
108
+ help='Enable MCP validation for enhanced accuracy (≥99.5% target)'
109
+ )
110
+ @click.option(
111
+ '--confidence-threshold',
112
+ type=float,
113
+ default=99.5,
114
+ help='Minimum confidence threshold for validation (default: 99.5%%)'
115
+ )
116
+ @wraps(f)
117
+ def wrapper(*args, **kwargs):
118
+ return f(*args, **kwargs)
119
+ return wrapper
120
+
121
+
122
+ def enterprise_options(f: Callable) -> Callable:
123
+ """
124
+ Enterprise-specific options for multi-account operations.
125
+
126
+ Provides enterprise deployment options:
127
+ - --all: Use all available AWS profiles
128
+ - --combine: Combine profiles from same AWS account
129
+ - --approval-required: Require human approval for operations
130
+
131
+ Usage:
132
+ @enterprise_options
133
+ @click.command()
134
+ def my_command(all_profiles, combine, approval_required, **kwargs):
135
+ # Your enterprise command logic
136
+ """
137
+ @click.option(
138
+ '--all',
139
+ 'all_profiles',
140
+ is_flag=True,
141
+ help='Use all available AWS profiles for multi-account operations'
142
+ )
143
+ @click.option(
144
+ '--combine',
145
+ is_flag=True,
146
+ help='Combine profiles from the same AWS account for unified reporting'
147
+ )
148
+ @click.option(
149
+ '--approval-required',
150
+ is_flag=True,
151
+ default=True,
152
+ help='Require human approval for state-changing operations (enterprise default)'
153
+ )
154
+ @wraps(f)
155
+ def wrapper(*args, **kwargs):
156
+ return f(*args, **kwargs)
157
+ return wrapper
158
+
159
+
160
+ def performance_options(f: Callable) -> Callable:
161
+ """
162
+ Performance monitoring options for enterprise operations.
163
+
164
+ Provides performance monitoring and optimization options:
165
+ - --performance-target: Target execution time in seconds
166
+ - --timeout: Maximum execution timeout
167
+ - --parallel: Enable parallel processing where supported
168
+
169
+ Usage:
170
+ @performance_options
171
+ @click.command()
172
+ def my_command(performance_target, timeout, parallel, **kwargs):
173
+ # Your performance-monitored command
174
+ """
175
+ @click.option(
176
+ '--performance-target',
177
+ type=int,
178
+ default=30,
179
+ help='Target execution time in seconds (enterprise default: 30s)'
180
+ )
181
+ @click.option(
182
+ '--timeout',
183
+ type=int,
184
+ default=300,
185
+ help='Maximum execution timeout in seconds (default: 5 minutes)'
186
+ )
187
+ @click.option(
188
+ '--parallel',
189
+ is_flag=True,
190
+ help='Enable parallel processing for multi-resource operations'
191
+ )
192
+ @wraps(f)
193
+ def wrapper(*args, **kwargs):
194
+ return f(*args, **kwargs)
195
+ return wrapper
196
+
197
+
198
+ def all_standard_options(f: Callable) -> Callable:
199
+ """
200
+ Convenience decorator applying all standard options.
201
+
202
+ Combines common_aws_options, common_output_options, mcp_validation_option,
203
+ enterprise_options, and performance_options for comprehensive CLI commands.
204
+
205
+ Usage:
206
+ @all_standard_options
207
+ @click.command()
208
+ def comprehensive_command(**kwargs):
209
+ # Command with all standard options available
210
+ """
211
+ @performance_options
212
+ @enterprise_options
213
+ @mcp_validation_option
214
+ @common_output_options
215
+ @common_aws_options
216
+ @wraps(f)
217
+ def wrapper(*args, **kwargs):
218
+ return f(*args, **kwargs)
219
+ return wrapper
@@ -0,0 +1,424 @@
1
+ """
2
+ Error Handling Enhancement for runbooks package - Enterprise Error Management
3
+
4
+ Provides standardized error handling decorators and utilities that build upon the existing
5
+ enhanced_exception_handler.py infrastructure while adding commonly needed patterns.
6
+
7
+ Following KISS & DRY principles - enhance existing structure with practical decorators.
8
+ """
9
+
10
+ import sys
11
+ import time
12
+ from functools import wraps
13
+ from typing import Callable, Dict, Any, Optional
14
+
15
+ from botocore.exceptions import ClientError, NoCredentialsError, PartialCredentialsError, ProfileNotFound
16
+
17
+ from .rich_utils import print_error, print_warning, print_info, print_success, console
18
+ from .enhanced_exception_handler import (
19
+ EnterpriseExceptionHandler,
20
+ ErrorContext,
21
+ create_exception_handler,
22
+ enhanced_error_handling
23
+ )
24
+
25
+
26
+ def handle_aws_errors(module_name: str = "runbooks", enable_recovery: bool = True):
27
+ """
28
+ Decorator for standardized AWS error handling with Rich CLI formatting.
29
+
30
+ Provides consistent error handling across all runbooks modules with:
31
+ - AWS-specific error classification and guidance
32
+ - Profile override recommendations
33
+ - Rich CLI formatted error messages
34
+ - Automatic recovery suggestions
35
+
36
+ Args:
37
+ module_name: Name of the module using this decorator
38
+ enable_recovery: Enable interactive error recovery workflows
39
+
40
+ Usage:
41
+ @handle_aws_errors(module_name="finops")
42
+ def my_aws_operation(profile=None, region=None, **kwargs):
43
+ # Your AWS operation code here
44
+ """
45
+ def decorator(f: Callable) -> Callable:
46
+ @wraps(f)
47
+ def wrapper(*args, **kwargs):
48
+ # Extract common parameters for error context
49
+ profile = kwargs.get('profile')
50
+ region = kwargs.get('region', 'us-east-1')
51
+ operation = kwargs.get('operation', f.__name__)
52
+
53
+ # Create error context
54
+ context = ErrorContext(
55
+ module_name=module_name,
56
+ operation=operation,
57
+ aws_profile=profile,
58
+ aws_region=region,
59
+ user_context=kwargs
60
+ )
61
+
62
+ # Create exception handler
63
+ handler = create_exception_handler(module_name, enable_rich_output=True)
64
+
65
+ try:
66
+ return f(*args, **kwargs)
67
+
68
+ except ClientError as e:
69
+ error_code = e.response.get('Error', {}).get('Code', 'Unknown')
70
+ service = e.operation_name if hasattr(e, 'operation_name') else 'AWS'
71
+
72
+ # Handle specific AWS errors with targeted guidance
73
+ if error_code == 'ExpiredToken':
74
+ print_error("AWS SSO token expired")
75
+ profile_name = profile or "your-profile"
76
+ print_info(f"Run: [bold green]aws sso login --profile {profile_name}[/]")
77
+ sys.exit(1)
78
+
79
+ elif error_code in ['AccessDenied', 'UnauthorizedOperation', 'Forbidden']:
80
+ print_error(f"Access denied: {e.response['Error']['Message']}")
81
+ print_warning("Check IAM permissions for this operation")
82
+
83
+ # Provide profile recommendations
84
+ if operation in ['finops', 'cost-analysis']:
85
+ print_info("Try using billing profile: [bold green]--profile BILLING_PROFILE[/]")
86
+ elif operation in ['inventory', 'organizations']:
87
+ print_info("Try using management profile: [bold green]--profile MANAGEMENT_PROFILE[/]")
88
+ elif operation in ['operate', 'resource-management']:
89
+ print_info("Try using ops profile: [bold green]--profile CENTRALISED_OPS_PROFILE[/]")
90
+
91
+ sys.exit(1)
92
+
93
+ elif error_code in ['Throttling', 'ThrottlingException', 'RequestLimitExceeded']:
94
+ print_warning(f"AWS API throttling detected: {error_code}")
95
+ print_info("Implementing automatic retry with backoff...")
96
+ time.sleep(2) # Basic backoff
97
+ return f(*args, **kwargs) # Retry once
98
+
99
+ else:
100
+ # Use enterprise exception handler for complex cases
101
+ enhanced_error = handler.handle_aws_error(e, context, operation)
102
+ if enable_recovery and enhanced_error.retry_possible:
103
+ handler.create_error_recovery_workflow(enhanced_error, interactive=False)
104
+ sys.exit(1)
105
+
106
+ except (NoCredentialsError, PartialCredentialsError, ProfileNotFound) as e:
107
+ enhanced_error = handler.handle_credentials_error(e, context)
108
+ if enable_recovery:
109
+ handler.create_error_recovery_workflow(enhanced_error, interactive=True)
110
+ sys.exit(1)
111
+
112
+ except ConnectionError as e:
113
+ print_error(f"Network connection failed: {str(e)}")
114
+ print_info("Check your internet connection and try again")
115
+ sys.exit(1)
116
+
117
+ except Exception as e:
118
+ print_error(f"Unexpected error in {operation}: {str(e)}")
119
+ if kwargs.get('debug') or kwargs.get('verbose'):
120
+ console.print_exception()
121
+ sys.exit(1)
122
+
123
+ return wrapper
124
+ return decorator
125
+
126
+
127
+ def handle_performance_errors(target_seconds: int = 30, module_name: str = "runbooks"):
128
+ """
129
+ Decorator for performance monitoring and error handling.
130
+
131
+ Monitors operation execution time and provides performance guidance
132
+ when operations exceed enterprise targets.
133
+
134
+ Args:
135
+ target_seconds: Target execution time in seconds
136
+ module_name: Name of the module for error context
137
+
138
+ Usage:
139
+ @handle_performance_errors(target_seconds=15, module_name="finops")
140
+ def my_operation(**kwargs):
141
+ # Your operation code here
142
+ """
143
+ def decorator(f: Callable) -> Callable:
144
+ @wraps(f)
145
+ def wrapper(*args, **kwargs):
146
+ start_time = time.time()
147
+ operation = kwargs.get('operation', f.__name__)
148
+
149
+ try:
150
+ result = f(*args, **kwargs)
151
+ execution_time = time.time() - start_time
152
+
153
+ # Performance feedback
154
+ if execution_time <= target_seconds:
155
+ print_success(f"⚡ Performance: {execution_time:.1f}s (target: <{target_seconds}s)")
156
+ else:
157
+ print_warning(f"⚠️ Performance: {execution_time:.1f}s (exceeded {target_seconds}s target)")
158
+
159
+ # Provide optimization suggestions
160
+ if execution_time > target_seconds * 2: # Significantly exceeded
161
+ print_info("Performance optimization suggestions:")
162
+ print_info(f" • Consider using --parallel for {operation}")
163
+ print_info(" • Try a different AWS region for better performance")
164
+ print_info(" • Check for API throttling or network issues")
165
+
166
+ # Create performance error for enterprise tracking
167
+ context = ErrorContext(
168
+ module_name=module_name,
169
+ operation=operation,
170
+ performance_context={
171
+ 'execution_time': execution_time,
172
+ 'target_seconds': target_seconds,
173
+ 'performance_ratio': execution_time / target_seconds
174
+ }
175
+ )
176
+
177
+ handler = create_exception_handler(module_name)
178
+ handler.handle_performance_error(operation, execution_time, target_seconds, context)
179
+
180
+ return result
181
+
182
+ except Exception as e:
183
+ execution_time = time.time() - start_time
184
+ print_error(f"❌ Operation failed after {execution_time:.1f}s: {str(e)}")
185
+ raise
186
+
187
+ return wrapper
188
+ return decorator
189
+
190
+
191
+ def handle_validation_errors(f: Callable) -> Callable:
192
+ """
193
+ Decorator for data validation error handling.
194
+
195
+ Provides clear guidance for data validation failures with
196
+ suggestions for correction.
197
+
198
+ Usage:
199
+ @handle_validation_errors
200
+ def my_validation_function(data, **kwargs):
201
+ # Your validation code here
202
+ """
203
+ @wraps(f)
204
+ def wrapper(*args, **kwargs):
205
+ try:
206
+ return f(*args, **kwargs)
207
+
208
+ except (ValueError, TypeError) as e:
209
+ error_msg = str(e)
210
+
211
+ if 'profile' in error_msg.lower():
212
+ print_error(f"Profile validation error: {error_msg}")
213
+ print_info("Check available profiles: [bold green]aws configure list-profiles[/]")
214
+
215
+ elif 'region' in error_msg.lower():
216
+ print_error(f"Region validation error: {error_msg}")
217
+ print_info("Use valid AWS region like: [bold green]us-east-1, us-west-2, eu-west-1[/]")
218
+
219
+ elif 'format' in error_msg.lower():
220
+ print_error(f"Format validation error: {error_msg}")
221
+ print_info("Supported formats: [bold green]json, csv, table, pdf, markdown[/]")
222
+
223
+ else:
224
+ print_error(f"Data validation error: {error_msg}")
225
+ print_info("Review input parameters and try again")
226
+
227
+ sys.exit(1)
228
+
229
+ except Exception as e:
230
+ print_error(f"Validation failed: {str(e)}")
231
+ raise
232
+
233
+ return wrapper
234
+
235
+
236
+ def graceful_degradation(fallback_function: Optional[Callable] = None,
237
+ enable_fallback: bool = True):
238
+ """
239
+ Decorator for graceful degradation with fallback operations.
240
+
241
+ Automatically attempts fallback operations when primary operation fails,
242
+ providing seamless user experience with transparent recovery.
243
+
244
+ Args:
245
+ fallback_function: Optional fallback function to use
246
+ enable_fallback: Enable automatic fallback attempts
247
+
248
+ Usage:
249
+ @graceful_degradation(fallback_function=simple_analysis)
250
+ def complex_analysis(**kwargs):
251
+ # Complex operation that might fail
252
+
253
+ # Or with automatic fallback detection
254
+ @graceful_degradation()
255
+ def main_operation(**kwargs):
256
+ # Will attempt fallback_operation if this fails
257
+
258
+ def fallback_operation(**kwargs):
259
+ # Simpler fallback version
260
+ """
261
+ def decorator(f: Callable) -> Callable:
262
+ @wraps(f)
263
+ def wrapper(*args, **kwargs):
264
+ operation = kwargs.get('operation', f.__name__)
265
+
266
+ try:
267
+ print_info(f"🚀 Attempting primary operation: {operation}")
268
+ return f(*args, **kwargs)
269
+
270
+ except Exception as primary_error:
271
+ print_warning(f"⚠️ Primary operation failed: {operation}")
272
+ print_info(f"Error: {str(primary_error)}")
273
+
274
+ if not enable_fallback:
275
+ raise primary_error
276
+
277
+ # Try fallback function if provided
278
+ if fallback_function:
279
+ try:
280
+ print_info(f"🔄 Attempting fallback: {fallback_function.__name__}")
281
+ result = fallback_function(*args, **kwargs)
282
+ print_success(f"✅ Fallback operation succeeded: {fallback_function.__name__}")
283
+ return result
284
+
285
+ except Exception as fallback_error:
286
+ print_error(f"❌ Fallback operation failed: {fallback_function.__name__}")
287
+ print_error(f"Primary error: {str(primary_error)}")
288
+ print_error(f"Fallback error: {str(fallback_error)}")
289
+ raise primary_error
290
+
291
+ # Try to find automatic fallback based on naming convention
292
+ fallback_name = f"fallback_{f.__name__}"
293
+ if hasattr(f.__module__, fallback_name):
294
+ try:
295
+ fallback_func = getattr(f.__module__, fallback_name)
296
+ print_info(f"🔄 Attempting automatic fallback: {fallback_name}")
297
+ result = fallback_func(*args, **kwargs)
298
+ print_success(f"✅ Automatic fallback succeeded: {fallback_name}")
299
+ return result
300
+
301
+ except Exception:
302
+ pass
303
+
304
+ # No fallback available, raise original error
305
+ print_error("❌ No fallback available, operation failed")
306
+ raise primary_error
307
+
308
+ return wrapper
309
+ return decorator
310
+
311
+
312
+ def enterprise_error_context(module_name: str):
313
+ """
314
+ Context manager for enterprise error handling with comprehensive logging.
315
+
316
+ Provides enterprise-grade error handling with audit trails, performance
317
+ monitoring, and comprehensive error analysis.
318
+
319
+ Usage:
320
+ with enterprise_error_context("finops") as ctx:
321
+ ctx.set_operation("cost_analysis")
322
+ ctx.set_profile("BILLING_PROFILE")
323
+ # Your operation code here
324
+ """
325
+ class EnterpriseErrorContext:
326
+ def __init__(self, module_name: str):
327
+ self.module_name = module_name
328
+ self.handler = create_exception_handler(module_name)
329
+ self.context = ErrorContext(module_name=module_name, operation="unknown")
330
+
331
+ def set_operation(self, operation: str):
332
+ self.context.operation = operation
333
+
334
+ def set_profile(self, profile: str):
335
+ self.context.aws_profile = profile
336
+
337
+ def set_region(self, region: str):
338
+ self.context.aws_region = region
339
+
340
+ def add_user_context(self, **kwargs):
341
+ self.context.user_context.update(kwargs)
342
+
343
+ def __enter__(self):
344
+ return self
345
+
346
+ def __exit__(self, exc_type, exc_value, traceback):
347
+ if exc_value is not None:
348
+ enhanced_error = self.handler.handle_exception(
349
+ exc_value,
350
+ self.context,
351
+ {'context_manager': True}
352
+ )
353
+
354
+ # Try recovery for retryable errors
355
+ if enhanced_error.retry_possible:
356
+ recovery_success = self.handler.create_error_recovery_workflow(
357
+ enhanced_error,
358
+ interactive=False
359
+ )
360
+ if recovery_success:
361
+ return True # Suppress exception
362
+
363
+ return False # Let exception propagate
364
+
365
+ return EnterpriseErrorContext(module_name)
366
+
367
+
368
+ # Utility functions for common error scenarios
369
+ def validate_aws_profile(profile: str) -> bool:
370
+ """
371
+ Validate AWS profile exists and is accessible.
372
+
373
+ Args:
374
+ profile: AWS profile name to validate
375
+
376
+ Returns:
377
+ True if profile is valid and accessible
378
+
379
+ Raises:
380
+ SystemExit if profile validation fails
381
+ """
382
+ try:
383
+ import boto3
384
+ session = boto3.Session(profile_name=profile)
385
+ sts = session.client('sts')
386
+ identity = sts.get_caller_identity()
387
+ print_success(f"Profile validation successful: {profile}")
388
+ print_info(f"Account: {identity.get('Account', 'Unknown')}")
389
+ print_info(f"User: {identity.get('Arn', 'Unknown')}")
390
+ return True
391
+
392
+ except ProfileNotFound:
393
+ print_error(f"AWS profile not found: {profile}")
394
+ print_info("Check available profiles: [bold green]aws configure list-profiles[/]")
395
+ sys.exit(1)
396
+
397
+ except Exception as e:
398
+ print_error(f"Profile validation failed: {profile}")
399
+ print_error(f"Error: {str(e)}")
400
+ sys.exit(1)
401
+
402
+
403
+ def check_aws_connectivity(region: str = 'us-east-1') -> bool:
404
+ """
405
+ Check basic AWS connectivity and service availability.
406
+
407
+ Args:
408
+ region: AWS region to test connectivity
409
+
410
+ Returns:
411
+ True if connectivity is successful
412
+ """
413
+ try:
414
+ import boto3
415
+ session = boto3.Session()
416
+ sts = session.client('sts', region_name=region)
417
+ sts.get_caller_identity()
418
+ print_success(f"AWS connectivity verified: {region}")
419
+ return True
420
+
421
+ except Exception as e:
422
+ print_warning(f"AWS connectivity issue: {str(e)}")
423
+ print_info("Check internet connection and AWS service status")
424
+ return False