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.
Files changed (111) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/base.py +5 -1
  3. runbooks/cfat/__init__.py +8 -4
  4. runbooks/cfat/assessment/collectors.py +171 -14
  5. runbooks/cfat/assessment/compliance.py +871 -0
  6. runbooks/cfat/assessment/runner.py +122 -11
  7. runbooks/cfat/models.py +6 -2
  8. runbooks/common/logger.py +14 -0
  9. runbooks/common/rich_utils.py +451 -0
  10. runbooks/enterprise/__init__.py +68 -0
  11. runbooks/enterprise/error_handling.py +411 -0
  12. runbooks/enterprise/logging.py +439 -0
  13. runbooks/enterprise/multi_tenant.py +583 -0
  14. runbooks/finops/README.md +468 -241
  15. runbooks/finops/__init__.py +39 -3
  16. runbooks/finops/cli.py +83 -18
  17. runbooks/finops/cross_validation.py +375 -0
  18. runbooks/finops/dashboard_runner.py +812 -164
  19. runbooks/finops/enhanced_dashboard_runner.py +525 -0
  20. runbooks/finops/finops_dashboard.py +1892 -0
  21. runbooks/finops/helpers.py +485 -51
  22. runbooks/finops/optimizer.py +823 -0
  23. runbooks/finops/tests/__init__.py +19 -0
  24. runbooks/finops/tests/results_test_finops_dashboard.xml +1 -0
  25. runbooks/finops/tests/run_comprehensive_tests.py +421 -0
  26. runbooks/finops/tests/run_tests.py +305 -0
  27. runbooks/finops/tests/test_finops_dashboard.py +705 -0
  28. runbooks/finops/tests/test_integration.py +477 -0
  29. runbooks/finops/tests/test_performance.py +380 -0
  30. runbooks/finops/tests/test_performance_benchmarks.py +500 -0
  31. runbooks/finops/tests/test_reference_images_validation.py +867 -0
  32. runbooks/finops/tests/test_single_account_features.py +715 -0
  33. runbooks/finops/tests/validate_test_suite.py +220 -0
  34. runbooks/finops/types.py +1 -1
  35. runbooks/hitl/enhanced_workflow_engine.py +725 -0
  36. runbooks/inventory/artifacts/scale-optimize-status.txt +12 -0
  37. runbooks/inventory/collectors/aws_comprehensive.py +442 -0
  38. runbooks/inventory/collectors/enterprise_scale.py +281 -0
  39. runbooks/inventory/core/collector.py +172 -13
  40. runbooks/inventory/discovery.md +1 -1
  41. runbooks/inventory/list_ec2_instances.py +18 -20
  42. runbooks/inventory/list_ssm_parameters.py +31 -3
  43. runbooks/inventory/organizations_discovery.py +1269 -0
  44. runbooks/inventory/rich_inventory_display.py +393 -0
  45. runbooks/inventory/run_on_multi_accounts.py +35 -19
  46. runbooks/inventory/runbooks.security.report_generator.log +0 -0
  47. runbooks/inventory/runbooks.security.run_script.log +0 -0
  48. runbooks/inventory/vpc_flow_analyzer.py +1030 -0
  49. runbooks/main.py +2215 -119
  50. runbooks/metrics/dora_metrics_engine.py +599 -0
  51. runbooks/operate/__init__.py +2 -2
  52. runbooks/operate/base.py +122 -10
  53. runbooks/operate/deployment_framework.py +1032 -0
  54. runbooks/operate/deployment_validator.py +853 -0
  55. runbooks/operate/dynamodb_operations.py +10 -6
  56. runbooks/operate/ec2_operations.py +319 -11
  57. runbooks/operate/executive_dashboard.py +779 -0
  58. runbooks/operate/mcp_integration.py +750 -0
  59. runbooks/operate/nat_gateway_operations.py +1120 -0
  60. runbooks/operate/networking_cost_heatmap.py +685 -0
  61. runbooks/operate/privatelink_operations.py +940 -0
  62. runbooks/operate/s3_operations.py +10 -6
  63. runbooks/operate/vpc_endpoints.py +644 -0
  64. runbooks/operate/vpc_operations.py +1038 -0
  65. runbooks/remediation/__init__.py +2 -2
  66. runbooks/remediation/acm_remediation.py +1 -1
  67. runbooks/remediation/base.py +1 -1
  68. runbooks/remediation/cloudtrail_remediation.py +1 -1
  69. runbooks/remediation/cognito_remediation.py +1 -1
  70. runbooks/remediation/dynamodb_remediation.py +1 -1
  71. runbooks/remediation/ec2_remediation.py +1 -1
  72. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -1
  73. runbooks/remediation/kms_enable_key_rotation.py +1 -1
  74. runbooks/remediation/kms_remediation.py +1 -1
  75. runbooks/remediation/lambda_remediation.py +1 -1
  76. runbooks/remediation/multi_account.py +1 -1
  77. runbooks/remediation/rds_remediation.py +1 -1
  78. runbooks/remediation/s3_block_public_access.py +1 -1
  79. runbooks/remediation/s3_enable_access_logging.py +1 -1
  80. runbooks/remediation/s3_encryption.py +1 -1
  81. runbooks/remediation/s3_remediation.py +1 -1
  82. runbooks/remediation/vpc_remediation.py +475 -0
  83. runbooks/security/__init__.py +3 -1
  84. runbooks/security/compliance_automation.py +632 -0
  85. runbooks/security/report_generator.py +10 -0
  86. runbooks/security/run_script.py +31 -5
  87. runbooks/security/security_baseline_tester.py +169 -30
  88. runbooks/security/security_export.py +477 -0
  89. runbooks/validation/__init__.py +10 -0
  90. runbooks/validation/benchmark.py +484 -0
  91. runbooks/validation/cli.py +356 -0
  92. runbooks/validation/mcp_validator.py +768 -0
  93. runbooks/vpc/__init__.py +38 -0
  94. runbooks/vpc/config.py +212 -0
  95. runbooks/vpc/cost_engine.py +347 -0
  96. runbooks/vpc/heatmap_engine.py +605 -0
  97. runbooks/vpc/manager_interface.py +634 -0
  98. runbooks/vpc/networking_wrapper.py +1260 -0
  99. runbooks/vpc/rich_formatters.py +679 -0
  100. runbooks/vpc/tests/__init__.py +5 -0
  101. runbooks/vpc/tests/conftest.py +356 -0
  102. runbooks/vpc/tests/test_cli_integration.py +530 -0
  103. runbooks/vpc/tests/test_config.py +458 -0
  104. runbooks/vpc/tests/test_cost_engine.py +479 -0
  105. runbooks/vpc/tests/test_networking_wrapper.py +512 -0
  106. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/METADATA +40 -12
  107. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/RECORD +111 -50
  108. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/WHEEL +0 -0
  109. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/entry_points.txt +0 -0
  110. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/licenses/LICENSE +0 -0
  111. {runbooks-0.7.6.dist-info → runbooks-0.7.9.dist-info}/top_level.txt +0 -0
runbooks/operate/base.py CHANGED
@@ -11,14 +11,30 @@ from dataclasses import dataclass, field
11
11
  from datetime import datetime
12
12
  from enum import Enum
13
13
  from typing import Any, Dict, List, Optional, Union
14
+ import time
14
15
 
15
16
  import boto3
16
17
  from botocore.exceptions import ClientError, NoCredentialsError
17
18
  from loguru import logger
19
+ from rich.console import Console
20
+ from rich.progress import Progress, SpinnerColumn, TextColumn
21
+ from rich.panel import Panel
22
+ from rich.table import Table
18
23
 
19
24
  from runbooks.inventory.models.account import AWSAccount
20
25
  from runbooks.inventory.utils.aws_helpers import aws_api_retry, get_boto3_session
21
26
 
27
+ # Enterprise 4-Profile Architecture - Proven FinOps Patterns
28
+ ENTERPRISE_PROFILES = {
29
+ "BILLING_PROFILE": "ams-admin-Billing-ReadOnlyAccess-909135376185",
30
+ "MANAGEMENT_PROFILE": "ams-admin-ReadOnlyAccess-909135376185",
31
+ "CENTRALISED_OPS_PROFILE": "ams-centralised-ops-ReadOnlyAccess-335083429030",
32
+ "SINGLE_ACCOUNT_PROFILE": "ams-shared-services-non-prod-ReadOnlyAccess-499201730520"
33
+ }
34
+
35
+ # Rich console instance for consistent formatting
36
+ console = Console()
37
+
22
38
 
23
39
  class OperationStatus(Enum):
24
40
  """Status of an AWS operation."""
@@ -118,18 +134,28 @@ class BaseOperation(ABC):
118
134
 
119
135
  def __init__(self, profile: Optional[str] = None, region: Optional[str] = None, dry_run: bool = False):
120
136
  """
121
- Initialize base operation class.
137
+ Initialize base operation class with enterprise patterns.
122
138
 
123
139
  Args:
124
- profile: AWS profile name for authentication
140
+ profile: AWS profile name for authentication (supports ENTERPRISE_PROFILES)
125
141
  region: AWS region for operations
126
142
  dry_run: Enable dry-run mode for safe testing
127
143
  """
128
- self.profile = profile
144
+ # Support enterprise profile shortcuts
145
+ if profile in ENTERPRISE_PROFILES:
146
+ self.profile = ENTERPRISE_PROFILES[profile]
147
+ console.print(f"[blue]Using enterprise profile: {profile} -> {self.profile}[/blue]")
148
+ else:
149
+ self.profile = profile
150
+
129
151
  self.region = region or "us-east-1"
130
152
  self.dry_run = dry_run
131
153
  self._session = None
132
154
  self._clients = {}
155
+
156
+ # Performance benchmarking
157
+ self._operation_start_time = None
158
+ self._performance_target = 2.0 # <2s target for operate operations
133
159
 
134
160
  @property
135
161
  def session(self) -> boto3.Session:
@@ -185,7 +211,7 @@ class BaseOperation(ABC):
185
211
 
186
212
  def confirm_operation(self, context: OperationContext, resource_id: str, operation_type: str) -> bool:
187
213
  """
188
- Request user confirmation for destructive operations.
214
+ Request user confirmation for destructive operations with Rich CLI.
189
215
 
190
216
  Args:
191
217
  context: Operation context
@@ -196,16 +222,24 @@ class BaseOperation(ABC):
196
222
  True if operation is confirmed
197
223
  """
198
224
  if context.dry_run:
199
- logger.info(f"[DRY-RUN] Would perform {operation_type} on {resource_id}")
225
+ console.print(Panel(
226
+ f"[yellow]Would perform {operation_type} on {resource_id}[/yellow]",
227
+ title="🏃 DRY-RUN MODE",
228
+ border_style="yellow"
229
+ ))
200
230
  return True
201
231
 
202
232
  if context.force or not self.requires_confirmation:
203
233
  return True
204
234
 
205
- # In a real implementation, this would integrate with CLI for confirmation
206
- logger.warning(
207
- f"Destructive operation: {operation_type} on {resource_id} in account {context.account.account_id}"
208
- )
235
+ # Rich CLI confirmation display
236
+ console.print(Panel(
237
+ f"[red]⚠️ Destructive operation: {operation_type}[/red]\n"
238
+ f"[white]Resource: {resource_id}[/white]\n"
239
+ f"[white]Account: {context.account.account_id}[/white]",
240
+ title="🚨 CONFIRMATION REQUIRED",
241
+ border_style="red"
242
+ ))
209
243
  return True # Simplified for this implementation
210
244
 
211
245
  @aws_api_retry
@@ -307,5 +341,83 @@ class BaseOperation(ABC):
307
341
  List of historical operation results
308
342
  """
309
343
  # In a real implementation, this would query a database or log store
310
- logger.info(f"Operation history requested for {resource_id or 'all resources'}")
344
+ console.print(f"[blue]📊 Operation history requested for {resource_id or 'all resources'}[/blue]")
311
345
  return []
346
+
347
+ def start_performance_benchmark(self) -> None:
348
+ """Start performance timing for operation benchmarking."""
349
+ self._operation_start_time = time.time()
350
+
351
+ def end_performance_benchmark(self, operation_name: str) -> float:
352
+ """
353
+ End performance timing and display results.
354
+
355
+ Args:
356
+ operation_name: Name of the operation for reporting
357
+
358
+ Returns:
359
+ Elapsed time in seconds
360
+ """
361
+ if self._operation_start_time is None:
362
+ return 0.0
363
+
364
+ elapsed_time = time.time() - self._operation_start_time
365
+
366
+ # Performance validation against target
367
+ if elapsed_time <= self._performance_target:
368
+ console.print(f"[green]⚡ {operation_name} completed in {elapsed_time:.2f}s (target: {self._performance_target}s) ✅[/green]")
369
+ else:
370
+ console.print(f"[yellow]⚠️ {operation_name} completed in {elapsed_time:.2f}s (exceeded target: {self._performance_target}s)[/yellow]")
371
+
372
+ self._operation_start_time = None
373
+ return elapsed_time
374
+
375
+ def display_operation_summary(self, results: List[OperationResult]) -> None:
376
+ """
377
+ Display operation summary using Rich table formatting.
378
+
379
+ Args:
380
+ results: List of operation results to summarize
381
+ """
382
+ if not results:
383
+ console.print("[yellow]No operations to display[/yellow]")
384
+ return
385
+
386
+ table = Table(title="🔧 Operation Summary")
387
+ table.add_column("Operation", style="cyan")
388
+ table.add_column("Resource", style="magenta")
389
+ table.add_column("Status", style="green")
390
+ table.add_column("Duration", style="blue")
391
+
392
+ success_count = 0
393
+ total_count = len(results)
394
+
395
+ for result in results:
396
+ status_icon = "✅" if result.success else "❌"
397
+ status_text = f"{status_icon} {result.status.value}"
398
+
399
+ duration = "N/A"
400
+ if result.completed_at and result.started_at:
401
+ elapsed = (result.completed_at - result.started_at).total_seconds()
402
+ duration = f"{elapsed:.2f}s"
403
+
404
+ if result.success:
405
+ success_count += 1
406
+
407
+ table.add_row(
408
+ result.operation_type,
409
+ result.resource_id,
410
+ status_text,
411
+ duration
412
+ )
413
+
414
+ console.print(table)
415
+
416
+ # Success rate summary
417
+ success_rate = (success_count / total_count) * 100 if total_count > 0 else 0
418
+ if success_rate >= 95:
419
+ console.print(f"[green]🎯 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Excellent![/green]")
420
+ elif success_rate >= 90:
421
+ console.print(f"[yellow]📊 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Good[/yellow]")
422
+ else:
423
+ console.print(f"[red]⚠️ Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Needs Attention[/red]")