Download scripts/deploy_aws.py from esalguero/FREDML: direct link, hf CLI and curl.
- Browser
- Download file 10.6 kB
-
https://huggingface.co/esalguero/FREDML/resolve/main/scripts/deploy_aws.py
- Command line
-
hf download hf://esalguero/FREDML/scripts/deploy_aws.py
-
curl -L -o deploy_aws.py https://huggingface.co/esalguero/FREDML/resolve/main/scripts/deploy_aws.py
10.6 kB
| #!/usr/bin/env python3 | |
| """ | |
| AWS Deployment Script for FRED ML | |
| Deploys Lambda function, S3 bucket, and EventBridge rule | |
| """ | |
| import boto3 | |
| import json | |
| import os | |
| import zipfile | |
| import tempfile | |
| import shutil | |
| from pathlib import Path | |
| import argparse | |
| import logging | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| class FredMLDeployer: | |
| def __init__(self, region='us-east-1'): | |
| """Initialize the deployer with AWS clients""" | |
| self.region = region | |
| self.cloudformation = boto3.client('cloudformation', region_name=region) | |
| self.s3 = boto3.client('s3', region_name=region) | |
| self.lambda_client = boto3.client('lambda', region_name=region) | |
| self.ssm = boto3.client('ssm', region_name=region) | |
| def create_lambda_package(self, source_dir: str, output_path: str): | |
| """Create Lambda deployment package""" | |
| logger.info("Creating Lambda deployment package...") | |
| with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zipf: | |
| # Add Python files | |
| for root, dirs, files in os.walk(source_dir): | |
| for file in files: | |
| if file.endswith('.py'): | |
| file_path = os.path.join(root, file) | |
| arcname = os.path.relpath(file_path, source_dir) | |
| zipf.write(file_path, arcname) | |
| # Add requirements | |
| requirements_path = os.path.join(source_dir, 'requirements.txt') | |
| if os.path.exists(requirements_path): | |
| zipf.write(requirements_path, 'requirements.txt') | |
| def deploy_s3_bucket(self, stack_name: str, bucket_name: str): | |
| """Deploy S3 bucket using CloudFormation""" | |
| logger.info(f"Deploying S3 bucket: {bucket_name}") | |
| template_path = Path(__file__).parent.parent / 'infrastructure' / 's3' / 'bucket.yaml' | |
| with open(template_path, 'r') as f: | |
| template_body = f.read() | |
| try: | |
| response = self.cloudformation.create_stack( | |
| StackName=stack_name, | |
| TemplateBody=template_body, | |
| Parameters=[ | |
| { | |
| 'ParameterKey': 'BucketName', | |
| 'ParameterValue': bucket_name | |
| } | |
| ], | |
| Capabilities=['CAPABILITY_NAMED_IAM'] | |
| ) | |
| logger.info(f"Stack creation initiated: {response['StackId']}") | |
| return response['StackId'] | |
| except self.cloudformation.exceptions.AlreadyExistsException: | |
| logger.info(f"Stack {stack_name} already exists, updating...") | |
| response = self.cloudformation.update_stack( | |
| StackName=stack_name, | |
| TemplateBody=template_body, | |
| Parameters=[ | |
| { | |
| 'ParameterKey': 'BucketName', | |
| 'ParameterValue': bucket_name | |
| } | |
| ], | |
| Capabilities=['CAPABILITY_NAMED_IAM'] | |
| ) | |
| logger.info(f"Stack update initiated: {response['StackId']}") | |
| return response['StackId'] | |
| def deploy_lambda_function(self, function_name: str, s3_bucket: str, api_key: str): | |
| """Deploy Lambda function""" | |
| logger.info(f"Deploying Lambda function: {function_name}") | |
| # Create deployment package | |
| lambda_dir = Path(__file__).parent.parent / 'lambda' | |
| package_path = tempfile.mktemp(suffix='.zip') | |
| try: | |
| self.create_lambda_package(str(lambda_dir), package_path) | |
| # Update SSM parameter with API key | |
| try: | |
| self.ssm.put_parameter( | |
| Name='/fred-ml/api-key', | |
| Value=api_key, | |
| Type='SecureString', | |
| Overwrite=True | |
| ) | |
| logger.info("Updated FRED API key in SSM") | |
| except Exception as e: | |
| logger.error(f"Failed to update API key: {e}") | |
| # Deploy function code | |
| with open(package_path, 'rb') as f: | |
| code = f.read() | |
| try: | |
| # Try to update existing function | |
| self.lambda_client.update_function_code( | |
| FunctionName=function_name, | |
| ZipFile=code | |
| ) | |
| logger.info(f"Updated Lambda function: {function_name}") | |
| except self.lambda_client.exceptions.ResourceNotFoundException: | |
| # Create new function | |
| template_path = Path(__file__).parent.parent / 'infrastructure' / 'lambda' / 'function.yaml' | |
| with open(template_path, 'r') as f: | |
| template_body = f.read() | |
| # Replace placeholder with actual code | |
| template_body = template_body.replace( | |
| 'import json\ndef lambda_handler(event, context):\n return {\n \'statusCode\': 200,\n \'body\': json.dumps(\'Hello from Lambda!\')\n }', | |
| 'import json\ndef lambda_handler(event, context):\n return {\n \'statusCode\': 200,\n \'body\': json.dumps(\'FRED ML Lambda Function\')\n }' | |
| ) | |
| stack_name = f"{function_name}-stack" | |
| response = self.cloudformation.create_stack( | |
| StackName=stack_name, | |
| TemplateBody=template_body, | |
| Parameters=[ | |
| { | |
| 'ParameterKey': 'FunctionName', | |
| 'ParameterValue': function_name | |
| }, | |
| { | |
| 'ParameterKey': 'S3BucketName', | |
| 'ParameterValue': s3_bucket | |
| } | |
| ], | |
| Capabilities=['CAPABILITY_NAMED_IAM'] | |
| ) | |
| logger.info(f"Lambda stack creation initiated: {response['StackId']}") | |
| finally: | |
| # Clean up | |
| if os.path.exists(package_path): | |
| os.remove(package_path) | |
| def deploy_eventbridge_rule(self, stack_name: str, lambda_function: str, s3_bucket: str): | |
| """Deploy EventBridge rule for quarterly scheduling""" | |
| logger.info(f"Deploying EventBridge rule: {stack_name}") | |
| template_path = Path(__file__).parent.parent / 'infrastructure' / 'eventbridge' / 'quarterly-rule.yaml' | |
| with open(template_path, 'r') as f: | |
| template_body = f.read() | |
| try: | |
| response = self.cloudformation.create_stack( | |
| StackName=stack_name, | |
| TemplateBody=template_body, | |
| Parameters=[ | |
| { | |
| 'ParameterKey': 'LambdaFunctionName', | |
| 'ParameterValue': lambda_function | |
| }, | |
| { | |
| 'ParameterKey': 'S3BucketName', | |
| 'ParameterValue': s3_bucket | |
| } | |
| ], | |
| Capabilities=['CAPABILITY_NAMED_IAM'] | |
| ) | |
| logger.info(f"EventBridge stack creation initiated: {response['StackId']}") | |
| return response['StackId'] | |
| except self.cloudformation.exceptions.AlreadyExistsException: | |
| logger.info(f"Stack {stack_name} already exists, updating...") | |
| response = self.cloudformation.update_stack( | |
| StackName=stack_name, | |
| TemplateBody=template_body, | |
| Parameters=[ | |
| { | |
| 'ParameterKey': 'LambdaFunctionName', | |
| 'ParameterValue': lambda_function | |
| }, | |
| { | |
| 'ParameterKey': 'S3BucketName', | |
| 'ParameterValue': s3_bucket | |
| } | |
| ], | |
| Capabilities=['CAPABILITY_NAMED_IAM'] | |
| ) | |
| logger.info(f"EventBridge stack update initiated: {response['StackId']}") | |
| return response['StackId'] | |
| def wait_for_stack_completion(self, stack_name: str): | |
| """Wait for CloudFormation stack to complete""" | |
| logger.info(f"Waiting for stack {stack_name} to complete...") | |
| waiter = self.cloudformation.get_waiter('stack_create_complete') | |
| try: | |
| waiter.wait(StackName=stack_name) | |
| logger.info(f"Stack {stack_name} completed successfully") | |
| except Exception as e: | |
| logger.error(f"Stack {stack_name} failed: {e}") | |
| raise | |
| def deploy_all(self, bucket_name: str, function_name: str, api_key: str): | |
| """Deploy all components""" | |
| logger.info("Starting FRED ML deployment...") | |
| try: | |
| # Deploy S3 bucket | |
| s3_stack_name = f"{bucket_name}-stack" | |
| self.deploy_s3_bucket(s3_stack_name, bucket_name) | |
| self.wait_for_stack_completion(s3_stack_name) | |
| # Deploy Lambda function | |
| self.deploy_lambda_function(function_name, bucket_name, api_key) | |
| # Deploy EventBridge rule | |
| eventbridge_stack_name = f"{function_name}-eventbridge-stack" | |
| self.deploy_eventbridge_rule(eventbridge_stack_name, function_name, bucket_name) | |
| self.wait_for_stack_completion(eventbridge_stack_name) | |
| logger.info("FRED ML deployment completed successfully!") | |
| except Exception as e: | |
| logger.error(f"Deployment failed: {e}") | |
| raise | |
| def main(): | |
| parser = argparse.ArgumentParser(description='Deploy FRED ML to AWS') | |
| parser.add_argument('--region', default='us-west-2', help='AWS region') | |
| parser.add_argument('--bucket', default='fredmlv1', help='S3 bucket name') | |
| parser.add_argument('--function', default='fred-ml-processor', help='Lambda function name') | |
| parser.add_argument('--api-key', required=True, help='FRED API key') | |
| args = parser.parse_args() | |
| deployer = FredMLDeployer(region=args.region) | |
| deployer.deploy_all(args.bucket, args.function, args.api_key) | |
| if __name__ == "__main__": | |
| main() |