runbooks 0.7.9__py3-none-any.whl → 0.9.0__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 (95) hide show
  1. runbooks/__init__.py +1 -1
  2. runbooks/cfat/README.md +12 -1
  3. runbooks/cfat/__init__.py +1 -1
  4. runbooks/cfat/assessment/runner.py +42 -34
  5. runbooks/cfat/models.py +1 -1
  6. runbooks/common/__init__.py +152 -0
  7. runbooks/common/accuracy_validator.py +1039 -0
  8. runbooks/common/context_logger.py +440 -0
  9. runbooks/common/cross_module_integration.py +594 -0
  10. runbooks/common/enhanced_exception_handler.py +1108 -0
  11. runbooks/common/enterprise_audit_integration.py +634 -0
  12. runbooks/common/mcp_integration.py +539 -0
  13. runbooks/common/performance_monitor.py +387 -0
  14. runbooks/common/profile_utils.py +216 -0
  15. runbooks/common/rich_utils.py +171 -0
  16. runbooks/feedback/user_feedback_collector.py +440 -0
  17. runbooks/finops/README.md +339 -451
  18. runbooks/finops/__init__.py +4 -21
  19. runbooks/finops/account_resolver.py +279 -0
  20. runbooks/finops/accuracy_cross_validator.py +638 -0
  21. runbooks/finops/aws_client.py +721 -36
  22. runbooks/finops/budget_integration.py +313 -0
  23. runbooks/finops/cli.py +59 -5
  24. runbooks/finops/cost_processor.py +211 -37
  25. runbooks/finops/dashboard_router.py +900 -0
  26. runbooks/finops/dashboard_runner.py +990 -232
  27. runbooks/finops/embedded_mcp_validator.py +288 -0
  28. runbooks/finops/enhanced_dashboard_runner.py +8 -7
  29. runbooks/finops/enhanced_progress.py +327 -0
  30. runbooks/finops/enhanced_trend_visualization.py +423 -0
  31. runbooks/finops/finops_dashboard.py +29 -1880
  32. runbooks/finops/helpers.py +509 -196
  33. runbooks/finops/iam_guidance.py +400 -0
  34. runbooks/finops/markdown_exporter.py +466 -0
  35. runbooks/finops/multi_dashboard.py +1502 -0
  36. runbooks/finops/optimizer.py +15 -15
  37. runbooks/finops/profile_processor.py +2 -2
  38. runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
  39. runbooks/finops/runbooks.security.report_generator.log +0 -0
  40. runbooks/finops/runbooks.security.run_script.log +0 -0
  41. runbooks/finops/runbooks.security.security_export.log +0 -0
  42. runbooks/finops/service_mapping.py +195 -0
  43. runbooks/finops/single_dashboard.py +710 -0
  44. runbooks/finops/tests/test_reference_images_validation.py +1 -1
  45. runbooks/inventory/README.md +12 -1
  46. runbooks/inventory/core/collector.py +157 -29
  47. runbooks/inventory/list_ec2_instances.py +9 -6
  48. runbooks/inventory/list_ssm_parameters.py +10 -10
  49. runbooks/inventory/organizations_discovery.py +210 -164
  50. runbooks/inventory/rich_inventory_display.py +74 -107
  51. runbooks/inventory/run_on_multi_accounts.py +13 -13
  52. runbooks/main.py +740 -134
  53. runbooks/metrics/dora_metrics_engine.py +711 -17
  54. runbooks/monitoring/performance_monitor.py +433 -0
  55. runbooks/operate/README.md +394 -0
  56. runbooks/operate/base.py +215 -47
  57. runbooks/operate/ec2_operations.py +7 -5
  58. runbooks/operate/privatelink_operations.py +1 -1
  59. runbooks/operate/vpc_endpoints.py +1 -1
  60. runbooks/remediation/README.md +489 -13
  61. runbooks/remediation/commons.py +8 -4
  62. runbooks/security/ENTERPRISE_SECURITY_FRAMEWORK.md +506 -0
  63. runbooks/security/README.md +12 -1
  64. runbooks/security/__init__.py +164 -33
  65. runbooks/security/compliance_automation.py +12 -10
  66. runbooks/security/compliance_automation_engine.py +1021 -0
  67. runbooks/security/enterprise_security_framework.py +931 -0
  68. runbooks/security/enterprise_security_policies.json +293 -0
  69. runbooks/security/integration_test_enterprise_security.py +879 -0
  70. runbooks/security/module_security_integrator.py +641 -0
  71. runbooks/security/report_generator.py +1 -1
  72. runbooks/security/run_script.py +4 -8
  73. runbooks/security/security_baseline_tester.py +36 -49
  74. runbooks/security/security_export.py +99 -120
  75. runbooks/sre/README.md +472 -0
  76. runbooks/sre/__init__.py +33 -0
  77. runbooks/sre/mcp_reliability_engine.py +1049 -0
  78. runbooks/sre/performance_optimization_engine.py +1032 -0
  79. runbooks/sre/reliability_monitoring_framework.py +1011 -0
  80. runbooks/validation/__init__.py +2 -2
  81. runbooks/validation/benchmark.py +154 -149
  82. runbooks/validation/cli.py +159 -147
  83. runbooks/validation/mcp_validator.py +265 -236
  84. runbooks/vpc/README.md +478 -0
  85. runbooks/vpc/__init__.py +2 -2
  86. runbooks/vpc/manager_interface.py +366 -351
  87. runbooks/vpc/networking_wrapper.py +62 -33
  88. runbooks/vpc/rich_formatters.py +22 -8
  89. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/METADATA +136 -54
  90. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/RECORD +94 -55
  91. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/entry_points.txt +1 -1
  92. runbooks/finops/cross_validation.py +0 -375
  93. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/WHEEL +0 -0
  94. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/licenses/LICENSE +0 -0
  95. {runbooks-0.7.9.dist-info → runbooks-0.9.0.dist-info}/top_level.txt +0 -0
runbooks/operate/base.py CHANGED
@@ -6,30 +6,35 @@ ensuring consistent patterns, safety features, and enterprise-grade reliability
6
6
  across all service-specific operations.
7
7
  """
8
8
 
9
+ import asyncio
10
+ import time
9
11
  from abc import ABC, abstractmethod
10
12
  from dataclasses import dataclass, field
11
13
  from datetime import datetime
12
14
  from enum import Enum
13
- from typing import Any, Dict, List, Optional, Union
14
- import time
15
+ from typing import Any, Callable, Dict, List, Optional, Union
15
16
 
16
17
  import boto3
17
18
  from botocore.exceptions import ClientError, NoCredentialsError
18
19
  from loguru import logger
19
20
  from rich.console import Console
20
- from rich.progress import Progress, SpinnerColumn, TextColumn
21
21
  from rich.panel import Panel
22
+ from rich.progress import Progress, SpinnerColumn, TextColumn
22
23
  from rich.table import Table
23
24
 
25
+ from runbooks.common.cross_module_integration import DataFlowType, EnterpriseCrossModuleIntegrator
26
+ from runbooks.common.mcp_integration import EnterpriseMCPIntegrator, MCPOperationType
27
+ from runbooks.common.profile_utils import create_operational_session, get_profile_for_operation
28
+ from runbooks.common.rich_utils import print_error, print_info, print_success, print_warning
24
29
  from runbooks.inventory.models.account import AWSAccount
25
30
  from runbooks.inventory.utils.aws_helpers import aws_api_retry, get_boto3_session
26
31
 
27
32
  # Enterprise 4-Profile Architecture - Proven FinOps Patterns
28
33
  ENTERPRISE_PROFILES = {
29
34
  "BILLING_PROFILE": "ams-admin-Billing-ReadOnlyAccess-909135376185",
30
- "MANAGEMENT_PROFILE": "ams-admin-ReadOnlyAccess-909135376185",
35
+ "MANAGEMENT_PROFILE": "ams-admin-ReadOnlyAccess-909135376185",
31
36
  "CENTRALISED_OPS_PROFILE": "ams-centralised-ops-ReadOnlyAccess-335083429030",
32
- "SINGLE_ACCOUNT_PROFILE": "ams-shared-services-non-prod-ReadOnlyAccess-499201730520"
37
+ "SINGLE_ACCOUNT_PROFILE": "ams-shared-services-non-prod-ReadOnlyAccess-499201730520",
33
38
  }
34
39
 
35
40
  # Rich console instance for consistent formatting
@@ -147,16 +152,23 @@ class BaseOperation(ABC):
147
152
  console.print(f"[blue]Using enterprise profile: {profile} -> {self.profile}[/blue]")
148
153
  else:
149
154
  self.profile = profile
150
-
155
+
151
156
  self.region = region or "us-east-1"
152
157
  self.dry_run = dry_run
153
158
  self._session = None
154
159
  self._clients = {}
155
-
160
+
156
161
  # Performance benchmarking
157
162
  self._operation_start_time = None
158
163
  self._performance_target = 2.0 # <2s target for operate operations
159
164
 
165
+ # Phase 4: MCP Integration Framework
166
+ self.mcp_integrator = EnterpriseMCPIntegrator(self.profile)
167
+ self.cross_module_integrator = EnterpriseCrossModuleIntegrator(self.profile)
168
+ self.enable_mcp_validation = True
169
+
170
+ print_info(f"BaseOperation initialized with MCP integration for {self.service_name or 'unknown'} service")
171
+
160
172
  @property
161
173
  def session(self) -> boto3.Session:
162
174
  """Get or create AWS session."""
@@ -222,24 +234,28 @@ class BaseOperation(ABC):
222
234
  True if operation is confirmed
223
235
  """
224
236
  if context.dry_run:
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
- ))
237
+ console.print(
238
+ Panel(
239
+ f"[yellow]Would perform {operation_type} on {resource_id}[/yellow]",
240
+ title="🏃 DRY-RUN MODE",
241
+ border_style="yellow",
242
+ )
243
+ )
230
244
  return True
231
245
 
232
246
  if context.force or not self.requires_confirmation:
233
247
  return True
234
248
 
235
249
  # 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
- ))
250
+ console.print(
251
+ Panel(
252
+ f"[red]⚠️ Destructive operation: {operation_type}[/red]\n"
253
+ f"[white]Resource: {resource_id}[/white]\n"
254
+ f"[white]Account: {context.account.account_id}[/white]",
255
+ title="🚨 CONFIRMATION REQUIRED",
256
+ border_style="red",
257
+ )
258
+ )
243
259
  return True # Simplified for this implementation
244
260
 
245
261
  @aws_api_retry
@@ -343,81 +359,233 @@ class BaseOperation(ABC):
343
359
  # In a real implementation, this would query a database or log store
344
360
  console.print(f"[blue]📊 Operation history requested for {resource_id or 'all resources'}[/blue]")
345
361
  return []
346
-
362
+
347
363
  def start_performance_benchmark(self) -> None:
348
364
  """Start performance timing for operation benchmarking."""
349
365
  self._operation_start_time = time.time()
350
-
366
+
351
367
  def end_performance_benchmark(self, operation_name: str) -> float:
352
368
  """
353
369
  End performance timing and display results.
354
-
370
+
355
371
  Args:
356
372
  operation_name: Name of the operation for reporting
357
-
373
+
358
374
  Returns:
359
375
  Elapsed time in seconds
360
376
  """
361
377
  if self._operation_start_time is None:
362
378
  return 0.0
363
-
379
+
364
380
  elapsed_time = time.time() - self._operation_start_time
365
-
381
+
366
382
  # Performance validation against target
367
383
  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]")
384
+ console.print(
385
+ f"[green]⚡ {operation_name} completed in {elapsed_time:.2f}s (target: {self._performance_target}s) ✅[/green]"
386
+ )
369
387
  else:
370
- console.print(f"[yellow]⚠️ {operation_name} completed in {elapsed_time:.2f}s (exceeded target: {self._performance_target}s)[/yellow]")
371
-
388
+ console.print(
389
+ f"[yellow]⚠️ {operation_name} completed in {elapsed_time:.2f}s (exceeded target: {self._performance_target}s)[/yellow]"
390
+ )
391
+
372
392
  self._operation_start_time = None
373
393
  return elapsed_time
374
-
394
+
375
395
  def display_operation_summary(self, results: List[OperationResult]) -> None:
376
396
  """
377
397
  Display operation summary using Rich table formatting.
378
-
398
+
379
399
  Args:
380
400
  results: List of operation results to summarize
381
401
  """
382
402
  if not results:
383
403
  console.print("[yellow]No operations to display[/yellow]")
384
404
  return
385
-
405
+
386
406
  table = Table(title="🔧 Operation Summary")
387
407
  table.add_column("Operation", style="cyan")
388
408
  table.add_column("Resource", style="magenta")
389
409
  table.add_column("Status", style="green")
390
410
  table.add_column("Duration", style="blue")
391
-
411
+
392
412
  success_count = 0
393
413
  total_count = len(results)
394
-
414
+
395
415
  for result in results:
396
416
  status_icon = "✅" if result.success else "❌"
397
417
  status_text = f"{status_icon} {result.status.value}"
398
-
418
+
399
419
  duration = "N/A"
400
420
  if result.completed_at and result.started_at:
401
421
  elapsed = (result.completed_at - result.started_at).total_seconds()
402
422
  duration = f"{elapsed:.2f}s"
403
-
423
+
404
424
  if result.success:
405
425
  success_count += 1
406
-
407
- table.add_row(
408
- result.operation_type,
409
- result.resource_id,
410
- status_text,
411
- duration
412
- )
413
-
426
+
427
+ table.add_row(result.operation_type, result.resource_id, status_text, duration)
428
+
414
429
  console.print(table)
415
-
430
+
416
431
  # Success rate summary
417
432
  success_rate = (success_count / total_count) * 100 if total_count > 0 else 0
418
433
  if success_rate >= 95:
419
- console.print(f"[green]🎯 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Excellent![/green]")
434
+ console.print(
435
+ f"[green]🎯 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Excellent![/green]"
436
+ )
420
437
  elif success_rate >= 90:
421
- console.print(f"[yellow]📊 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Good[/yellow]")
438
+ console.print(
439
+ f"[yellow]📊 Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Good[/yellow]"
440
+ )
422
441
  else:
423
- console.print(f"[red]⚠️ Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Needs Attention[/red]")
442
+ console.print(
443
+ f"[red]⚠️ Success Rate: {success_rate:.1f}% ({success_count}/{total_count}) - Needs Attention[/red]"
444
+ )
445
+
446
+ # Phase 4: MCP Integration Methods
447
+ async def validate_operation_with_mcp(self, operation_data: Dict[str, Any]) -> Dict[str, Any]:
448
+ """
449
+ Validate operation results using MCP integration.
450
+
451
+ Args:
452
+ operation_data: Operation results to validate
453
+
454
+ Returns:
455
+ Dictionary containing validation results
456
+ """
457
+ try:
458
+ if not self.enable_mcp_validation:
459
+ return {"validation_skipped": True, "reason": "MCP validation disabled"}
460
+
461
+ print_info("Validating operation results with MCP integration")
462
+
463
+ validation_result = await self.mcp_integrator.validate_operate_operations(operation_data)
464
+
465
+ if validation_result.success:
466
+ print_success(f"Operation MCP validation passed: {validation_result.accuracy_score}% accuracy")
467
+ else:
468
+ print_warning("Operation MCP validation encountered issues")
469
+
470
+ return validation_result.to_dict()
471
+
472
+ except Exception as e:
473
+ print_error(f"MCP validation failed: {str(e)[:50]}...")
474
+ return {"validation_error": str(e), "validation_failed": True}
475
+
476
+ async def prepare_data_for_finops_analysis(self, operation_results: List[OperationResult]) -> Dict[str, Any]:
477
+ """
478
+ Prepare operation results for FinOps cost analysis integration.
479
+
480
+ Args:
481
+ operation_results: List of operation results
482
+
483
+ Returns:
484
+ Dictionary formatted for FinOps module consumption
485
+ """
486
+ try:
487
+ print_info("Preparing operation data for FinOps analysis")
488
+
489
+ # Convert operation results to data flow format
490
+ operation_data = {
491
+ "operations": [
492
+ {
493
+ "id": result.operation_id,
494
+ "type": result.operation_type,
495
+ "resource_id": result.resource_id,
496
+ "resource_type": result.resource_type,
497
+ "account_id": result.account_id,
498
+ "region": result.region,
499
+ "success": result.success,
500
+ "started_at": result.started_at.isoformat(),
501
+ "completed_at": result.completed_at.isoformat() if result.completed_at else None,
502
+ "metadata": result.metadata,
503
+ }
504
+ for result in operation_results
505
+ ]
506
+ }
507
+
508
+ data_flow_result = await self.cross_module_integrator.execute_data_flow(
509
+ flow_type=DataFlowType.OPERATE_TO_FINOPS, source_data=operation_data
510
+ )
511
+
512
+ if data_flow_result.success:
513
+ print_success("Operate → FinOps data flow completed successfully")
514
+ return data_flow_result.transformed_data
515
+ else:
516
+ print_error(f"Data flow failed: {', '.join(data_flow_result.error_details)}")
517
+ return {}
518
+
519
+ except Exception as e:
520
+ print_error(f"Failed to prepare data for FinOps analysis: {str(e)}")
521
+ return {}
522
+
523
+ def execute_operation_with_validation(
524
+ self, context: OperationContext, operation_func: Callable, *args, **kwargs
525
+ ) -> List[OperationResult]:
526
+ """
527
+ Execute operation with automatic MCP validation and performance tracking.
528
+
529
+ Args:
530
+ context: Operation context
531
+ operation_func: Operation function to execute
532
+ *args: Arguments for operation function
533
+ **kwargs: Keyword arguments for operation function
534
+
535
+ Returns:
536
+ List of operation results with MCP validation
537
+ """
538
+ self.start_performance_benchmark()
539
+
540
+ try:
541
+ # Execute the operation
542
+ results = operation_func(context, *args, **kwargs)
543
+
544
+ # Add MCP validation asynchronously if enabled
545
+ if self.enable_mcp_validation and results:
546
+ try:
547
+ operation_data = {
548
+ "operations": [result.__dict__ for result in results],
549
+ "context": context.__dict__,
550
+ }
551
+
552
+ validation_result = asyncio.run(self.validate_operation_with_mcp(operation_data))
553
+
554
+ # Add validation results to operation metadata
555
+ for result in results:
556
+ result.metadata["mcp_validation"] = validation_result
557
+
558
+ except Exception as e:
559
+ print_warning(f"MCP validation failed: {str(e)[:50]}... - operation completed without validation")
560
+
561
+ # End performance benchmark
562
+ elapsed_time = self.end_performance_benchmark(f"{context.operation_type} operation")
563
+
564
+ # Add performance metrics to results
565
+ for result in results:
566
+ result.metadata["performance_seconds"] = elapsed_time
567
+ result.metadata["performance_target_met"] = elapsed_time <= self._performance_target
568
+
569
+ return results
570
+
571
+ except Exception as e:
572
+ self.end_performance_benchmark(f"{context.operation_type} operation (failed)")
573
+ raise e
574
+
575
+ def get_mcp_integration_status(self) -> Dict[str, Any]:
576
+ """
577
+ Get current MCP integration status and configuration.
578
+
579
+ Returns:
580
+ Dictionary containing MCP integration details
581
+ """
582
+ return {
583
+ "service_name": self.service_name,
584
+ "mcp_validation_enabled": self.enable_mcp_validation,
585
+ "mcp_integrator_initialized": self.mcp_integrator is not None,
586
+ "cross_module_integrator_initialized": self.cross_module_integrator is not None,
587
+ "supported_operations": list(self.supported_operations),
588
+ "performance_target_seconds": self._performance_target,
589
+ "profile": self.profile,
590
+ "region": self.region,
591
+ }
@@ -200,11 +200,13 @@ class EC2Operations(BaseOperation):
200
200
 
201
201
  try:
202
202
  if context.dry_run:
203
- console.print(Panel(
204
- f"[yellow]Would start instance {instance_id}[/yellow]",
205
- title="🏃 DRY-RUN MODE",
206
- border_style="yellow"
207
- ))
203
+ console.print(
204
+ Panel(
205
+ f"[yellow]Would start instance {instance_id}[/yellow]",
206
+ title="🏃 DRY-RUN MODE",
207
+ border_style="yellow",
208
+ )
209
+ )
208
210
  result.mark_completed(OperationStatus.DRY_RUN)
209
211
  else:
210
212
  response = self.execute_aws_call(ec2_client, "start_instances", InstanceIds=[instance_id])
@@ -31,7 +31,6 @@ from typing import Any, Dict, List, Optional, Set, Tuple
31
31
  import boto3
32
32
  from botocore.exceptions import BotoCoreError, ClientError
33
33
 
34
- from runbooks.operate.base import BaseOperation, OperationResult
35
34
  from runbooks.common.rich_utils import (
36
35
  console,
37
36
  create_panel,
@@ -43,6 +42,7 @@ from runbooks.common.rich_utils import (
43
42
  print_success,
44
43
  print_warning,
45
44
  )
45
+ from runbooks.operate.base import BaseOperation, OperationResult
46
46
 
47
47
  logger = logging.getLogger(__name__)
48
48
 
@@ -29,7 +29,6 @@ from typing import Any, Dict, List, Optional, Tuple
29
29
  import boto3
30
30
  from botocore.exceptions import BotoCoreError, ClientError
31
31
 
32
- from runbooks.operate.base import BaseOperation, OperationResult
33
32
  from runbooks.common.rich_utils import (
34
33
  console,
35
34
  create_panel,
@@ -39,6 +38,7 @@ from runbooks.common.rich_utils import (
39
38
  print_status,
40
39
  print_success,
41
40
  )
41
+ from runbooks.operate.base import BaseOperation, OperationResult
42
42
 
43
43
  logger = logging.getLogger(__name__)
44
44