runbooks 1.1.4__py3-none-any.whl → 1.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. runbooks/__init__.py +31 -2
  2. runbooks/__init___optimized.py +18 -4
  3. runbooks/_platform/__init__.py +1 -5
  4. runbooks/_platform/core/runbooks_wrapper.py +141 -138
  5. runbooks/aws2/accuracy_validator.py +812 -0
  6. runbooks/base.py +7 -0
  7. runbooks/cfat/assessment/compliance.py +1 -1
  8. runbooks/cfat/assessment/runner.py +1 -0
  9. runbooks/cfat/cloud_foundations_assessment.py +227 -239
  10. runbooks/cli/__init__.py +1 -1
  11. runbooks/cli/commands/cfat.py +64 -23
  12. runbooks/cli/commands/finops.py +1005 -54
  13. runbooks/cli/commands/inventory.py +138 -35
  14. runbooks/cli/commands/operate.py +9 -36
  15. runbooks/cli/commands/security.py +42 -18
  16. runbooks/cli/commands/validation.py +432 -18
  17. runbooks/cli/commands/vpc.py +81 -17
  18. runbooks/cli/registry.py +22 -10
  19. runbooks/cloudops/__init__.py +20 -27
  20. runbooks/cloudops/base.py +96 -107
  21. runbooks/cloudops/cost_optimizer.py +544 -542
  22. runbooks/cloudops/infrastructure_optimizer.py +5 -4
  23. runbooks/cloudops/interfaces.py +224 -225
  24. runbooks/cloudops/lifecycle_manager.py +5 -4
  25. runbooks/cloudops/mcp_cost_validation.py +252 -235
  26. runbooks/cloudops/models.py +78 -53
  27. runbooks/cloudops/monitoring_automation.py +5 -4
  28. runbooks/cloudops/notebook_framework.py +177 -213
  29. runbooks/cloudops/security_enforcer.py +125 -159
  30. runbooks/common/accuracy_validator.py +11 -0
  31. runbooks/common/aws_pricing.py +349 -326
  32. runbooks/common/aws_pricing_api.py +211 -212
  33. runbooks/common/aws_profile_manager.py +40 -36
  34. runbooks/common/aws_utils.py +74 -79
  35. runbooks/common/business_logic.py +126 -104
  36. runbooks/common/cli_decorators.py +36 -60
  37. runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
  38. runbooks/common/cross_account_manager.py +197 -204
  39. runbooks/common/date_utils.py +27 -39
  40. runbooks/common/decorators.py +29 -19
  41. runbooks/common/dry_run_examples.py +173 -208
  42. runbooks/common/dry_run_framework.py +157 -155
  43. runbooks/common/enhanced_exception_handler.py +15 -4
  44. runbooks/common/enhanced_logging_example.py +50 -64
  45. runbooks/common/enhanced_logging_integration_example.py +65 -37
  46. runbooks/common/env_utils.py +16 -16
  47. runbooks/common/error_handling.py +40 -38
  48. runbooks/common/lazy_loader.py +41 -23
  49. runbooks/common/logging_integration_helper.py +79 -86
  50. runbooks/common/mcp_cost_explorer_integration.py +476 -493
  51. runbooks/common/mcp_integration.py +63 -74
  52. runbooks/common/memory_optimization.py +140 -118
  53. runbooks/common/module_cli_base.py +37 -58
  54. runbooks/common/organizations_client.py +175 -193
  55. runbooks/common/patterns.py +23 -25
  56. runbooks/common/performance_monitoring.py +67 -71
  57. runbooks/common/performance_optimization_engine.py +283 -274
  58. runbooks/common/profile_utils.py +111 -37
  59. runbooks/common/rich_utils.py +201 -141
  60. runbooks/common/sre_performance_suite.py +177 -186
  61. runbooks/enterprise/__init__.py +1 -1
  62. runbooks/enterprise/logging.py +144 -106
  63. runbooks/enterprise/security.py +187 -204
  64. runbooks/enterprise/validation.py +43 -56
  65. runbooks/finops/__init__.py +26 -30
  66. runbooks/finops/account_resolver.py +1 -1
  67. runbooks/finops/advanced_optimization_engine.py +980 -0
  68. runbooks/finops/automation_core.py +268 -231
  69. runbooks/finops/business_case_config.py +184 -179
  70. runbooks/finops/cli.py +660 -139
  71. runbooks/finops/commvault_ec2_analysis.py +157 -164
  72. runbooks/finops/compute_cost_optimizer.py +336 -320
  73. runbooks/finops/config.py +20 -20
  74. runbooks/finops/cost_optimizer.py +484 -618
  75. runbooks/finops/cost_processor.py +332 -214
  76. runbooks/finops/dashboard_runner.py +1006 -172
  77. runbooks/finops/ebs_cost_optimizer.py +991 -657
  78. runbooks/finops/elastic_ip_optimizer.py +317 -257
  79. runbooks/finops/enhanced_mcp_integration.py +340 -0
  80. runbooks/finops/enhanced_progress.py +32 -29
  81. runbooks/finops/enhanced_trend_visualization.py +3 -2
  82. runbooks/finops/enterprise_wrappers.py +223 -285
  83. runbooks/finops/executive_export.py +203 -160
  84. runbooks/finops/helpers.py +130 -288
  85. runbooks/finops/iam_guidance.py +1 -1
  86. runbooks/finops/infrastructure/__init__.py +80 -0
  87. runbooks/finops/infrastructure/commands.py +506 -0
  88. runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
  89. runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
  90. runbooks/finops/markdown_exporter.py +337 -174
  91. runbooks/finops/mcp_validator.py +1952 -0
  92. runbooks/finops/nat_gateway_optimizer.py +1512 -481
  93. runbooks/finops/network_cost_optimizer.py +657 -587
  94. runbooks/finops/notebook_utils.py +226 -188
  95. runbooks/finops/optimization_engine.py +1136 -0
  96. runbooks/finops/optimizer.py +19 -23
  97. runbooks/finops/rds_snapshot_optimizer.py +367 -411
  98. runbooks/finops/reservation_optimizer.py +427 -363
  99. runbooks/finops/scenario_cli_integration.py +64 -65
  100. runbooks/finops/scenarios.py +1277 -438
  101. runbooks/finops/schemas.py +218 -182
  102. runbooks/finops/snapshot_manager.py +2289 -0
  103. runbooks/finops/types.py +3 -3
  104. runbooks/finops/validation_framework.py +259 -265
  105. runbooks/finops/vpc_cleanup_exporter.py +189 -144
  106. runbooks/finops/vpc_cleanup_optimizer.py +591 -573
  107. runbooks/finops/workspaces_analyzer.py +171 -182
  108. runbooks/integration/__init__.py +89 -0
  109. runbooks/integration/mcp_integration.py +1920 -0
  110. runbooks/inventory/CLAUDE.md +816 -0
  111. runbooks/inventory/__init__.py +2 -2
  112. runbooks/inventory/cloud_foundations_integration.py +144 -149
  113. runbooks/inventory/collectors/aws_comprehensive.py +1 -1
  114. runbooks/inventory/collectors/aws_networking.py +109 -99
  115. runbooks/inventory/collectors/base.py +4 -0
  116. runbooks/inventory/core/collector.py +495 -313
  117. runbooks/inventory/drift_detection_cli.py +69 -96
  118. runbooks/inventory/inventory_mcp_cli.py +48 -46
  119. runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
  120. runbooks/inventory/mcp_inventory_validator.py +549 -465
  121. runbooks/inventory/mcp_vpc_validator.py +359 -442
  122. runbooks/inventory/organizations_discovery.py +55 -51
  123. runbooks/inventory/rich_inventory_display.py +33 -32
  124. runbooks/inventory/unified_validation_engine.py +278 -251
  125. runbooks/inventory/vpc_analyzer.py +732 -695
  126. runbooks/inventory/vpc_architecture_validator.py +293 -348
  127. runbooks/inventory/vpc_dependency_analyzer.py +382 -378
  128. runbooks/inventory/vpc_flow_analyzer.py +1 -1
  129. runbooks/main.py +49 -34
  130. runbooks/main_final.py +91 -60
  131. runbooks/main_minimal.py +22 -10
  132. runbooks/main_optimized.py +131 -100
  133. runbooks/main_ultra_minimal.py +7 -2
  134. runbooks/mcp/__init__.py +36 -0
  135. runbooks/mcp/integration.py +679 -0
  136. runbooks/monitoring/performance_monitor.py +9 -4
  137. runbooks/operate/dynamodb_operations.py +3 -1
  138. runbooks/operate/ec2_operations.py +145 -137
  139. runbooks/operate/iam_operations.py +146 -152
  140. runbooks/operate/networking_cost_heatmap.py +29 -8
  141. runbooks/operate/rds_operations.py +223 -254
  142. runbooks/operate/s3_operations.py +107 -118
  143. runbooks/operate/vpc_operations.py +646 -616
  144. runbooks/remediation/base.py +1 -1
  145. runbooks/remediation/commons.py +10 -7
  146. runbooks/remediation/commvault_ec2_analysis.py +70 -66
  147. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
  148. runbooks/remediation/multi_account.py +24 -21
  149. runbooks/remediation/rds_snapshot_list.py +86 -60
  150. runbooks/remediation/remediation_cli.py +92 -146
  151. runbooks/remediation/universal_account_discovery.py +83 -79
  152. runbooks/remediation/workspaces_list.py +46 -41
  153. runbooks/security/__init__.py +19 -0
  154. runbooks/security/assessment_runner.py +1150 -0
  155. runbooks/security/baseline_checker.py +812 -0
  156. runbooks/security/cloudops_automation_security_validator.py +509 -535
  157. runbooks/security/compliance_automation_engine.py +17 -17
  158. runbooks/security/config/__init__.py +2 -2
  159. runbooks/security/config/compliance_config.py +50 -50
  160. runbooks/security/config_template_generator.py +63 -76
  161. runbooks/security/enterprise_security_framework.py +1 -1
  162. runbooks/security/executive_security_dashboard.py +519 -508
  163. runbooks/security/multi_account_security_controls.py +959 -1210
  164. runbooks/security/real_time_security_monitor.py +422 -444
  165. runbooks/security/security_baseline_tester.py +1 -1
  166. runbooks/security/security_cli.py +143 -112
  167. runbooks/security/test_2way_validation.py +439 -0
  168. runbooks/security/two_way_validation_framework.py +852 -0
  169. runbooks/sre/production_monitoring_framework.py +167 -177
  170. runbooks/tdd/__init__.py +15 -0
  171. runbooks/tdd/cli.py +1071 -0
  172. runbooks/utils/__init__.py +14 -17
  173. runbooks/utils/logger.py +7 -2
  174. runbooks/utils/version_validator.py +50 -47
  175. runbooks/validation/__init__.py +6 -6
  176. runbooks/validation/cli.py +9 -3
  177. runbooks/validation/comprehensive_2way_validator.py +745 -704
  178. runbooks/validation/mcp_validator.py +906 -228
  179. runbooks/validation/terraform_citations_validator.py +104 -115
  180. runbooks/validation/terraform_drift_detector.py +447 -451
  181. runbooks/vpc/README.md +617 -0
  182. runbooks/vpc/__init__.py +8 -1
  183. runbooks/vpc/analyzer.py +577 -0
  184. runbooks/vpc/cleanup_wrapper.py +476 -413
  185. runbooks/vpc/cli_cloudtrail_commands.py +339 -0
  186. runbooks/vpc/cli_mcp_validation_commands.py +480 -0
  187. runbooks/vpc/cloudtrail_audit_integration.py +717 -0
  188. runbooks/vpc/config.py +92 -97
  189. runbooks/vpc/cost_engine.py +411 -148
  190. runbooks/vpc/cost_explorer_integration.py +553 -0
  191. runbooks/vpc/cross_account_session.py +101 -106
  192. runbooks/vpc/enhanced_mcp_validation.py +917 -0
  193. runbooks/vpc/eni_gate_validator.py +961 -0
  194. runbooks/vpc/heatmap_engine.py +185 -160
  195. runbooks/vpc/mcp_no_eni_validator.py +680 -639
  196. runbooks/vpc/nat_gateway_optimizer.py +358 -0
  197. runbooks/vpc/networking_wrapper.py +15 -8
  198. runbooks/vpc/pdca_remediation_planner.py +528 -0
  199. runbooks/vpc/performance_optimized_analyzer.py +219 -231
  200. runbooks/vpc/runbooks_adapter.py +1167 -241
  201. runbooks/vpc/tdd_red_phase_stubs.py +601 -0
  202. runbooks/vpc/test_data_loader.py +358 -0
  203. runbooks/vpc/tests/conftest.py +314 -4
  204. runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
  205. runbooks/vpc/tests/test_cost_engine.py +0 -2
  206. runbooks/vpc/topology_generator.py +326 -0
  207. runbooks/vpc/unified_scenarios.py +1297 -1124
  208. runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
  209. runbooks-1.1.5.dist-info/METADATA +328 -0
  210. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/RECORD +214 -193
  211. runbooks/finops/README.md +0 -414
  212. runbooks/finops/accuracy_cross_validator.py +0 -647
  213. runbooks/finops/business_cases.py +0 -950
  214. runbooks/finops/dashboard_router.py +0 -922
  215. runbooks/finops/ebs_optimizer.py +0 -973
  216. runbooks/finops/embedded_mcp_validator.py +0 -1629
  217. runbooks/finops/enhanced_dashboard_runner.py +0 -527
  218. runbooks/finops/finops_dashboard.py +0 -584
  219. runbooks/finops/finops_scenarios.py +0 -1218
  220. runbooks/finops/legacy_migration.py +0 -730
  221. runbooks/finops/multi_dashboard.py +0 -1519
  222. runbooks/finops/single_dashboard.py +0 -1113
  223. runbooks/finops/unlimited_scenarios.py +0 -393
  224. runbooks-1.1.4.dist-info/METADATA +0 -800
  225. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/WHEEL +0 -0
  226. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/entry_points.txt +0 -0
  227. {runbooks-1.1.4.dist-info → runbooks-1.1.5.dist-info}/licenses/LICENSE +0 -0
  228. {runbooks-1.1.4.dist-info → runbooks-1.1.5.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
- "success": False,
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(self,
92
- resources: List[str] = None,
93
- profile: str = None,
94
- all_accounts: bool = False,
95
- include_costs: bool = False,
96
- regions: List[str] = None) -> pd.DataFrame:
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-accounts")
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(f"[red]Error executing inventory command: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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(self,
142
- profile: str = None,
143
- all_accounts: bool = False,
144
- target_reduction: str = "20-40%",
145
- breakdown_by: List[str] = None,
146
- export_format: str = "json") -> Dict[str, Any]:
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-accounts")
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(f"[red]Error executing FinOps analysis: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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(self,
190
- profile: str = None,
191
- all_accounts: bool = False,
192
- checks: str = "all",
193
- language: str = "EN",
194
- format: str = "json") -> Dict[str, Any]:
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-accounts")
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(f"[red]Error executing security assessment: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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(self,
237
- profile: str = None,
238
- compliance_framework: str = "AWS Well-Architected",
239
- output_format: str = "json",
240
- serve_web: bool = False,
241
- port: int = 8080) -> Dict[str, Any]:
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(f"[red]Error executing CFAT assessment: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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(self, action: str, instance_ids: List[str], profile: str = None, dry_run: bool = True) -> Dict[str, Any]:
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(f"[red]❌ EC2 {action} operation failed: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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(f"[red]Error validating MCP servers: {result.get('error', result.get('stderr', 'Unknown error'))}[/red]")
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
- content,
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
- content,
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
- content,
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))