runbooks 0.9.8__tar.gz → 0.9.9__tar.gz
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-0.9.8/src/runbooks.egg-info → runbooks-0.9.9}/PKG-INFO +1 -1
- {runbooks-0.9.8 → runbooks-0.9.9}/pyproject.toml +1 -1
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/__init__.py +1 -1
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/rich_utils.py +3 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/markdown_exporter.py +226 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/optimizer.py +2 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/single_dashboard.py +2 -2
- runbooks-0.9.9/src/runbooks/finops/vpc_cleanup_exporter.py +328 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/vpc_cleanup_optimizer.py +536 -35
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/main.py +315 -7
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/vpc_operations.py +1 -1
- runbooks-0.9.9/src/runbooks/vpc/unified_scenarios.py +3199 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/vpc_cleanup_integration.py +4 -4
- {runbooks-0.9.8 → runbooks-0.9.9/src/runbooks.egg-info}/PKG-INFO +1 -1
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks.egg-info/SOURCES.txt +2 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/LICENSE +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/MANIFEST.in +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/setup.cfg +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/conftest.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/__main__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/_platform/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/_platform/core/runbooks_wrapper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/base.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/app.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/asana-import.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/cfat-checks.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/cfat.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/collectors.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/compliance.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/jira-import.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/runner.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/assessment/validators.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/cli.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/asana-import.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/cfat-checks.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/cfat.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/checks-output.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/cloudshell-console-run.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/cloudshell-download.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/cloudshell-output.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/downloadfile.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/jira-import.csv +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/open-cloudshell.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/docs/report-header.png +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/models.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/package-lock.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/package.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/report.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/reporting/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/reporting/exporters.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/reporting/formatters.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/reporting/templates.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/run-assessment.sh +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/runner.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-cloudtrail-existence.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-config-existence.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-control-tower.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-ec2-existence.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-iam-users.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-legacy-cur.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-org-cloudformation.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/check-vpc-existence.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/create-asanaimport.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/create-backlog.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/create-jiraimport.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/create-report.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/define-account-type.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-enabled-org-policy-types.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-enabled-org-services.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-idc-info.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-org-da-accounts.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-org-details.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-org-member-accounts.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-org-ous.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/get-regions.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/actions/zip-assessment.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/src/types/index.d.ts +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tests/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tests/test_cli.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tests/test_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tests/test_models.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tests/test_reporting.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/tsconfig.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cfat/webpack.config.cjs +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/base.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/cost_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/infrastructure_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/interfaces.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/lifecycle_manager.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/mcp_cost_validation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/models.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/monitoring_automation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/notebook_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/cloudops/security_enforcer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/accuracy_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/aws_utils.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/context_logger.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/cross_module_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/enhanced_exception_handler.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/enhanced_logging_example.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/enhanced_logging_integration_example.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/enterprise_audit_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/logger.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/logging_integration_helper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/mcp_cost_explorer_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/mcp_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/performance_monitor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/common/profile_utils.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/config.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/enterprise/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/enterprise/error_handling.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/enterprise/logging.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/enterprise/multi_tenant.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/enterprise/security.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/feedback/user_feedback_collector.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/account_resolver.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/accuracy_cross_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/automation_core.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/aws_client.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/budget_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/business_cases.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/cli.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/commvault_ec2_analysis.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/compute_cost_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/cost_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/cost_processor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/dashboard_router.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/dashboard_runner.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/ebs_cost_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/ebs_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/elastic_ip_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/embedded_mcp_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/enhanced_dashboard_runner.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/enhanced_progress.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/enhanced_trend_visualization.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/enterprise_wrappers.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/finops_dashboard.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/finops_scenarios.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/helpers.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/iam_guidance.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/legacy_migration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/main.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/multi_dashboard.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/nat_gateway_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/network_cost_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/notebook_utils.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/profile_processor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/reservation_optimizer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/runbooks.inventory.organizations_discovery.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/runbooks.security.report_generator.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/runbooks.security.run_script.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/runbooks.security.security_export.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/scenarios.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/schemas.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/service_mapping.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/results_test_finops_dashboard.xml +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/run_comprehensive_tests.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/run_tests.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_finops_dashboard.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_performance.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_performance_benchmarks.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_reference_images_validation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/test_single_account_features.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/tests/validate_test_suite.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/types.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/validation_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/visualisations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/finops/workspaces_analyzer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/hitl/enhanced_workflow_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/.gitignore +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/ArgumentsClass.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/LandingZone/delete_lz.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/common_test_data.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/common_test_functions.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/script_test_data.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/setup.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/src.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_Inventory_Modules.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_cfn_describe_stacks.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_ec2_describe_instances.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_lambda_list_functions.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_moto_integration_example.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/Tests/test_org_list_accounts.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/account_class.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/all_my_instances_wrapper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/artifacts/scale-optimize-status.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/aws_decorators.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/check_cloudtrail_compliance.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/check_controltower_readiness.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/check_landingzone_readiness.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/aws_comprehensive.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/aws_compute.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/aws_management.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/aws_networking.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/base.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/collectors/enterprise_scale.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/core/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/core/collector.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/core/formatter.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/draw_org_structure.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/ec2_vpc_utils.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_cfn_drift_detection.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_cfn_orphaned_stacks.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_cfn_stackset_drift.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_ec2_security_groups.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_landingzone_versions.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/find_vpc_flow_logs.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/inventory.sh +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/inventory_modules.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_cfn_stacks.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_cfn_stackset_operation_results.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_cfn_stackset_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_cfn_stacksets.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_config_recorders_delivery_channels.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ds_directories.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ec2_availability_zones.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ec2_ebs_volumes.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ec2_instances.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ecs_clusters_and_tasks.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_elbs_load_balancers.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_enis_network_interfaces.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_guardduty_detectors.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_iam_policies.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_iam_roles.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_iam_saml_providers.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_lambda_functions.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_org_accounts.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_org_accounts_users.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_rds_db_instances.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_route53_hosted_zones.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_servicecatalog_provisioned_products.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_sns_topics.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_ssm_parameters.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_vpc_subnets.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/list_vpcs.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/mcp_vpc_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/models/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/models/account.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/models/inventory.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/models/resource.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/organizations_discovery.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/recover_cfn_stack_ids.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/requirements.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/rich_inventory_display.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/run_on_multi_accounts.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/runbooks.inventory.organizations_discovery.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/runbooks.security.report_generator.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/runbooks.security.run_script.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/runbooks.security.security_export.log +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/utils/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/utils/aws_helpers.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/utils/threading_utils.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/utils/validation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/verify_ec2_security_groups.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/vpc_analyzer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/vpc_architecture_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/vpc_dependency_analyzer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/inventory/vpc_flow_analyzer.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/metrics/dora_metrics_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/monitoring/performance_monitor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/base.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/cloudformation_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/cloudwatch_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/deployment_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/deployment_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/dynamodb_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/ec2_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/executive_dashboard.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/iam_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/mcp_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/nat_gateway_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/networking_cost_heatmap.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/privatelink_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/rds_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/s3_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/tagging_operations.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/tags.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/operate/vpc_endpoints.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/Tests/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/Tests/update_policy.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/acm_cert_expired_unused.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/acm_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/api_gateway_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/base.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/cloudtrail_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/cloudtrail_s3_modifications.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/cognito_active_users.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/cognito_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/cognito_user_password_reset.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/commons.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/commvault_ec2_analysis.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/dynamodb_optimize.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/dynamodb_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/dynamodb_server_side_encryption.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/ec2_public_ips.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/ec2_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/ec2_subnet_disable_auto_ip_assignment.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/ec2_unattached_ebs_volumes.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/ec2_unused_security_groups.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/kms_enable_key_rotation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/kms_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/lambda_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/lambda_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/multi_account.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/rds_instance_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/rds_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/rds_snapshot_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/requirements.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_block_public_access.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_bucket_public_access.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_disable_static_website_hosting.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_downloader.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_enable_access_logging.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_encryption.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_force_ssl_secure_policy.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_object_search.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/s3_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/scan_for_phrase.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/vpc_remediation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/remediation/workspaces_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/account_level_bucket_public_access.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/alternate_contacts.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/bucket_public_access.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/cloudwatch_alarm_configuration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/direct_attached_policy.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/guardduty_enabled.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/iam_password_policy.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/iam_user_mfa.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/multi_region_instance_usage.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/multi_region_trail.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/root_access_key.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/root_mfa.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/root_usage.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/trail_enabled.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/checklist/trusted_advisor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/cloudops_automation_security_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/compliance_automation.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/compliance_automation_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/config-origin.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/config.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/enterprise_security_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/enterprise_security_policies.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/executive_security_dashboard.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/integration_test_enterprise_security.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/module_security_integrator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/multi_account_security_controls.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/permission.json +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/real_time_security_monitor.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/report_generator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/report_template_en.html +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/report_template_jp.html +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/report_template_kr.html +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/report_template_vn.html +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/run_script.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/security_baseline_tester.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/security_export.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/common.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/enums.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/language.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/level_const.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/security/utils/permission_list.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/mcp_reliability_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/performance_optimization_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/production_monitoring_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/sre/reliability_monitoring_framework.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/utils/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/utils/logger.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/utils/version_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/validation/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/validation/benchmark.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/validation/cli.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/validation/mcp_validator.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/README.md +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/cleanup_wrapper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/config.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/cost_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/heatmap_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/manager_interface.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/networking_wrapper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/rich_formatters.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/runbooks_adapter.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/__init__.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/conftest.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/test_cli_integration.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/test_config.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/test_cost_engine.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks/vpc/tests/test_networking_wrapper.py +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks.egg-info/dependency_links.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks.egg-info/entry_points.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks.egg-info/requires.txt +0 -0
- {runbooks-0.9.8 → runbooks-0.9.9}/src/runbooks.egg-info/top_level.txt +0 -0
@@ -13,7 +13,7 @@
|
|
13
13
|
## Metadata: https://docs.astral.sh/uv/concepts/projects/config/
|
14
14
|
name = "runbooks"
|
15
15
|
## Enhanced with AWS Operations integration, unified CLI architecture, and comprehensive service operations
|
16
|
-
version = "0.9.
|
16
|
+
version = "0.9.9"
|
17
17
|
description = "CloudOps Automation Toolkit with Enhanced Cloud Foundations Assessment for DevOps and SRE teams."
|
18
18
|
readme = "README.md"
|
19
19
|
requires-python = ">=3.11,<3.14"
|
@@ -61,7 +61,7 @@ s3_ops = S3Operations()
|
|
61
61
|
|
62
62
|
# Centralized Version Management - Single Source of Truth
|
63
63
|
# All modules MUST import __version__ from this location
|
64
|
-
__version__ = "0.9.
|
64
|
+
__version__ = "0.9.9"
|
65
65
|
|
66
66
|
# Fallback for legacy importlib.metadata usage during transition
|
67
67
|
try:
|
@@ -132,6 +132,7 @@ def print_banner() -> None:
|
|
132
132
|
|
133
133
|
def create_table(
|
134
134
|
title: Optional[str] = None,
|
135
|
+
caption: Optional[str] = None,
|
135
136
|
columns: List[Dict[str, Any]] = None,
|
136
137
|
show_header: bool = True,
|
137
138
|
show_footer: bool = False,
|
@@ -143,6 +144,7 @@ def create_table(
|
|
143
144
|
|
144
145
|
Args:
|
145
146
|
title: Table title
|
147
|
+
caption: Table caption (displayed below the table)
|
146
148
|
columns: List of column definitions [{"name": "Col1", "style": "cyan", "justify": "left"}]
|
147
149
|
show_header: Show header row
|
148
150
|
show_footer: Show footer row
|
@@ -154,6 +156,7 @@ def create_table(
|
|
154
156
|
"""
|
155
157
|
table = Table(
|
156
158
|
title=title,
|
159
|
+
caption=caption,
|
157
160
|
show_header=show_header,
|
158
161
|
show_footer=show_footer,
|
159
162
|
box=box_style,
|
@@ -423,6 +423,232 @@ class MarkdownExporter:
|
|
423
423
|
highest = max(profiles, key=lambda p: p.get("potential_savings", 0))
|
424
424
|
return highest.get("profile_name", "Unknown")[:20]
|
425
425
|
|
426
|
+
def format_vpc_cleanup_table(self, vpc_candidates: List[Any]) -> str:
|
427
|
+
"""
|
428
|
+
Format VPC cleanup candidates into 15-column markdown table.
|
429
|
+
|
430
|
+
Args:
|
431
|
+
vpc_candidates: List of VPCCandidate objects from vpc.unified_scenarios
|
432
|
+
|
433
|
+
Returns:
|
434
|
+
Markdown formatted table string with VPC cleanup analysis
|
435
|
+
"""
|
436
|
+
if not vpc_candidates:
|
437
|
+
return "⚠️ No VPC candidates to format"
|
438
|
+
|
439
|
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S UTC")
|
440
|
+
|
441
|
+
# Build table header and separator
|
442
|
+
headers = [
|
443
|
+
"Account_ID", "VPC_ID", "VPC_Name", "CIDR_Block", "Overlapping",
|
444
|
+
"Is_Default", "ENI_Count", "Tags", "Flow_Logs", "TGW/Peering",
|
445
|
+
"LBs_Present", "IaC", "Timeline", "Decision", "Owners/Approvals", "Notes"
|
446
|
+
]
|
447
|
+
|
448
|
+
markdown_lines = [
|
449
|
+
"# VPC Cleanup Analysis Report",
|
450
|
+
"",
|
451
|
+
f"**Generated**: {timestamp}",
|
452
|
+
f"**Total VPC Candidates**: {len(vpc_candidates)}",
|
453
|
+
f"**Analysis Source**: CloudOps Runbooks VPC Module v0.9.9",
|
454
|
+
"",
|
455
|
+
"## VPC Cleanup Decision Table",
|
456
|
+
"",
|
457
|
+
"| " + " | ".join(headers) + " |",
|
458
|
+
"| " + " | ".join(["---" for _ in headers]) + " |"
|
459
|
+
]
|
460
|
+
|
461
|
+
# Process each VPC candidate
|
462
|
+
for candidate in vpc_candidates:
|
463
|
+
# Extract data with safe attribute access and formatting
|
464
|
+
account_id = getattr(candidate, 'account_id', 'Unknown')
|
465
|
+
vpc_id = getattr(candidate, 'vpc_id', 'Unknown')
|
466
|
+
vpc_name = getattr(candidate, 'vpc_name', '') or 'Unnamed'
|
467
|
+
cidr_block = getattr(candidate, 'cidr_block', 'Unknown')
|
468
|
+
|
469
|
+
# Handle overlapping logic - may need to calculate from CIDR analysis
|
470
|
+
overlapping = "Yes" if getattr(candidate, 'overlapping', False) else "No"
|
471
|
+
|
472
|
+
# Format boolean indicators with emoji
|
473
|
+
is_default = "⚠️ Yes" if getattr(candidate, 'is_default', False) else "✅ No"
|
474
|
+
flow_logs = "✅ Yes" if getattr(candidate, 'flow_logs_enabled', False) else "❌ No"
|
475
|
+
tgw_peering = "✅ Yes" if getattr(candidate, 'tgw_peering_attached', False) else "❌ No"
|
476
|
+
load_balancers = "✅ Yes" if getattr(candidate, 'load_balancers_present', False) else "❌ No"
|
477
|
+
iac_managed = "✅ Yes" if getattr(candidate, 'iac_managed', False) else "❌ No"
|
478
|
+
|
479
|
+
# ENI Count handling
|
480
|
+
eni_count = getattr(candidate, 'eni_count', 0)
|
481
|
+
|
482
|
+
# Tags formatting - prioritize important tags with enhanced display
|
483
|
+
tags = getattr(candidate, 'tags', {}) or {}
|
484
|
+
relevant_tags = []
|
485
|
+
if tags:
|
486
|
+
# Priority order for business-relevant tags
|
487
|
+
priority_keys = ['Name', 'Environment', 'Project', 'Owner', 'BusinessOwner', 'Team', 'CostCenter', 'Application']
|
488
|
+
for key in priority_keys:
|
489
|
+
if key in tags and tags[key] and len(relevant_tags) < 3: # Increased limit for better visibility
|
490
|
+
relevant_tags.append(f"{key}:{tags[key]}")
|
491
|
+
|
492
|
+
# Add other important tags if space available
|
493
|
+
for key, value in tags.items():
|
494
|
+
if key not in priority_keys and value and len(relevant_tags) < 3:
|
495
|
+
relevant_tags.append(f"{key}:{value}")
|
496
|
+
|
497
|
+
# Enhanced display logic for tags
|
498
|
+
if relevant_tags:
|
499
|
+
tags_display = "; ".join(relevant_tags)
|
500
|
+
if len(tags_display) > 35: # Slightly increased width for better readability
|
501
|
+
tags_display = tags_display[:32] + "..."
|
502
|
+
elif tags:
|
503
|
+
# If tags exist but none were priority, show count
|
504
|
+
tags_display = f"({len(tags)} tags)"
|
505
|
+
else:
|
506
|
+
# No tags at all
|
507
|
+
tags_display = "No tags"
|
508
|
+
|
509
|
+
# Timeline and Decision
|
510
|
+
timeline = getattr(candidate, 'cleanup_timeline', '') or getattr(candidate, 'implementation_timeline', 'Unknown')
|
511
|
+
|
512
|
+
# Decision handling - check for different decision attribute names
|
513
|
+
decision_attr = getattr(candidate, 'decision', None)
|
514
|
+
if decision_attr:
|
515
|
+
if hasattr(decision_attr, 'value'):
|
516
|
+
decision = decision_attr.value
|
517
|
+
else:
|
518
|
+
decision = str(decision_attr)
|
519
|
+
else:
|
520
|
+
# Fallback decision logic based on risk/dependencies
|
521
|
+
decision = getattr(candidate, 'cleanup_bucket', 'Unknown')
|
522
|
+
|
523
|
+
# Owners/Approvals - Enhanced extraction from tags if not populated
|
524
|
+
owners = getattr(candidate, 'owners_approvals', []) or getattr(candidate, 'stakeholders', [])
|
525
|
+
|
526
|
+
# If no owners found via attributes, try to extract from tags directly
|
527
|
+
if not owners and tags:
|
528
|
+
owner_keys = ['Owner', 'BusinessOwner', 'TechnicalOwner', 'Team', 'Contact', 'CreatedBy', 'ManagedBy']
|
529
|
+
for key in owner_keys:
|
530
|
+
if key in tags and tags[key]:
|
531
|
+
if 'business' in key.lower() or 'manager' in tags[key].lower():
|
532
|
+
owners.append(f"{tags[key]} (Business)")
|
533
|
+
elif 'technical' in key.lower() or any(tech in tags[key].lower() for tech in ['ops', 'devops', 'engineering']):
|
534
|
+
owners.append(f"{tags[key]} (Technical)")
|
535
|
+
else:
|
536
|
+
owners.append(tags[key])
|
537
|
+
break # Take first found owner to avoid clutter
|
538
|
+
|
539
|
+
if owners:
|
540
|
+
owners_display = "; ".join(owners)
|
541
|
+
if len(owners_display) > 30: # Increased width for better display
|
542
|
+
owners_display = owners_display[:27] + "..."
|
543
|
+
else:
|
544
|
+
# Enhanced "unknown" display based on VPC characteristics
|
545
|
+
if getattr(candidate, 'is_default', False):
|
546
|
+
owners_display = "System Default"
|
547
|
+
elif getattr(candidate, 'iac_detected', False):
|
548
|
+
owners_display = "IaC Managed"
|
549
|
+
else:
|
550
|
+
owners_display = "No owner tags"
|
551
|
+
|
552
|
+
# Notes - combination of risk assessment and business impact
|
553
|
+
notes_parts = []
|
554
|
+
risk_level = getattr(candidate, 'risk_level', None)
|
555
|
+
if risk_level:
|
556
|
+
risk_val = risk_level.value if hasattr(risk_level, 'value') else str(risk_level)
|
557
|
+
notes_parts.append(f"Risk:{risk_val}")
|
558
|
+
|
559
|
+
business_impact = getattr(candidate, 'business_impact', '')
|
560
|
+
if business_impact:
|
561
|
+
notes_parts.append(business_impact[:15]) # Truncate
|
562
|
+
|
563
|
+
notes = "; ".join(notes_parts) if notes_parts else getattr(candidate, 'notes', 'No notes')
|
564
|
+
if len(notes) > 30: # Truncate for table formatting
|
565
|
+
notes = notes[:27] + "..."
|
566
|
+
|
567
|
+
# Create table row - escape pipes for markdown compatibility
|
568
|
+
row_data = [
|
569
|
+
account_id, vpc_id, vpc_name, cidr_block, overlapping,
|
570
|
+
is_default, str(eni_count), tags_display, flow_logs, tgw_peering,
|
571
|
+
load_balancers, iac_managed, timeline, decision, owners_display, notes
|
572
|
+
]
|
573
|
+
|
574
|
+
# Escape pipes and format row
|
575
|
+
escaped_data = [str(cell).replace("|", "\\|") for cell in row_data]
|
576
|
+
markdown_lines.append("| " + " | ".join(escaped_data) + " |")
|
577
|
+
|
578
|
+
# Add summary statistics
|
579
|
+
total_vpcs = len(vpc_candidates)
|
580
|
+
default_vpcs = sum(1 for c in vpc_candidates if getattr(c, 'is_default', False))
|
581
|
+
flow_logs_enabled = sum(1 for c in vpc_candidates if getattr(c, 'flow_logs_enabled', False))
|
582
|
+
iac_managed_count = sum(1 for c in vpc_candidates if getattr(c, 'iac_managed', False))
|
583
|
+
zero_eni_vpcs = sum(1 for c in vpc_candidates if getattr(c, 'eni_count', 1) == 0)
|
584
|
+
|
585
|
+
markdown_lines.extend([
|
586
|
+
"",
|
587
|
+
"## Analysis Summary",
|
588
|
+
"",
|
589
|
+
f"- **Total VPCs Analyzed**: {total_vpcs}",
|
590
|
+
f"- **Default VPCs**: {default_vpcs} ({(default_vpcs/total_vpcs*100):.1f}%)",
|
591
|
+
f"- **Flow Logs Enabled**: {flow_logs_enabled} ({(flow_logs_enabled/total_vpcs*100):.1f}%)",
|
592
|
+
f"- **IaC Managed**: {iac_managed_count} ({(iac_managed_count/total_vpcs*100):.1f}%)",
|
593
|
+
f"- **Zero ENI Attachments**: {zero_eni_vpcs} ({(zero_eni_vpcs/total_vpcs*100):.1f}%)",
|
594
|
+
"",
|
595
|
+
"## Cleanup Recommendations",
|
596
|
+
"",
|
597
|
+
"1. **Priority 1**: VPCs with zero ENI attachments and no dependencies",
|
598
|
+
"2. **Priority 2**: Default VPCs with no active resources",
|
599
|
+
"3. **Priority 3**: Non-IaC managed VPCs requiring manual cleanup",
|
600
|
+
"4. **Review Required**: VPCs with unclear ownership or business impact",
|
601
|
+
"",
|
602
|
+
"---",
|
603
|
+
f"*Generated by CloudOps Runbooks VPC Module v0.9.9 at {timestamp}*"
|
604
|
+
])
|
605
|
+
|
606
|
+
return "\n".join(markdown_lines)
|
607
|
+
|
608
|
+
def export_vpc_analysis_to_file(self, vpc_candidates: List[Any], filename: str = None, output_dir: str = "./exports") -> str:
|
609
|
+
"""
|
610
|
+
Export VPC analysis to markdown file with intelligent naming.
|
611
|
+
|
612
|
+
Args:
|
613
|
+
vpc_candidates: List of VPC candidates from analysis
|
614
|
+
filename: Base filename (optional, auto-generated if not provided)
|
615
|
+
output_dir: Output directory path
|
616
|
+
|
617
|
+
Returns:
|
618
|
+
Path to exported file
|
619
|
+
"""
|
620
|
+
if not filename:
|
621
|
+
timestamp = datetime.now().strftime("%Y-%m-%d")
|
622
|
+
filename = f"vpc-cleanup-analysis-{timestamp}.md"
|
623
|
+
|
624
|
+
# Ensure .md extension
|
625
|
+
if not filename.endswith('.md'):
|
626
|
+
filename = f"{filename}.md"
|
627
|
+
|
628
|
+
# Create output directory
|
629
|
+
output_path = Path(output_dir)
|
630
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
631
|
+
|
632
|
+
# Generate markdown content
|
633
|
+
markdown_content = self.format_vpc_cleanup_table(vpc_candidates)
|
634
|
+
|
635
|
+
# Write to file
|
636
|
+
filepath = output_path / filename
|
637
|
+
|
638
|
+
print_info(f"📝 Exporting VPC analysis to: {filename}")
|
639
|
+
|
640
|
+
try:
|
641
|
+
with open(filepath, "w", encoding="utf-8") as f:
|
642
|
+
f.write(markdown_content)
|
643
|
+
|
644
|
+
print_success(f"✅ VPC analysis exported: {filepath}")
|
645
|
+
print_info(f"🔗 Ready for executive review or documentation systems")
|
646
|
+
return str(filepath)
|
647
|
+
|
648
|
+
except Exception as e:
|
649
|
+
print_warning(f"❌ Failed to export VPC analysis: {e}")
|
650
|
+
return ""
|
651
|
+
|
426
652
|
|
427
653
|
def export_finops_to_markdown(
|
428
654
|
profile_data: Union[Dict[str, Any], List[Dict[str, Any]]],
|
@@ -638,7 +638,7 @@ class SingleAccountDashboard:
|
|
638
638
|
style="dim",
|
639
639
|
)
|
640
640
|
|
641
|
-
|
641
|
+
rich_console.print(table)
|
642
642
|
|
643
643
|
# Summary panel (using filtered services for consistent analysis)
|
644
644
|
total_current = sum(filtered_current_services.values())
|
@@ -681,7 +681,7 @@ class SingleAccountDashboard:
|
|
681
681
|
• Services Analyzed: {len(all_services)}{period_info}
|
682
682
|
"""
|
683
683
|
|
684
|
-
|
684
|
+
rich_console.print(Panel(summary_text.strip(), title="📊 Analysis Summary", style="info"))
|
685
685
|
|
686
686
|
def _export_service_analysis(
|
687
687
|
self, args: argparse.Namespace, cost_data: Dict[str, Any], service_costs: List[str], account_id: str
|
@@ -0,0 +1,328 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
VPC Cleanup Exporter Module - Enterprise VPC Cleanup Result Export
|
4
|
+
|
5
|
+
This module provides export functionality for VPC cleanup analysis results,
|
6
|
+
leveraging the existing markdown_exporter infrastructure with VPC-specific formatting.
|
7
|
+
|
8
|
+
Author: CloudOps Runbooks Team
|
9
|
+
Version: 0.9.9
|
10
|
+
"""
|
11
|
+
|
12
|
+
import csv
|
13
|
+
import json
|
14
|
+
import os
|
15
|
+
from datetime import datetime
|
16
|
+
from typing import Any, Dict, List
|
17
|
+
|
18
|
+
from .markdown_exporter import MarkdownExporter
|
19
|
+
|
20
|
+
|
21
|
+
def _format_tags_for_display(tags_dict: Dict[str, str]) -> str:
|
22
|
+
"""Format tags for display with priority order."""
|
23
|
+
if not tags_dict:
|
24
|
+
return "No tags"
|
25
|
+
|
26
|
+
priority_keys = ['Name', 'Environment', 'Project', 'Owner', 'BusinessOwner', 'Team', 'CostCenter']
|
27
|
+
relevant_tags = []
|
28
|
+
|
29
|
+
for key in priority_keys:
|
30
|
+
if key in tags_dict and tags_dict[key]:
|
31
|
+
relevant_tags.append(f"{key}:{tags_dict[key]}")
|
32
|
+
|
33
|
+
# Add other important tags
|
34
|
+
for key, value in tags_dict.items():
|
35
|
+
if key not in priority_keys and value and len(relevant_tags) < 5:
|
36
|
+
relevant_tags.append(f"{key}:{value}")
|
37
|
+
|
38
|
+
return "; ".join(relevant_tags) if relevant_tags else f"({len(tags_dict)} tags)"
|
39
|
+
|
40
|
+
|
41
|
+
def export_vpc_cleanup_results(vpc_result: Any, export_formats: List[str], output_dir: str = "./") -> Dict[str, str]:
|
42
|
+
"""
|
43
|
+
Export VPC cleanup results in multiple formats.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
vpc_result: VPC cleanup analysis result object
|
47
|
+
export_formats: List of formats to export (markdown, csv, json, pdf)
|
48
|
+
output_dir: Directory to save exported files
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
Dict mapping format to exported filename
|
52
|
+
"""
|
53
|
+
results = {}
|
54
|
+
|
55
|
+
# Extract VPC candidates from result - use correct attribute name
|
56
|
+
vpc_candidates = getattr(vpc_result, 'cleanup_candidates', [])
|
57
|
+
if not vpc_candidates:
|
58
|
+
# Fallback to other possible attribute names
|
59
|
+
vpc_candidates = getattr(vpc_result, 'vpc_candidates', [])
|
60
|
+
|
61
|
+
if 'markdown' in export_formats:
|
62
|
+
try:
|
63
|
+
exporter = MarkdownExporter()
|
64
|
+
markdown_filename = exporter.export_vpc_analysis_to_file(
|
65
|
+
vpc_candidates,
|
66
|
+
filename="vpc-cleanup-candidates.md",
|
67
|
+
output_dir=output_dir
|
68
|
+
)
|
69
|
+
results['markdown'] = markdown_filename
|
70
|
+
except Exception as e:
|
71
|
+
print(f"Warning: Markdown export failed: {e}")
|
72
|
+
results['markdown'] = None
|
73
|
+
|
74
|
+
# Real implementations for other formats
|
75
|
+
if 'csv' in export_formats:
|
76
|
+
try:
|
77
|
+
csv_filename = _export_vpc_candidates_csv(vpc_candidates, output_dir)
|
78
|
+
results['csv'] = csv_filename
|
79
|
+
except Exception as e:
|
80
|
+
print(f"Warning: CSV export failed: {e}")
|
81
|
+
results['csv'] = None
|
82
|
+
|
83
|
+
if 'json' in export_formats:
|
84
|
+
try:
|
85
|
+
json_filename = _export_vpc_candidates_json(vpc_candidates, output_dir)
|
86
|
+
results['json'] = json_filename
|
87
|
+
except Exception as e:
|
88
|
+
print(f"Warning: JSON export failed: {e}")
|
89
|
+
results['json'] = None
|
90
|
+
|
91
|
+
if 'pdf' in export_formats:
|
92
|
+
try:
|
93
|
+
pdf_filename = _export_vpc_candidates_pdf(vpc_candidates, output_dir)
|
94
|
+
results['pdf'] = pdf_filename
|
95
|
+
except Exception as e:
|
96
|
+
print(f"Warning: PDF export failed: {e}")
|
97
|
+
results['pdf'] = None
|
98
|
+
|
99
|
+
return results
|
100
|
+
|
101
|
+
|
102
|
+
def _export_vpc_candidates_csv(vpc_candidates: List[Any], output_dir: str) -> str:
|
103
|
+
"""Export VPC candidates to CSV format with all 15 columns."""
|
104
|
+
filename = os.path.join(output_dir, "vpc-cleanup-candidates.csv")
|
105
|
+
|
106
|
+
# 15-column headers for comprehensive VPC analysis
|
107
|
+
headers = [
|
108
|
+
"Account_ID", "VPC_ID", "VPC_Name", "CIDR_Block", "Overlapping",
|
109
|
+
"Is_Default", "ENI_Count", "Tags", "Flow_Logs", "TGW/Peering",
|
110
|
+
"LBs_Present", "IaC", "Timeline", "Decision", "Owners/Approvals", "Notes"
|
111
|
+
]
|
112
|
+
|
113
|
+
with open(filename, 'w', newline='', encoding='utf-8') as csvfile:
|
114
|
+
writer = csv.writer(csvfile)
|
115
|
+
writer.writerow(headers)
|
116
|
+
|
117
|
+
for candidate in vpc_candidates:
|
118
|
+
# Extract data with enhanced tag and owner handling
|
119
|
+
tags_dict = getattr(candidate, 'tags', {}) or {}
|
120
|
+
|
121
|
+
# Enhanced tag display - prioritize important tags
|
122
|
+
if tags_dict:
|
123
|
+
priority_keys = ['Name', 'Environment', 'Project', 'Owner', 'BusinessOwner', 'Team']
|
124
|
+
relevant_tags = []
|
125
|
+
for key in priority_keys:
|
126
|
+
if key in tags_dict and tags_dict[key]:
|
127
|
+
relevant_tags.append(f"{key}:{tags_dict[key]}")
|
128
|
+
|
129
|
+
# Add other important tags
|
130
|
+
for key, value in tags_dict.items():
|
131
|
+
if key not in priority_keys and value and len(relevant_tags) < 5:
|
132
|
+
relevant_tags.append(f"{key}:{value}")
|
133
|
+
|
134
|
+
tags_str = "; ".join(relevant_tags)
|
135
|
+
else:
|
136
|
+
tags_str = "No tags"
|
137
|
+
|
138
|
+
load_balancers = getattr(candidate, 'load_balancers', []) or []
|
139
|
+
lbs_present = "Yes" if load_balancers else "No"
|
140
|
+
|
141
|
+
# Enhanced owner extraction
|
142
|
+
owners = getattr(candidate, 'owners_approvals', []) or []
|
143
|
+
|
144
|
+
# If no owners found via attributes, extract from tags directly
|
145
|
+
if not owners and tags_dict:
|
146
|
+
owner_keys = ['Owner', 'BusinessOwner', 'TechnicalOwner', 'Team', 'Contact', 'CreatedBy', 'ManagedBy']
|
147
|
+
for key in owner_keys:
|
148
|
+
if key in tags_dict and tags_dict[key]:
|
149
|
+
if 'business' in key.lower() or 'manager' in tags_dict[key].lower():
|
150
|
+
owners.append(f"{tags_dict[key]} (Business)")
|
151
|
+
elif 'technical' in key.lower() or any(tech in tags_dict[key].lower() for tech in ['ops', 'devops', 'engineering']):
|
152
|
+
owners.append(f"{tags_dict[key]} (Technical)")
|
153
|
+
else:
|
154
|
+
owners.append(tags_dict[key])
|
155
|
+
|
156
|
+
if owners:
|
157
|
+
owners_str = "; ".join(owners)
|
158
|
+
else:
|
159
|
+
# Enhanced fallback for CSV
|
160
|
+
if getattr(candidate, 'is_default', False):
|
161
|
+
owners_str = "System Default VPC"
|
162
|
+
elif getattr(candidate, 'iac_detected', False):
|
163
|
+
owners_str = "IaC Managed"
|
164
|
+
else:
|
165
|
+
owners_str = "No owner tags found"
|
166
|
+
|
167
|
+
row = [
|
168
|
+
getattr(candidate, 'account_id', 'Unknown'),
|
169
|
+
getattr(candidate, 'vpc_id', ''),
|
170
|
+
getattr(candidate, 'vpc_name', 'Unnamed'),
|
171
|
+
getattr(candidate, 'cidr_block', ''),
|
172
|
+
"No", # Overlapping analysis would need CIDR comparison
|
173
|
+
"Yes" if getattr(candidate, 'is_default', False) else "No",
|
174
|
+
getattr(candidate, 'dependency_analysis', {}).eni_count if hasattr(candidate, 'dependency_analysis') else 0,
|
175
|
+
tags_str,
|
176
|
+
"Yes" if getattr(candidate, 'flow_logs_enabled', False) else "No",
|
177
|
+
"No", # TGW/Peering analysis placeholder
|
178
|
+
lbs_present,
|
179
|
+
"Yes" if getattr(candidate, 'iac_detected', False) else "No",
|
180
|
+
"Unknown", # Timeline analysis placeholder
|
181
|
+
getattr(candidate, 'cleanup_recommendation', 'unknown'),
|
182
|
+
owners_str,
|
183
|
+
"Generated by CloudOps Runbooks VPC Module"
|
184
|
+
]
|
185
|
+
writer.writerow(row)
|
186
|
+
|
187
|
+
return filename
|
188
|
+
|
189
|
+
|
190
|
+
def _export_vpc_candidates_json(vpc_candidates: List[Any], output_dir: str) -> str:
|
191
|
+
"""Export VPC candidates to JSON format with full data structure."""
|
192
|
+
filename = os.path.join(output_dir, "vpc-cleanup-candidates.json")
|
193
|
+
|
194
|
+
# Convert candidates to serializable format
|
195
|
+
candidates_data = []
|
196
|
+
for candidate in vpc_candidates:
|
197
|
+
candidate_dict = {
|
198
|
+
"account_id": getattr(candidate, 'account_id', 'Unknown'),
|
199
|
+
"vpc_id": getattr(candidate, 'vpc_id', ''),
|
200
|
+
"vpc_name": getattr(candidate, 'vpc_name', 'Unnamed'),
|
201
|
+
"cidr_block": getattr(candidate, 'cidr_block', ''),
|
202
|
+
"region": getattr(candidate, 'region', 'unknown'),
|
203
|
+
"is_default": getattr(candidate, 'is_default', False),
|
204
|
+
"state": getattr(candidate, 'state', 'unknown'),
|
205
|
+
"tags": getattr(candidate, 'tags', {}) or {},
|
206
|
+
"tags_summary": _format_tags_for_display(getattr(candidate, 'tags', {}) or {}),
|
207
|
+
"flow_logs_enabled": getattr(candidate, 'flow_logs_enabled', False),
|
208
|
+
"load_balancers": getattr(candidate, 'load_balancers', []) or [],
|
209
|
+
"iac_detected": getattr(candidate, 'iac_detected', False),
|
210
|
+
"owners_approvals": getattr(candidate, 'owners_approvals', []) or [],
|
211
|
+
"cleanup_bucket": getattr(candidate, 'cleanup_bucket', 'unknown'),
|
212
|
+
"cleanup_recommendation": getattr(candidate, 'cleanup_recommendation', 'unknown'),
|
213
|
+
"risk_assessment": getattr(candidate, 'risk_assessment', 'unknown'),
|
214
|
+
"business_impact": getattr(candidate, 'business_impact', 'unknown')
|
215
|
+
}
|
216
|
+
|
217
|
+
# Add dependency analysis if available
|
218
|
+
if hasattr(candidate, 'dependency_analysis') and candidate.dependency_analysis:
|
219
|
+
dep_analysis = candidate.dependency_analysis
|
220
|
+
candidate_dict["dependency_analysis"] = {
|
221
|
+
"eni_count": getattr(dep_analysis, 'eni_count', 0),
|
222
|
+
"route_tables": getattr(dep_analysis, 'route_tables', []),
|
223
|
+
"security_groups": getattr(dep_analysis, 'security_groups', []),
|
224
|
+
"internet_gateways": getattr(dep_analysis, 'internet_gateways', []),
|
225
|
+
"nat_gateways": getattr(dep_analysis, 'nat_gateways', []),
|
226
|
+
"vpc_endpoints": getattr(dep_analysis, 'vpc_endpoints', []),
|
227
|
+
"peering_connections": getattr(dep_analysis, 'peering_connections', []),
|
228
|
+
"dependency_risk_level": getattr(dep_analysis, 'dependency_risk_level', 'unknown')
|
229
|
+
}
|
230
|
+
|
231
|
+
candidates_data.append(candidate_dict)
|
232
|
+
|
233
|
+
# Create export metadata
|
234
|
+
export_data = {
|
235
|
+
"metadata": {
|
236
|
+
"export_timestamp": datetime.now().isoformat(),
|
237
|
+
"total_candidates": len(candidates_data),
|
238
|
+
"generator": "CloudOps Runbooks VPC Module v0.9.9"
|
239
|
+
},
|
240
|
+
"vpc_candidates": candidates_data
|
241
|
+
}
|
242
|
+
|
243
|
+
with open(filename, 'w', encoding='utf-8') as jsonfile:
|
244
|
+
json.dump(export_data, jsonfile, indent=2, ensure_ascii=False)
|
245
|
+
|
246
|
+
return filename
|
247
|
+
|
248
|
+
|
249
|
+
def _export_vpc_candidates_pdf(vpc_candidates: List[Any], output_dir: str) -> str:
|
250
|
+
"""Export VPC candidates to PDF format for executive presentation."""
|
251
|
+
filename = os.path.join(output_dir, "vpc-cleanup-candidates.pdf")
|
252
|
+
|
253
|
+
try:
|
254
|
+
# Try to use reportlab for PDF generation
|
255
|
+
from reportlab.lib import colors
|
256
|
+
from reportlab.lib.pagesizes import letter, A4
|
257
|
+
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
|
258
|
+
from reportlab.lib.styles import getSampleStyleSheet
|
259
|
+
|
260
|
+
doc = SimpleDocTemplate(filename, pagesize=A4)
|
261
|
+
styles = getSampleStyleSheet()
|
262
|
+
story = []
|
263
|
+
|
264
|
+
# Title
|
265
|
+
title = Paragraph("VPC Cleanup Analysis Report", styles['Title'])
|
266
|
+
story.append(title)
|
267
|
+
story.append(Spacer(1, 20))
|
268
|
+
|
269
|
+
# Summary
|
270
|
+
summary_text = f"""
|
271
|
+
<b>Generated:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}<br/>
|
272
|
+
<b>Total VPC Candidates:</b> {len(vpc_candidates)}<br/>
|
273
|
+
<b>Analysis Source:</b> CloudOps Runbooks VPC Module v0.9.9
|
274
|
+
"""
|
275
|
+
summary = Paragraph(summary_text, styles['Normal'])
|
276
|
+
story.append(summary)
|
277
|
+
story.append(Spacer(1, 20))
|
278
|
+
|
279
|
+
# Create table data
|
280
|
+
table_data = [
|
281
|
+
["Account ID", "VPC ID", "VPC Name", "CIDR", "Default", "ENI Count", "Decision"]
|
282
|
+
]
|
283
|
+
|
284
|
+
for candidate in vpc_candidates:
|
285
|
+
row = [
|
286
|
+
str(getattr(candidate, 'account_id', 'Unknown'))[:15], # Truncate for PDF width
|
287
|
+
str(getattr(candidate, 'vpc_id', ''))[:20],
|
288
|
+
str(getattr(candidate, 'vpc_name', 'Unnamed'))[:15],
|
289
|
+
str(getattr(candidate, 'cidr_block', ''))[:15],
|
290
|
+
"Yes" if getattr(candidate, 'is_default', False) else "No",
|
291
|
+
str(getattr(candidate, 'dependency_analysis', {}).eni_count if hasattr(candidate, 'dependency_analysis') else 0),
|
292
|
+
str(getattr(candidate, 'cleanup_recommendation', 'unknown'))[:10]
|
293
|
+
]
|
294
|
+
table_data.append(row)
|
295
|
+
|
296
|
+
# Create table
|
297
|
+
table = Table(table_data)
|
298
|
+
table.setStyle(TableStyle([
|
299
|
+
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
300
|
+
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
301
|
+
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
302
|
+
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
303
|
+
('FONTSIZE', (0, 0), (-1, 0), 10),
|
304
|
+
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
305
|
+
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
306
|
+
('FONTSIZE', (0, 1), (-1, -1), 8),
|
307
|
+
('GRID', (0, 0), (-1, -1), 1, colors.black)
|
308
|
+
]))
|
309
|
+
|
310
|
+
story.append(table)
|
311
|
+
doc.build(story)
|
312
|
+
|
313
|
+
except ImportError:
|
314
|
+
# Fallback: create a simple text-based PDF placeholder
|
315
|
+
with open(filename, 'w', encoding='utf-8') as f:
|
316
|
+
f.write("VPC Cleanup Analysis Report (PDF)\n")
|
317
|
+
f.write("=" * 40 + "\n\n")
|
318
|
+
f.write(f"Generated: {datetime.now().isoformat()}\n")
|
319
|
+
f.write(f"Total VPC Candidates: {len(vpc_candidates)}\n\n")
|
320
|
+
|
321
|
+
for i, candidate in enumerate(vpc_candidates, 1):
|
322
|
+
f.write(f"{i}. VPC {getattr(candidate, 'vpc_id', 'Unknown')}\n")
|
323
|
+
f.write(f" Account: {getattr(candidate, 'account_id', 'Unknown')}\n")
|
324
|
+
f.write(f" CIDR: {getattr(candidate, 'cidr_block', 'Unknown')}\n")
|
325
|
+
f.write(f" ENI Count: {getattr(candidate, 'dependency_analysis', {}).eni_count if hasattr(candidate, 'dependency_analysis') else 0}\n")
|
326
|
+
f.write(f" Decision: {getattr(candidate, 'cleanup_recommendation', 'unknown')}\n\n")
|
327
|
+
|
328
|
+
return filename
|