runbooks 1.0.0__py3-none-any.whl → 1.0.2__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 +1 -1
- runbooks/cfat/WEIGHT_CONFIG_README.md +368 -0
- runbooks/cfat/app.ts +27 -19
- runbooks/cfat/assessment/runner.py +6 -5
- runbooks/cfat/tests/test_weight_configuration.ts +449 -0
- runbooks/cfat/weight_config.ts +574 -0
- runbooks/cloudops/models.py +20 -14
- runbooks/common/__init__.py +26 -9
- runbooks/common/aws_pricing.py +1070 -105
- runbooks/common/aws_pricing_api.py +276 -44
- runbooks/common/date_utils.py +115 -0
- runbooks/common/dry_run_examples.py +587 -0
- runbooks/common/dry_run_framework.py +520 -0
- runbooks/common/enhanced_exception_handler.py +10 -7
- runbooks/common/mcp_cost_explorer_integration.py +5 -4
- runbooks/common/memory_optimization.py +533 -0
- runbooks/common/performance_optimization_engine.py +1153 -0
- runbooks/common/profile_utils.py +86 -118
- runbooks/common/rich_utils.py +3 -3
- runbooks/common/sre_performance_suite.py +574 -0
- runbooks/finops/business_case_config.py +314 -0
- runbooks/finops/cost_processor.py +19 -4
- runbooks/finops/dashboard_runner.py +47 -28
- runbooks/finops/ebs_cost_optimizer.py +1 -1
- runbooks/finops/ebs_optimizer.py +56 -9
- runbooks/finops/embedded_mcp_validator.py +642 -36
- runbooks/finops/enhanced_trend_visualization.py +7 -2
- runbooks/finops/executive_export.py +789 -0
- runbooks/finops/finops_dashboard.py +6 -5
- runbooks/finops/finops_scenarios.py +34 -27
- runbooks/finops/iam_guidance.py +6 -1
- runbooks/finops/nat_gateway_optimizer.py +46 -27
- runbooks/finops/notebook_utils.py +1 -1
- runbooks/finops/schemas.py +73 -58
- runbooks/finops/single_dashboard.py +20 -4
- runbooks/finops/tests/test_integration.py +3 -1
- runbooks/finops/vpc_cleanup_exporter.py +2 -1
- runbooks/finops/vpc_cleanup_optimizer.py +22 -29
- runbooks/inventory/core/collector.py +51 -28
- runbooks/inventory/discovery.md +197 -247
- runbooks/inventory/inventory_modules.py +2 -2
- runbooks/inventory/list_ec2_instances.py +3 -3
- runbooks/inventory/models/account.py +5 -3
- runbooks/inventory/models/inventory.py +1 -1
- runbooks/inventory/models/resource.py +5 -3
- runbooks/inventory/organizations_discovery.py +102 -13
- runbooks/inventory/unified_validation_engine.py +2 -15
- runbooks/main.py +255 -92
- runbooks/operate/base.py +9 -6
- runbooks/operate/deployment_framework.py +5 -4
- runbooks/operate/deployment_validator.py +6 -5
- runbooks/operate/mcp_integration.py +6 -5
- runbooks/operate/networking_cost_heatmap.py +17 -13
- runbooks/operate/vpc_operations.py +82 -13
- runbooks/remediation/base.py +3 -1
- runbooks/remediation/commons.py +5 -5
- runbooks/remediation/commvault_ec2_analysis.py +66 -18
- runbooks/remediation/config/accounts_example.json +31 -0
- runbooks/remediation/multi_account.py +120 -7
- runbooks/remediation/remediation_cli.py +710 -0
- runbooks/remediation/universal_account_discovery.py +377 -0
- runbooks/remediation/workspaces_list.py +2 -2
- runbooks/security/compliance_automation_engine.py +99 -20
- runbooks/security/config/__init__.py +24 -0
- runbooks/security/config/compliance_config.py +255 -0
- runbooks/security/config/compliance_weights_example.json +22 -0
- runbooks/security/config_template_generator.py +500 -0
- runbooks/security/security_cli.py +377 -0
- runbooks/validation/cli.py +8 -7
- runbooks/validation/comprehensive_2way_validator.py +26 -15
- runbooks/validation/mcp_validator.py +62 -8
- runbooks/vpc/config.py +49 -15
- runbooks/vpc/cross_account_session.py +5 -1
- runbooks/vpc/heatmap_engine.py +438 -59
- runbooks/vpc/mcp_no_eni_validator.py +115 -36
- runbooks/vpc/performance_optimized_analyzer.py +546 -0
- runbooks/vpc/runbooks_adapter.py +33 -12
- runbooks/vpc/tests/conftest.py +4 -2
- runbooks/vpc/tests/test_cost_engine.py +3 -1
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/METADATA +1 -1
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/RECORD +85 -79
- runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/finops/runbooks.security.report_generator.log +0 -0
- runbooks/finops/runbooks.security.run_script.log +0 -0
- runbooks/finops/runbooks.security.security_export.log +0 -0
- runbooks/finops/tests/results_test_finops_dashboard.xml +0 -1
- runbooks/inventory/artifacts/scale-optimize-status.txt +0 -12
- runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/inventory/runbooks.security.report_generator.log +0 -0
- runbooks/inventory/runbooks.security.run_script.log +0 -0
- runbooks/inventory/runbooks.security.security_export.log +0 -0
- runbooks/vpc/runbooks.inventory.organizations_discovery.log +0 -0
- runbooks/vpc/runbooks.security.report_generator.log +0 -0
- runbooks/vpc/runbooks.security.run_script.log +0 -0
- runbooks/vpc/runbooks.security.security_export.log +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/WHEEL +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/entry_points.txt +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.0.0.dist-info → runbooks-1.0.2.dist-info}/top_level.txt +0 -0
@@ -610,18 +610,9 @@ class VPCCleanupOptimizer:
|
|
610
610
|
|
611
611
|
print_header("🌐 Real-Time NO-ENI VPC Discovery", "MCP-Validated VPC Cleanup Analysis")
|
612
612
|
|
613
|
-
#
|
614
|
-
from runbooks.common.profile_utils import get_enterprise_profile_mapping
|
615
|
-
enterprise_profiles = get_enterprise_profile_mapping()
|
616
|
-
|
617
|
-
# Override with current profile if available
|
618
|
-
current_profile_type = self._determine_profile_type(self.profile)
|
619
|
-
if current_profile_type:
|
620
|
-
enterprise_profiles[current_profile_type] = self.profile
|
621
|
-
|
622
|
-
# Initialize MCP validator for dynamic discovery
|
613
|
+
# Initialize MCP validator with universal profile support
|
623
614
|
print_info("🔧 Initializing dynamic MCP validator...")
|
624
|
-
mcp_validator = NOENIVPCMCPValidator(
|
615
|
+
mcp_validator = NOENIVPCMCPValidator(user_profile=self.profile)
|
625
616
|
|
626
617
|
# Perform dynamic discovery across all accounts
|
627
618
|
print_info("🚀 Starting real-time discovery across all AWS accounts...")
|
@@ -641,7 +632,7 @@ class VPCCleanupOptimizer:
|
|
641
632
|
# Get detailed VPC information for each NO-ENI VPC
|
642
633
|
try:
|
643
634
|
# Use appropriate session for this account
|
644
|
-
session = self._get_session_for_account(target.account_id
|
635
|
+
session = self._get_session_for_account(target.account_id)
|
645
636
|
ec2_client = session.client('ec2', region_name=target.region)
|
646
637
|
|
647
638
|
# Get VPC details
|
@@ -708,26 +699,28 @@ class VPCCleanupOptimizer:
|
|
708
699
|
return 'CENTRALISED_OPS'
|
709
700
|
return None
|
710
701
|
|
711
|
-
def _get_session_for_account(self, account_id: str
|
712
|
-
"""Get appropriate session for accessing a specific account."""
|
702
|
+
def _get_session_for_account(self, account_id: str) -> boto3.Session:
|
703
|
+
"""Get appropriate session for accessing a specific account using universal profile management."""
|
704
|
+
from runbooks.common.profile_utils import get_profile_for_operation
|
705
|
+
|
713
706
|
# In enterprise setup, would assume role here
|
714
|
-
# For now, return session with best available profile
|
707
|
+
# For now, return session with best available profile using three-tier priority system
|
715
708
|
|
716
|
-
#
|
717
|
-
|
709
|
+
# Try different operation types in priority order
|
710
|
+
profile_types = ['management', 'operational', 'billing']
|
718
711
|
|
719
|
-
for profile_type in
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
712
|
+
for profile_type in profile_types:
|
713
|
+
try:
|
714
|
+
profile_name = get_profile_for_operation(profile_type, self.profile)
|
715
|
+
session = boto3.Session(profile_name=profile_name)
|
716
|
+
# Verify access
|
717
|
+
sts_client = session.client('sts')
|
718
|
+
identity = sts_client.get_caller_identity()
|
719
|
+
|
720
|
+
if identity['Account'] == account_id:
|
721
|
+
return session
|
722
|
+
except Exception:
|
723
|
+
continue
|
731
724
|
|
732
725
|
# Fallback to current session
|
733
726
|
return self.session
|
@@ -42,12 +42,13 @@ try:
|
|
42
42
|
ENHANCED_PROFILES_AVAILABLE = True
|
43
43
|
except ImportError:
|
44
44
|
ENHANCED_PROFILES_AVAILABLE = False
|
45
|
-
# Fallback profile definitions
|
45
|
+
# Fallback profile definitions with universal environment support
|
46
|
+
import os
|
46
47
|
ENTERPRISE_PROFILES = {
|
47
|
-
"BILLING_PROFILE": "
|
48
|
-
"MANAGEMENT_PROFILE": "
|
49
|
-
"CENTRALISED_OPS_PROFILE": "
|
50
|
-
"SINGLE_ACCOUNT_PROFILE": "
|
48
|
+
"BILLING_PROFILE": os.getenv("BILLING_PROFILE", "default-billing-profile"),
|
49
|
+
"MANAGEMENT_PROFILE": os.getenv("MANAGEMENT_PROFILE", "default-management-profile"),
|
50
|
+
"CENTRALISED_OPS_PROFILE": os.getenv("CENTRALISED_OPS_PROFILE", "default-ops-profile"),
|
51
|
+
"SINGLE_ACCOUNT_PROFILE": os.getenv("SINGLE_AWS_PROFILE", "default-single-profile"),
|
51
52
|
}
|
52
53
|
|
53
54
|
|
@@ -141,28 +142,35 @@ class EnhancedInventoryCollector(CloudFoundationsBase):
|
|
141
142
|
|
142
143
|
Strategic Alignment: "Do one thing and do it well"
|
143
144
|
- Single profile override pattern: --profile takes precedence
|
144
|
-
-
|
145
|
-
-
|
145
|
+
- Universal AWS environment compatibility: works with ANY profile configuration
|
146
|
+
- Graceful fallback system for discovery across different AWS setups
|
146
147
|
|
147
148
|
Returns:
|
148
149
|
str: The active profile to use for all operations
|
149
150
|
"""
|
150
|
-
#
|
151
|
+
# PRIMARY: User --profile parameter takes absolute precedence (Universal Compatibility)
|
151
152
|
if self.profile:
|
152
|
-
print_info(f"Using user-specified profile
|
153
|
-
logger.info("Profile override via --profile parameter -
|
153
|
+
print_info(f"✅ Universal AWS Compatibility: Using user-specified profile '{self.profile}'")
|
154
|
+
logger.info("Profile override via --profile parameter - universal environment support")
|
154
155
|
return self.profile
|
155
156
|
|
156
|
-
#
|
157
|
+
# SECONDARY: Environment variable fallback with intelligent prioritization
|
158
|
+
# Priority order: Management > Billing > Operations > Default (Organizations discovery preference)
|
157
159
|
env_profile = (
|
158
160
|
os.getenv("MANAGEMENT_PROFILE") or
|
159
161
|
os.getenv("BILLING_PROFILE") or
|
160
162
|
os.getenv("CENTRALISED_OPS_PROFILE") or
|
163
|
+
os.getenv("SINGLE_AWS_PROFILE") or
|
161
164
|
"default"
|
162
165
|
)
|
163
166
|
|
164
|
-
|
165
|
-
|
167
|
+
if env_profile != "default":
|
168
|
+
print_info(f"✅ Universal AWS Compatibility: Using environment profile '{env_profile}'")
|
169
|
+
logger.info(f"Environment variable profile selected: {env_profile}")
|
170
|
+
else:
|
171
|
+
print_info("✅ Universal AWS Compatibility: Using 'default' profile - works with any AWS CLI configuration")
|
172
|
+
logger.info("Using default profile - universal compatibility mode")
|
173
|
+
|
166
174
|
return env_profile
|
167
175
|
|
168
176
|
def _initialize_collectors(self) -> Dict[str, str]:
|
@@ -226,21 +234,19 @@ class EnhancedInventoryCollector(CloudFoundationsBase):
|
|
226
234
|
|
227
235
|
def get_organization_accounts(self) -> List[str]:
|
228
236
|
"""
|
229
|
-
Get list of accounts in AWS Organization.
|
237
|
+
Get list of accounts in AWS Organization with universal compatibility.
|
230
238
|
|
231
239
|
Strategic Alignment: "Do one thing and do it well"
|
232
|
-
-
|
233
|
-
-
|
234
|
-
-
|
240
|
+
- Universal AWS environment compatibility: works with ANY Organizations setup
|
241
|
+
- Intelligent fallback system: Organizations → standalone account detection
|
242
|
+
- Graceful handling of different permission scenarios
|
235
243
|
"""
|
236
244
|
try:
|
237
|
-
# Use
|
238
|
-
|
239
|
-
management_profile = self.active_profile
|
240
|
-
management_session = create_management_session(profile=management_profile)
|
245
|
+
# Use active profile for Organizations operations (Universal Compatibility)
|
246
|
+
management_session = create_management_session(profile=self.active_profile)
|
241
247
|
organizations_client = management_session.client("organizations")
|
242
248
|
|
243
|
-
print_info("
|
249
|
+
print_info(f"🔍 Universal Discovery: Attempting Organizations API with profile '{self.active_profile}'...")
|
244
250
|
response = self._make_aws_call(organizations_client.list_accounts)
|
245
251
|
|
246
252
|
accounts = []
|
@@ -248,14 +254,31 @@ class EnhancedInventoryCollector(CloudFoundationsBase):
|
|
248
254
|
if account["Status"] == "ACTIVE":
|
249
255
|
accounts.append(account["Id"])
|
250
256
|
|
251
|
-
|
252
|
-
|
253
|
-
|
257
|
+
if accounts:
|
258
|
+
print_success(f"✅ Organizations Discovery: Found {len(accounts)} active accounts in organization")
|
259
|
+
logger.info(f"Organizations discovery successful: {len(accounts)} accounts with profile {self.active_profile}")
|
260
|
+
return accounts
|
261
|
+
else:
|
262
|
+
print_warning("⚠️ Organizations Discovery: No active accounts found in organization")
|
263
|
+
return [self.get_account_id()]
|
254
264
|
|
255
265
|
except Exception as e:
|
256
|
-
|
257
|
-
|
258
|
-
|
266
|
+
# Enhanced error messages for different AWS environment scenarios
|
267
|
+
error_message = str(e).lower()
|
268
|
+
|
269
|
+
if "accessdenied" in error_message or "unauthorized" in error_message:
|
270
|
+
print_warning(f"⚠️ Universal Compatibility: Profile '{self.active_profile}' lacks Organizations permissions")
|
271
|
+
print_info("💡 Single Account Mode: Continuing with current account (universal compatibility)")
|
272
|
+
elif "organizationsnotinuse" in error_message:
|
273
|
+
print_info(f"ℹ️ Standalone Account: Profile '{self.active_profile}' not in an AWS Organization")
|
274
|
+
print_info("💡 Single Account Mode: Continuing with current account")
|
275
|
+
else:
|
276
|
+
print_warning(f"⚠️ Organizations Discovery Failed: {e}")
|
277
|
+
print_info("💡 Fallback Mode: Continuing with current account for universal compatibility")
|
278
|
+
|
279
|
+
logger.warning(f"Organization discovery failed, graceful fallback: {e}")
|
280
|
+
|
281
|
+
# Universal fallback: always return current account for single-account operations
|
259
282
|
return [self.get_account_id()]
|
260
283
|
|
261
284
|
def get_current_account_id(self) -> str:
|