runbooks 1.1.4__py3-none-any.whl → 1.1.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runbooks/__init__.py +31 -2
- runbooks/__init___optimized.py +18 -4
- runbooks/_platform/__init__.py +1 -5
- runbooks/_platform/core/runbooks_wrapper.py +141 -138
- runbooks/aws2/accuracy_validator.py +812 -0
- runbooks/base.py +7 -0
- runbooks/cfat/assessment/compliance.py +1 -1
- runbooks/cfat/assessment/runner.py +1 -0
- runbooks/cfat/cloud_foundations_assessment.py +227 -239
- runbooks/cli/__init__.py +1 -1
- runbooks/cli/commands/cfat.py +64 -23
- runbooks/cli/commands/finops.py +1005 -54
- runbooks/cli/commands/inventory.py +135 -91
- runbooks/cli/commands/operate.py +9 -36
- runbooks/cli/commands/security.py +42 -18
- runbooks/cli/commands/validation.py +432 -18
- runbooks/cli/commands/vpc.py +81 -17
- runbooks/cli/registry.py +22 -10
- runbooks/cloudops/__init__.py +20 -27
- runbooks/cloudops/base.py +96 -107
- runbooks/cloudops/cost_optimizer.py +544 -542
- runbooks/cloudops/infrastructure_optimizer.py +5 -4
- runbooks/cloudops/interfaces.py +224 -225
- runbooks/cloudops/lifecycle_manager.py +5 -4
- runbooks/cloudops/mcp_cost_validation.py +252 -235
- runbooks/cloudops/models.py +78 -53
- runbooks/cloudops/monitoring_automation.py +5 -4
- runbooks/cloudops/notebook_framework.py +177 -213
- runbooks/cloudops/security_enforcer.py +125 -159
- runbooks/common/accuracy_validator.py +17 -12
- runbooks/common/aws_pricing.py +349 -326
- runbooks/common/aws_pricing_api.py +211 -212
- runbooks/common/aws_profile_manager.py +40 -36
- runbooks/common/aws_utils.py +74 -79
- runbooks/common/business_logic.py +126 -104
- runbooks/common/cli_decorators.py +36 -60
- runbooks/common/comprehensive_cost_explorer_integration.py +455 -463
- runbooks/common/cross_account_manager.py +197 -204
- runbooks/common/date_utils.py +27 -39
- runbooks/common/decorators.py +29 -19
- runbooks/common/dry_run_examples.py +173 -208
- runbooks/common/dry_run_framework.py +157 -155
- runbooks/common/enhanced_exception_handler.py +15 -4
- runbooks/common/enhanced_logging_example.py +50 -64
- runbooks/common/enhanced_logging_integration_example.py +65 -37
- runbooks/common/env_utils.py +16 -16
- runbooks/common/error_handling.py +40 -38
- runbooks/common/lazy_loader.py +41 -23
- runbooks/common/logging_integration_helper.py +79 -86
- runbooks/common/mcp_cost_explorer_integration.py +476 -493
- runbooks/common/mcp_integration.py +99 -79
- runbooks/common/memory_optimization.py +140 -118
- runbooks/common/module_cli_base.py +37 -58
- runbooks/common/organizations_client.py +175 -193
- runbooks/common/patterns.py +23 -25
- runbooks/common/performance_monitoring.py +67 -71
- runbooks/common/performance_optimization_engine.py +283 -274
- runbooks/common/profile_utils.py +111 -37
- runbooks/common/rich_utils.py +315 -141
- runbooks/common/sre_performance_suite.py +177 -186
- runbooks/enterprise/__init__.py +1 -1
- runbooks/enterprise/logging.py +144 -106
- runbooks/enterprise/security.py +187 -204
- runbooks/enterprise/validation.py +43 -56
- runbooks/finops/__init__.py +26 -30
- runbooks/finops/account_resolver.py +1 -1
- runbooks/finops/advanced_optimization_engine.py +980 -0
- runbooks/finops/automation_core.py +268 -231
- runbooks/finops/business_case_config.py +184 -179
- runbooks/finops/cli.py +660 -139
- runbooks/finops/commvault_ec2_analysis.py +157 -164
- runbooks/finops/compute_cost_optimizer.py +336 -320
- runbooks/finops/config.py +20 -20
- runbooks/finops/cost_optimizer.py +484 -618
- runbooks/finops/cost_processor.py +332 -214
- runbooks/finops/dashboard_runner.py +1006 -172
- runbooks/finops/ebs_cost_optimizer.py +991 -657
- runbooks/finops/elastic_ip_optimizer.py +317 -257
- runbooks/finops/enhanced_mcp_integration.py +340 -0
- runbooks/finops/enhanced_progress.py +32 -29
- runbooks/finops/enhanced_trend_visualization.py +3 -2
- runbooks/finops/enterprise_wrappers.py +223 -285
- runbooks/finops/executive_export.py +203 -160
- runbooks/finops/helpers.py +130 -288
- runbooks/finops/iam_guidance.py +1 -1
- runbooks/finops/infrastructure/__init__.py +80 -0
- runbooks/finops/infrastructure/commands.py +506 -0
- runbooks/finops/infrastructure/load_balancer_optimizer.py +866 -0
- runbooks/finops/infrastructure/vpc_endpoint_optimizer.py +832 -0
- runbooks/finops/markdown_exporter.py +337 -174
- runbooks/finops/mcp_validator.py +1952 -0
- runbooks/finops/nat_gateway_optimizer.py +1512 -481
- runbooks/finops/network_cost_optimizer.py +657 -587
- runbooks/finops/notebook_utils.py +226 -188
- runbooks/finops/optimization_engine.py +1136 -0
- runbooks/finops/optimizer.py +19 -23
- runbooks/finops/rds_snapshot_optimizer.py +367 -411
- runbooks/finops/reservation_optimizer.py +427 -363
- runbooks/finops/scenario_cli_integration.py +64 -65
- runbooks/finops/scenarios.py +1277 -438
- runbooks/finops/schemas.py +218 -182
- runbooks/finops/snapshot_manager.py +2289 -0
- runbooks/finops/types.py +3 -3
- runbooks/finops/validation_framework.py +259 -265
- runbooks/finops/vpc_cleanup_exporter.py +189 -144
- runbooks/finops/vpc_cleanup_optimizer.py +591 -573
- runbooks/finops/workspaces_analyzer.py +171 -182
- runbooks/integration/__init__.py +89 -0
- runbooks/integration/mcp_integration.py +1920 -0
- runbooks/inventory/CLAUDE.md +816 -0
- runbooks/inventory/__init__.py +2 -2
- runbooks/inventory/aws_decorators.py +2 -3
- runbooks/inventory/check_cloudtrail_compliance.py +2 -4
- runbooks/inventory/check_controltower_readiness.py +152 -151
- runbooks/inventory/check_landingzone_readiness.py +85 -84
- runbooks/inventory/cloud_foundations_integration.py +144 -149
- runbooks/inventory/collectors/aws_comprehensive.py +1 -1
- runbooks/inventory/collectors/aws_networking.py +109 -99
- runbooks/inventory/collectors/base.py +4 -0
- runbooks/inventory/core/collector.py +495 -313
- runbooks/inventory/core/formatter.py +11 -0
- runbooks/inventory/draw_org_structure.py +8 -9
- runbooks/inventory/drift_detection_cli.py +69 -96
- runbooks/inventory/ec2_vpc_utils.py +2 -2
- runbooks/inventory/find_cfn_drift_detection.py +5 -7
- runbooks/inventory/find_cfn_orphaned_stacks.py +7 -9
- runbooks/inventory/find_cfn_stackset_drift.py +5 -6
- runbooks/inventory/find_ec2_security_groups.py +48 -42
- runbooks/inventory/find_landingzone_versions.py +4 -6
- runbooks/inventory/find_vpc_flow_logs.py +7 -9
- runbooks/inventory/inventory_mcp_cli.py +48 -46
- runbooks/inventory/inventory_modules.py +103 -91
- runbooks/inventory/list_cfn_stacks.py +9 -10
- runbooks/inventory/list_cfn_stackset_operation_results.py +1 -3
- runbooks/inventory/list_cfn_stackset_operations.py +79 -57
- runbooks/inventory/list_cfn_stacksets.py +8 -10
- runbooks/inventory/list_config_recorders_delivery_channels.py +49 -39
- runbooks/inventory/list_ds_directories.py +65 -53
- runbooks/inventory/list_ec2_availability_zones.py +2 -4
- runbooks/inventory/list_ec2_ebs_volumes.py +32 -35
- runbooks/inventory/list_ec2_instances.py +23 -28
- runbooks/inventory/list_ecs_clusters_and_tasks.py +26 -34
- runbooks/inventory/list_elbs_load_balancers.py +22 -20
- runbooks/inventory/list_enis_network_interfaces.py +26 -33
- runbooks/inventory/list_guardduty_detectors.py +2 -4
- runbooks/inventory/list_iam_policies.py +2 -4
- runbooks/inventory/list_iam_roles.py +5 -7
- runbooks/inventory/list_iam_saml_providers.py +4 -6
- runbooks/inventory/list_lambda_functions.py +38 -38
- runbooks/inventory/list_org_accounts.py +6 -8
- runbooks/inventory/list_org_accounts_users.py +55 -44
- runbooks/inventory/list_rds_db_instances.py +31 -33
- runbooks/inventory/list_rds_snapshots_aggregator.py +192 -208
- runbooks/inventory/list_route53_hosted_zones.py +3 -5
- runbooks/inventory/list_servicecatalog_provisioned_products.py +37 -41
- runbooks/inventory/list_sns_topics.py +2 -4
- runbooks/inventory/list_ssm_parameters.py +4 -7
- runbooks/inventory/list_vpc_subnets.py +2 -4
- runbooks/inventory/list_vpcs.py +7 -10
- runbooks/inventory/mcp_inventory_validator.py +554 -468
- runbooks/inventory/mcp_vpc_validator.py +359 -442
- runbooks/inventory/organizations_discovery.py +63 -55
- runbooks/inventory/recover_cfn_stack_ids.py +7 -8
- runbooks/inventory/requirements.txt +0 -1
- runbooks/inventory/rich_inventory_display.py +35 -34
- runbooks/inventory/run_on_multi_accounts.py +3 -5
- runbooks/inventory/unified_validation_engine.py +281 -253
- runbooks/inventory/verify_ec2_security_groups.py +1 -1
- runbooks/inventory/vpc_analyzer.py +735 -697
- runbooks/inventory/vpc_architecture_validator.py +293 -348
- runbooks/inventory/vpc_dependency_analyzer.py +384 -380
- runbooks/inventory/vpc_flow_analyzer.py +1 -1
- runbooks/main.py +49 -34
- runbooks/main_final.py +91 -60
- runbooks/main_minimal.py +22 -10
- runbooks/main_optimized.py +131 -100
- runbooks/main_ultra_minimal.py +7 -2
- runbooks/mcp/__init__.py +36 -0
- runbooks/mcp/integration.py +679 -0
- runbooks/monitoring/performance_monitor.py +9 -4
- runbooks/operate/dynamodb_operations.py +3 -1
- runbooks/operate/ec2_operations.py +145 -137
- runbooks/operate/iam_operations.py +146 -152
- runbooks/operate/networking_cost_heatmap.py +29 -8
- runbooks/operate/rds_operations.py +223 -254
- runbooks/operate/s3_operations.py +107 -118
- runbooks/operate/vpc_operations.py +646 -616
- runbooks/remediation/base.py +1 -1
- runbooks/remediation/commons.py +10 -7
- runbooks/remediation/commvault_ec2_analysis.py +70 -66
- runbooks/remediation/ec2_unattached_ebs_volumes.py +1 -0
- runbooks/remediation/multi_account.py +24 -21
- runbooks/remediation/rds_snapshot_list.py +86 -60
- runbooks/remediation/remediation_cli.py +92 -146
- runbooks/remediation/universal_account_discovery.py +83 -79
- runbooks/remediation/workspaces_list.py +46 -41
- runbooks/security/__init__.py +19 -0
- runbooks/security/assessment_runner.py +1150 -0
- runbooks/security/baseline_checker.py +812 -0
- runbooks/security/cloudops_automation_security_validator.py +509 -535
- runbooks/security/compliance_automation_engine.py +17 -17
- runbooks/security/config/__init__.py +2 -2
- runbooks/security/config/compliance_config.py +50 -50
- runbooks/security/config_template_generator.py +63 -76
- runbooks/security/enterprise_security_framework.py +1 -1
- runbooks/security/executive_security_dashboard.py +519 -508
- runbooks/security/multi_account_security_controls.py +959 -1210
- runbooks/security/real_time_security_monitor.py +422 -444
- runbooks/security/security_baseline_tester.py +1 -1
- runbooks/security/security_cli.py +143 -112
- runbooks/security/test_2way_validation.py +439 -0
- runbooks/security/two_way_validation_framework.py +852 -0
- runbooks/sre/production_monitoring_framework.py +167 -177
- runbooks/tdd/__init__.py +15 -0
- runbooks/tdd/cli.py +1071 -0
- runbooks/utils/__init__.py +14 -17
- runbooks/utils/logger.py +7 -2
- runbooks/utils/version_validator.py +50 -47
- runbooks/validation/__init__.py +6 -6
- runbooks/validation/cli.py +9 -3
- runbooks/validation/comprehensive_2way_validator.py +745 -704
- runbooks/validation/mcp_validator.py +906 -228
- runbooks/validation/terraform_citations_validator.py +104 -115
- runbooks/validation/terraform_drift_detector.py +461 -454
- runbooks/vpc/README.md +617 -0
- runbooks/vpc/__init__.py +8 -1
- runbooks/vpc/analyzer.py +577 -0
- runbooks/vpc/cleanup_wrapper.py +476 -413
- runbooks/vpc/cli_cloudtrail_commands.py +339 -0
- runbooks/vpc/cli_mcp_validation_commands.py +480 -0
- runbooks/vpc/cloudtrail_audit_integration.py +717 -0
- runbooks/vpc/config.py +92 -97
- runbooks/vpc/cost_engine.py +411 -148
- runbooks/vpc/cost_explorer_integration.py +553 -0
- runbooks/vpc/cross_account_session.py +101 -106
- runbooks/vpc/enhanced_mcp_validation.py +917 -0
- runbooks/vpc/eni_gate_validator.py +961 -0
- runbooks/vpc/heatmap_engine.py +185 -160
- runbooks/vpc/mcp_no_eni_validator.py +680 -639
- runbooks/vpc/nat_gateway_optimizer.py +358 -0
- runbooks/vpc/networking_wrapper.py +15 -8
- runbooks/vpc/pdca_remediation_planner.py +528 -0
- runbooks/vpc/performance_optimized_analyzer.py +219 -231
- runbooks/vpc/runbooks_adapter.py +1167 -241
- runbooks/vpc/tdd_red_phase_stubs.py +601 -0
- runbooks/vpc/test_data_loader.py +358 -0
- runbooks/vpc/tests/conftest.py +314 -4
- runbooks/vpc/tests/test_cleanup_framework.py +1022 -0
- runbooks/vpc/tests/test_cost_engine.py +0 -2
- runbooks/vpc/topology_generator.py +326 -0
- runbooks/vpc/unified_scenarios.py +1297 -1124
- runbooks/vpc/vpc_cleanup_integration.py +1943 -1115
- runbooks-1.1.6.dist-info/METADATA +327 -0
- runbooks-1.1.6.dist-info/RECORD +489 -0
- runbooks/finops/README.md +0 -414
- runbooks/finops/accuracy_cross_validator.py +0 -647
- runbooks/finops/business_cases.py +0 -950
- runbooks/finops/dashboard_router.py +0 -922
- runbooks/finops/ebs_optimizer.py +0 -973
- runbooks/finops/embedded_mcp_validator.py +0 -1629
- runbooks/finops/enhanced_dashboard_runner.py +0 -527
- runbooks/finops/finops_dashboard.py +0 -584
- runbooks/finops/finops_scenarios.py +0 -1218
- runbooks/finops/legacy_migration.py +0 -730
- runbooks/finops/multi_dashboard.py +0 -1519
- runbooks/finops/single_dashboard.py +0 -1113
- runbooks/finops/unlimited_scenarios.py +0 -393
- runbooks-1.1.4.dist-info/METADATA +0 -800
- runbooks-1.1.4.dist-info/RECORD +0 -468
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/WHEEL +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/entry_points.txt +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.1.4.dist-info → runbooks-1.1.6.dist-info}/top_level.txt +0 -0
@@ -326,7 +326,7 @@ class EnterpriseExceptionHandler:
|
|
326
326
|
# Defensive check for None values
|
327
327
|
if execution_time is None or performance_target is None or performance_target == 0:
|
328
328
|
return None
|
329
|
-
|
329
|
+
|
330
330
|
performance_ratio = execution_time / performance_target
|
331
331
|
|
332
332
|
# Only create error if performance significantly exceeded (>150% of target)
|
@@ -974,11 +974,21 @@ class EnterpriseExceptionHandler:
|
|
974
974
|
def _initialize_profile_recommendations(self) -> Dict[str, List[str]]:
|
975
975
|
"""Initialize profile recommendations for different operations with universal support."""
|
976
976
|
import os
|
977
|
+
|
977
978
|
# Environment variable-driven profile recommendations
|
978
979
|
return {
|
979
|
-
"inventory": [
|
980
|
-
|
981
|
-
|
980
|
+
"inventory": [
|
981
|
+
os.getenv("MANAGEMENT_PROFILE", "management-profile"),
|
982
|
+
os.getenv("CENTRALISED_OPS_PROFILE", "ops-profile"),
|
983
|
+
],
|
984
|
+
"operate": [
|
985
|
+
os.getenv("CENTRALISED_OPS_PROFILE", "ops-profile"),
|
986
|
+
os.getenv("MANAGEMENT_PROFILE", "management-profile"),
|
987
|
+
],
|
988
|
+
"finops": [
|
989
|
+
os.getenv("BILLING_PROFILE", "billing-profile"),
|
990
|
+
os.getenv("MANAGEMENT_PROFILE", "management-profile"),
|
991
|
+
],
|
982
992
|
"security": [os.getenv("MANAGEMENT_PROFILE", "management-profile")],
|
983
993
|
"cfat": [os.getenv("MANAGEMENT_PROFILE", "management-profile")],
|
984
994
|
}
|
@@ -994,6 +1004,7 @@ class EnterpriseExceptionHandler:
|
|
994
1004
|
if service == "ce" and error_code == "AccessDenied":
|
995
1005
|
# Cost Explorer requires special billing permissions
|
996
1006
|
import os
|
1007
|
+
|
997
1008
|
base_analysis["recommended_profiles"] = [os.getenv("BILLING_PROFILE", "billing-profile")]
|
998
1009
|
|
999
1010
|
return base_analysis
|
@@ -15,158 +15,144 @@ from runbooks.enterprise.logging import get_context_logger, EnterpriseRichLogger
|
|
15
15
|
|
16
16
|
class EnhancedLoggingExample:
|
17
17
|
"""Demonstrates enhanced logging integration patterns for different user types."""
|
18
|
-
|
18
|
+
|
19
19
|
def __init__(self, log_level: str = "INFO", json_output: bool = False):
|
20
20
|
"""
|
21
21
|
Initialize with enhanced logger.
|
22
|
-
|
22
|
+
|
23
23
|
Args:
|
24
24
|
log_level: Logging level (DEBUG, INFO, WARNING, ERROR)
|
25
25
|
json_output: Enable structured JSON output
|
26
26
|
"""
|
27
27
|
self.logger = get_context_logger(level=log_level, json_output=json_output)
|
28
28
|
self.log_level = log_level.upper()
|
29
|
-
|
29
|
+
|
30
30
|
def demonstrate_debug_logging(self):
|
31
31
|
"""Demonstrate DEBUG level logging for tech users (SRE/DevOps)."""
|
32
32
|
print("\n=== DEBUG Level Logging (Tech Users) ===")
|
33
|
-
|
33
|
+
|
34
34
|
# AWS API tracing example
|
35
35
|
start_time = time.time()
|
36
|
-
|
36
|
+
|
37
37
|
# Simulate AWS API call
|
38
38
|
time.sleep(0.1)
|
39
39
|
duration = time.time() - start_time
|
40
|
-
|
40
|
+
|
41
41
|
self.logger.debug_tech(
|
42
42
|
"EC2 instances discovered in region us-east-1",
|
43
|
-
aws_api={
|
44
|
-
"service": "ec2",
|
45
|
-
"operation": "describe_instances",
|
46
|
-
"region": "us-east-1"
|
47
|
-
},
|
43
|
+
aws_api={"service": "ec2", "operation": "describe_instances", "region": "us-east-1"},
|
48
44
|
duration=duration,
|
49
45
|
request_id="12345-abcde-67890",
|
50
|
-
resource_count=42
|
46
|
+
resource_count=42,
|
51
47
|
)
|
52
|
-
|
48
|
+
|
53
49
|
# Performance metrics
|
54
50
|
self.logger.debug_tech(
|
55
51
|
"Cost analysis query executed",
|
56
|
-
aws_api={
|
57
|
-
"service": "ce",
|
58
|
-
"operation": "get_cost_and_usage"
|
59
|
-
},
|
52
|
+
aws_api={"service": "ce", "operation": "get_cost_and_usage"},
|
60
53
|
duration=2.435,
|
61
54
|
data_points=1500,
|
62
|
-
cache_hit=False
|
55
|
+
cache_hit=False,
|
63
56
|
)
|
64
|
-
|
57
|
+
|
65
58
|
def demonstrate_info_logging(self):
|
66
59
|
"""Demonstrate INFO level logging for standard users."""
|
67
60
|
print("\n=== INFO Level Logging (Standard Users) ===")
|
68
|
-
|
61
|
+
|
69
62
|
# Standard operation status
|
70
63
|
self.logger.info_standard("Starting cost analysis for account 123456789012")
|
71
|
-
|
64
|
+
|
72
65
|
# Progress indication
|
73
66
|
self.logger.info_standard("Processing 15 AWS services across 3 regions")
|
74
|
-
|
67
|
+
|
75
68
|
# Completion status
|
76
69
|
self.logger.info_standard(
|
77
|
-
"Cost analysis completed successfully",
|
78
|
-
execution_time="12.3s",
|
79
|
-
resources_analyzed=245
|
70
|
+
"Cost analysis completed successfully", execution_time="12.3s", resources_analyzed=245
|
80
71
|
)
|
81
|
-
|
72
|
+
|
82
73
|
def demonstrate_warning_logging(self):
|
83
74
|
"""Demonstrate WARNING level logging for business users."""
|
84
75
|
print("\n=== WARNING Level Logging (Business Users) ===")
|
85
|
-
|
76
|
+
|
86
77
|
# Cost alerts with recommendations
|
87
78
|
self.logger.warning_business(
|
88
79
|
"High storage costs detected in S3",
|
89
80
|
recommendation="Consider implementing lifecycle policies for objects older than 90 days",
|
90
81
|
cost_impact=2847.50,
|
91
|
-
affected_buckets=12
|
82
|
+
affected_buckets=12,
|
92
83
|
)
|
93
|
-
|
84
|
+
|
94
85
|
# Resource optimization alerts
|
95
86
|
self.logger.warning_business(
|
96
87
|
"Underutilized EC2 instances found",
|
97
88
|
recommendation="Review instance sizing for potential rightsizing opportunities",
|
98
89
|
cost_impact=1250.00,
|
99
|
-
instance_count=8
|
90
|
+
instance_count=8,
|
100
91
|
)
|
101
|
-
|
92
|
+
|
102
93
|
# Budget threshold warnings
|
103
94
|
self.logger.warning_business(
|
104
95
|
"Monthly budget threshold exceeded",
|
105
96
|
recommendation="Review cost allocation and consider implementing cost controls",
|
106
97
|
cost_impact=450.75,
|
107
|
-
budget_utilization="105%"
|
98
|
+
budget_utilization="105%",
|
108
99
|
)
|
109
|
-
|
100
|
+
|
110
101
|
def demonstrate_error_logging(self):
|
111
102
|
"""Demonstrate ERROR level logging for all users."""
|
112
103
|
print("\n=== ERROR Level Logging (All Users) ===")
|
113
|
-
|
104
|
+
|
114
105
|
# AWS authentication errors
|
115
106
|
self.logger.error_all(
|
116
107
|
"Unable to access Cost Explorer API",
|
117
108
|
solution="Run 'aws sso login' to refresh your authentication tokens",
|
118
109
|
aws_error="ExpiredToken: Token has expired",
|
119
|
-
profile="billing-profile"
|
110
|
+
profile="billing-profile",
|
120
111
|
)
|
121
|
-
|
112
|
+
|
122
113
|
# Configuration errors
|
123
114
|
self.logger.error_all(
|
124
115
|
"Invalid AWS profile configuration",
|
125
116
|
solution="Check your ~/.aws/config file or contact your AWS administrator",
|
126
|
-
aws_error="ProfileNotFound: The config profile (invalid-profile) could not be found"
|
117
|
+
aws_error="ProfileNotFound: The config profile (invalid-profile) could not be found",
|
127
118
|
)
|
128
|
-
|
119
|
+
|
129
120
|
# Service access errors
|
130
121
|
self.logger.error_all(
|
131
122
|
"Insufficient permissions for Organizations API",
|
132
123
|
solution="Request 'organizations:ListAccounts' permission or use a different profile",
|
133
|
-
aws_error="AccessDenied: User is not authorized to perform organizations:ListAccounts"
|
124
|
+
aws_error="AccessDenied: User is not authorized to perform organizations:ListAccounts",
|
134
125
|
)
|
135
|
-
|
126
|
+
|
136
127
|
def demonstrate_structured_logging(self):
|
137
128
|
"""Demonstrate structured JSON logging for programmatic use."""
|
138
129
|
print("\n=== Structured JSON Logging (Programmatic Use) ===")
|
139
|
-
|
130
|
+
|
140
131
|
# Create JSON logger
|
141
132
|
json_logger = get_context_logger(level=self.log_level, json_output=True)
|
142
|
-
|
133
|
+
|
143
134
|
# JSON structured logs
|
144
135
|
json_logger.info_standard(
|
145
136
|
"Cost analysis completed",
|
146
137
|
total_cost=15432.75,
|
147
138
|
account_count=5,
|
148
|
-
service_breakdown={
|
149
|
-
"EC2": 8750.25,
|
150
|
-
"S3": 3200.50,
|
151
|
-
"RDS": 2482.00,
|
152
|
-
"Lambda": 1000.00
|
153
|
-
}
|
139
|
+
service_breakdown={"EC2": 8750.25, "S3": 3200.50, "RDS": 2482.00, "Lambda": 1000.00},
|
154
140
|
)
|
155
|
-
|
141
|
+
|
156
142
|
json_logger.warning_business(
|
157
143
|
"Budget variance detected",
|
158
144
|
recommendation="Implement cost controls",
|
159
145
|
cost_impact=2500.00,
|
160
|
-
variance_percentage=15.2
|
146
|
+
variance_percentage=15.2,
|
161
147
|
)
|
162
|
-
|
148
|
+
|
163
149
|
def demonstrate_contextual_logging(self):
|
164
150
|
"""Demonstrate context-aware logging based on execution environment."""
|
165
151
|
print("\n=== Context-Aware Logging ===")
|
166
|
-
|
152
|
+
|
167
153
|
# Logging adapts to CLI vs Jupyter vs CI/CD environments
|
168
154
|
self.logger.info_standard("Environment-aware logging initialized")
|
169
|
-
|
155
|
+
|
170
156
|
# Performance logging with context
|
171
157
|
with self.logger_performance_context("cost_analysis_operation") as perf:
|
172
158
|
# Simulate work
|
@@ -181,27 +167,27 @@ def demo_user_type_scenarios():
|
|
181
167
|
"""
|
182
168
|
print("Enhanced Multi-Level Logging System Demo")
|
183
169
|
print("=" * 50)
|
184
|
-
|
170
|
+
|
185
171
|
# Tech users (DEBUG level)
|
186
172
|
print("\n🔧 TECH USER SCENARIO (--log-level DEBUG)")
|
187
173
|
tech_demo = EnhancedLoggingExample(log_level="DEBUG")
|
188
174
|
tech_demo.demonstrate_debug_logging()
|
189
|
-
|
190
|
-
# Standard users (INFO level)
|
175
|
+
|
176
|
+
# Standard users (INFO level)
|
191
177
|
print("\n👥 STANDARD USER SCENARIO (--log-level INFO)")
|
192
178
|
standard_demo = EnhancedLoggingExample(log_level="INFO")
|
193
179
|
standard_demo.demonstrate_info_logging()
|
194
|
-
|
180
|
+
|
195
181
|
# Business users (WARNING level)
|
196
182
|
print("\n💼 BUSINESS USER SCENARIO (--log-level WARNING)")
|
197
183
|
business_demo = EnhancedLoggingExample(log_level="WARNING")
|
198
184
|
business_demo.demonstrate_warning_logging()
|
199
|
-
|
185
|
+
|
200
186
|
# Error scenarios (ERROR level)
|
201
187
|
print("\n🚨 ERROR SCENARIOS (--log-level ERROR)")
|
202
188
|
error_demo = EnhancedLoggingExample(log_level="ERROR")
|
203
189
|
error_demo.demonstrate_error_logging()
|
204
|
-
|
190
|
+
|
205
191
|
# JSON output for automation
|
206
192
|
print("\n📄 STRUCTURED JSON OUTPUT (--json-output)")
|
207
193
|
json_demo = EnhancedLoggingExample(log_level="INFO", json_output=True)
|
@@ -211,21 +197,21 @@ def demo_user_type_scenarios():
|
|
211
197
|
# Performance context manager for demonstration
|
212
198
|
class MockPerformanceContext:
|
213
199
|
"""Mock performance context for demonstration."""
|
214
|
-
|
200
|
+
|
215
201
|
def __init__(self, operation_name: str):
|
216
202
|
self.operation_name = operation_name
|
217
203
|
self.metrics = {}
|
218
204
|
self.start_time = time.time()
|
219
|
-
|
205
|
+
|
220
206
|
def __enter__(self):
|
221
207
|
return self
|
222
|
-
|
208
|
+
|
223
209
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
224
210
|
duration = time.time() - self.start_time
|
225
211
|
print(f"Performance: {self.operation_name} completed in {duration:.3f}s")
|
226
212
|
if self.metrics:
|
227
213
|
print(f"Metrics: {self.metrics}")
|
228
|
-
|
214
|
+
|
229
215
|
def add_metric(self, key: str, value: Any):
|
230
216
|
self.metrics[key] = value
|
231
217
|
|
@@ -236,4 +222,4 @@ EnhancedLoggingExample.logger_performance_context = lambda self, name: MockPerfo
|
|
236
222
|
|
237
223
|
if __name__ == "__main__":
|
238
224
|
"""Run the enhanced logging demonstration."""
|
239
|
-
demo_user_type_scenarios()
|
225
|
+
demo_user_type_scenarios()
|
@@ -12,14 +12,14 @@ multi-level logging architecture for user-type specific content.
|
|
12
12
|
runbooks finops --log-level DEBUG --profile my-profile
|
13
13
|
```
|
14
14
|
|
15
|
-
### Standard Users (INFO level - default)
|
15
|
+
### Standard Users (INFO level - default)
|
16
16
|
```bash
|
17
17
|
runbooks finops --profile my-profile
|
18
18
|
```
|
19
19
|
|
20
20
|
### Business Users (WARNING level)
|
21
21
|
```bash
|
22
|
-
runbooks finops --log-level WARNING --profile my-profile
|
22
|
+
runbooks finops --log-level WARNING --profile my-profile
|
23
23
|
```
|
24
24
|
|
25
25
|
### Error Focus (ERROR level)
|
@@ -47,7 +47,7 @@ class EnhancedLoggingIntegrationExample:
|
|
47
47
|
def __init__(self, module_name: str = "example", log_level: str = "INFO", json_output: bool = False):
|
48
48
|
"""
|
49
49
|
Initialize with enhanced logging.
|
50
|
-
|
50
|
+
|
51
51
|
Args:
|
52
52
|
module_name: Name of the module
|
53
53
|
log_level: Logging level (DEBUG, INFO, WARNING, ERROR)
|
@@ -63,21 +63,39 @@ class EnhancedLoggingIntegrationExample:
|
|
63
63
|
|
64
64
|
# Simulate AWS operations with different outcomes
|
65
65
|
operations = [
|
66
|
-
{
|
67
|
-
|
66
|
+
{
|
67
|
+
"service": "cost-explorer",
|
68
|
+
"operation": "get_cost_and_usage",
|
69
|
+
"duration": 0.8,
|
70
|
+
"success": True,
|
71
|
+
"resource_count": 25,
|
72
|
+
},
|
73
|
+
{
|
74
|
+
"service": "ec2",
|
75
|
+
"operation": "describe_instances",
|
76
|
+
"duration": 1.2,
|
77
|
+
"success": True,
|
78
|
+
"resource_count": 10,
|
79
|
+
},
|
68
80
|
{"service": "s3", "operation": "list_buckets", "duration": 0.3, "success": True, "resource_count": 5},
|
69
|
-
{
|
81
|
+
{
|
82
|
+
"service": "iam",
|
83
|
+
"operation": "get_account_summary",
|
84
|
+
"duration": 15.2,
|
85
|
+
"success": False,
|
86
|
+
"error": "AccessDenied: Insufficient permissions",
|
87
|
+
},
|
70
88
|
]
|
71
89
|
|
72
90
|
for op in operations:
|
73
91
|
self.logger.log_aws_operation(
|
74
92
|
operation=op["operation"],
|
75
|
-
service=op["service"],
|
93
|
+
service=op["service"],
|
76
94
|
duration=op["duration"],
|
77
95
|
success=op["success"],
|
78
96
|
resource_count=op.get("resource_count"),
|
79
97
|
error=op.get("error"),
|
80
|
-
request_id=f"req-{int(time.time())}-{hash(op['service']) % 10000}"
|
98
|
+
request_id=f"req-{int(time.time())}-{hash(op['service']) % 10000}",
|
81
99
|
)
|
82
100
|
time.sleep(0.1) # Brief pause for demonstration
|
83
101
|
|
@@ -88,23 +106,23 @@ class EnhancedLoggingIntegrationExample:
|
|
88
106
|
|
89
107
|
cost_scenarios = [
|
90
108
|
{
|
91
|
-
"operation": "monthly_ec2_spend_analysis",
|
92
|
-
"cost_impact": 2500.0,
|
109
|
+
"operation": "monthly_ec2_spend_analysis",
|
110
|
+
"cost_impact": 2500.0,
|
93
111
|
"savings_opportunity": 750.0,
|
94
|
-
"recommendation": "Consider Reserved Instances for consistent workloads"
|
112
|
+
"recommendation": "Consider Reserved Instances for consistent workloads",
|
95
113
|
},
|
96
114
|
{
|
97
115
|
"operation": "s3_storage_optimization",
|
98
116
|
"cost_impact": 150.0,
|
99
|
-
"savings_opportunity": 45.0,
|
100
|
-
"recommendation": "Implement lifecycle policies for infrequent access data"
|
117
|
+
"savings_opportunity": 45.0,
|
118
|
+
"recommendation": "Implement lifecycle policies for infrequent access data",
|
101
119
|
},
|
102
120
|
{
|
103
121
|
"operation": "unused_eip_analysis",
|
104
122
|
"cost_impact": 50.0,
|
105
123
|
"savings_opportunity": 50.0,
|
106
|
-
"recommendation": "Release 10 unused Elastic IPs immediately"
|
107
|
-
}
|
124
|
+
"recommendation": "Release 10 unused Elastic IPs immediately",
|
125
|
+
},
|
108
126
|
]
|
109
127
|
|
110
128
|
for scenario in cost_scenarios:
|
@@ -117,9 +135,19 @@ class EnhancedLoggingIntegrationExample:
|
|
117
135
|
print("=" * 60)
|
118
136
|
|
119
137
|
performance_scenarios = [
|
120
|
-
{
|
121
|
-
|
122
|
-
|
138
|
+
{
|
139
|
+
"operation": "inventory_collection",
|
140
|
+
"duration": 2.1,
|
141
|
+
"threshold": 5.0,
|
142
|
+
"memory_usage": 52428800,
|
143
|
+
}, # Fast operation
|
144
|
+
{
|
145
|
+
"operation": "large_cost_analysis",
|
146
|
+
"duration": 8.5,
|
147
|
+
"threshold": 5.0,
|
148
|
+
"memory_usage": 104857600,
|
149
|
+
}, # Slow operation
|
150
|
+
{"operation": "security_scan", "duration": 0.8, "threshold": 2.0, "memory_usage": 26214400}, # Quick scan
|
123
151
|
]
|
124
152
|
|
125
153
|
for scenario in performance_scenarios:
|
@@ -137,9 +165,9 @@ class EnhancedLoggingIntegrationExample:
|
|
137
165
|
"severity": "high",
|
138
166
|
"remediation_steps": [
|
139
167
|
"Review bucket policy for public access",
|
140
|
-
"Remove public read permissions if not required",
|
141
|
-
"Enable bucket logging for audit trail"
|
142
|
-
]
|
168
|
+
"Remove public read permissions if not required",
|
169
|
+
"Enable bucket logging for audit trail",
|
170
|
+
],
|
143
171
|
},
|
144
172
|
{
|
145
173
|
"finding": "IAM user without MFA enabled",
|
@@ -147,14 +175,14 @@ class EnhancedLoggingIntegrationExample:
|
|
147
175
|
"remediation_steps": [
|
148
176
|
"Enable MFA for the affected user",
|
149
177
|
"Review IAM policies for excessive permissions",
|
150
|
-
"Consider using IAM roles instead of users"
|
151
|
-
]
|
178
|
+
"Consider using IAM roles instead of users",
|
179
|
+
],
|
152
180
|
},
|
153
181
|
{
|
154
182
|
"finding": "Security group with overly permissive rules",
|
155
183
|
"severity": "low",
|
156
|
-
"remediation_steps": ["Review and tighten security group rules"]
|
157
|
-
}
|
184
|
+
"remediation_steps": ["Review and tighten security group rules"],
|
185
|
+
},
|
158
186
|
]
|
159
187
|
|
160
188
|
for finding in security_findings:
|
@@ -185,16 +213,16 @@ class EnhancedLoggingIntegrationExample:
|
|
185
213
|
"""Demonstrate JSON output for programmatic use."""
|
186
214
|
print(f"\n📋 JSON OUTPUT EXAMPLE ({self.log_level} level)")
|
187
215
|
print("=" * 60)
|
188
|
-
|
216
|
+
|
189
217
|
# Create a JSON logger
|
190
218
|
json_logger = get_module_logger("example_json", level=self.log_level, json_output=True)
|
191
|
-
|
219
|
+
|
192
220
|
json_logger.info_standard("JSON output demonstration", resource_count=42, operation_status="completed")
|
193
221
|
json_logger.log_cost_analysis(
|
194
222
|
"json_cost_analysis",
|
195
223
|
cost_impact=1200.0,
|
196
224
|
savings_opportunity=360.0,
|
197
|
-
recommendation="Optimize resource allocation for cost efficiency"
|
225
|
+
recommendation="Optimize resource allocation for cost efficiency",
|
198
226
|
)
|
199
227
|
|
200
228
|
def run_all_demonstrations(self):
|
@@ -209,8 +237,8 @@ class EnhancedLoggingIntegrationExample:
|
|
209
237
|
self.demonstrate_performance_logging()
|
210
238
|
self.demonstrate_security_logging()
|
211
239
|
self.demonstrate_operation_context()
|
212
|
-
|
213
|
-
if not hasattr(self.logger,
|
240
|
+
|
241
|
+
if not hasattr(self.logger, "json_output") or not self.logger.json_output:
|
214
242
|
self.demonstrate_json_output()
|
215
243
|
|
216
244
|
def _get_user_type_description(self) -> str:
|
@@ -218,8 +246,8 @@ class EnhancedLoggingIntegrationExample:
|
|
218
246
|
descriptions = {
|
219
247
|
"DEBUG": "Tech Users (SRE/DevOps) - Full technical details, API traces, performance metrics",
|
220
248
|
"INFO": "Standard Users - Clean operation status, progress indicators, business-friendly output",
|
221
|
-
"WARNING": "Business Users - Cost insights, recommendations, optimization opportunities",
|
222
|
-
"ERROR": "All Users - Clear error messages with solutions and troubleshooting steps"
|
249
|
+
"WARNING": "Business Users - Cost insights, recommendations, optimization opportunities",
|
250
|
+
"ERROR": "All Users - Clear error messages with solutions and troubleshooting steps",
|
223
251
|
}
|
224
252
|
return descriptions.get(self.log_level, "Unknown user type")
|
225
253
|
|
@@ -230,28 +258,28 @@ def main():
|
|
230
258
|
print("=" * 80)
|
231
259
|
print("This demonstration shows how logging adapts content based on user type:")
|
232
260
|
print("• DEBUG Level: Technical users (SRE/DevOps)")
|
233
|
-
print("• INFO Level: Standard users (default)")
|
261
|
+
print("• INFO Level: Standard users (default)")
|
234
262
|
print("• WARNING Level: Business users")
|
235
263
|
print("• ERROR Level: All users (minimal output)")
|
236
264
|
print("=" * 80)
|
237
265
|
|
238
266
|
# Test all log levels
|
239
267
|
log_levels = ["DEBUG", "INFO", "WARNING", "ERROR"]
|
240
|
-
|
268
|
+
|
241
269
|
for level in log_levels:
|
242
270
|
demo = EnhancedLoggingIntegrationExample("enhanced_logging_demo", level)
|
243
271
|
demo.run_all_demonstrations()
|
244
|
-
|
272
|
+
|
245
273
|
if level != "ERROR": # Add separator except for last level
|
246
274
|
print(f"\n{'=' * 80}\n")
|
247
275
|
|
248
276
|
print("\n✅ DEMONSTRATION COMPLETE")
|
249
277
|
print("\nTo use enhanced logging in your module:")
|
250
|
-
print("1. from runbooks.enterprise.logging import get_module_logger")
|
278
|
+
print("1. from runbooks.enterprise.logging import get_module_logger")
|
251
279
|
print("2. logger = get_module_logger('your_module_name')")
|
252
280
|
print("3. Use logger.info_standard(), logger.debug_tech(), logger.warning_business(), etc.")
|
253
281
|
print("4. Use logger.log_aws_operation(), logger.log_cost_analysis() for convenience")
|
254
282
|
|
255
283
|
|
256
284
|
if __name__ == "__main__":
|
257
|
-
main()
|
285
|
+
main()
|
runbooks/common/env_utils.py
CHANGED
@@ -12,13 +12,13 @@ from typing import Union
|
|
12
12
|
def get_required_env(var_name: str) -> str:
|
13
13
|
"""
|
14
14
|
Get required string environment variable - NO hardcoded defaults.
|
15
|
-
|
15
|
+
|
16
16
|
Args:
|
17
17
|
var_name: Environment variable name
|
18
|
-
|
18
|
+
|
19
19
|
Returns:
|
20
20
|
Environment variable value
|
21
|
-
|
21
|
+
|
22
22
|
Raises:
|
23
23
|
ValueError: If environment variable is not set
|
24
24
|
"""
|
@@ -31,13 +31,13 @@ def get_required_env(var_name: str) -> str:
|
|
31
31
|
def get_required_env_int(var_name: str) -> int:
|
32
32
|
"""
|
33
33
|
Get required integer environment variable - NO hardcoded defaults.
|
34
|
-
|
34
|
+
|
35
35
|
Args:
|
36
36
|
var_name: Environment variable name
|
37
|
-
|
37
|
+
|
38
38
|
Returns:
|
39
39
|
Environment variable value as integer
|
40
|
-
|
40
|
+
|
41
41
|
Raises:
|
42
42
|
ValueError: If environment variable is not set or not a valid integer
|
43
43
|
"""
|
@@ -51,13 +51,13 @@ def get_required_env_int(var_name: str) -> int:
|
|
51
51
|
def get_required_env_float(var_name: str) -> float:
|
52
52
|
"""
|
53
53
|
Get required float environment variable - NO hardcoded defaults.
|
54
|
-
|
54
|
+
|
55
55
|
Args:
|
56
56
|
var_name: Environment variable name
|
57
|
-
|
57
|
+
|
58
58
|
Returns:
|
59
59
|
Environment variable value as float
|
60
|
-
|
60
|
+
|
61
61
|
Raises:
|
62
62
|
ValueError: If environment variable is not set or not a valid float
|
63
63
|
"""
|
@@ -71,20 +71,20 @@ def get_required_env_float(var_name: str) -> float:
|
|
71
71
|
def get_required_env_bool(var_name: str) -> bool:
|
72
72
|
"""
|
73
73
|
Get required boolean environment variable - NO hardcoded defaults.
|
74
|
-
|
74
|
+
|
75
75
|
Args:
|
76
76
|
var_name: Environment variable name
|
77
|
-
|
77
|
+
|
78
78
|
Returns:
|
79
79
|
Environment variable value as boolean
|
80
|
-
|
80
|
+
|
81
81
|
Raises:
|
82
82
|
ValueError: If environment variable is not set
|
83
83
|
"""
|
84
84
|
value = get_required_env(var_name).lower()
|
85
|
-
if value in (
|
85
|
+
if value in ("true", "1", "yes", "on"):
|
86
86
|
return True
|
87
|
-
elif value in (
|
87
|
+
elif value in ("false", "0", "no", "off"):
|
88
88
|
return False
|
89
89
|
else:
|
90
90
|
raise ValueError(f"Environment variable {var_name} must be a valid boolean (true/false), got: {value}")
|
@@ -92,5 +92,5 @@ def get_required_env_bool(var_name: str) -> bool:
|
|
92
92
|
|
93
93
|
# Legacy compatibility function names for existing code
|
94
94
|
_get_required_env_float = get_required_env_float
|
95
|
-
_get_required_env_int = get_required_env_int
|
96
|
-
_get_required_env = get_required_env
|
95
|
+
_get_required_env_int = get_required_env_int
|
96
|
+
_get_required_env = get_required_env
|