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.
Files changed (273) 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 +135 -91
  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 +17 -12
  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 +99 -79
  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 +315 -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/aws_decorators.py +2 -3
  113. runbooks/inventory/check_cloudtrail_compliance.py +2 -4
  114. runbooks/inventory/check_controltower_readiness.py +152 -151
  115. runbooks/inventory/check_landingzone_readiness.py +85 -84
  116. runbooks/inventory/cloud_foundations_integration.py +144 -149
  117. runbooks/inventory/collectors/aws_comprehensive.py +1 -1
  118. runbooks/inventory/collectors/aws_networking.py +109 -99
  119. runbooks/inventory/collectors/base.py +4 -0
  120. runbooks/inventory/core/collector.py +495 -313
  121. runbooks/inventory/core/formatter.py +11 -0
  122. runbooks/inventory/draw_org_structure.py +8 -9
  123. runbooks/inventory/drift_detection_cli.py +69 -96
  124. runbooks/inventory/ec2_vpc_utils.py +2 -2
  125. runbooks/inventory/find_cfn_drift_detection.py +5 -7
  126. runbooks/inventory/find_cfn_orphaned_stacks.py +7 -9
  127. runbooks/inventory/find_cfn_stackset_drift.py +5 -6
  128. runbooks/inventory/find_ec2_security_groups.py +48 -42
  129. runbooks/inventory/find_landingzone_versions.py +4 -6
  130. runbooks/inventory/find_vpc_flow_logs.py +7 -9
  131. runbooks/inventory/inventory_mcp_cli.py +48 -46
  132. runbooks/inventory/inventory_modules.py +103 -91
  133. runbooks/inventory/list_cfn_stacks.py +9 -10
  134. runbooks/inventory/list_cfn_stackset_operation_results.py +1 -3
  135. runbooks/inventory/list_cfn_stackset_operations.py +79 -57
  136. runbooks/inventory/list_cfn_stacksets.py +8 -10
  137. runbooks/inventory/list_config_recorders_delivery_channels.py +49 -39
  138. runbooks/inventory/list_ds_directories.py +65 -53
  139. runbooks/inventory/list_ec2_availability_zones.py +2 -4
  140. runbooks/inventory/list_ec2_ebs_volumes.py +32 -35
  141. runbooks/inventory/list_ec2_instances.py +23 -28
  142. runbooks/inventory/list_ecs_clusters_and_tasks.py +26 -34
  143. runbooks/inventory/list_elbs_load_balancers.py +22 -20
  144. runbooks/inventory/list_enis_network_interfaces.py +26 -33
  145. runbooks/inventory/list_guardduty_detectors.py +2 -4
  146. runbooks/inventory/list_iam_policies.py +2 -4
  147. runbooks/inventory/list_iam_roles.py +5 -7
  148. runbooks/inventory/list_iam_saml_providers.py +4 -6
  149. runbooks/inventory/list_lambda_functions.py +38 -38
  150. runbooks/inventory/list_org_accounts.py +6 -8
  151. runbooks/inventory/list_org_accounts_users.py +55 -44
  152. runbooks/inventory/list_rds_db_instances.py +31 -33
  153. runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
  154. runbooks/inventory/list_route53_hosted_zones.py +3 -5
  155. runbooks/inventory/list_servicecatalog_provisioned_products.py +37 -41
  156. runbooks/inventory/list_sns_topics.py +2 -4
  157. runbooks/inventory/list_ssm_parameters.py +4 -7
  158. runbooks/inventory/list_vpc_subnets.py +2 -4
  159. runbooks/inventory/list_vpcs.py +7 -10
  160. runbooks/inventory/mcp_inventory_validator.py +554 -468
  161. runbooks/inventory/mcp_vpc_validator.py +359 -442
  162. runbooks/inventory/organizations_discovery.py +63 -55
  163. runbooks/inventory/recover_cfn_stack_ids.py +7 -8
  164. runbooks/inventory/requirements.txt +0 -1
  165. runbooks/inventory/rich_inventory_display.py +35 -34
  166. runbooks/inventory/run_on_multi_accounts.py +3 -5
  167. runbooks/inventory/unified_validation_engine.py +281 -253
  168. runbooks/inventory/verify_ec2_security_groups.py +1 -1
  169. runbooks/inventory/vpc_analyzer.py +735 -697
  170. runbooks/inventory/vpc_architecture_validator.py +293 -348
  171. runbooks/inventory/vpc_dependency_analyzer.py +384 -380
  172. runbooks/inventory/vpc_flow_analyzer.py +1 -1
  173. runbooks/main.py +49 -34
  174. runbooks/main_final.py +91 -60
  175. runbooks/main_minimal.py +22 -10
  176. runbooks/main_optimized.py +131 -100
  177. runbooks/main_ultra_minimal.py +7 -2
  178. runbooks/mcp/__init__.py +36 -0
  179. runbooks/mcp/integration.py +679 -0
  180. runbooks/monitoring/performance_monitor.py +9 -4
  181. runbooks/operate/dynamodb_operations.py +3 -1
  182. runbooks/operate/ec2_operations.py +145 -137
  183. runbooks/operate/iam_operations.py +146 -152
  184. runbooks/operate/networking_cost_heatmap.py +29 -8
  185. runbooks/operate/rds_operations.py +223 -254
  186. runbooks/operate/s3_operations.py +107 -118
  187. runbooks/operate/vpc_operations.py +646 -616
  188. runbooks/remediation/base.py +1 -1
  189. runbooks/remediation/commons.py +10 -7
  190. runbooks/remediation/commvault_ec2_analysis.py +70 -66
  191. runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
  192. runbooks/remediation/multi_account.py +24 -21
  193. runbooks/remediation/rds_snapshot_list.py +86 -60
  194. runbooks/remediation/remediation_cli.py +92 -146
  195. runbooks/remediation/universal_account_discovery.py +83 -79
  196. runbooks/remediation/workspaces_list.py +46 -41
  197. runbooks/security/__init__.py +19 -0
  198. runbooks/security/assessment_runner.py +1150 -0
  199. runbooks/security/baseline_checker.py +812 -0
  200. runbooks/security/cloudops_automation_security_validator.py +509 -535
  201. runbooks/security/compliance_automation_engine.py +17 -17
  202. runbooks/security/config/__init__.py +2 -2
  203. runbooks/security/config/compliance_config.py +50 -50
  204. runbooks/security/config_template_generator.py +63 -76
  205. runbooks/security/enterprise_security_framework.py +1 -1
  206. runbooks/security/executive_security_dashboard.py +519 -508
  207. runbooks/security/multi_account_security_controls.py +959 -1210
  208. runbooks/security/real_time_security_monitor.py +422 -444
  209. runbooks/security/security_baseline_tester.py +1 -1
  210. runbooks/security/security_cli.py +143 -112
  211. runbooks/security/test_2way_validation.py +439 -0
  212. runbooks/security/two_way_validation_framework.py +852 -0
  213. runbooks/sre/production_monitoring_framework.py +167 -177
  214. runbooks/tdd/__init__.py +15 -0
  215. runbooks/tdd/cli.py +1071 -0
  216. runbooks/utils/__init__.py +14 -17
  217. runbooks/utils/logger.py +7 -2
  218. runbooks/utils/version_validator.py +50 -47
  219. runbooks/validation/__init__.py +6 -6
  220. runbooks/validation/cli.py +9 -3
  221. runbooks/validation/comprehensive_2way_validator.py +745 -704
  222. runbooks/validation/mcp_validator.py +906 -228
  223. runbooks/validation/terraform_citations_validator.py +104 -115
  224. runbooks/validation/terraform_drift_detector.py +461 -454
  225. runbooks/vpc/README.md +617 -0
  226. runbooks/vpc/__init__.py +8 -1
  227. runbooks/vpc/analyzer.py +577 -0
  228. runbooks/vpc/cleanup_wrapper.py +476 -413
  229. runbooks/vpc/cli_cloudtrail_commands.py +339 -0
  230. runbooks/vpc/cli_mcp_validation_commands.py +480 -0
  231. runbooks/vpc/cloudtrail_audit_integration.py +717 -0
  232. runbooks/vpc/config.py +92 -97
  233. runbooks/vpc/cost_engine.py +411 -148
  234. runbooks/vpc/cost_explorer_integration.py +553 -0
  235. runbooks/vpc/cross_account_session.py +101 -106
  236. runbooks/vpc/enhanced_mcp_validation.py +917 -0
  237. runbooks/vpc/eni_gate_validator.py +961 -0
  238. runbooks/vpc/heatmap_engine.py +185 -160
  239. runbooks/vpc/mcp_no_eni_validator.py +680 -639
  240. runbooks/vpc/nat_gateway_optimizer.py +358 -0
  241. runbooks/vpc/networking_wrapper.py +15 -8
  242. runbooks/vpc/pdca_remediation_planner.py +528 -0
  243. runbooks/vpc/performance_optimized_analyzer.py +219 -231
  244. runbooks/vpc/runbooks_adapter.py +1167 -241
  245. runbooks/vpc/tdd_red_phase_stubs.py +601 -0
  246. runbooks/vpc/test_data_loader.py +358 -0
  247. runbooks/vpc/tests/conftest.py +314 -4
  248. runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
  249. runbooks/vpc/tests/test_cost_engine.py +0 -2
  250. runbooks/vpc/topology_generator.py +326 -0
  251. runbooks/vpc/unified_scenarios.py +1297 -1124
  252. runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
  253. runbooks-1.1.6.dist-info/METADATA +327 -0
  254. runbooks-1.1.6.dist-info/RECORD +489 -0
  255. runbooks/finops/README.md +0 -414
  256. runbooks/finops/accuracy_cross_validator.py +0 -647
  257. runbooks/finops/business_cases.py +0 -950
  258. runbooks/finops/dashboard_router.py +0 -922
  259. runbooks/finops/ebs_optimizer.py +0 -973
  260. runbooks/finops/embedded_mcp_validator.py +0 -1629
  261. runbooks/finops/enhanced_dashboard_runner.py +0 -527
  262. runbooks/finops/finops_dashboard.py +0 -584
  263. runbooks/finops/finops_scenarios.py +0 -1218
  264. runbooks/finops/legacy_migration.py +0 -730
  265. runbooks/finops/multi_dashboard.py +0 -1519
  266. runbooks/finops/single_dashboard.py +0 -1113
  267. runbooks/finops/unlimited_scenarios.py +0 -393
  268. runbooks-1.1.4.dist-info/METADATA +0 -800
  269. runbooks-1.1.4.dist-info/RECORD +0 -468
  270. {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/WHEEL +0 -0
  271. {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/entry_points.txt +0 -0
  272. {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/licenses/LICENSE +0 -0
  273. {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/top_level.txt +0 -0
@@ -1,647 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Accuracy Cross-Validator - Real-Time Numerical Verification Engine
4
- ================================================================
5
-
6
- BUSINESS CRITICAL: "Are you really 100% sure about ALL of NUMBERS & figures?"
7
-
8
- This module provides real-time cross-validation of ALL numerical data displayed
9
- in FinOps dashboards, ensuring 100% accuracy with enterprise-grade validation.
10
-
11
- Features:
12
- - Real-time cross-validation between multiple data sources
13
- - Automated discrepancy detection and alerting
14
- - 99.99% accuracy validation with <0.01% tolerance
15
- - Live accuracy scoring and quality gates
16
- - Complete audit trail for compliance reporting
17
- - Performance optimized for enterprise scale
18
- """
19
-
20
- import asyncio
21
- import json
22
- import logging
23
- import time
24
- from dataclasses import dataclass, field
25
- from datetime import datetime, timedelta
26
- from decimal import ROUND_HALF_UP, Decimal, getcontext
27
- from enum import Enum
28
- from typing import Any, Callable, Dict, List, Optional, Tuple, Union
29
-
30
- # Set decimal context for financial precision
31
- getcontext().prec = 28
32
-
33
- import boto3
34
- from rich.console import Console
35
- from rich.panel import Panel
36
- from rich.progress import BarColumn, Progress, SpinnerColumn, TaskProgressColumn, TextColumn
37
- from rich.table import Table
38
-
39
- from ..common.rich_utils import (
40
- console as rich_console,
41
- )
42
- from ..common.rich_utils import (
43
- format_cost,
44
- print_error,
45
- print_info,
46
- print_success,
47
- print_warning,
48
- )
49
-
50
-
51
- class ValidationStatus(Enum):
52
- """Validation status enumeration for clear status tracking."""
53
-
54
- PASSED = "PASSED"
55
- FAILED = "FAILED"
56
- WARNING = "WARNING"
57
- ERROR = "ERROR"
58
- IN_PROGRESS = "IN_PROGRESS"
59
-
60
-
61
- class AccuracyLevel(Enum):
62
- """Accuracy level definitions for enterprise compliance."""
63
-
64
- ENTERPRISE = 99.99 # 99.99% - Enterprise financial reporting
65
- BUSINESS = 99.50 # 99.50% - Business intelligence
66
- OPERATIONAL = 95.00 # 95.00% - Operational monitoring
67
- DEVELOPMENT = 90.00 # 90.00% - Development/testing
68
-
69
-
70
- @dataclass
71
- class ValidationResult:
72
- """Comprehensive validation result with full audit trail."""
73
-
74
- description: str
75
- calculated_value: Union[float, int, str]
76
- reference_value: Union[float, int, str]
77
- accuracy_percent: float
78
- absolute_difference: float
79
- tolerance_met: bool
80
- validation_status: ValidationStatus
81
- source: str
82
- timestamp: str = field(default_factory=lambda: datetime.now().isoformat())
83
- metadata: Dict[str, Any] = field(default_factory=dict)
84
-
85
-
86
- @dataclass
87
- class CrossValidationReport:
88
- """Comprehensive cross-validation report for enterprise audit."""
89
-
90
- total_validations: int
91
- passed_validations: int
92
- failed_validations: int
93
- overall_accuracy: float
94
- accuracy_level_met: AccuracyLevel
95
- validation_results: List[ValidationResult]
96
- execution_time: float
97
- report_timestamp: str
98
- compliance_status: Dict[str, Any]
99
- quality_gates: Dict[str, bool]
100
-
101
-
102
- class AccuracyCrossValidator:
103
- """
104
- Enterprise-grade accuracy cross-validation engine.
105
-
106
- Provides real-time numerical accuracy verification with comprehensive
107
- audit trails and quality gates for financial compliance.
108
- """
109
-
110
- def __init__(
111
- self,
112
- accuracy_level: AccuracyLevel = AccuracyLevel.ENTERPRISE,
113
- tolerance_percent: float = 0.01,
114
- console: Optional[Console] = None,
115
- ):
116
- """
117
- Initialize accuracy cross-validator.
118
-
119
- Args:
120
- accuracy_level: Required accuracy level (default: ENTERPRISE 99.99%)
121
- tolerance_percent: Tolerance threshold (default: 0.01%)
122
- console: Rich console for output (optional)
123
- """
124
- self.accuracy_level = accuracy_level
125
- self.tolerance_percent = tolerance_percent
126
- self.console = console or rich_console
127
- self.validation_results: List[ValidationResult] = []
128
- self.logger = logging.getLogger(__name__)
129
-
130
- # Performance tracking
131
- self.validation_start_time = None
132
- self.validation_counts = {
133
- ValidationStatus.PASSED: 0,
134
- ValidationStatus.FAILED: 0,
135
- ValidationStatus.WARNING: 0,
136
- ValidationStatus.ERROR: 0,
137
- }
138
-
139
- def validate_financial_calculation(
140
- self, calculated_value: float, reference_value: float, description: str, source: str = "financial_calculation"
141
- ) -> ValidationResult:
142
- """
143
- Validate financial calculation with enterprise precision.
144
-
145
- Args:
146
- calculated_value: System calculated value
147
- reference_value: Reference/expected value
148
- description: Description of calculation
149
- source: Source identifier for audit trail
150
-
151
- Returns:
152
- Comprehensive validation result
153
- """
154
- # Use Decimal for precise financial calculations
155
- calc_decimal = Decimal(str(calculated_value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
156
- ref_decimal = Decimal(str(reference_value)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
157
-
158
- # Calculate accuracy metrics
159
- if ref_decimal != 0:
160
- accuracy_percent = float((1 - abs(calc_decimal - ref_decimal) / abs(ref_decimal)) * 100)
161
- else:
162
- accuracy_percent = 100.0 if calc_decimal == 0 else 0.0
163
-
164
- absolute_difference = float(abs(calc_decimal - ref_decimal))
165
-
166
- # Determine validation status
167
- tolerance_met = (absolute_difference / max(float(abs(ref_decimal)), 1)) * 100 <= self.tolerance_percent
168
- accuracy_met = accuracy_percent >= self.accuracy_level.value
169
-
170
- if accuracy_met and tolerance_met:
171
- validation_status = ValidationStatus.PASSED
172
- elif accuracy_percent >= AccuracyLevel.BUSINESS.value:
173
- validation_status = ValidationStatus.WARNING
174
- else:
175
- validation_status = ValidationStatus.FAILED
176
-
177
- # Create validation result
178
- result = ValidationResult(
179
- description=description,
180
- calculated_value=float(calc_decimal),
181
- reference_value=float(ref_decimal),
182
- accuracy_percent=accuracy_percent,
183
- absolute_difference=absolute_difference,
184
- tolerance_met=tolerance_met,
185
- validation_status=validation_status,
186
- source=source,
187
- metadata={
188
- "accuracy_level_required": self.accuracy_level.value,
189
- "tolerance_threshold": self.tolerance_percent,
190
- "precision_used": "Decimal_2dp",
191
- },
192
- )
193
-
194
- # Track result
195
- self._track_validation_result(result)
196
- return result
197
-
198
- def validate_count_accuracy(
199
- self, calculated_count: int, reference_count: int, description: str, source: str = "count_validation"
200
- ) -> ValidationResult:
201
- """
202
- Validate count accuracy (must be exact for counts).
203
-
204
- Args:
205
- calculated_count: System calculated count
206
- reference_count: Reference count
207
- description: Description of count
208
- source: Source identifier
209
-
210
- Returns:
211
- Validation result (exact match required for counts)
212
- """
213
- # Counts must be exact integers
214
- accuracy_percent = 100.0 if calculated_count == reference_count else 0.0
215
- absolute_difference = abs(calculated_count - reference_count)
216
-
217
- validation_status = ValidationStatus.PASSED if accuracy_percent == 100.0 else ValidationStatus.FAILED
218
-
219
- result = ValidationResult(
220
- description=description,
221
- calculated_value=calculated_count,
222
- reference_value=reference_count,
223
- accuracy_percent=accuracy_percent,
224
- absolute_difference=absolute_difference,
225
- tolerance_met=accuracy_percent == 100.0,
226
- validation_status=validation_status,
227
- source=source,
228
- metadata={"validation_type": "exact_count_match", "precision_required": "integer_exact"},
229
- )
230
-
231
- self._track_validation_result(result)
232
- return result
233
-
234
- def validate_percentage_calculation(
235
- self,
236
- calculated_percent: float,
237
- numerator: float,
238
- denominator: float,
239
- description: str,
240
- source: str = "percentage_calculation",
241
- ) -> ValidationResult:
242
- """
243
- Validate percentage calculation with mathematical verification.
244
-
245
- Args:
246
- calculated_percent: System calculated percentage
247
- numerator: Numerator value
248
- denominator: Denominator value
249
- description: Description of percentage
250
- source: Source identifier
251
-
252
- Returns:
253
- Validation result with mathematical verification
254
- """
255
- # Calculate expected percentage
256
- if denominator != 0:
257
- expected_percent = (numerator / denominator) * 100
258
- else:
259
- expected_percent = 0.0
260
-
261
- return self.validate_financial_calculation(
262
- calculated_percent, expected_percent, f"Percentage Validation: {description}", f"{source}_percentage"
263
- )
264
-
265
- def validate_sum_aggregation(
266
- self, calculated_sum: float, individual_values: List[float], description: str, source: str = "sum_aggregation"
267
- ) -> ValidationResult:
268
- """
269
- Validate sum aggregation accuracy.
270
-
271
- Args:
272
- calculated_sum: System calculated sum
273
- individual_values: Individual values to sum
274
- description: Description of aggregation
275
- source: Source identifier
276
-
277
- Returns:
278
- Validation result for aggregation
279
- """
280
- # Calculate expected sum with safe Decimal precision
281
- try:
282
- # Convert each value safely to Decimal
283
- decimal_values = []
284
- for val in individual_values:
285
- try:
286
- decimal_val = Decimal(str(val)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
287
- decimal_values.append(decimal_val)
288
- except:
289
- # If individual value fails, use rounded float
290
- decimal_values.append(Decimal(str(round(float(val), 2))))
291
-
292
- expected_sum = sum(decimal_values)
293
- except Exception:
294
- # Ultimate fallback to float calculation
295
- expected_sum = Decimal(str(round(sum(individual_values), 2)))
296
-
297
- return self.validate_financial_calculation(
298
- calculated_sum, float(expected_sum), f"Sum Aggregation: {description}", f"{source}_aggregation"
299
- )
300
-
301
- async def cross_validate_with_aws_api(
302
- self, runbooks_data: Dict[str, Any], aws_profiles: List[str]
303
- ) -> List[ValidationResult]:
304
- """
305
- Cross-validate runbooks data against AWS API independently.
306
-
307
- Args:
308
- runbooks_data: Data from runbooks analysis
309
- aws_profiles: AWS profiles for independent validation
310
-
311
- Returns:
312
- List of cross-validation results
313
- """
314
- cross_validation_results = []
315
-
316
- with Progress(
317
- SpinnerColumn(),
318
- TextColumn("[progress.description]{task.description}"),
319
- BarColumn(),
320
- TaskProgressColumn(),
321
- console=self.console,
322
- ) as progress:
323
- task = progress.add_task("Cross-validating with AWS APIs...", total=len(aws_profiles))
324
-
325
- for profile in aws_profiles:
326
- try:
327
- # Get independent AWS data
328
- aws_data = await self._get_independent_aws_data(profile)
329
-
330
- # Find corresponding runbooks data
331
- runbooks_profile_data = self._extract_profile_data(runbooks_data, profile)
332
-
333
- # Validate total costs
334
- if "total_cost" in runbooks_profile_data and "total_cost" in aws_data:
335
- cost_validation = self.validate_financial_calculation(
336
- runbooks_profile_data["total_cost"],
337
- aws_data["total_cost"],
338
- f"Total cost cross-validation: {profile[:30]}...",
339
- "aws_api_cross_validation",
340
- )
341
- cross_validation_results.append(cost_validation)
342
-
343
- # Validate service-level costs
344
- runbooks_services = runbooks_profile_data.get("services", {})
345
- aws_services = aws_data.get("services", {})
346
-
347
- for service in set(runbooks_services.keys()) & set(aws_services.keys()):
348
- service_validation = self.validate_financial_calculation(
349
- runbooks_services[service],
350
- aws_services[service],
351
- f"Service cost cross-validation: {service}",
352
- f"aws_api_service_validation_{profile[:20]}",
353
- )
354
- cross_validation_results.append(service_validation)
355
-
356
- progress.advance(task)
357
-
358
- except Exception as e:
359
- error_result = ValidationResult(
360
- description=f"Cross-validation error for {profile[:30]}...",
361
- calculated_value=0.0,
362
- reference_value=0.0,
363
- accuracy_percent=0.0,
364
- absolute_difference=0.0,
365
- tolerance_met=False,
366
- validation_status=ValidationStatus.ERROR,
367
- source="aws_api_cross_validation_error",
368
- metadata={"error": str(e)},
369
- )
370
- cross_validation_results.append(error_result)
371
- self._track_validation_result(error_result)
372
- progress.advance(task)
373
-
374
- return cross_validation_results
375
-
376
- async def _get_independent_aws_data(self, profile: str) -> Dict[str, Any]:
377
- """Get independent cost data from AWS API for cross-validation."""
378
- try:
379
- session = boto3.Session(profile_name=profile)
380
- ce_client = session.client("ce", region_name="us-east-1")
381
-
382
- # Get current month cost data with September 1st fix
383
- end_date = datetime.now().date()
384
- start_date = end_date.replace(day=1)
385
-
386
- # CRITICAL FIX: September 1st boundary handling (matches cost_processor.py)
387
- if end_date.day == 1:
388
- self.console.log(f"[yellow]⚠️ Cross-Validator: First day of month detected ({end_date.strftime('%B %d, %Y')}) - using partial period[/]")
389
- # For AWS Cost Explorer, end date is exclusive, so add one day to include today
390
- end_date = end_date + timedelta(days=1)
391
- else:
392
- # Normal case: include up to today (exclusive end date)
393
- end_date = end_date + timedelta(days=1)
394
-
395
- response = ce_client.get_cost_and_usage(
396
- TimePeriod={"Start": start_date.isoformat(), "End": end_date.isoformat()},
397
- Granularity="MONTHLY",
398
- Metrics=["UnblendedCost"],
399
- GroupBy=[{"Type": "DIMENSION", "Key": "SERVICE"}],
400
- )
401
-
402
- # Process response
403
- total_cost = 0.0
404
- services = {}
405
-
406
- if response.get("ResultsByTime"):
407
- for result in response["ResultsByTime"]:
408
- for group in result.get("Groups", []):
409
- service = group.get("Keys", ["Unknown"])[0]
410
- cost = float(group.get("Metrics", {}).get("UnblendedCost", {}).get("Amount", 0))
411
- services[service] = cost
412
- total_cost += cost
413
-
414
- return {
415
- "total_cost": total_cost,
416
- "services": services,
417
- "profile": profile,
418
- "data_source": "independent_aws_api",
419
- }
420
-
421
- except Exception as e:
422
- return {
423
- "total_cost": 0.0,
424
- "services": {},
425
- "profile": profile,
426
- "data_source": "error_fallback",
427
- "error": str(e),
428
- }
429
-
430
- def _extract_profile_data(self, runbooks_data: Dict[str, Any], profile: str) -> Dict[str, Any]:
431
- """Extract data for specific profile from runbooks results."""
432
- # Adapt based on actual runbooks data structure
433
- # This is a simplified implementation
434
- return {
435
- "total_cost": runbooks_data.get("total_cost", 0.0),
436
- "services": runbooks_data.get("services", {}),
437
- "profile": profile,
438
- }
439
-
440
- def _track_validation_result(self, result: ValidationResult) -> None:
441
- """Track validation result for reporting."""
442
- self.validation_results.append(result)
443
- self.validation_counts[result.validation_status] += 1
444
-
445
- def generate_accuracy_report(self) -> CrossValidationReport:
446
- """
447
- Generate comprehensive accuracy report for enterprise compliance.
448
-
449
- Returns:
450
- Complete cross-validation report with audit trail
451
- """
452
- if not self.validation_results:
453
- return CrossValidationReport(
454
- total_validations=0,
455
- passed_validations=0,
456
- failed_validations=0,
457
- overall_accuracy=0.0,
458
- accuracy_level_met=AccuracyLevel.DEVELOPMENT,
459
- validation_results=[],
460
- execution_time=0.0,
461
- report_timestamp=datetime.now().isoformat(),
462
- compliance_status={"status": "NO_VALIDATIONS"},
463
- quality_gates={"audit_ready": False},
464
- )
465
-
466
- # Calculate metrics
467
- total_validations = len(self.validation_results)
468
- passed_validations = self.validation_counts[ValidationStatus.PASSED]
469
- failed_validations = self.validation_counts[ValidationStatus.FAILED]
470
-
471
- # Calculate overall accuracy
472
- valid_results = [r for r in self.validation_results if r.accuracy_percent > 0]
473
- if valid_results:
474
- overall_accuracy = sum(r.accuracy_percent for r in valid_results) / len(valid_results)
475
- else:
476
- overall_accuracy = 0.0
477
-
478
- # Determine accuracy level met
479
- accuracy_level_met = AccuracyLevel.DEVELOPMENT
480
- if overall_accuracy >= AccuracyLevel.ENTERPRISE.value:
481
- accuracy_level_met = AccuracyLevel.ENTERPRISE
482
- elif overall_accuracy >= AccuracyLevel.BUSINESS.value:
483
- accuracy_level_met = AccuracyLevel.BUSINESS
484
- elif overall_accuracy >= AccuracyLevel.OPERATIONAL.value:
485
- accuracy_level_met = AccuracyLevel.OPERATIONAL
486
-
487
- # Calculate execution time
488
- execution_time = time.time() - (self.validation_start_time or time.time())
489
-
490
- # Compliance assessment
491
- compliance_status = {
492
- "enterprise_grade": overall_accuracy >= AccuracyLevel.ENTERPRISE.value,
493
- "audit_ready": overall_accuracy >= AccuracyLevel.ENTERPRISE.value
494
- and (passed_validations / total_validations) >= 0.95,
495
- "regulatory_compliant": overall_accuracy >= AccuracyLevel.BUSINESS.value,
496
- "meets_tolerance": sum(1 for r in self.validation_results if r.tolerance_met) / total_validations >= 0.95,
497
- }
498
-
499
- # Quality gates
500
- quality_gates = {
501
- "accuracy_threshold_met": overall_accuracy >= self.accuracy_level.value,
502
- "tolerance_requirements_met": compliance_status["meets_tolerance"],
503
- "performance_acceptable": execution_time < 30.0, # 30 second performance target
504
- "audit_ready": compliance_status["audit_ready"],
505
- }
506
-
507
- return CrossValidationReport(
508
- total_validations=total_validations,
509
- passed_validations=passed_validations,
510
- failed_validations=failed_validations,
511
- overall_accuracy=overall_accuracy,
512
- accuracy_level_met=accuracy_level_met,
513
- validation_results=self.validation_results,
514
- execution_time=execution_time,
515
- report_timestamp=datetime.now().isoformat(),
516
- compliance_status=compliance_status,
517
- quality_gates=quality_gates,
518
- )
519
-
520
- def display_accuracy_report(self, report: CrossValidationReport) -> None:
521
- """Display accuracy report with Rich CLI formatting."""
522
- # Create summary table
523
- summary_table = Table(title="📊 Numerical Accuracy Validation Report")
524
- summary_table.add_column("Metric", style="cyan")
525
- summary_table.add_column("Value", style="green")
526
- summary_table.add_column("Status", style="bold")
527
-
528
- # Add summary rows
529
- summary_table.add_row("Total Validations", str(report.total_validations), "📋")
530
- summary_table.add_row("Passed Validations", str(report.passed_validations), "✅")
531
- summary_table.add_row(
532
- "Failed Validations", str(report.failed_validations), "❌" if report.failed_validations > 0 else "✅"
533
- )
534
- summary_table.add_row(
535
- "Overall Accuracy",
536
- f"{report.overall_accuracy:.2f}%",
537
- "✅" if report.overall_accuracy >= self.accuracy_level.value else "⚠️",
538
- )
539
- summary_table.add_row(
540
- "Accuracy Level",
541
- report.accuracy_level_met.name,
542
- "🏆" if report.accuracy_level_met == AccuracyLevel.ENTERPRISE else "📊",
543
- )
544
- summary_table.add_row(
545
- "Execution Time", f"{report.execution_time:.2f}s", "⚡" if report.execution_time < 30 else "⏰"
546
- )
547
-
548
- self.console.print(summary_table)
549
-
550
- # Compliance status
551
- if report.compliance_status["audit_ready"]:
552
- print_success("✅ System meets enterprise audit requirements")
553
- elif report.compliance_status["enterprise_grade"]:
554
- print_warning("⚠️ Enterprise accuracy achieved, but validation coverage needs improvement")
555
- else:
556
- print_error("❌ System does not meet enterprise accuracy requirements")
557
-
558
- # Quality gates summary
559
- gates_passed = sum(1 for gate_met in report.quality_gates.values() if gate_met)
560
- gates_total = len(report.quality_gates)
561
-
562
- if gates_passed == gates_total:
563
- print_success(f"✅ All quality gates passed ({gates_passed}/{gates_total})")
564
- else:
565
- print_warning(f"⚠️ Quality gates: {gates_passed}/{gates_total} passed")
566
-
567
- def export_audit_report(self, report: CrossValidationReport, file_path: str) -> None:
568
- """Export comprehensive audit report for compliance review."""
569
- audit_data = {
570
- "report_metadata": {
571
- "report_type": "numerical_accuracy_cross_validation",
572
- "accuracy_level_required": self.accuracy_level.name,
573
- "tolerance_threshold": self.tolerance_percent,
574
- "report_timestamp": report.report_timestamp,
575
- "execution_time": report.execution_time,
576
- },
577
- "summary_metrics": {
578
- "total_validations": report.total_validations,
579
- "passed_validations": report.passed_validations,
580
- "failed_validations": report.failed_validations,
581
- "overall_accuracy": report.overall_accuracy,
582
- "accuracy_level_achieved": report.accuracy_level_met.name,
583
- },
584
- "compliance_assessment": report.compliance_status,
585
- "quality_gates": report.quality_gates,
586
- "detailed_validation_results": [
587
- {
588
- "description": r.description,
589
- "calculated_value": r.calculated_value,
590
- "reference_value": r.reference_value,
591
- "accuracy_percent": r.accuracy_percent,
592
- "absolute_difference": r.absolute_difference,
593
- "tolerance_met": r.tolerance_met,
594
- "validation_status": r.validation_status.value,
595
- "source": r.source,
596
- "timestamp": r.timestamp,
597
- "metadata": r.metadata,
598
- }
599
- for r in report.validation_results
600
- ],
601
- }
602
-
603
- with open(file_path, "w") as f:
604
- json.dump(audit_data, f, indent=2, default=str)
605
-
606
- def start_validation_session(self) -> None:
607
- """Start validation session timing."""
608
- self.validation_start_time = time.time()
609
- self.validation_results.clear()
610
- self.validation_counts = {status: 0 for status in ValidationStatus}
611
-
612
-
613
- # Convenience functions for integration
614
- def create_accuracy_validator(
615
- accuracy_level: AccuracyLevel = AccuracyLevel.ENTERPRISE, tolerance_percent: float = 0.01
616
- ) -> AccuracyCrossValidator:
617
- """Factory function to create accuracy cross-validator."""
618
- return AccuracyCrossValidator(accuracy_level=accuracy_level, tolerance_percent=tolerance_percent)
619
-
620
-
621
- async def validate_finops_data_accuracy(
622
- runbooks_data: Dict[str, Any], aws_profiles: List[str], accuracy_level: AccuracyLevel = AccuracyLevel.ENTERPRISE
623
- ) -> CrossValidationReport:
624
- """
625
- Comprehensive FinOps data accuracy validation.
626
-
627
- Args:
628
- runbooks_data: Data from runbooks FinOps analysis
629
- aws_profiles: AWS profiles for cross-validation
630
- accuracy_level: Required accuracy level
631
-
632
- Returns:
633
- Complete validation report
634
- """
635
- validator = create_accuracy_validator(accuracy_level=accuracy_level)
636
- validator.start_validation_session()
637
-
638
- # Perform cross-validation with AWS APIs
639
- cross_validation_results = await validator.cross_validate_with_aws_api(runbooks_data, aws_profiles)
640
-
641
- # Generate comprehensive report
642
- report = validator.generate_accuracy_report()
643
-
644
- # Display results
645
- validator.display_accuracy_report(report)
646
-
647
- return report