runbooks 1.1.4__py3-none-any.whl → 1.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +31 -2
- runbooks/__init___optimized.py +18 -4
- runbooks/_platform/__init__.py +1 -5
- runbooks/_platform/core/runbooks_wrapper.py +141 -138
- runbooks/aws2/accuracy_validator.py +812 -0
- runbooks/base.py +7 -0
- runbooks/cfat/assessment/compliance.py +1 -1
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cli/__init__.py +1 -1
- runbooks/cli/commands/cfat.py +64 -23
- runbooks/cli/commands/finops.py +1005 -54
- runbooks/cli/commands/inventory.py +135 -91
- runbooks/cli/commands/operate.py +9 -36
- runbooks/cli/commands/security.py +42 -18
- runbooks/cli/commands/validation.py +432 -18
- runbooks/cli/commands/vpc.py +81 -17
- runbooks/cli/registry.py +22 -10
- runbooks/cloudops/__init__.py +20 -27
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +544 -542
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +224 -225
- runbooks/cloudops/lifecycle_manager.py +5 -4
- runbooks/cloudops/mcp_cost_validation.py +252 -235
- runbooks/cloudops/models.py +78 -53
- runbooks/cloudops/monitoring_automation.py +5 -4
- runbooks/cloudops/notebook_framework.py +177 -213
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +17 -12
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +40 -36
- runbooks/common/aws_utils.py +74 -79
- runbooks/common/business_logic.py +126 -104
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
- runbooks/common/cross_account_manager.py +197 -204
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +29 -19
- runbooks/common/dry_run_examples.py +173 -208
- runbooks/common/dry_run_framework.py +157 -155
- runbooks/common/enhanced_exception_handler.py +15 -4
- runbooks/common/enhanced_logging_example.py +50 -64
- runbooks/common/enhanced_logging_integration_example.py +65 -37
- runbooks/common/env_utils.py +16 -16
- runbooks/common/error_handling.py +40 -38
- runbooks/common/lazy_loader.py +41 -23
- runbooks/common/logging_integration_helper.py +79 -86
- runbooks/common/mcp_cost_explorer_integration.py +476 -493
- runbooks/common/mcp_integration.py +99 -79
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +175 -193
- runbooks/common/patterns.py +23 -25
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +111 -37
- runbooks/common/rich_utils.py +315 -141
- runbooks/common/sre_performance_suite.py +177 -186
- runbooks/enterprise/__init__.py +1 -1
- runbooks/enterprise/logging.py +144 -106
- runbooks/enterprise/security.py +187 -204
- runbooks/enterprise/validation.py +43 -56
- runbooks/finops/__init__.py +26 -30
- runbooks/finops/account_resolver.py +1 -1
- runbooks/finops/advanced_optimization_engine.py +980 -0
- runbooks/finops/automation_core.py +268 -231
- runbooks/finops/business_case_config.py +184 -179
- runbooks/finops/cli.py +660 -139
- runbooks/finops/commvault_ec2_analysis.py +157 -164
- runbooks/finops/compute_cost_optimizer.py +336 -320
- runbooks/finops/config.py +20 -20
- runbooks/finops/cost_optimizer.py +484 -618
- runbooks/finops/cost_processor.py +332 -214
- runbooks/finops/dashboard_runner.py +1006 -172
- runbooks/finops/ebs_cost_optimizer.py +991 -657
- runbooks/finops/elastic_ip_optimizer.py +317 -257
- runbooks/finops/enhanced_mcp_integration.py +340 -0
- runbooks/finops/enhanced_progress.py +32 -29
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +223 -285
- runbooks/finops/executive_export.py +203 -160
- runbooks/finops/helpers.py +130 -288
- runbooks/finops/iam_guidance.py +1 -1
- runbooks/finops/infrastructure/__init__.py +80 -0
- runbooks/finops/infrastructure/commands.py +506 -0
- runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
- runbooks/finops/markdown_exporter.py +337 -174
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1512 -481
- runbooks/finops/network_cost_optimizer.py +657 -587
- runbooks/finops/notebook_utils.py +226 -188
- runbooks/finops/optimization_engine.py +1136 -0
- runbooks/finops/optimizer.py +19 -23
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +64 -65
- runbooks/finops/scenarios.py +1277 -438
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +259 -265
- runbooks/finops/vpc_cleanup_exporter.py +189 -144
- runbooks/finops/vpc_cleanup_optimizer.py +591 -573
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/aws_decorators.py +2 -3
- runbooks/inventory/check_cloudtrail_compliance.py +2 -4
- runbooks/inventory/check_controltower_readiness.py +152 -151
- runbooks/inventory/check_landingzone_readiness.py +85 -84
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +1 -1
- runbooks/inventory/collectors/aws_networking.py +109 -99
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/core/formatter.py +11 -0
- runbooks/inventory/draw_org_structure.py +8 -9
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/ec2_vpc_utils.py +2 -2
- runbooks/inventory/find_cfn_drift_detection.py +5 -7
- runbooks/inventory/find_cfn_orphaned_stacks.py +7 -9
- runbooks/inventory/find_cfn_stackset_drift.py +5 -6
- runbooks/inventory/find_ec2_security_groups.py +48 -42
- runbooks/inventory/find_landingzone_versions.py +4 -6
- runbooks/inventory/find_vpc_flow_logs.py +7 -9
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/inventory_modules.py +103 -91
- runbooks/inventory/list_cfn_stacks.py +9 -10
- runbooks/inventory/list_cfn_stackset_operation_results.py +1 -3
- runbooks/inventory/list_cfn_stackset_operations.py +79 -57
- runbooks/inventory/list_cfn_stacksets.py +8 -10
- runbooks/inventory/list_config_recorders_delivery_channels.py +49 -39
- runbooks/inventory/list_ds_directories.py +65 -53
- runbooks/inventory/list_ec2_availability_zones.py +2 -4
- runbooks/inventory/list_ec2_ebs_volumes.py +32 -35
- runbooks/inventory/list_ec2_instances.py +23 -28
- runbooks/inventory/list_ecs_clusters_and_tasks.py +26 -34
- runbooks/inventory/list_elbs_load_balancers.py +22 -20
- runbooks/inventory/list_enis_network_interfaces.py +26 -33
- runbooks/inventory/list_guardduty_detectors.py +2 -4
- runbooks/inventory/list_iam_policies.py +2 -4
- runbooks/inventory/list_iam_roles.py +5 -7
- runbooks/inventory/list_iam_saml_providers.py +4 -6
- runbooks/inventory/list_lambda_functions.py +38 -38
- runbooks/inventory/list_org_accounts.py +6 -8
- runbooks/inventory/list_org_accounts_users.py +55 -44
- runbooks/inventory/list_rds_db_instances.py +31 -33
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/list_route53_hosted_zones.py +3 -5
- runbooks/inventory/list_servicecatalog_provisioned_products.py +37 -41
- runbooks/inventory/list_sns_topics.py +2 -4
- runbooks/inventory/list_ssm_parameters.py +4 -7
- runbooks/inventory/list_vpc_subnets.py +2 -4
- runbooks/inventory/list_vpcs.py +7 -10
- runbooks/inventory/mcp_inventory_validator.py +554 -468
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +63 -55
- runbooks/inventory/recover_cfn_stack_ids.py +7 -8
- runbooks/inventory/requirements.txt +0 -1
- runbooks/inventory/rich_inventory_display.py +35 -34
- runbooks/inventory/run_on_multi_accounts.py +3 -5
- runbooks/inventory/unified_validation_engine.py +281 -253
- runbooks/inventory/verify_ec2_security_groups.py +1 -1
- runbooks/inventory/vpc_analyzer.py +735 -697
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +384 -380
- runbooks/inventory/vpc_flow_analyzer.py +1 -1
- runbooks/main.py +49 -34
- runbooks/main_final.py +91 -60
- runbooks/main_minimal.py +22 -10
- runbooks/main_optimized.py +131 -100
- runbooks/main_ultra_minimal.py +7 -2
- runbooks/mcp/__init__.py +36 -0
- runbooks/mcp/integration.py +679 -0
- runbooks/monitoring/performance_monitor.py +9 -4
- runbooks/operate/dynamodb_operations.py +3 -1
- runbooks/operate/ec2_operations.py +145 -137
- runbooks/operate/iam_operations.py +146 -152
- runbooks/operate/networking_cost_heatmap.py +29 -8
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_operations.py +646 -616
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +70 -66
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +86 -60
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +46 -41
- runbooks/security/__init__.py +19 -0
- runbooks/security/assessment_runner.py +1150 -0
- runbooks/security/baseline_checker.py +812 -0
- runbooks/security/cloudops_automation_security_validator.py +509 -535
- runbooks/security/compliance_automation_engine.py +17 -17
- runbooks/security/config/__init__.py +2 -2
- runbooks/security/config/compliance_config.py +50 -50
- runbooks/security/config_template_generator.py +63 -76
- runbooks/security/enterprise_security_framework.py +1 -1
- runbooks/security/executive_security_dashboard.py +519 -508
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/security_baseline_tester.py +1 -1
- runbooks/security/security_cli.py +143 -112
- runbooks/security/test_2way_validation.py +439 -0
- runbooks/security/two_way_validation_framework.py +852 -0
- runbooks/sre/production_monitoring_framework.py +167 -177
- runbooks/tdd/__init__.py +15 -0
- runbooks/tdd/cli.py +1071 -0
- runbooks/utils/__init__.py +14 -17
- runbooks/utils/logger.py +7 -2
- runbooks/utils/version_validator.py +50 -47
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +745 -704
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +461 -454
- runbooks/vpc/README.md +617 -0
- runbooks/vpc/__init__.py +8 -1
- runbooks/vpc/analyzer.py +577 -0
- runbooks/vpc/cleanup_wrapper.py +476 -413
- runbooks/vpc/cli_cloudtrail_commands.py +339 -0
- runbooks/vpc/cli_mcp_validation_commands.py +480 -0
- runbooks/vpc/cloudtrail_audit_integration.py +717 -0
- runbooks/vpc/config.py +92 -97
- runbooks/vpc/cost_engine.py +411 -148
- runbooks/vpc/cost_explorer_integration.py +553 -0
- runbooks/vpc/cross_account_session.py +101 -106
- runbooks/vpc/enhanced_mcp_validation.py +917 -0
- runbooks/vpc/eni_gate_validator.py +961 -0
- runbooks/vpc/heatmap_engine.py +185 -160
- runbooks/vpc/mcp_no_eni_validator.py +680 -639
- runbooks/vpc/nat_gateway_optimizer.py +358 -0
- runbooks/vpc/networking_wrapper.py +15 -8
- runbooks/vpc/pdca_remediation_planner.py +528 -0
- runbooks/vpc/performance_optimized_analyzer.py +219 -231
- runbooks/vpc/runbooks_adapter.py +1167 -241
- runbooks/vpc/tdd_red_phase_stubs.py +601 -0
- runbooks/vpc/test_data_loader.py +358 -0
- runbooks/vpc/tests/conftest.py +314 -4
- runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
- runbooks/vpc/tests/test_cost_engine.py +0 -2
- runbooks/vpc/topology_generator.py +326 -0
- runbooks/vpc/unified_scenarios.py +1297 -1124
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.6.dist-info/METADATA +327 -0
- runbooks-1.1.6.dist-info/RECORD +489 -0
- runbooks/finops/README.md +0 -414
- runbooks/finops/accuracy_cross_validator.py +0 -647
- runbooks/finops/business_cases.py +0 -950
- runbooks/finops/dashboard_router.py +0 -922
- runbooks/finops/ebs_optimizer.py +0 -973
- runbooks/finops/embedded_mcp_validator.py +0 -1629
- runbooks/finops/enhanced_dashboard_runner.py +0 -527
- runbooks/finops/finops_dashboard.py +0 -584
- runbooks/finops/finops_scenarios.py +0 -1218
- runbooks/finops/legacy_migration.py +0 -730
- runbooks/finops/multi_dashboard.py +0 -1519
- runbooks/finops/single_dashboard.py +0 -1113
- runbooks/finops/unlimited_scenarios.py +0 -393
- runbooks-1.1.4.dist-info/METADATA +0 -800
- runbooks-1.1.4.dist-info/RECORD +0 -468
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/WHEEL +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
|
|
2
2
|
Enterprise FinOps Platform - RunbooksWrapper
|
3
3
|
Provides unified access to all runbooks CLI commands with MCP validation and Rich output
|
4
4
|
"""
|
5
|
+
|
5
6
|
import subprocess
|
6
7
|
import json
|
7
8
|
import yaml
|
@@ -18,32 +19,33 @@ from rich import box
|
|
18
19
|
|
19
20
|
console = Console()
|
20
21
|
|
22
|
+
|
21
23
|
class RunbooksWrapper:
|
22
24
|
"""
|
23
25
|
Enterprise wrapper for runbooks CLI commands with MCP validation and Rich output.
|
24
|
-
|
26
|
+
|
25
27
|
Provides Jupyter-friendly interface to all runbooks functionality:
|
26
28
|
- Inventory collection and analysis
|
27
|
-
- FinOps cost analysis and optimization
|
29
|
+
- FinOps cost analysis and optimization
|
28
30
|
- Security assessments and remediation
|
29
31
|
- CFAT well-architected evaluations
|
30
32
|
- Operations automation
|
31
33
|
- Organization management
|
32
34
|
"""
|
33
|
-
|
35
|
+
|
34
36
|
def __init__(self, default_profile: Optional[str] = None):
|
35
37
|
"""Initialize wrapper with optional default AWS profile."""
|
36
38
|
self.default_profile = default_profile
|
37
39
|
self.console = Console()
|
38
|
-
|
40
|
+
|
39
41
|
def _execute_command(self, command: str, capture_output: bool = True) -> Dict[str, Any]:
|
40
42
|
"""
|
41
43
|
Execute runbooks command with error handling and rich output.
|
42
|
-
|
44
|
+
|
43
45
|
Args:
|
44
46
|
command: Full runbooks command to execute
|
45
47
|
capture_output: Whether to capture command output
|
46
|
-
|
48
|
+
|
47
49
|
Returns:
|
48
50
|
Dictionary with command result, output, and metadata
|
49
51
|
"""
|
@@ -55,74 +57,71 @@ class RunbooksWrapper:
|
|
55
57
|
transient=True,
|
56
58
|
) as progress:
|
57
59
|
progress.add_task(description="Executing command...", total=None)
|
58
|
-
|
60
|
+
|
59
61
|
result = subprocess.run(
|
60
62
|
command.split(),
|
61
63
|
capture_output=capture_output,
|
62
64
|
text=True,
|
63
|
-
timeout=300 # 5 minute timeout
|
65
|
+
timeout=300, # 5 minute timeout
|
64
66
|
)
|
65
|
-
|
67
|
+
|
66
68
|
return {
|
67
69
|
"success": result.returncode == 0,
|
68
70
|
"returncode": result.returncode,
|
69
71
|
"stdout": result.stdout,
|
70
72
|
"stderr": result.stderr,
|
71
73
|
"command": command,
|
72
|
-
"timestamp": datetime.now().isoformat()
|
74
|
+
"timestamp": datetime.now().isoformat(),
|
73
75
|
}
|
74
|
-
|
76
|
+
|
75
77
|
except subprocess.TimeoutExpired:
|
76
78
|
return {
|
77
79
|
"success": False,
|
78
80
|
"error": "Command timed out after 5 minutes",
|
79
81
|
"command": command,
|
80
|
-
"timestamp": datetime.now().isoformat()
|
82
|
+
"timestamp": datetime.now().isoformat(),
|
81
83
|
}
|
82
84
|
except Exception as e:
|
83
|
-
return {
|
84
|
-
|
85
|
-
"error": str(e),
|
86
|
-
"command": command,
|
87
|
-
"timestamp": datetime.now().isoformat()
|
88
|
-
}
|
89
|
-
|
85
|
+
return {"success": False, "error": str(e), "command": command, "timestamp": datetime.now().isoformat()}
|
86
|
+
|
90
87
|
# Inventory Operations
|
91
|
-
def inventory_collect(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
88
|
+
def inventory_collect(
|
89
|
+
self,
|
90
|
+
resources: List[str] = None,
|
91
|
+
profile: str = None,
|
92
|
+
all_accounts: bool = False,
|
93
|
+
include_costs: bool = False,
|
94
|
+
regions: List[str] = None,
|
95
|
+
) -> pd.DataFrame:
|
97
96
|
"""
|
98
97
|
Collect inventory across AWS accounts and services.
|
99
|
-
|
98
|
+
|
100
99
|
Args:
|
101
100
|
resources: List of AWS resources (ec2, s3, rds, lambda, etc.)
|
102
101
|
profile: AWS profile to use
|
103
102
|
all_accounts: Scan all accounts in organization
|
104
103
|
include_costs: Include cost analysis
|
105
104
|
regions: Specific regions to scan
|
106
|
-
|
105
|
+
|
107
106
|
Returns:
|
108
107
|
DataFrame with inventory results
|
109
108
|
"""
|
110
109
|
cmd_parts = ["runbooks", "inventory", "collect"]
|
111
|
-
|
110
|
+
|
112
111
|
if resources:
|
113
112
|
cmd_parts.extend(["-r", ",".join(resources)])
|
114
113
|
if profile or self.default_profile:
|
115
114
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
116
115
|
if all_accounts:
|
117
|
-
cmd_parts.append("--all-
|
116
|
+
cmd_parts.append("--all-profiles")
|
118
117
|
if include_costs:
|
119
118
|
cmd_parts.append("--include-costs")
|
120
119
|
if regions:
|
121
120
|
cmd_parts.extend(["--regions", ",".join(regions)])
|
122
|
-
|
121
|
+
|
123
122
|
command = " ".join(cmd_parts)
|
124
123
|
result = self._execute_command(command)
|
125
|
-
|
124
|
+
|
126
125
|
if result["success"]:
|
127
126
|
try:
|
128
127
|
# Parse JSON output to DataFrame
|
@@ -134,45 +133,49 @@ class RunbooksWrapper:
|
|
134
133
|
console.print("[yellow]Warning: Could not parse JSON output, returning raw text[/yellow]")
|
135
134
|
return pd.DataFrame({"output": [result["stdout"]]})
|
136
135
|
else:
|
137
|
-
console.print(
|
136
|
+
console.print(
|
137
|
+
f"[red]Error executing inventory command: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
138
|
+
)
|
138
139
|
return pd.DataFrame()
|
139
|
-
|
140
|
-
# FinOps Operations
|
141
|
-
def finops_analyze(
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
140
|
+
|
141
|
+
# FinOps Operations
|
142
|
+
def finops_analyze(
|
143
|
+
self,
|
144
|
+
profile: str = None,
|
145
|
+
all_accounts: bool = False,
|
146
|
+
target_reduction: str = "20-40%",
|
147
|
+
breakdown_by: List[str] = None,
|
148
|
+
export_format: str = "json",
|
149
|
+
) -> Dict[str, Any]:
|
147
150
|
"""
|
148
151
|
Perform FinOps cost analysis and optimization recommendations.
|
149
|
-
|
152
|
+
|
150
153
|
Args:
|
151
|
-
profile: AWS billing profile
|
154
|
+
profile: AWS billing profile
|
152
155
|
all_accounts: Analyze all accounts
|
153
156
|
target_reduction: Target cost reduction percentage
|
154
157
|
breakdown_by: Breakdown by service, account, region
|
155
158
|
export_format: Export format (json, csv, html)
|
156
|
-
|
159
|
+
|
157
160
|
Returns:
|
158
161
|
Dictionary with cost analysis results
|
159
162
|
"""
|
160
163
|
cmd_parts = ["runbooks", "finops", "--analyze"]
|
161
|
-
|
164
|
+
|
162
165
|
if profile or self.default_profile:
|
163
166
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
164
167
|
if all_accounts:
|
165
|
-
cmd_parts.append("--all-
|
168
|
+
cmd_parts.append("--all-profiles")
|
166
169
|
if target_reduction:
|
167
170
|
cmd_parts.extend(["--target-reduction", target_reduction])
|
168
171
|
if breakdown_by:
|
169
172
|
cmd_parts.extend(["--breakdown-by", ",".join(breakdown_by)])
|
170
173
|
if export_format:
|
171
174
|
cmd_parts.extend(["--export", export_format])
|
172
|
-
|
175
|
+
|
173
176
|
command = " ".join(cmd_parts)
|
174
177
|
result = self._execute_command(command)
|
175
|
-
|
178
|
+
|
176
179
|
if result["success"]:
|
177
180
|
try:
|
178
181
|
data = json.loads(result["stdout"])
|
@@ -182,45 +185,49 @@ class RunbooksWrapper:
|
|
182
185
|
console.print("[yellow]Warning: Could not parse JSON output[/yellow]")
|
183
186
|
return {"raw_output": result["stdout"]}
|
184
187
|
else:
|
185
|
-
console.print(
|
188
|
+
console.print(
|
189
|
+
f"[red]Error executing FinOps analysis: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
190
|
+
)
|
186
191
|
return {}
|
187
|
-
|
192
|
+
|
188
193
|
# Security Operations
|
189
|
-
def security_assess(
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
194
|
+
def security_assess(
|
195
|
+
self,
|
196
|
+
profile: str = None,
|
197
|
+
all_accounts: bool = False,
|
198
|
+
checks: str = "all",
|
199
|
+
language: str = "EN",
|
200
|
+
format: str = "json",
|
201
|
+
) -> Dict[str, Any]:
|
195
202
|
"""
|
196
203
|
Perform security assessment across accounts.
|
197
|
-
|
204
|
+
|
198
205
|
Args:
|
199
206
|
profile: AWS profile to use
|
200
207
|
all_accounts: Assess all accounts
|
201
208
|
checks: Specific security checks or "all"
|
202
209
|
language: Report language (EN, JP, KR, VN)
|
203
210
|
format: Output format (json, html, csv)
|
204
|
-
|
211
|
+
|
205
212
|
Returns:
|
206
213
|
Dictionary with security assessment results
|
207
214
|
"""
|
208
215
|
cmd_parts = ["runbooks", "security", "assess"]
|
209
|
-
|
216
|
+
|
210
217
|
if profile or self.default_profile:
|
211
218
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
212
219
|
if all_accounts:
|
213
|
-
cmd_parts.append("--all-
|
220
|
+
cmd_parts.append("--all-profiles")
|
214
221
|
if checks:
|
215
222
|
cmd_parts.extend(["--checks", checks])
|
216
223
|
if language:
|
217
224
|
cmd_parts.extend(["--language", language])
|
218
225
|
if format:
|
219
226
|
cmd_parts.extend(["--format", format])
|
220
|
-
|
227
|
+
|
221
228
|
command = " ".join(cmd_parts)
|
222
229
|
result = self._execute_command(command)
|
223
|
-
|
230
|
+
|
224
231
|
if result["success"]:
|
225
232
|
try:
|
226
233
|
data = json.loads(result["stdout"])
|
@@ -229,31 +236,35 @@ class RunbooksWrapper:
|
|
229
236
|
except json.JSONDecodeError:
|
230
237
|
return {"raw_output": result["stdout"]}
|
231
238
|
else:
|
232
|
-
console.print(
|
239
|
+
console.print(
|
240
|
+
f"[red]Error executing security assessment: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
241
|
+
)
|
233
242
|
return {}
|
234
|
-
|
243
|
+
|
235
244
|
# CFAT Operations
|
236
|
-
def cfat_assess(
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
245
|
+
def cfat_assess(
|
246
|
+
self,
|
247
|
+
profile: str = None,
|
248
|
+
compliance_framework: str = "AWS Well-Architected",
|
249
|
+
output_format: str = "json",
|
250
|
+
serve_web: bool = False,
|
251
|
+
port: int = 8080,
|
252
|
+
) -> Dict[str, Any]:
|
242
253
|
"""
|
243
254
|
Perform Cloud Foundation Assessment Tool evaluation.
|
244
|
-
|
255
|
+
|
245
256
|
Args:
|
246
257
|
profile: AWS profile to use
|
247
258
|
compliance_framework: Framework to assess against
|
248
259
|
output_format: Output format
|
249
260
|
serve_web: Start web server for results
|
250
261
|
port: Web server port
|
251
|
-
|
262
|
+
|
252
263
|
Returns:
|
253
264
|
Dictionary with CFAT assessment results
|
254
265
|
"""
|
255
266
|
cmd_parts = ["runbooks", "cfat", "assess"]
|
256
|
-
|
267
|
+
|
257
268
|
if profile or self.default_profile:
|
258
269
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
259
270
|
if compliance_framework:
|
@@ -262,10 +273,10 @@ class RunbooksWrapper:
|
|
262
273
|
cmd_parts.extend(["--output", output_format])
|
263
274
|
if serve_web:
|
264
275
|
cmd_parts.extend(["--serve-web", "--port", str(port)])
|
265
|
-
|
276
|
+
|
266
277
|
command = " ".join(cmd_parts)
|
267
278
|
result = self._execute_command(command)
|
268
|
-
|
279
|
+
|
269
280
|
if result["success"]:
|
270
281
|
try:
|
271
282
|
data = json.loads(result["stdout"])
|
@@ -274,63 +285,69 @@ class RunbooksWrapper:
|
|
274
285
|
except json.JSONDecodeError:
|
275
286
|
return {"raw_output": result["stdout"]}
|
276
287
|
else:
|
277
|
-
console.print(
|
288
|
+
console.print(
|
289
|
+
f"[red]Error executing CFAT assessment: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
290
|
+
)
|
278
291
|
return {}
|
279
|
-
|
292
|
+
|
280
293
|
# Operations
|
281
|
-
def operate_ec2(
|
294
|
+
def operate_ec2(
|
295
|
+
self, action: str, instance_ids: List[str], profile: str = None, dry_run: bool = True
|
296
|
+
) -> Dict[str, Any]:
|
282
297
|
"""
|
283
298
|
Perform EC2 operations (start, stop, terminate).
|
284
|
-
|
299
|
+
|
285
300
|
Args:
|
286
301
|
action: Action to perform (start, stop, terminate)
|
287
302
|
instance_ids: List of instance IDs
|
288
303
|
profile: AWS profile to use
|
289
304
|
dry_run: Perform dry run only
|
290
|
-
|
305
|
+
|
291
306
|
Returns:
|
292
307
|
Dictionary with operation results
|
293
308
|
"""
|
294
309
|
cmd_parts = ["runbooks", "operate", "ec2", action]
|
295
310
|
cmd_parts.extend(["--instance-ids"] + instance_ids)
|
296
|
-
|
311
|
+
|
297
312
|
if profile or self.default_profile:
|
298
313
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
299
314
|
if dry_run:
|
300
315
|
cmd_parts.append("--dry-run")
|
301
|
-
|
316
|
+
|
302
317
|
command = " ".join(cmd_parts)
|
303
318
|
result = self._execute_command(command)
|
304
|
-
|
319
|
+
|
305
320
|
if result["success"]:
|
306
321
|
console.print(f"[green]✅ EC2 {action} operation completed successfully[/green]")
|
307
322
|
return {"success": True, "output": result["stdout"]}
|
308
323
|
else:
|
309
|
-
console.print(
|
324
|
+
console.print(
|
325
|
+
f"[red]❌ EC2 {action} operation failed: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
326
|
+
)
|
310
327
|
return {"success": False, "error": result.get("error", result.get("stderr"))}
|
311
|
-
|
328
|
+
|
312
329
|
# Organization Management
|
313
330
|
def org_list_ous(self, profile: str = None, output_format: str = "table") -> pd.DataFrame:
|
314
331
|
"""
|
315
332
|
List organizational units in AWS Organizations.
|
316
|
-
|
333
|
+
|
317
334
|
Args:
|
318
335
|
profile: AWS management profile
|
319
336
|
output_format: Output format (table, json)
|
320
|
-
|
337
|
+
|
321
338
|
Returns:
|
322
339
|
DataFrame with OU information
|
323
340
|
"""
|
324
341
|
cmd_parts = ["runbooks", "org", "list-ous"]
|
325
|
-
|
342
|
+
|
326
343
|
if profile or self.default_profile:
|
327
344
|
cmd_parts.extend(["--profile", profile or self.default_profile])
|
328
345
|
if output_format:
|
329
346
|
cmd_parts.extend(["--output", output_format])
|
330
|
-
|
347
|
+
|
331
348
|
command = " ".join(cmd_parts)
|
332
349
|
result = self._execute_command(command)
|
333
|
-
|
350
|
+
|
334
351
|
if result["success"]:
|
335
352
|
try:
|
336
353
|
if output_format == "json":
|
@@ -345,26 +362,26 @@ class RunbooksWrapper:
|
|
345
362
|
else:
|
346
363
|
console.print(f"[red]Error listing OUs: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
|
347
364
|
return pd.DataFrame()
|
348
|
-
|
365
|
+
|
349
366
|
# MCP Validation
|
350
367
|
def validate_mcp_servers(self, billing_profile: str = None) -> Dict[str, Any]:
|
351
368
|
"""
|
352
369
|
Validate MCP servers connectivity and accuracy.
|
353
|
-
|
370
|
+
|
354
371
|
Args:
|
355
372
|
billing_profile: Billing profile for validation
|
356
|
-
|
373
|
+
|
357
374
|
Returns:
|
358
375
|
Dictionary with validation results
|
359
376
|
"""
|
360
377
|
cmd_parts = ["runbooks", "validate", "mcp-servers"]
|
361
|
-
|
378
|
+
|
362
379
|
if billing_profile or self.default_profile:
|
363
380
|
cmd_parts.extend(["--billing-profile", billing_profile or self.default_profile])
|
364
|
-
|
381
|
+
|
365
382
|
command = " ".join(cmd_parts)
|
366
383
|
result = self._execute_command(command)
|
367
|
-
|
384
|
+
|
368
385
|
if result["success"]:
|
369
386
|
try:
|
370
387
|
data = json.loads(result["stdout"])
|
@@ -373,53 +390,51 @@ class RunbooksWrapper:
|
|
373
390
|
except json.JSONDecodeError:
|
374
391
|
return {"raw_output": result["stdout"]}
|
375
392
|
else:
|
376
|
-
console.print(
|
393
|
+
console.print(
|
394
|
+
f"[red]Error validating MCP servers: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]"
|
395
|
+
)
|
377
396
|
return {}
|
378
|
-
|
397
|
+
|
379
398
|
# Rich Display Methods
|
380
399
|
def _display_inventory_summary(self, df: pd.DataFrame):
|
381
400
|
"""Display inventory results summary with Rich formatting."""
|
382
401
|
if df.empty:
|
383
402
|
console.print("[yellow]No inventory data to display[/yellow]")
|
384
403
|
return
|
385
|
-
|
404
|
+
|
386
405
|
table = Table(title="📊 Inventory Summary", box=box.ROUNDED)
|
387
406
|
table.add_column("Metric", style="cyan")
|
388
407
|
table.add_column("Count", justify="right", style="green")
|
389
|
-
|
408
|
+
|
390
409
|
total_resources = len(df)
|
391
410
|
resource_types = df.get("ResourceType", pd.Series()).nunique() if "ResourceType" in df.columns else 0
|
392
411
|
accounts = df.get("AccountId", pd.Series()).nunique() if "AccountId" in df.columns else 0
|
393
|
-
|
412
|
+
|
394
413
|
table.add_row("Total Resources", str(total_resources))
|
395
414
|
table.add_row("Resource Types", str(resource_types))
|
396
415
|
table.add_row("AWS Accounts", str(accounts))
|
397
|
-
|
416
|
+
|
398
417
|
console.print(table)
|
399
|
-
|
418
|
+
|
400
419
|
def _display_finops_summary(self, data: Dict[str, Any]):
|
401
420
|
"""Display FinOps analysis summary with Rich formatting."""
|
402
421
|
panel_content = []
|
403
|
-
|
422
|
+
|
404
423
|
if "total_cost" in data:
|
405
424
|
panel_content.append(f"💰 Total Monthly Cost: ${data['total_cost']:,.2f}")
|
406
425
|
if "potential_savings" in data:
|
407
426
|
panel_content.append(f"💸 Potential Savings: ${data['potential_savings']:,.2f}")
|
408
427
|
if "optimization_recommendations" in data:
|
409
428
|
panel_content.append(f"📋 Recommendations: {len(data['optimization_recommendations'])}")
|
410
|
-
|
429
|
+
|
411
430
|
content = "\n".join(panel_content) if panel_content else "FinOps analysis completed"
|
412
|
-
|
413
|
-
console.print(Panel(
|
414
|
-
|
415
|
-
title="💰 FinOps Analysis Summary",
|
416
|
-
border_style="green"
|
417
|
-
))
|
418
|
-
|
431
|
+
|
432
|
+
console.print(Panel(content, title="💰 FinOps Analysis Summary", border_style="green"))
|
433
|
+
|
419
434
|
def _display_security_summary(self, data: Dict[str, Any]):
|
420
435
|
"""Display security assessment summary with Rich formatting."""
|
421
436
|
panel_content = []
|
422
|
-
|
437
|
+
|
423
438
|
if "total_checks" in data:
|
424
439
|
panel_content.append(f"🔍 Total Checks: {data['total_checks']}")
|
425
440
|
if "passed_checks" in data:
|
@@ -428,51 +443,39 @@ class RunbooksWrapper:
|
|
428
443
|
panel_content.append(f"❌ Failed: {data['failed_checks']}")
|
429
444
|
if "compliance_score" in data:
|
430
445
|
panel_content.append(f"📊 Compliance Score: {data['compliance_score']}%")
|
431
|
-
|
446
|
+
|
432
447
|
content = "\n".join(panel_content) if panel_content else "Security assessment completed"
|
433
|
-
|
434
|
-
console.print(Panel(
|
435
|
-
|
436
|
-
title="🔒 Security Assessment Summary",
|
437
|
-
border_style="red"
|
438
|
-
))
|
439
|
-
|
448
|
+
|
449
|
+
console.print(Panel(content, title="🔒 Security Assessment Summary", border_style="red"))
|
450
|
+
|
440
451
|
def _display_cfat_summary(self, data: Dict[str, Any]):
|
441
452
|
"""Display CFAT assessment summary with Rich formatting."""
|
442
453
|
panel_content = []
|
443
|
-
|
454
|
+
|
444
455
|
if "well_architected_score" in data:
|
445
456
|
panel_content.append(f"🏗️ Well-Architected Score: {data['well_architected_score']}%")
|
446
457
|
if "pillars_assessed" in data:
|
447
458
|
panel_content.append(f"📋 Pillars Assessed: {len(data['pillars_assessed'])}")
|
448
459
|
if "high_risk_findings" in data:
|
449
460
|
panel_content.append(f"⚠️ High Risk Findings: {data['high_risk_findings']}")
|
450
|
-
|
461
|
+
|
451
462
|
content = "\n".join(panel_content) if panel_content else "CFAT assessment completed"
|
452
|
-
|
453
|
-
console.print(Panel(
|
454
|
-
|
455
|
-
title="🏗️ CFAT Assessment Summary",
|
456
|
-
border_style="blue"
|
457
|
-
))
|
458
|
-
|
463
|
+
|
464
|
+
console.print(Panel(content, title="🏗️ CFAT Assessment Summary", border_style="blue"))
|
465
|
+
|
459
466
|
def _display_mcp_validation_summary(self, data: Dict[str, Any]):
|
460
467
|
"""Display MCP validation summary with Rich formatting."""
|
461
468
|
panel_content = []
|
462
|
-
|
469
|
+
|
463
470
|
if "accuracy_rate" in data:
|
464
471
|
panel_content.append(f"🎯 Accuracy Rate: {data['accuracy_rate']}%")
|
465
472
|
if "servers_validated" in data:
|
466
473
|
panel_content.append(f"🖥️ Servers Validated: {data['servers_validated']}")
|
467
474
|
if "validation_time" in data:
|
468
475
|
panel_content.append(f"⏱️ Validation Time: {data['validation_time']}s")
|
469
|
-
|
476
|
+
|
470
477
|
content = "\n".join(panel_content) if panel_content else "MCP validation completed"
|
471
|
-
|
478
|
+
|
472
479
|
color = "green" if data.get("accuracy_rate", 0) >= 99.5 else "yellow"
|
473
|
-
|
474
|
-
console.print(Panel(
|
475
|
-
content,
|
476
|
-
title="🔍 MCP Validation Summary",
|
477
|
-
border_style=color
|
478
|
-
))
|
480
|
+
|
481
|
+
console.print(Panel(content, title="🔍 MCP Validation Summary", border_style=color))
|