runbooks 0.7.9__py3-none-any.whl → 0.9.1__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/cfat/README.md +12 -1
- runbooks/cfat/__init__.py +1 -1
- runbooks/cfat/assessment/compliance.py +4 -1
- runbooks/cfat/assessment/runner.py +42 -34
- runbooks/cfat/models.py +1 -1
- runbooks/cloudops/__init__.py +123 -0
- runbooks/cloudops/base.py +385 -0
- runbooks/cloudops/cost_optimizer.py +811 -0
- runbooks/cloudops/infrastructure_optimizer.py +29 -0
- runbooks/cloudops/interfaces.py +828 -0
- runbooks/cloudops/lifecycle_manager.py +29 -0
- runbooks/cloudops/mcp_cost_validation.py +678 -0
- runbooks/cloudops/models.py +251 -0
- runbooks/cloudops/monitoring_automation.py +29 -0
- runbooks/cloudops/notebook_framework.py +676 -0
- runbooks/cloudops/security_enforcer.py +449 -0
- runbooks/common/__init__.py +152 -0
- runbooks/common/accuracy_validator.py +1039 -0
- runbooks/common/context_logger.py +440 -0
- runbooks/common/cross_module_integration.py +594 -0
- runbooks/common/enhanced_exception_handler.py +1108 -0
- runbooks/common/enterprise_audit_integration.py +634 -0
- runbooks/common/mcp_cost_explorer_integration.py +900 -0
- runbooks/common/mcp_integration.py +548 -0
- runbooks/common/performance_monitor.py +387 -0
- runbooks/common/profile_utils.py +216 -0
- runbooks/common/rich_utils.py +172 -1
- runbooks/feedback/user_feedback_collector.py +440 -0
- runbooks/finops/README.md +377 -458
- runbooks/finops/__init__.py +4 -21
- runbooks/finops/account_resolver.py +279 -0
- runbooks/finops/accuracy_cross_validator.py +638 -0
- runbooks/finops/aws_client.py +721 -36
- runbooks/finops/budget_integration.py +313 -0
- runbooks/finops/cli.py +59 -5
- runbooks/finops/cost_optimizer.py +1340 -0
- runbooks/finops/cost_processor.py +211 -37
- runbooks/finops/dashboard_router.py +900 -0
- runbooks/finops/dashboard_runner.py +990 -232
- runbooks/finops/embedded_mcp_validator.py +288 -0
- runbooks/finops/enhanced_dashboard_runner.py +8 -7
- runbooks/finops/enhanced_progress.py +327 -0
- runbooks/finops/enhanced_trend_visualization.py +423 -0
- runbooks/finops/finops_dashboard.py +184 -1829
- runbooks/finops/helpers.py +509 -196
- runbooks/finops/iam_guidance.py +400 -0
- runbooks/finops/markdown_exporter.py +466 -0
- runbooks/finops/multi_dashboard.py +1502 -0
- runbooks/finops/optimizer.py +15 -15
- runbooks/finops/profile_processor.py +2 -2
- runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/finops/runbooks.security.report_generator.log +0 -0
- runbooks/finops/runbooks.security.run_script.log +0 -0
- runbooks/finops/runbooks.security.security_export.log +0 -0
- runbooks/finops/schemas.py +589 -0
- runbooks/finops/service_mapping.py +195 -0
- runbooks/finops/single_dashboard.py +710 -0
- runbooks/finops/tests/test_reference_images_validation.py +1 -1
- runbooks/inventory/README.md +12 -1
- runbooks/inventory/core/collector.py +157 -29
- runbooks/inventory/list_ec2_instances.py +9 -6
- runbooks/inventory/list_ssm_parameters.py +10 -10
- runbooks/inventory/organizations_discovery.py +210 -164
- runbooks/inventory/rich_inventory_display.py +74 -107
- runbooks/inventory/run_on_multi_accounts.py +13 -13
- runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/inventory/runbooks.security.security_export.log +0 -0
- runbooks/main.py +1371 -240
- runbooks/metrics/dora_metrics_engine.py +711 -17
- runbooks/monitoring/performance_monitor.py +433 -0
- runbooks/operate/README.md +394 -0
- runbooks/operate/base.py +215 -47
- runbooks/operate/ec2_operations.py +435 -5
- runbooks/operate/iam_operations.py +598 -3
- runbooks/operate/privatelink_operations.py +1 -1
- runbooks/operate/rds_operations.py +508 -0
- runbooks/operate/s3_operations.py +508 -0
- runbooks/operate/vpc_endpoints.py +1 -1
- runbooks/remediation/README.md +489 -13
- runbooks/remediation/base.py +5 -3
- runbooks/remediation/commons.py +8 -4
- runbooks/security/ENTERPRISE_SECURITY_FRAMEWORK.md +506 -0
- runbooks/security/README.md +12 -1
- runbooks/security/__init__.py +265 -33
- runbooks/security/cloudops_automation_security_validator.py +1164 -0
- runbooks/security/compliance_automation.py +12 -10
- runbooks/security/compliance_automation_engine.py +1021 -0
- runbooks/security/enterprise_security_framework.py +930 -0
- runbooks/security/enterprise_security_policies.json +293 -0
- runbooks/security/executive_security_dashboard.py +1247 -0
- runbooks/security/integration_test_enterprise_security.py +879 -0
- runbooks/security/module_security_integrator.py +641 -0
- runbooks/security/multi_account_security_controls.py +2254 -0
- runbooks/security/real_time_security_monitor.py +1196 -0
- runbooks/security/report_generator.py +1 -1
- runbooks/security/run_script.py +4 -8
- runbooks/security/security_baseline_tester.py +39 -52
- runbooks/security/security_export.py +99 -120
- runbooks/sre/README.md +472 -0
- runbooks/sre/__init__.py +33 -0
- runbooks/sre/mcp_reliability_engine.py +1049 -0
- runbooks/sre/performance_optimization_engine.py +1032 -0
- runbooks/sre/production_monitoring_framework.py +584 -0
- runbooks/sre/reliability_monitoring_framework.py +1011 -0
- runbooks/validation/__init__.py +2 -2
- runbooks/validation/benchmark.py +154 -149
- runbooks/validation/cli.py +159 -147
- runbooks/validation/mcp_validator.py +291 -248
- runbooks/vpc/README.md +478 -0
- runbooks/vpc/__init__.py +2 -2
- runbooks/vpc/manager_interface.py +366 -351
- runbooks/vpc/networking_wrapper.py +68 -36
- runbooks/vpc/rich_formatters.py +22 -8
- runbooks-0.9.1.dist-info/METADATA +308 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/RECORD +120 -59
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/entry_points.txt +1 -1
- runbooks/finops/cross_validation.py +0 -375
- runbooks-0.7.9.dist-info/METADATA +0 -636
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/WHEEL +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/licenses/LICENSE +0 -0
- {runbooks-0.7.9.dist-info → runbooks-0.9.1.dist-info}/top_level.txt +0 -0
runbooks/validation/cli.py
CHANGED
@@ -18,60 +18,58 @@ Usage:
|
|
18
18
|
import asyncio
|
19
19
|
import sys
|
20
20
|
from pathlib import Path
|
21
|
-
from typing import
|
21
|
+
from typing import List, Optional
|
22
|
+
|
22
23
|
import click
|
24
|
+
from rich import box
|
23
25
|
from rich.console import Console
|
24
26
|
from rich.panel import Panel
|
25
27
|
from rich.table import Table
|
26
|
-
from rich import box
|
27
28
|
|
28
29
|
from .mcp_validator import MCPValidator, ValidationStatus
|
29
30
|
|
30
31
|
console = Console()
|
31
32
|
|
33
|
+
|
32
34
|
@click.group()
|
33
35
|
@click.version_option(version="1.0.0", prog_name="MCP Validator")
|
34
36
|
def cli():
|
35
37
|
"""Enterprise MCP Validation Framework - 99.5% Accuracy Target"""
|
36
38
|
pass
|
37
39
|
|
40
|
+
|
38
41
|
@cli.command()
|
39
|
-
@click.option(
|
40
|
-
@click.option(
|
41
|
-
@click.option(
|
42
|
-
@click.option(
|
42
|
+
@click.option("--tolerance", default=5.0, help="Tolerance percentage for variance detection")
|
43
|
+
@click.option("--performance-target", default=30.0, help="Performance target in seconds")
|
44
|
+
@click.option("--save-report", is_flag=True, help="Save detailed report to artifacts")
|
45
|
+
@click.option("--profile", help="AWS profile override")
|
43
46
|
def validate_all(tolerance: float, performance_target: float, save_report: bool, profile: Optional[str]):
|
44
47
|
"""Run comprehensive validation across all critical operations."""
|
45
|
-
|
46
|
-
console.print(
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
|
49
|
+
console.print(
|
50
|
+
Panel(
|
51
|
+
"[bold blue]Enterprise MCP Validation Framework[/bold blue]\n"
|
52
|
+
f"Target Accuracy: 99.5% | Tolerance: ±{tolerance}% | Performance: <{performance_target}s",
|
53
|
+
title="MCP Validator",
|
54
|
+
)
|
55
|
+
)
|
56
|
+
|
52
57
|
# Initialize validator
|
53
58
|
profiles = None
|
54
59
|
if profile:
|
55
|
-
profiles = {
|
56
|
-
|
57
|
-
'management': profile,
|
58
|
-
'centralised_ops': profile,
|
59
|
-
'single_aws': profile
|
60
|
-
}
|
61
|
-
|
60
|
+
profiles = {"billing": profile, "management": profile, "centralised_ops": profile, "single_aws": profile}
|
61
|
+
|
62
62
|
validator = MCPValidator(
|
63
|
-
profiles=profiles,
|
64
|
-
tolerance_percentage=tolerance,
|
65
|
-
performance_target_seconds=performance_target
|
63
|
+
profiles=profiles, tolerance_percentage=tolerance, performance_target_seconds=performance_target
|
66
64
|
)
|
67
|
-
|
65
|
+
|
68
66
|
# Run validation
|
69
67
|
try:
|
70
68
|
report = asyncio.run(validator.validate_all_operations())
|
71
|
-
|
69
|
+
|
72
70
|
# Display results
|
73
71
|
validator.display_validation_report(report)
|
74
|
-
|
72
|
+
|
75
73
|
# Exit code based on results
|
76
74
|
if report.overall_accuracy >= 99.5:
|
77
75
|
console.print("[bold green]✅ Validation PASSED - Deploy with confidence[/bold green]")
|
@@ -82,149 +80,154 @@ def validate_all(tolerance: float, performance_target: float, save_report: bool,
|
|
82
80
|
else:
|
83
81
|
console.print("[bold red]❌ Validation FAILED - Address issues before deployment[/bold red]")
|
84
82
|
sys.exit(2)
|
85
|
-
|
83
|
+
|
86
84
|
except Exception as e:
|
87
85
|
console.print(f"[bold red]Error running validation: {e}[/bold red]")
|
88
86
|
sys.exit(3)
|
89
87
|
|
88
|
+
|
90
89
|
@cli.command()
|
91
|
-
@click.option(
|
92
|
-
@click.option(
|
90
|
+
@click.option("--profile", default="ams-admin-Billing-ReadOnlyAccess-909135376185", help="AWS billing profile")
|
91
|
+
@click.option("--tolerance", default=5.0, help="Cost variance tolerance percentage")
|
93
92
|
def validate_costs(profile: str, tolerance: float):
|
94
93
|
"""Validate Cost Explorer data accuracy."""
|
95
|
-
|
96
|
-
console.print(
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
validator = MCPValidator(
|
103
|
-
profiles={'billing': profile},
|
104
|
-
tolerance_percentage=tolerance
|
94
|
+
|
95
|
+
console.print(
|
96
|
+
Panel(
|
97
|
+
f"[bold cyan]Cost Explorer Validation[/bold cyan]\nProfile: {profile}\nTolerance: ±{tolerance}%",
|
98
|
+
title="Cost Validation",
|
99
|
+
)
|
105
100
|
)
|
106
|
-
|
101
|
+
|
102
|
+
validator = MCPValidator(profiles={"billing": profile}, tolerance_percentage=tolerance)
|
103
|
+
|
107
104
|
try:
|
108
105
|
result = asyncio.run(validator.validate_cost_explorer())
|
109
|
-
|
106
|
+
|
110
107
|
# Display result
|
111
108
|
status_color = "green" if result.status == ValidationStatus.PASSED else "red"
|
112
|
-
|
109
|
+
|
113
110
|
table = Table(title="Cost Validation Result", box=box.ROUNDED)
|
114
111
|
table.add_column("Metric", style="cyan")
|
115
112
|
table.add_column("Value", style="bold")
|
116
|
-
|
113
|
+
|
117
114
|
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
118
115
|
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
119
116
|
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
120
117
|
table.add_row("Timestamp", result.timestamp.strftime("%Y-%m-%d %H:%M:%S"))
|
121
|
-
|
118
|
+
|
122
119
|
if result.error_message:
|
123
120
|
table.add_row("Error", f"[red]{result.error_message}[/red]")
|
124
|
-
|
121
|
+
|
125
122
|
console.print(table)
|
126
|
-
|
123
|
+
|
127
124
|
# Variance details
|
128
125
|
if result.variance_details:
|
129
|
-
console.print(
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
126
|
+
console.print(
|
127
|
+
Panel(
|
128
|
+
f"Runbooks Total: {result.variance_details.get('details', {}).get('runbooks_total', 'N/A')}\n"
|
129
|
+
f"MCP Available: {result.variance_details.get('details', {}).get('mcp_available', 'N/A')}",
|
130
|
+
title="Variance Analysis",
|
131
|
+
)
|
132
|
+
)
|
133
|
+
|
135
134
|
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
136
|
-
|
135
|
+
|
137
136
|
except Exception as e:
|
138
137
|
console.print(f"[bold red]Error validating costs: {e}[/bold red]")
|
139
138
|
sys.exit(3)
|
140
139
|
|
140
|
+
|
141
141
|
@cli.command()
|
142
|
-
@click.option(
|
142
|
+
@click.option("--profile", default="ams-admin-ReadOnlyAccess-909135376185", help="AWS management profile")
|
143
143
|
def validate_organizations(profile: str):
|
144
144
|
"""Validate Organizations API data accuracy."""
|
145
|
-
|
146
|
-
console.print(
|
147
|
-
f"[bold cyan]Organizations Validation[/bold cyan]\
|
148
|
-
|
149
|
-
|
150
|
-
)
|
151
|
-
|
152
|
-
validator = MCPValidator(profiles={'management': profile})
|
153
|
-
|
145
|
+
|
146
|
+
console.print(
|
147
|
+
Panel(f"[bold cyan]Organizations Validation[/bold cyan]\nProfile: {profile}", title="Organizations Validation")
|
148
|
+
)
|
149
|
+
|
150
|
+
validator = MCPValidator(profiles={"management": profile})
|
151
|
+
|
154
152
|
try:
|
155
153
|
result = asyncio.run(validator.validate_organizations_data())
|
156
|
-
|
154
|
+
|
157
155
|
# Display result
|
158
156
|
status_color = "green" if result.status == ValidationStatus.PASSED else "red"
|
159
|
-
|
157
|
+
|
160
158
|
table = Table(title="Organizations Validation Result", box=box.ROUNDED)
|
161
159
|
table.add_column("Metric", style="cyan")
|
162
160
|
table.add_column("Value", style="bold")
|
163
|
-
|
161
|
+
|
164
162
|
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
165
163
|
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
166
164
|
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
167
|
-
|
165
|
+
|
168
166
|
if result.variance_details:
|
169
|
-
details = result.variance_details.get(
|
170
|
-
table.add_row("Runbooks Accounts", str(details.get(
|
171
|
-
table.add_row("MCP Accounts", str(details.get(
|
172
|
-
|
167
|
+
details = result.variance_details.get("details", {})
|
168
|
+
table.add_row("Runbooks Accounts", str(details.get("runbooks_accounts", "N/A")))
|
169
|
+
table.add_row("MCP Accounts", str(details.get("mcp_accounts", "N/A")))
|
170
|
+
|
173
171
|
console.print(table)
|
174
|
-
|
172
|
+
|
175
173
|
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
176
|
-
|
174
|
+
|
177
175
|
except Exception as e:
|
178
176
|
console.print(f"[bold red]Error validating organizations: {e}[/bold red]")
|
179
177
|
sys.exit(3)
|
180
178
|
|
179
|
+
|
181
180
|
@cli.command()
|
182
|
-
@click.option(
|
183
|
-
@click.option(
|
184
|
-
@click.option(
|
181
|
+
@click.option("--target-accuracy", default=99.5, help="Target accuracy percentage")
|
182
|
+
@click.option("--iterations", default=5, help="Number of benchmark iterations")
|
183
|
+
@click.option("--performance-target", default=30.0, help="Performance target in seconds")
|
185
184
|
def benchmark(target_accuracy: float, iterations: int, performance_target: float):
|
186
185
|
"""Run performance benchmark for MCP validation framework."""
|
187
|
-
|
188
|
-
console.print(
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
186
|
+
|
187
|
+
console.print(
|
188
|
+
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
|
+
|
196
197
|
validator = MCPValidator(performance_target_seconds=performance_target)
|
197
|
-
|
198
|
+
|
198
199
|
results = []
|
199
|
-
|
200
|
+
|
200
201
|
try:
|
201
202
|
for i in range(iterations):
|
202
|
-
console.print(f"\n[bold cyan]Iteration {i+1}/{iterations}[/bold cyan]")
|
203
|
-
|
203
|
+
console.print(f"\n[bold cyan]Iteration {i + 1}/{iterations}[/bold cyan]")
|
204
|
+
|
204
205
|
report = asyncio.run(validator.validate_all_operations())
|
205
206
|
results.append(report)
|
206
|
-
|
207
|
-
console.print(
|
208
|
-
|
209
|
-
|
210
|
-
|
207
|
+
|
208
|
+
console.print(
|
209
|
+
f"Accuracy: {report.overall_accuracy:.1f}% | "
|
210
|
+
f"Time: {report.execution_time:.1f}s | "
|
211
|
+
f"Passed: {report.passed_validations}/{report.total_validations}"
|
212
|
+
)
|
213
|
+
|
211
214
|
# Benchmark summary
|
212
215
|
avg_accuracy = sum(r.overall_accuracy for r in results) / len(results)
|
213
216
|
avg_time = sum(r.execution_time for r in results) / len(results)
|
214
217
|
success_rate = len([r for r in results if r.overall_accuracy >= target_accuracy]) / len(results) * 100
|
215
|
-
|
218
|
+
|
216
219
|
summary_table = Table(title="Benchmark Summary", box=box.ROUNDED)
|
217
220
|
summary_table.add_column("Metric", style="cyan")
|
218
221
|
summary_table.add_column("Value", style="bold")
|
219
|
-
|
222
|
+
|
220
223
|
summary_table.add_row("Average Accuracy", f"{avg_accuracy:.2f}%")
|
221
224
|
summary_table.add_row("Average Time", f"{avg_time:.2f}s")
|
222
225
|
summary_table.add_row("Success Rate", f"{success_rate:.1f}%")
|
223
226
|
summary_table.add_row("Target Met", "✅ YES" if avg_accuracy >= target_accuracy else "❌ NO")
|
224
227
|
summary_table.add_row("Performance Met", "✅ YES" if avg_time <= performance_target else "❌ NO")
|
225
|
-
|
228
|
+
|
226
229
|
console.print(summary_table)
|
227
|
-
|
230
|
+
|
228
231
|
# Performance analysis
|
229
232
|
if avg_accuracy >= target_accuracy and avg_time <= performance_target:
|
230
233
|
console.print("[bold green]🎯 Benchmark PASSED - Production ready[/bold green]")
|
@@ -232,125 +235,134 @@ def benchmark(target_accuracy: float, iterations: int, performance_target: float
|
|
232
235
|
else:
|
233
236
|
console.print("[bold red]⚠️ Benchmark FAILED - Optimization needed[/bold red]")
|
234
237
|
sys.exit(1)
|
235
|
-
|
238
|
+
|
236
239
|
except Exception as e:
|
237
240
|
console.print(f"[bold red]Benchmark error: {e}[/bold red]")
|
238
241
|
sys.exit(3)
|
239
242
|
|
243
|
+
|
240
244
|
@cli.command()
|
241
|
-
@click.option(
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
245
|
+
@click.option(
|
246
|
+
"--operation",
|
247
|
+
type=click.Choice(["costs", "organizations", "ec2", "security", "vpc"]),
|
248
|
+
help="Specific operation to validate",
|
249
|
+
)
|
250
|
+
@click.option("--profile", help="AWS profile to use")
|
251
|
+
@click.option("--tolerance", default=5.0, help="Tolerance percentage")
|
246
252
|
def validate_single(operation: str, profile: Optional[str], tolerance: float):
|
247
253
|
"""Validate a single operation."""
|
248
|
-
|
249
|
-
console.print(
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
254
|
+
|
255
|
+
console.print(
|
256
|
+
Panel(
|
257
|
+
f"[bold cyan]Single Operation Validation[/bold cyan]\n"
|
258
|
+
f"Operation: {operation.title()}\n"
|
259
|
+
f"Profile: {profile or 'default'}\n"
|
260
|
+
f"Tolerance: ±{tolerance}%",
|
261
|
+
title="Single Validation",
|
262
|
+
)
|
263
|
+
)
|
264
|
+
|
257
265
|
validator = MCPValidator(tolerance_percentage=tolerance)
|
258
|
-
|
266
|
+
|
259
267
|
try:
|
260
268
|
# Map operations to methods
|
261
269
|
operation_map = {
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
270
|
+
"costs": validator.validate_cost_explorer,
|
271
|
+
"organizations": validator.validate_organizations_data,
|
272
|
+
"ec2": validator.validate_ec2_inventory,
|
273
|
+
"security": validator.validate_security_baseline,
|
274
|
+
"vpc": validator.validate_vpc_analysis,
|
267
275
|
}
|
268
|
-
|
276
|
+
|
269
277
|
if operation not in operation_map:
|
270
278
|
console.print(f"[red]Unknown operation: {operation}[/red]")
|
271
279
|
sys.exit(1)
|
272
|
-
|
280
|
+
|
273
281
|
result = asyncio.run(operation_map[operation]())
|
274
|
-
|
282
|
+
|
275
283
|
# Display result
|
276
284
|
status_color = {
|
277
285
|
ValidationStatus.PASSED: "green",
|
278
286
|
ValidationStatus.WARNING: "yellow",
|
279
287
|
ValidationStatus.FAILED: "red",
|
280
288
|
ValidationStatus.ERROR: "red",
|
281
|
-
ValidationStatus.TIMEOUT: "red"
|
289
|
+
ValidationStatus.TIMEOUT: "red",
|
282
290
|
}[result.status]
|
283
|
-
|
291
|
+
|
284
292
|
table = Table(title=f"{operation.title()} Validation Result", box=box.ROUNDED)
|
285
293
|
table.add_column("Metric", style="cyan")
|
286
294
|
table.add_column("Value", style="bold")
|
287
|
-
|
295
|
+
|
288
296
|
table.add_row("Status", f"[{status_color}]{result.status.value}[/{status_color}]")
|
289
297
|
table.add_row("Accuracy", f"{result.accuracy_percentage:.2f}%")
|
290
298
|
table.add_row("Execution Time", f"{result.execution_time:.2f}s")
|
291
299
|
table.add_row("Timestamp", result.timestamp.strftime("%Y-%m-%d %H:%M:%S"))
|
292
|
-
|
300
|
+
|
293
301
|
if result.error_message:
|
294
302
|
table.add_row("Error", f"[red]{result.error_message}[/red]")
|
295
|
-
|
303
|
+
|
296
304
|
console.print(table)
|
297
|
-
|
305
|
+
|
298
306
|
sys.exit(0 if result.status == ValidationStatus.PASSED else 1)
|
299
|
-
|
307
|
+
|
300
308
|
except Exception as e:
|
301
309
|
console.print(f"[bold red]Error validating {operation}: {e}[/bold red]")
|
302
310
|
sys.exit(3)
|
303
311
|
|
312
|
+
|
304
313
|
@cli.command()
|
305
314
|
def status():
|
306
315
|
"""Show MCP validation framework status."""
|
307
|
-
|
316
|
+
|
308
317
|
table = Table(title="MCP Validation Framework Status", box=box.ROUNDED)
|
309
318
|
table.add_column("Component", style="cyan")
|
310
319
|
table.add_column("Status", style="bold")
|
311
320
|
table.add_column("Details")
|
312
|
-
|
321
|
+
|
313
322
|
# Check MCP integration
|
314
323
|
try:
|
315
324
|
from notebooks.mcp_integration import MCPIntegrationManager
|
325
|
+
|
316
326
|
table.add_row("MCP Integration", "[green]✅ Available[/green]", "Ready for validation")
|
317
327
|
except ImportError:
|
318
328
|
table.add_row("MCP Integration", "[red]❌ Unavailable[/red]", "Install MCP dependencies")
|
319
|
-
|
329
|
+
|
320
330
|
# Check AWS profiles
|
321
331
|
profiles = [
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
332
|
+
"ams-admin-Billing-ReadOnlyAccess-909135376185",
|
333
|
+
"ams-admin-ReadOnlyAccess-909135376185",
|
334
|
+
"ams-centralised-ops-ReadOnlyAccess-335083429030",
|
335
|
+
"ams-shared-services-non-prod-ReadOnlyAccess-499201730520",
|
326
336
|
]
|
327
|
-
|
337
|
+
|
328
338
|
for profile in profiles:
|
329
339
|
try:
|
330
340
|
import boto3
|
341
|
+
|
331
342
|
session = boto3.Session(profile_name=profile)
|
332
|
-
sts = session.client(
|
343
|
+
sts = session.client("sts")
|
333
344
|
identity = sts.get_caller_identity()
|
334
345
|
table.add_row(f"Profile: {profile[:20]}...", "[green]✅ Valid[/green]", f"Account: {identity['Account']}")
|
335
346
|
except Exception as e:
|
336
347
|
table.add_row(f"Profile: {profile[:20]}...", "[red]❌ Invalid[/red]", str(e)[:50])
|
337
|
-
|
348
|
+
|
338
349
|
# Check validation components
|
339
350
|
components = [
|
340
|
-
(
|
341
|
-
(
|
342
|
-
(
|
343
|
-
(
|
351
|
+
("Cost Explorer", "runbooks.finops"),
|
352
|
+
("Organizations", "runbooks.inventory"),
|
353
|
+
("Security", "runbooks.security"),
|
354
|
+
("VPC Analysis", "runbooks.vpc"),
|
344
355
|
]
|
345
|
-
|
356
|
+
|
346
357
|
for name, module in components:
|
347
358
|
try:
|
348
359
|
__import__(module)
|
349
360
|
table.add_row(f"Component: {name}", "[green]✅ Ready[/green]", "Module loaded")
|
350
361
|
except ImportError:
|
351
362
|
table.add_row(f"Component: {name}", "[red]❌ Missing[/red]", "Module not available")
|
352
|
-
|
363
|
+
|
353
364
|
console.print(table)
|
354
365
|
|
355
|
-
|
356
|
-
|
366
|
+
|
367
|
+
if __name__ == "__main__":
|
368
|
+
cli()
|