runbooks 0.7.0__py3-none-any.whl → 0.7.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 +87 -37
- runbooks/cfat/README.md +300 -49
- runbooks/cfat/__init__.py +2 -2
- runbooks/finops/__init__.py +1 -1
- runbooks/finops/cli.py +1 -1
- runbooks/inventory/collectors/__init__.py +8 -0
- runbooks/inventory/collectors/aws_management.py +791 -0
- runbooks/inventory/collectors/aws_networking.py +3 -3
- runbooks/main.py +3389 -782
- runbooks/operate/__init__.py +207 -0
- runbooks/operate/base.py +311 -0
- runbooks/operate/cloudformation_operations.py +619 -0
- runbooks/operate/cloudwatch_operations.py +496 -0
- runbooks/operate/dynamodb_operations.py +812 -0
- runbooks/operate/ec2_operations.py +926 -0
- runbooks/operate/iam_operations.py +569 -0
- runbooks/operate/s3_operations.py +1211 -0
- runbooks/operate/tagging_operations.py +655 -0
- runbooks/remediation/CLAUDE.md +100 -0
- runbooks/remediation/DOME9.md +218 -0
- runbooks/remediation/README.md +26 -0
- runbooks/remediation/Tests/__init__.py +0 -0
- runbooks/remediation/Tests/update_policy.py +74 -0
- runbooks/remediation/__init__.py +95 -0
- runbooks/remediation/acm_cert_expired_unused.py +98 -0
- runbooks/remediation/acm_remediation.py +875 -0
- runbooks/remediation/api_gateway_list.py +167 -0
- runbooks/remediation/base.py +643 -0
- runbooks/remediation/cloudtrail_remediation.py +908 -0
- runbooks/remediation/cloudtrail_s3_modifications.py +296 -0
- runbooks/remediation/cognito_active_users.py +78 -0
- runbooks/remediation/cognito_remediation.py +856 -0
- runbooks/remediation/cognito_user_password_reset.py +163 -0
- runbooks/remediation/commons.py +455 -0
- runbooks/remediation/dynamodb_optimize.py +155 -0
- runbooks/remediation/dynamodb_remediation.py +744 -0
- runbooks/remediation/dynamodb_server_side_encryption.py +108 -0
- runbooks/remediation/ec2_public_ips.py +134 -0
- runbooks/remediation/ec2_remediation.py +892 -0
- runbooks/remediation/ec2_subnet_disable_auto_ip_assignment.py +72 -0
- runbooks/remediation/ec2_unattached_ebs_volumes.py +448 -0
- runbooks/remediation/ec2_unused_security_groups.py +202 -0
- runbooks/remediation/kms_enable_key_rotation.py +651 -0
- runbooks/remediation/kms_remediation.py +717 -0
- runbooks/remediation/lambda_list.py +243 -0
- runbooks/remediation/lambda_remediation.py +971 -0
- runbooks/remediation/multi_account.py +569 -0
- runbooks/remediation/rds_instance_list.py +199 -0
- runbooks/remediation/rds_remediation.py +873 -0
- runbooks/remediation/rds_snapshot_list.py +192 -0
- runbooks/remediation/requirements.txt +118 -0
- runbooks/remediation/s3_block_public_access.py +159 -0
- runbooks/remediation/s3_bucket_public_access.py +143 -0
- runbooks/remediation/s3_disable_static_website_hosting.py +74 -0
- runbooks/remediation/s3_downloader.py +215 -0
- runbooks/remediation/s3_enable_access_logging.py +562 -0
- runbooks/remediation/s3_encryption.py +526 -0
- runbooks/remediation/s3_force_ssl_secure_policy.py +143 -0
- runbooks/remediation/s3_list.py +141 -0
- runbooks/remediation/s3_object_search.py +201 -0
- runbooks/remediation/s3_remediation.py +816 -0
- runbooks/remediation/scan_for_phrase.py +425 -0
- runbooks/remediation/workspaces_list.py +220 -0
- runbooks/security/__init__.py +9 -10
- runbooks/security/security_baseline_tester.py +4 -2
- runbooks-0.7.6.dist-info/METADATA +608 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/RECORD +84 -76
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/entry_points.txt +0 -1
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/top_level.txt +0 -1
- jupyter-agent/.env +0 -2
- jupyter-agent/.env.template +0 -2
- jupyter-agent/.gitattributes +0 -35
- jupyter-agent/.gradio/certificate.pem +0 -31
- jupyter-agent/README.md +0 -16
- jupyter-agent/__main__.log +0 -8
- jupyter-agent/app.py +0 -256
- jupyter-agent/cloudops-agent.png +0 -0
- jupyter-agent/ds-system-prompt.txt +0 -154
- jupyter-agent/jupyter-agent.png +0 -0
- jupyter-agent/llama3_template.jinja +0 -123
- jupyter-agent/requirements.txt +0 -9
- jupyter-agent/tmp/4ojbs8a02ir/jupyter-agent.ipynb +0 -68
- jupyter-agent/tmp/cm5iasgpm3p/jupyter-agent.ipynb +0 -91
- jupyter-agent/tmp/crqbsseag5/jupyter-agent.ipynb +0 -91
- jupyter-agent/tmp/hohanq1u097/jupyter-agent.ipynb +0 -57
- jupyter-agent/tmp/jns1sam29wm/jupyter-agent.ipynb +0 -53
- jupyter-agent/tmp/jupyter-agent.ipynb +0 -27
- jupyter-agent/utils.py +0 -409
- runbooks/aws/__init__.py +0 -58
- runbooks/aws/dynamodb_operations.py +0 -231
- runbooks/aws/ec2_copy_image_cross-region.py +0 -195
- runbooks/aws/ec2_describe_instances.py +0 -202
- runbooks/aws/ec2_ebs_snapshots_delete.py +0 -186
- runbooks/aws/ec2_run_instances.py +0 -213
- runbooks/aws/ec2_start_stop_instances.py +0 -212
- runbooks/aws/ec2_terminate_instances.py +0 -143
- runbooks/aws/ec2_unused_eips.py +0 -196
- runbooks/aws/ec2_unused_volumes.py +0 -188
- runbooks/aws/s3_create_bucket.py +0 -142
- runbooks/aws/s3_list_buckets.py +0 -152
- runbooks/aws/s3_list_objects.py +0 -156
- runbooks/aws/s3_object_operations.py +0 -183
- runbooks/aws/tagging_lambda_handler.py +0 -183
- runbooks/inventory/FAILED_SCRIPTS_TROUBLESHOOTING.md +0 -619
- runbooks/inventory/PASSED_SCRIPTS_GUIDE.md +0 -738
- runbooks/inventory/aws_organization.png +0 -0
- runbooks/inventory/cfn_move_stack_instances.py +0 -1526
- runbooks/inventory/delete_s3_buckets_objects.py +0 -169
- runbooks/inventory/lockdown_cfn_stackset_role.py +0 -224
- runbooks/inventory/update_aws_actions.py +0 -173
- runbooks/inventory/update_cfn_stacksets.py +0 -1215
- runbooks/inventory/update_cloudwatch_logs_retention_policy.py +0 -294
- runbooks/inventory/update_iam_roles_cross_accounts.py +0 -478
- runbooks/inventory/update_s3_public_access_block.py +0 -539
- runbooks/organizations/__init__.py +0 -12
- runbooks/organizations/manager.py +0 -374
- runbooks-0.7.0.dist-info/METADATA +0 -375
- /runbooks/inventory/{tests → Tests}/common_test_data.py +0 -0
- /runbooks/inventory/{tests → Tests}/common_test_functions.py +0 -0
- /runbooks/inventory/{tests → Tests}/script_test_data.py +0 -0
- /runbooks/inventory/{tests → Tests}/setup.py +0 -0
- /runbooks/inventory/{tests → Tests}/src.py +0 -0
- /runbooks/inventory/{tests/test_inventory_modules.py → Tests/test_Inventory_Modules.py} +0 -0
- /runbooks/inventory/{tests → Tests}/test_cfn_describe_stacks.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_ec2_describe_instances.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_lambda_list_functions.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_moto_integration_example.py +0 -0
- /runbooks/inventory/{tests → Tests}/test_org_list_accounts.py +0 -0
- /runbooks/inventory/{Inventory_Modules.py → inventory_modules.py} +0 -0
- /runbooks/{aws → operate}/tags.json +0 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/WHEEL +0 -0
- {runbooks-0.7.0.dist-info → runbooks-0.7.6.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,207 @@
|
|
1
|
+
"""
|
2
|
+
Enterprise AWS Operations Module - Production-Ready Infrastructure Automation
|
3
|
+
|
4
|
+
## Overview
|
5
|
+
|
6
|
+
The `runbooks.operate` module provides enterprise-grade AWS operational capabilities
|
7
|
+
designed for CloudOps, DevOps, and SRE teams managing large-scale, multi-account
|
8
|
+
AWS environments. This module transforms infrastructure operations from manual,
|
9
|
+
error-prone tasks into automated, auditable, and repeatable workflows.
|
10
|
+
|
11
|
+
## Design Philosophy
|
12
|
+
|
13
|
+
**KISS Architecture**: Simple, maintainable operations without legacy complexity
|
14
|
+
**Enterprise Ready**: Multi-deployment support (CLI, Lambda, Docker, Kubernetes)
|
15
|
+
**Safety First**: Comprehensive dry-run, validation, and confirmation workflows
|
16
|
+
**AI-Agent Optimized**: Predictable patterns for automation integration
|
17
|
+
|
18
|
+
## Core Capabilities
|
19
|
+
|
20
|
+
### 🖥️ **Compute Operations (EC2)**
|
21
|
+
- **Instance Lifecycle**: Start, stop, reboot, terminate with safety validations
|
22
|
+
- **Image Management**: AMI creation, cross-region copying with encryption
|
23
|
+
- **Volume Operations**: Cleanup unused EBS volumes, snapshot management
|
24
|
+
- **Network Resources**: Elastic IP cleanup and management
|
25
|
+
- **Advanced Features**: Block device mappings, monitoring, SNS notifications
|
26
|
+
|
27
|
+
### 🗄️ **Storage Operations (S3)**
|
28
|
+
- **Bucket Lifecycle**: Creation with region-specific constraints and validation
|
29
|
+
- **Object Operations**: Upload, download, delete with ACL management
|
30
|
+
- **Data Migration**: Cross-bucket synchronization with filtering
|
31
|
+
- **Compliance**: Public access block configuration and enforcement
|
32
|
+
- **Advanced Features**: Pagination, prefix filtering, size optimization
|
33
|
+
|
34
|
+
### 🗃️ **Database Operations (DynamoDB)**
|
35
|
+
- **Table Management**: Creation, deletion with billing mode optimization
|
36
|
+
- **Data Operations**: CRUD operations with batch processing
|
37
|
+
- **Backup & Recovery**: Point-in-time recovery and backup automation
|
38
|
+
- **Performance**: Throughput scaling and optimization
|
39
|
+
- **Advanced Features**: Resource-based operations, environment configuration
|
40
|
+
|
41
|
+
### 🏗️ **Infrastructure Operations**
|
42
|
+
- **CloudFormation**: Stack and StackSet operations with drift detection
|
43
|
+
- **IAM**: Cross-account role management and policy automation
|
44
|
+
- **CloudWatch**: Log retention and monitoring configuration
|
45
|
+
- **Tagging**: Cross-service resource tagging for governance
|
46
|
+
|
47
|
+
## Enterprise Features
|
48
|
+
|
49
|
+
### 🔒 **Safety & Security**
|
50
|
+
```python
|
51
|
+
# Dry-run mode for all operations
|
52
|
+
ec2_ops = EC2Operations(dry_run=True)
|
53
|
+
results = ec2_ops.terminate_instances(instance_ids)
|
54
|
+
|
55
|
+
# Confirmation prompts for destructive operations
|
56
|
+
s3_ops = S3Operations()
|
57
|
+
s3_ops.delete_bucket_and_objects("critical-bucket") # Requires confirmation
|
58
|
+
```
|
59
|
+
|
60
|
+
### 🌍 **Multi-Deployment Support**
|
61
|
+
```bash
|
62
|
+
# CLI execution
|
63
|
+
runbooks operate ec2 start --instance-ids i-123 --dry-run
|
64
|
+
|
65
|
+
# Environment variables for containers
|
66
|
+
export AWS_REGION=us-west-2
|
67
|
+
export DRY_RUN=true
|
68
|
+
python -m runbooks.operate.ec2_operations start
|
69
|
+
|
70
|
+
# Lambda handlers for serverless
|
71
|
+
from runbooks.operate.ec2_operations import lambda_handler_terminate_instances
|
72
|
+
```
|
73
|
+
|
74
|
+
### 📊 **Monitoring & Notifications**
|
75
|
+
```python
|
76
|
+
# SNS integration for operational awareness
|
77
|
+
ec2_ops = EC2Operations(sns_topic_arn="arn:aws:sns:us-east-1:123:alerts")
|
78
|
+
results = ec2_ops.cleanup_unused_volumes() # Sends cleanup summary
|
79
|
+
```
|
80
|
+
|
81
|
+
### 🎯 **Advanced Configuration**
|
82
|
+
```python
|
83
|
+
# Environment-driven configuration
|
84
|
+
ec2_ops = EC2Operations() # Reads AWS_PROFILE, AWS_REGION, DRY_RUN
|
85
|
+
s3_ops = S3Operations() # Reads S3_BUCKET, S3_KEY, LOCAL_FILE_PATH
|
86
|
+
db_ops = DynamoDBOperations() # Reads TABLE_NAME, MAX_BATCH_ITEMS
|
87
|
+
```
|
88
|
+
|
89
|
+
## Production Examples
|
90
|
+
|
91
|
+
### Multi-Account EC2 Management
|
92
|
+
```python
|
93
|
+
from runbooks.operate import EC2Operations
|
94
|
+
from runbooks.inventory.models.account import AWSAccount
|
95
|
+
|
96
|
+
# Production environment instance restart
|
97
|
+
ec2_ops = EC2Operations(profile="production", region="us-east-1")
|
98
|
+
context = OperationContext(
|
99
|
+
account=AWSAccount("123456789012", "production"),
|
100
|
+
region="us-east-1",
|
101
|
+
dry_run=False
|
102
|
+
)
|
103
|
+
|
104
|
+
# Restart instances with monitoring
|
105
|
+
results = ec2_ops.restart_instances(
|
106
|
+
context,
|
107
|
+
instance_ids=["i-prod123", "i-prod456"],
|
108
|
+
enable_monitoring=True
|
109
|
+
)
|
110
|
+
```
|
111
|
+
|
112
|
+
### S3 Data Migration
|
113
|
+
```python
|
114
|
+
from runbooks.operate import S3Operations
|
115
|
+
|
116
|
+
# Cross-region bucket synchronization
|
117
|
+
s3_ops = S3Operations(profile="data-migration")
|
118
|
+
results = s3_ops.sync_objects(
|
119
|
+
context,
|
120
|
+
source_bucket="prod-data-us-east-1",
|
121
|
+
destination_bucket="prod-data-us-west-2",
|
122
|
+
delete_removed=True
|
123
|
+
)
|
124
|
+
```
|
125
|
+
|
126
|
+
### DynamoDB Batch Processing
|
127
|
+
```python
|
128
|
+
from runbooks.operate import DynamoDBOperations
|
129
|
+
|
130
|
+
# High-volume data loading
|
131
|
+
db_ops = DynamoDBOperations(table_name="user-events")
|
132
|
+
results = db_ops.batch_write_items_enhanced(
|
133
|
+
context,
|
134
|
+
batch_size=500 # Optimized for high throughput
|
135
|
+
)
|
136
|
+
```
|
137
|
+
|
138
|
+
## CLI Integration
|
139
|
+
|
140
|
+
All operations integrate seamlessly with the standardized CLI:
|
141
|
+
|
142
|
+
```bash
|
143
|
+
# Resource Operations with Safety
|
144
|
+
runbooks operate ec2 terminate --instance-ids i-123 --confirm --region us-west-2
|
145
|
+
runbooks operate s3 create-bucket --bucket-name analytics-2024 --region eu-west-1
|
146
|
+
runbooks operate dynamodb create-table --table-name events --billing-mode PAY_PER_REQUEST
|
147
|
+
|
148
|
+
# Cleanup Operations
|
149
|
+
runbooks operate ec2 cleanup-unused-volumes --region us-east-1 --force
|
150
|
+
runbooks operate ec2 cleanup-unused-eips --profile production
|
151
|
+
|
152
|
+
# Advanced Operations
|
153
|
+
runbooks operate cloudformation move-stack-instances --source-stackset networking
|
154
|
+
runbooks operate iam update-roles-cross-accounts --role-name deployment-role
|
155
|
+
```
|
156
|
+
|
157
|
+
## Documentation & Support
|
158
|
+
|
159
|
+
- **Documentation**: https://cloudops.oceansoft.io/cloud-foundation/cfat-assessment-tool.html
|
160
|
+
- **Architecture**: KISS principle - no legacy complexity
|
161
|
+
- **Testing**: Comprehensive mocking and integration test coverage
|
162
|
+
- **Monitoring**: Built-in operational telemetry and alerting
|
163
|
+
|
164
|
+
## Target Users
|
165
|
+
|
166
|
+
- **CloudOps Engineers**: Multi-account infrastructure lifecycle management
|
167
|
+
- **DevOps Teams**: CI/CD pipeline integration and infrastructure automation
|
168
|
+
- **SRE Teams**: Operational excellence and incident response automation
|
169
|
+
- **Platform Teams**: Self-service infrastructure capabilities
|
170
|
+
- **Security Teams**: Compliance automation and policy enforcement
|
171
|
+
|
172
|
+
Version: 0.7.6 - Enterprise Production Ready
|
173
|
+
Compatibility: AWS SDK v3, Python 3.8+, Multi-deployment ready
|
174
|
+
"""
|
175
|
+
|
176
|
+
from runbooks.operate.base import BaseOperation, OperationContext, OperationResult, OperationStatus
|
177
|
+
from runbooks.operate.cloudformation_operations import CloudFormationOperations
|
178
|
+
from runbooks.operate.cloudwatch_operations import CloudWatchOperations
|
179
|
+
from runbooks.operate.dynamodb_operations import DynamoDBOperations
|
180
|
+
from runbooks.operate.ec2_operations import EC2Operations
|
181
|
+
from runbooks.operate.iam_operations import IAMOperations
|
182
|
+
from runbooks.operate.s3_operations import S3Operations
|
183
|
+
from runbooks.operate.tagging_operations import TaggingOperations
|
184
|
+
|
185
|
+
# Version info
|
186
|
+
__version__ = "0.7.6"
|
187
|
+
__author__ = "CloudOps Runbooks Team"
|
188
|
+
|
189
|
+
# Public API exports
|
190
|
+
__all__ = [
|
191
|
+
# Core functionality
|
192
|
+
"BaseOperation",
|
193
|
+
"OperationContext",
|
194
|
+
"OperationResult",
|
195
|
+
"OperationStatus",
|
196
|
+
# Service operations
|
197
|
+
"EC2Operations",
|
198
|
+
"S3Operations",
|
199
|
+
"DynamoDBOperations",
|
200
|
+
"TaggingOperations",
|
201
|
+
"CloudFormationOperations",
|
202
|
+
"IAMOperations",
|
203
|
+
"CloudWatchOperations",
|
204
|
+
# Module metadata
|
205
|
+
"__version__",
|
206
|
+
"__author__",
|
207
|
+
]
|
runbooks/operate/base.py
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
"""
|
2
|
+
Base operation classes for AWS resource management.
|
3
|
+
|
4
|
+
This module provides the abstract foundation for all AWS operational capabilities,
|
5
|
+
ensuring consistent patterns, safety features, and enterprise-grade reliability
|
6
|
+
across all service-specific operations.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from abc import ABC, abstractmethod
|
10
|
+
from dataclasses import dataclass, field
|
11
|
+
from datetime import datetime
|
12
|
+
from enum import Enum
|
13
|
+
from typing import Any, Dict, List, Optional, Union
|
14
|
+
|
15
|
+
import boto3
|
16
|
+
from botocore.exceptions import ClientError, NoCredentialsError
|
17
|
+
from loguru import logger
|
18
|
+
|
19
|
+
from runbooks.inventory.models.account import AWSAccount
|
20
|
+
from runbooks.inventory.utils.aws_helpers import aws_api_retry, get_boto3_session
|
21
|
+
|
22
|
+
|
23
|
+
class OperationStatus(Enum):
|
24
|
+
"""Status of an AWS operation."""
|
25
|
+
|
26
|
+
PENDING = "pending"
|
27
|
+
IN_PROGRESS = "in_progress"
|
28
|
+
SUCCESS = "success"
|
29
|
+
FAILED = "failed"
|
30
|
+
CANCELLED = "cancelled"
|
31
|
+
DRY_RUN = "dry_run"
|
32
|
+
|
33
|
+
|
34
|
+
@dataclass
|
35
|
+
class OperationContext:
|
36
|
+
"""Context information for AWS operations."""
|
37
|
+
|
38
|
+
account: AWSAccount
|
39
|
+
region: str
|
40
|
+
operation_type: str
|
41
|
+
resource_types: List[str]
|
42
|
+
dry_run: bool = False
|
43
|
+
force: bool = False
|
44
|
+
operation_timestamp: datetime = field(default_factory=datetime.utcnow)
|
45
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
46
|
+
|
47
|
+
def __post_init__(self):
|
48
|
+
"""Initialize context after creation."""
|
49
|
+
if not self.operation_timestamp:
|
50
|
+
self.operation_timestamp = datetime.utcnow()
|
51
|
+
|
52
|
+
|
53
|
+
@dataclass
|
54
|
+
class OperationResult:
|
55
|
+
"""Result of an AWS operation."""
|
56
|
+
|
57
|
+
operation_id: str
|
58
|
+
status: OperationStatus
|
59
|
+
operation_type: str
|
60
|
+
resource_type: str
|
61
|
+
resource_id: str
|
62
|
+
account_id: str
|
63
|
+
region: str
|
64
|
+
started_at: datetime
|
65
|
+
completed_at: Optional[datetime] = None
|
66
|
+
success: bool = False
|
67
|
+
error_message: Optional[str] = None
|
68
|
+
response_data: Dict[str, Any] = field(default_factory=dict)
|
69
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
70
|
+
|
71
|
+
def __post_init__(self):
|
72
|
+
"""Update success flag based on status."""
|
73
|
+
self.success = self.status == OperationStatus.SUCCESS
|
74
|
+
|
75
|
+
def mark_completed(self, status: OperationStatus, error_message: Optional[str] = None):
|
76
|
+
"""Mark operation as completed with given status."""
|
77
|
+
self.status = status
|
78
|
+
self.completed_at = datetime.utcnow()
|
79
|
+
self.success = status == OperationStatus.SUCCESS
|
80
|
+
if error_message:
|
81
|
+
self.error_message = error_message
|
82
|
+
|
83
|
+
def to_dict(self) -> Dict[str, Any]:
|
84
|
+
"""Convert result to dictionary format."""
|
85
|
+
return {
|
86
|
+
"operation_id": self.operation_id,
|
87
|
+
"status": self.status.value,
|
88
|
+
"operation_type": self.operation_type,
|
89
|
+
"resource_type": self.resource_type,
|
90
|
+
"resource_id": self.resource_id,
|
91
|
+
"account_id": self.account_id,
|
92
|
+
"region": self.region,
|
93
|
+
"started_at": self.started_at.isoformat(),
|
94
|
+
"completed_at": self.completed_at.isoformat() if self.completed_at else None,
|
95
|
+
"success": self.success,
|
96
|
+
"error_message": self.error_message,
|
97
|
+
"response_data": self.response_data,
|
98
|
+
"metadata": self.metadata,
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
class BaseOperation(ABC):
|
103
|
+
"""
|
104
|
+
Abstract base class for all AWS operations.
|
105
|
+
|
106
|
+
Provides common functionality including session management, error handling,
|
107
|
+
logging, and safety features that all operation classes should inherit.
|
108
|
+
|
109
|
+
Attributes:
|
110
|
+
service_name: AWS service name (e.g., 'ec2', 's3', 'dynamodb')
|
111
|
+
supported_operations: Set of operation types this class handles
|
112
|
+
requires_confirmation: Whether operations require explicit confirmation
|
113
|
+
"""
|
114
|
+
|
115
|
+
service_name: str = None
|
116
|
+
supported_operations: set = set()
|
117
|
+
requires_confirmation: bool = False
|
118
|
+
|
119
|
+
def __init__(self, profile: Optional[str] = None, region: Optional[str] = None, dry_run: bool = False):
|
120
|
+
"""
|
121
|
+
Initialize base operation class.
|
122
|
+
|
123
|
+
Args:
|
124
|
+
profile: AWS profile name for authentication
|
125
|
+
region: AWS region for operations
|
126
|
+
dry_run: Enable dry-run mode for safe testing
|
127
|
+
"""
|
128
|
+
self.profile = profile
|
129
|
+
self.region = region or "us-east-1"
|
130
|
+
self.dry_run = dry_run
|
131
|
+
self._session = None
|
132
|
+
self._clients = {}
|
133
|
+
|
134
|
+
@property
|
135
|
+
def session(self) -> boto3.Session:
|
136
|
+
"""Get or create AWS session."""
|
137
|
+
if self._session is None:
|
138
|
+
self._session = get_boto3_session(profile_name=self.profile)
|
139
|
+
return self._session
|
140
|
+
|
141
|
+
def get_client(self, service: str, region: Optional[str] = None) -> Any:
|
142
|
+
"""
|
143
|
+
Get AWS service client.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
service: AWS service name
|
147
|
+
region: Override region for this client
|
148
|
+
|
149
|
+
Returns:
|
150
|
+
Configured AWS service client
|
151
|
+
"""
|
152
|
+
client_key = f"{service}:{region or self.region}"
|
153
|
+
|
154
|
+
if client_key not in self._clients:
|
155
|
+
self._clients[client_key] = self.session.client(service, region_name=region or self.region)
|
156
|
+
|
157
|
+
return self._clients[client_key]
|
158
|
+
|
159
|
+
def validate_context(self, context: OperationContext) -> bool:
|
160
|
+
"""
|
161
|
+
Validate operation context before execution.
|
162
|
+
|
163
|
+
Args:
|
164
|
+
context: Operation context to validate
|
165
|
+
|
166
|
+
Returns:
|
167
|
+
True if context is valid
|
168
|
+
|
169
|
+
Raises:
|
170
|
+
ValueError: If context validation fails
|
171
|
+
"""
|
172
|
+
if not context.account:
|
173
|
+
raise ValueError("Operation context must include AWS account information")
|
174
|
+
|
175
|
+
if not context.region:
|
176
|
+
raise ValueError("Operation context must include AWS region")
|
177
|
+
|
178
|
+
if context.operation_type not in self.supported_operations:
|
179
|
+
raise ValueError(
|
180
|
+
f"Operation '{context.operation_type}' not supported. "
|
181
|
+
f"Supported operations: {list(self.supported_operations)}"
|
182
|
+
)
|
183
|
+
|
184
|
+
return True
|
185
|
+
|
186
|
+
def confirm_operation(self, context: OperationContext, resource_id: str, operation_type: str) -> bool:
|
187
|
+
"""
|
188
|
+
Request user confirmation for destructive operations.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
context: Operation context
|
192
|
+
resource_id: Resource identifier
|
193
|
+
operation_type: Type of operation
|
194
|
+
|
195
|
+
Returns:
|
196
|
+
True if operation is confirmed
|
197
|
+
"""
|
198
|
+
if context.dry_run:
|
199
|
+
logger.info(f"[DRY-RUN] Would perform {operation_type} on {resource_id}")
|
200
|
+
return True
|
201
|
+
|
202
|
+
if context.force or not self.requires_confirmation:
|
203
|
+
return True
|
204
|
+
|
205
|
+
# In a real implementation, this would integrate with CLI for confirmation
|
206
|
+
logger.warning(
|
207
|
+
f"Destructive operation: {operation_type} on {resource_id} in account {context.account.account_id}"
|
208
|
+
)
|
209
|
+
return True # Simplified for this implementation
|
210
|
+
|
211
|
+
@aws_api_retry
|
212
|
+
def execute_aws_call(self, client: Any, method_name: str, **kwargs) -> Dict[str, Any]:
|
213
|
+
"""
|
214
|
+
Execute AWS API call with retry and error handling.
|
215
|
+
|
216
|
+
Args:
|
217
|
+
client: AWS service client
|
218
|
+
method_name: Method name to call
|
219
|
+
**kwargs: Method arguments
|
220
|
+
|
221
|
+
Returns:
|
222
|
+
AWS API response
|
223
|
+
|
224
|
+
Raises:
|
225
|
+
ClientError: AWS service errors
|
226
|
+
"""
|
227
|
+
try:
|
228
|
+
method = getattr(client, method_name)
|
229
|
+
response = method(**kwargs)
|
230
|
+
|
231
|
+
logger.debug(f"AWS API call successful: {method_name}")
|
232
|
+
return response
|
233
|
+
|
234
|
+
except ClientError as e:
|
235
|
+
error_code = e.response.get("Error", {}).get("Code", "Unknown")
|
236
|
+
logger.error(f"AWS API call failed: {method_name} - {error_code}: {e}")
|
237
|
+
raise
|
238
|
+
except Exception as e:
|
239
|
+
logger.error(f"Unexpected error in AWS API call: {method_name} - {e}")
|
240
|
+
raise
|
241
|
+
|
242
|
+
def create_operation_result(
|
243
|
+
self,
|
244
|
+
context: OperationContext,
|
245
|
+
operation_type: str,
|
246
|
+
resource_type: str,
|
247
|
+
resource_id: str,
|
248
|
+
status: OperationStatus = OperationStatus.PENDING,
|
249
|
+
) -> OperationResult:
|
250
|
+
"""
|
251
|
+
Create operation result object.
|
252
|
+
|
253
|
+
Args:
|
254
|
+
context: Operation context
|
255
|
+
operation_type: Type of operation
|
256
|
+
resource_type: Type of resource
|
257
|
+
resource_id: Resource identifier
|
258
|
+
status: Initial status
|
259
|
+
|
260
|
+
Returns:
|
261
|
+
OperationResult object
|
262
|
+
"""
|
263
|
+
operation_id = f"{operation_type}-{resource_id}-{datetime.utcnow().strftime('%Y%m%d-%H%M%S')}"
|
264
|
+
|
265
|
+
return OperationResult(
|
266
|
+
operation_id=operation_id,
|
267
|
+
status=status,
|
268
|
+
operation_type=operation_type,
|
269
|
+
resource_type=resource_type,
|
270
|
+
resource_id=resource_id,
|
271
|
+
account_id=context.account.account_id,
|
272
|
+
region=context.region,
|
273
|
+
started_at=datetime.utcnow(),
|
274
|
+
metadata=context.metadata.copy(),
|
275
|
+
)
|
276
|
+
|
277
|
+
@abstractmethod
|
278
|
+
def execute_operation(self, context: OperationContext, operation_type: str, **kwargs) -> List[OperationResult]:
|
279
|
+
"""
|
280
|
+
Execute the specified operation.
|
281
|
+
|
282
|
+
Args:
|
283
|
+
context: Operation context
|
284
|
+
operation_type: Type of operation to execute
|
285
|
+
**kwargs: Operation-specific arguments
|
286
|
+
|
287
|
+
Returns:
|
288
|
+
List of operation results
|
289
|
+
|
290
|
+
Raises:
|
291
|
+
NotImplementedError: Must be implemented by subclasses
|
292
|
+
"""
|
293
|
+
raise NotImplementedError("Subclasses must implement execute_operation")
|
294
|
+
|
295
|
+
def get_operation_history(
|
296
|
+
self, resource_id: Optional[str] = None, operation_type: Optional[str] = None, limit: int = 100
|
297
|
+
) -> List[OperationResult]:
|
298
|
+
"""
|
299
|
+
Get operation history for resources.
|
300
|
+
|
301
|
+
Args:
|
302
|
+
resource_id: Filter by resource ID
|
303
|
+
operation_type: Filter by operation type
|
304
|
+
limit: Maximum results to return
|
305
|
+
|
306
|
+
Returns:
|
307
|
+
List of historical operation results
|
308
|
+
"""
|
309
|
+
# In a real implementation, this would query a database or log store
|
310
|
+
logger.info(f"Operation history requested for {resource_id or 'all resources'}")
|
311
|
+
return []
|