runbooks 0.7.6__py3-none-any.whl → 0.7.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +1 -1
- runbooks/base.py +5 -1
- runbooks/cfat/__init__.py +8 -4
- runbooks/cfat/assessment/collectors.py +171 -14
- runbooks/cfat/assessment/compliance.py +871 -0
- runbooks/cfat/assessment/runner.py +122 -11
- runbooks/cfat/models.py +6 -2
- runbooks/common/logger.py +14 -0
- runbooks/common/rich_utils.py +451 -0
- runbooks/enterprise/__init__.py +68 -0
- runbooks/enterprise/error_handling.py +411 -0
- runbooks/enterprise/logging.py +439 -0
- runbooks/enterprise/multi_tenant.py +583 -0
- runbooks/finops/README.md +468 -241
- runbooks/finops/__init__.py +39 -3
- runbooks/finops/cli.py +83 -18
- runbooks/finops/cross_validation.py +375 -0
- runbooks/finops/dashboard_runner.py +812 -164
- runbooks/finops/enhanced_dashboard_runner.py +525 -0
- runbooks/finops/finops_dashboard.py +1892 -0
- runbooks/finops/helpers.py +485 -51
- runbooks/finops/optimizer.py +823 -0
- runbooks/finops/tests/__init__.py +19 -0
- runbooks/finops/tests/results_test_finops_dashboard.xml +1 -0
- runbooks/finops/tests/run_comprehensive_tests.py +421 -0
- runbooks/finops/tests/run_tests.py +305 -0
- runbooks/finops/tests/test_finops_dashboard.py +705 -0
- runbooks/finops/tests/test_integration.py +477 -0
- runbooks/finops/tests/test_performance.py +380 -0
- runbooks/finops/tests/test_performance_benchmarks.py +500 -0
- runbooks/finops/tests/test_reference_images_validation.py +867 -0
- runbooks/finops/tests/test_single_account_features.py +715 -0
- runbooks/finops/tests/validate_test_suite.py +220 -0
- runbooks/finops/types.py +1 -1
- runbooks/hitl/enhanced_workflow_engine.py +725 -0
- runbooks/inventory/artifacts/scale-optimize-status.txt +12 -0
- runbooks/inventory/collectors/aws_comprehensive.py +442 -0
- runbooks/inventory/collectors/enterprise_scale.py +281 -0
- runbooks/inventory/core/collector.py +172 -13
- runbooks/inventory/discovery.md +1 -1
- runbooks/inventory/list_ec2_instances.py +18 -20
- runbooks/inventory/list_ssm_parameters.py +31 -3
- runbooks/inventory/organizations_discovery.py +1269 -0
- runbooks/inventory/rich_inventory_display.py +393 -0
- runbooks/inventory/run_on_multi_accounts.py +35 -19
- runbooks/inventory/runbooks.security.report_generator.log +0 -0
- runbooks/inventory/runbooks.security.run_script.log +0 -0
- runbooks/inventory/vpc_flow_analyzer.py +1030 -0
- runbooks/main.py +2215 -119
- runbooks/metrics/dora_metrics_engine.py +599 -0
- runbooks/operate/__init__.py +2 -2
- runbooks/operate/base.py +122 -10
- runbooks/operate/deployment_framework.py +1032 -0
- runbooks/operate/deployment_validator.py +853 -0
- runbooks/operate/dynamodb_operations.py +10 -6
- runbooks/operate/ec2_operations.py +319 -11
- runbooks/operate/executive_dashboard.py +779 -0
- runbooks/operate/mcp_integration.py +750 -0
- runbooks/operate/nat_gateway_operations.py +1120 -0
- runbooks/operate/networking_cost_heatmap.py +685 -0
- runbooks/operate/privatelink_operations.py +940 -0
- runbooks/operate/s3_operations.py +10 -6
- runbooks/operate/vpc_endpoints.py +644 -0
- runbooks/operate/vpc_operations.py +1038 -0
- runbooks/remediation/__init__.py +2 -2
- runbooks/remediation/acm_remediation.py +1 -1
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/cloudtrail_remediation.py +1 -1
- runbooks/remediation/cognito_remediation.py +1 -1
- runbooks/remediation/dynamodb_remediation.py +1 -1
- runbooks/remediation/ec2_remediation.py +1 -1
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -1
- runbooks/remediation/kms_enable_key_rotation.py +1 -1
- runbooks/remediation/kms_remediation.py +1 -1
- runbooks/remediation/lambda_remediation.py +1 -1
- runbooks/remediation/multi_account.py +1 -1
- runbooks/remediation/rds_remediation.py +1 -1
- runbooks/remediation/s3_block_public_access.py +1 -1
- runbooks/remediation/s3_enable_access_logging.py +1 -1
- runbooks/remediation/s3_encryption.py +1 -1
- runbooks/remediation/s3_remediation.py +1 -1
- runbooks/remediation/vpc_remediation.py +475 -0
- runbooks/security/__init__.py +3 -1
- runbooks/security/compliance_automation.py +632 -0
- runbooks/security/report_generator.py +10 -0
- runbooks/security/run_script.py +31 -5
- runbooks/security/security_baseline_tester.py +169 -30
- runbooks/security/security_export.py +477 -0
- runbooks/validation/__init__.py +10 -0
- runbooks/validation/benchmark.py +484 -0
- runbooks/validation/cli.py +356 -0
- runbooks/validation/mcp_validator.py +768 -0
- runbooks/vpc/__init__.py +38 -0
- runbooks/vpc/config.py +212 -0
- runbooks/vpc/cost_engine.py +347 -0
- runbooks/vpc/heatmap_engine.py +605 -0
- runbooks/vpc/manager_interface.py +634 -0
- runbooks/vpc/networking_wrapper.py +1260 -0
- runbooks/vpc/rich_formatters.py +679 -0
- runbooks/vpc/tests/__init__.py +5 -0
- runbooks/vpc/tests/conftest.py +356 -0
- runbooks/vpc/tests/test_cli_integration.py +530 -0
- runbooks/vpc/tests/test_config.py +458 -0
- runbooks/vpc/tests/test_cost_engine.py +479 -0
- runbooks/vpc/tests/test_networking_wrapper.py +512 -0
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/METADATA +40 -12
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/RECORD +111 -50
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/WHEEL +0 -0
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/entry_points.txt +0 -0
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,356 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
MCP Validation CLI - Enterprise Command Line Interface
|
4
|
+
|
5
|
+
Provides command-line access to MCP validation framework with enterprise features:
|
6
|
+
- Comprehensive validation across all critical operations
|
7
|
+
- Real-time progress monitoring with Rich UI
|
8
|
+
- Detailed reporting and recommendations
|
9
|
+
- Performance benchmarking with <30s target
|
10
|
+
- Multi-profile AWS integration
|
11
|
+
|
12
|
+
Usage:
|
13
|
+
python -m runbooks.validation.cli validate-all
|
14
|
+
python -m runbooks.validation.cli validate-costs --profile billing
|
15
|
+
python -m runbooks.validation.cli benchmark --target-accuracy 99.5
|
16
|
+
"""
|
17
|
+
|
18
|
+
import asyncio
|
19
|
+
import sys
|
20
|
+
from pathlib import Path
|
21
|
+
from typing import Optional, List
|
22
|
+
import click
|
23
|
+
from rich.console import Console
|
24
|
+
from rich.panel import Panel
|
25
|
+
from rich.table import Table
|
26
|
+
from rich import box
|
27
|
+
|
28
|
+
from .mcp_validator import MCPValidator, ValidationStatus
|
29
|
+
|
30
|
+
console = Console()
|
31
|
+
|
32
|
+
@click.group()
|
33
|
+
@click.version_option(version="1.0.0", prog_name="MCP Validator")
|
34
|
+
def cli():
|
35
|
+
"""Enterprise MCP Validation Framework - 99.5% Accuracy Target"""
|
36
|
+
pass
|
37
|
+
|
38
|
+
@cli.command()
|
39
|
+
@click.option('--tolerance', default=5.0, help='Tolerance percentage for variance detection')
|
40
|
+
@click.option('--performance-target', default=30.0, help='Performance target in seconds')
|
41
|
+
@click.option('--save-report', is_flag=True, help='Save detailed report to artifacts')
|
42
|
+
@click.option('--profile', help='AWS profile override')
|
43
|
+
def validate_all(tolerance: float, performance_target: float, save_report: bool, profile: Optional[str]):
|
44
|
+
"""Run comprehensive validation across all critical operations."""
|
45
|
+
|
46
|
+
console.print(Panel(
|
47
|
+
"[bold blue]Enterprise MCP Validation Framework[/bold blue]\n"
|
48
|
+
f"Target Accuracy: 99.5% | Tolerance: ±{tolerance}% | Performance: <{performance_target}s",
|
49
|
+
title="MCP Validator"
|
50
|
+
))
|
51
|
+
|
52
|
+
# Initialize validator
|
53
|
+
profiles = None
|
54
|
+
if profile:
|
55
|
+
profiles = {
|
56
|
+
'billing': profile,
|
57
|
+
'management': profile,
|
58
|
+
'centralised_ops': profile,
|
59
|
+
'single_aws': profile
|
60
|
+
}
|
61
|
+
|
62
|
+
validator = MCPValidator(
|
63
|
+
profiles=profiles,
|
64
|
+
tolerance_percentage=tolerance,
|
65
|
+
performance_target_seconds=performance_target
|
66
|
+
)
|
67
|
+
|
68
|
+
# Run validation
|
69
|
+
try:
|
70
|
+
report = asyncio.run(validator.validate_all_operations())
|
71
|
+
|
72
|
+
# Display results
|
73
|
+
validator.display_validation_report(report)
|
74
|
+
|
75
|
+
# Exit code based on results
|
76
|
+
if report.overall_accuracy >= 99.5:
|
77
|
+
console.print("[bold green]✅ Validation PASSED - Deploy with confidence[/bold green]")
|
78
|
+
sys.exit(0)
|
79
|
+
elif report.overall_accuracy >= 95.0:
|
80
|
+
console.print("[bold yellow]⚠️ Validation WARNING - Review before deployment[/bold yellow]")
|
81
|
+
sys.exit(1)
|
82
|
+
else:
|
83
|
+
console.print("[bold red]❌ Validation FAILED - Address issues before deployment[/bold red]")
|
84
|
+
sys.exit(2)
|
85
|
+
|
86
|
+
except Exception as e:
|
87
|
+
console.print(f"[bold red]Error running validation: {e}[/bold red]")
|
88
|
+
sys.exit(3)
|
89
|
+
|
90
|
+
@cli.command()
|
91
|
+
@click.option('--profile', default='ams-admin-Billing-ReadOnlyAccess-909135376185', help='AWS billing profile')
|
92
|
+
@click.option('--tolerance', default=5.0, help='Cost variance tolerance percentage')
|
93
|
+
def validate_costs(profile: str, tolerance: float):
|
94
|
+
"""Validate Cost Explorer data accuracy."""
|
95
|
+
|
96
|
+
console.print(Panel(
|
97
|
+
f"[bold cyan]Cost Explorer Validation[/bold cyan]\n"
|
98
|
+
f"Profile: {profile}\nTolerance: ±{tolerance}%",
|
99
|
+
title="Cost Validation"
|
100
|
+
))
|
101
|
+
|
102
|
+
validator = MCPValidator(
|
103
|
+
profiles={'billing': profile},
|
104
|
+
tolerance_percentage=tolerance
|
105
|
+
)
|
106
|
+
|
107
|
+
try:
|
108
|
+
result = asyncio.run(validator.validate_cost_explorer())
|
109
|
+
|
110
|
+
# Display result
|
111
|
+
status_color = "green" if result.status == ValidationStatus.PASSED else "red"
|
112
|
+
|
113
|
+
table = Table(title="Cost Validation Result", box=box.ROUNDED)
|
114
|
+
table.add_column("Metric", style="cyan")
|
115
|
+
table.add_column("Value", style="bold")
|
116
|
+
|
117
|
+
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
118
|
+
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
119
|
+
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
120
|
+
table.add_row("Timestamp", result.timestamp.strftime("%Y-%m-%d %H:%M:%S"))
|
121
|
+
|
122
|
+
if result.error_message:
|
123
|
+
table.add_row("Error", f"[red]{result.error_message}[/red]")
|
124
|
+
|
125
|
+
console.print(table)
|
126
|
+
|
127
|
+
# Variance details
|
128
|
+
if result.variance_details:
|
129
|
+
console.print(Panel(
|
130
|
+
f"Runbooks Total: {result.variance_details.get('details', {}).get('runbooks_total', 'N/A')}\n"
|
131
|
+
f"MCP Available: {result.variance_details.get('details', {}).get('mcp_available', 'N/A')}",
|
132
|
+
title="Variance Analysis"
|
133
|
+
))
|
134
|
+
|
135
|
+
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
136
|
+
|
137
|
+
except Exception as e:
|
138
|
+
console.print(f"[bold red]Error validating costs: {e}[/bold red]")
|
139
|
+
sys.exit(3)
|
140
|
+
|
141
|
+
@cli.command()
|
142
|
+
@click.option('--profile', default='ams-admin-ReadOnlyAccess-909135376185', help='AWS management profile')
|
143
|
+
def validate_organizations(profile: str):
|
144
|
+
"""Validate Organizations API data accuracy."""
|
145
|
+
|
146
|
+
console.print(Panel(
|
147
|
+
f"[bold cyan]Organizations Validation[/bold cyan]\n"
|
148
|
+
f"Profile: {profile}",
|
149
|
+
title="Organizations Validation"
|
150
|
+
))
|
151
|
+
|
152
|
+
validator = MCPValidator(profiles={'management': profile})
|
153
|
+
|
154
|
+
try:
|
155
|
+
result = asyncio.run(validator.validate_organizations_data())
|
156
|
+
|
157
|
+
# Display result
|
158
|
+
status_color = "green" if result.status == ValidationStatus.PASSED else "red"
|
159
|
+
|
160
|
+
table = Table(title="Organizations Validation Result", box=box.ROUNDED)
|
161
|
+
table.add_column("Metric", style="cyan")
|
162
|
+
table.add_column("Value", style="bold")
|
163
|
+
|
164
|
+
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
165
|
+
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
166
|
+
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
167
|
+
|
168
|
+
if result.variance_details:
|
169
|
+
details = result.variance_details.get('details', {})
|
170
|
+
table.add_row("Runbooks Accounts", str(details.get('runbooks_accounts', 'N/A')))
|
171
|
+
table.add_row("MCP Accounts", str(details.get('mcp_accounts', 'N/A')))
|
172
|
+
|
173
|
+
console.print(table)
|
174
|
+
|
175
|
+
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
176
|
+
|
177
|
+
except Exception as e:
|
178
|
+
console.print(f"[bold red]Error validating organizations: {e}[/bold red]")
|
179
|
+
sys.exit(3)
|
180
|
+
|
181
|
+
@cli.command()
|
182
|
+
@click.option('--target-accuracy', default=99.5, help='Target accuracy percentage')
|
183
|
+
@click.option('--iterations', default=5, help='Number of benchmark iterations')
|
184
|
+
@click.option('--performance-target', default=30.0, help='Performance target in seconds')
|
185
|
+
def benchmark(target_accuracy: float, iterations: int, performance_target: float):
|
186
|
+
"""Run performance benchmark for MCP validation framework."""
|
187
|
+
|
188
|
+
console.print(Panel(
|
189
|
+
f"[bold magenta]MCP Validation Benchmark[/bold magenta]\n"
|
190
|
+
f"Target Accuracy: {target_accuracy}%\n"
|
191
|
+
f"Iterations: {iterations}\n"
|
192
|
+
f"Performance Target: <{performance_target}s",
|
193
|
+
title="Benchmark Suite"
|
194
|
+
))
|
195
|
+
|
196
|
+
validator = MCPValidator(performance_target_seconds=performance_target)
|
197
|
+
|
198
|
+
results = []
|
199
|
+
|
200
|
+
try:
|
201
|
+
for i in range(iterations):
|
202
|
+
console.print(f"\n[bold cyan]Iteration {i+1}/{iterations}[/bold cyan]")
|
203
|
+
|
204
|
+
report = asyncio.run(validator.validate_all_operations())
|
205
|
+
results.append(report)
|
206
|
+
|
207
|
+
console.print(f"Accuracy: {report.overall_accuracy:.1f}% | "
|
208
|
+
f"Time: {report.execution_time:.1f}s | "
|
209
|
+
f"Passed: {report.passed_validations}/{report.total_validations}")
|
210
|
+
|
211
|
+
# Benchmark summary
|
212
|
+
avg_accuracy = sum(r.overall_accuracy for r in results) / len(results)
|
213
|
+
avg_time = sum(r.execution_time for r in results) / len(results)
|
214
|
+
success_rate = len([r for r in results if r.overall_accuracy >= target_accuracy]) / len(results) * 100
|
215
|
+
|
216
|
+
summary_table = Table(title="Benchmark Summary", box=box.ROUNDED)
|
217
|
+
summary_table.add_column("Metric", style="cyan")
|
218
|
+
summary_table.add_column("Value", style="bold")
|
219
|
+
|
220
|
+
summary_table.add_row("Average Accuracy", f"{avg_accuracy:.2f}%")
|
221
|
+
summary_table.add_row("Average Time", f"{avg_time:.2f}s")
|
222
|
+
summary_table.add_row("Success Rate", f"{success_rate:.1f}%")
|
223
|
+
summary_table.add_row("Target Met", "✅ YES" if avg_accuracy >= target_accuracy else "❌ NO")
|
224
|
+
summary_table.add_row("Performance Met", "✅ YES" if avg_time <= performance_target else "❌ NO")
|
225
|
+
|
226
|
+
console.print(summary_table)
|
227
|
+
|
228
|
+
# Performance analysis
|
229
|
+
if avg_accuracy >= target_accuracy and avg_time <= performance_target:
|
230
|
+
console.print("[bold green]🎯 Benchmark PASSED - Production ready[/bold green]")
|
231
|
+
sys.exit(0)
|
232
|
+
else:
|
233
|
+
console.print("[bold red]⚠️ Benchmark FAILED - Optimization needed[/bold red]")
|
234
|
+
sys.exit(1)
|
235
|
+
|
236
|
+
except Exception as e:
|
237
|
+
console.print(f"[bold red]Benchmark error: {e}[/bold red]")
|
238
|
+
sys.exit(3)
|
239
|
+
|
240
|
+
@cli.command()
|
241
|
+
@click.option('--operation',
|
242
|
+
type=click.Choice(['costs', 'organizations', 'ec2', 'security', 'vpc']),
|
243
|
+
help='Specific operation to validate')
|
244
|
+
@click.option('--profile', help='AWS profile to use')
|
245
|
+
@click.option('--tolerance', default=5.0, help='Tolerance percentage')
|
246
|
+
def validate_single(operation: str, profile: Optional[str], tolerance: float):
|
247
|
+
"""Validate a single operation."""
|
248
|
+
|
249
|
+
console.print(Panel(
|
250
|
+
f"[bold cyan]Single Operation Validation[/bold cyan]\n"
|
251
|
+
f"Operation: {operation.title()}\n"
|
252
|
+
f"Profile: {profile or 'default'}\n"
|
253
|
+
f"Tolerance: ±{tolerance}%",
|
254
|
+
title="Single Validation"
|
255
|
+
))
|
256
|
+
|
257
|
+
validator = MCPValidator(tolerance_percentage=tolerance)
|
258
|
+
|
259
|
+
try:
|
260
|
+
# Map operations to methods
|
261
|
+
operation_map = {
|
262
|
+
'costs': validator.validate_cost_explorer,
|
263
|
+
'organizations': validator.validate_organizations_data,
|
264
|
+
'ec2': validator.validate_ec2_inventory,
|
265
|
+
'security': validator.validate_security_baseline,
|
266
|
+
'vpc': validator.validate_vpc_analysis
|
267
|
+
}
|
268
|
+
|
269
|
+
if operation not in operation_map:
|
270
|
+
console.print(f"[red]Unknown operation: {operation}[/red]")
|
271
|
+
sys.exit(1)
|
272
|
+
|
273
|
+
result = asyncio.run(operation_map[operation]())
|
274
|
+
|
275
|
+
# Display result
|
276
|
+
status_color = {
|
277
|
+
ValidationStatus.PASSED: "green",
|
278
|
+
ValidationStatus.WARNING: "yellow",
|
279
|
+
ValidationStatus.FAILED: "red",
|
280
|
+
ValidationStatus.ERROR: "red",
|
281
|
+
ValidationStatus.TIMEOUT: "red"
|
282
|
+
}[result.status]
|
283
|
+
|
284
|
+
table = Table(title=f"{operation.title()} Validation Result", box=box.ROUNDED)
|
285
|
+
table.add_column("Metric", style="cyan")
|
286
|
+
table.add_column("Value", style="bold")
|
287
|
+
|
288
|
+
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
289
|
+
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
290
|
+
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
291
|
+
table.add_row("Timestamp", result.timestamp.strftime("%Y-%m-%d %H:%M:%S"))
|
292
|
+
|
293
|
+
if result.error_message:
|
294
|
+
table.add_row("Error", f"[red]{result.error_message}[/red]")
|
295
|
+
|
296
|
+
console.print(table)
|
297
|
+
|
298
|
+
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
299
|
+
|
300
|
+
except Exception as e:
|
301
|
+
console.print(f"[bold red]Error validating {operation}: {e}[/bold red]")
|
302
|
+
sys.exit(3)
|
303
|
+
|
304
|
+
@cli.command()
|
305
|
+
def status():
|
306
|
+
"""Show MCP validation framework status."""
|
307
|
+
|
308
|
+
table = Table(title="MCP Validation Framework Status", box=box.ROUNDED)
|
309
|
+
table.add_column("Component", style="cyan")
|
310
|
+
table.add_column("Status", style="bold")
|
311
|
+
table.add_column("Details")
|
312
|
+
|
313
|
+
# Check MCP integration
|
314
|
+
try:
|
315
|
+
from notebooks.mcp_integration import MCPIntegrationManager
|
316
|
+
table.add_row("MCP Integration", "[green]✅ Available[/green]", "Ready for validation")
|
317
|
+
except ImportError:
|
318
|
+
table.add_row("MCP Integration", "[red]❌ Unavailable[/red]", "Install MCP dependencies")
|
319
|
+
|
320
|
+
# Check AWS profiles
|
321
|
+
profiles = [
|
322
|
+
'ams-admin-Billing-ReadOnlyAccess-909135376185',
|
323
|
+
'ams-admin-ReadOnlyAccess-909135376185',
|
324
|
+
'ams-centralised-ops-ReadOnlyAccess-335083429030',
|
325
|
+
'ams-shared-services-non-prod-ReadOnlyAccess-499201730520'
|
326
|
+
]
|
327
|
+
|
328
|
+
for profile in profiles:
|
329
|
+
try:
|
330
|
+
import boto3
|
331
|
+
session = boto3.Session(profile_name=profile)
|
332
|
+
sts = session.client('sts')
|
333
|
+
identity = sts.get_caller_identity()
|
334
|
+
table.add_row(f"Profile: {profile[:20]}...", "[green]✅ Valid[/green]", f"Account: {identity['Account']}")
|
335
|
+
except Exception as e:
|
336
|
+
table.add_row(f"Profile: {profile[:20]}...", "[red]❌ Invalid[/red]", str(e)[:50])
|
337
|
+
|
338
|
+
# Check validation components
|
339
|
+
components = [
|
340
|
+
('Cost Explorer', 'runbooks.finops'),
|
341
|
+
('Organizations', 'runbooks.inventory'),
|
342
|
+
('Security', 'runbooks.security'),
|
343
|
+
('VPC Analysis', 'runbooks.vpc')
|
344
|
+
]
|
345
|
+
|
346
|
+
for name, module in components:
|
347
|
+
try:
|
348
|
+
__import__(module)
|
349
|
+
table.add_row(f"Component: {name}", "[green]✅ Ready[/green]", "Module loaded")
|
350
|
+
except ImportError:
|
351
|
+
table.add_row(f"Component: {name}", "[red]❌ Missing[/red]", "Module not available")
|
352
|
+
|
353
|
+
console.print(table)
|
354
|
+
|
355
|
+
if __name__ == '__main__':
|
356
|
+
cli()
|