UNPKG

cfn-forge

Version:

CloudFormation deployment automation tool with git-based workflows

447 lines (381 loc) 12.5 kB
name: basic-lambda description: Simple AWS Lambda function with CloudWatch logging and basic permissions version: 1.0.0 author: CFN-Forge cfnForgeVersion: 1.0.0 variables: projectName: prompt: "Project name" default: "my-lambda-function" description: prompt: "Project description" default: "A basic AWS Lambda function" runtime: prompt: "Lambda runtime" default: "nodejs18.x" options: ["nodejs18.x", "nodejs20.x", "python3.9", "python3.10", "python3.11", "python3.12"] memorySize: prompt: "Memory size (MB)" default: "128" type: "number" timeout: prompt: "Timeout (seconds)" default: "30" type: "number" triggerType: prompt: "Trigger type" default: "manual" options: ["manual", "s3", "eventbridge", "sqs"] files: include: - "**/*" exclude: - "template.yaml" - ".git/**" - "node_modules/**" structure: cloudformation.yaml: | AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: {{description}} Parameters: Environment: Type: String Default: dev AllowedValues: [dev, staging, prod] Description: Environment name Conditions: HasS3Trigger: !Equals ["{{triggerType}}", "s3"] HasEventBridgeTrigger: !Equals ["{{triggerType}}", "eventbridge"] HasSQSTrigger: !Equals ["{{triggerType}}", "sqs"] Resources: # Lambda Function {{projectName}}Function: Type: AWS::Serverless::Function Properties: FunctionName: !Sub "${AWS::StackName}-function" CodeUri: src/ Handler: !If - !Equals ["{{runtime}}", "python3.9"] - "handler.lambda_handler" - !If - !Equals ["{{runtime}}", "python3.10"] - "handler.lambda_handler" - !If - !Equals ["{{runtime}}", "python3.11"] - "handler.lambda_handler" - !If - !Equals ["{{runtime}}", "python3.12"] - "handler.lambda_handler" - "index.handler" Runtime: {{runtime}} MemorySize: {{memorySize}} Timeout: {{timeout}} Environment: Variables: ENVIRONMENT: !Ref Environment LOG_LEVEL: INFO Events: # S3 Trigger (conditional) S3Event: Type: S3 Condition: HasS3Trigger Properties: Bucket: !Ref S3Bucket Events: s3:ObjectCreated:* Filter: S3Key: Rules: - Name: prefix Value: uploads/ # EventBridge Trigger (conditional) EventBridgeRule: Type: EventBridgeRule Condition: HasEventBridgeTrigger Properties: Pattern: source: ["custom.application"] detail-type: ["Custom Event"] # SQS Trigger (conditional) SQSEvent: Type: SQS Condition: HasSQSTrigger Properties: Queue: !GetAtt SQSQueue.Arn BatchSize: 10 # S3 Bucket (if S3 trigger selected) S3Bucket: Type: AWS::S3::Bucket Condition: HasS3Trigger Properties: BucketName: !Sub "${AWS::StackName}-trigger-bucket" NotificationConfiguration: LambdaConfigurations: - Event: s3:ObjectCreated:* Function: !GetAtt {{projectName}}Function.Arn Filter: S3Key: Rules: - Name: prefix Value: uploads/ # SQS Queue (if SQS trigger selected) SQSQueue: Type: AWS::SQS::Queue Condition: HasSQSTrigger Properties: QueueName: !Sub "${AWS::StackName}-queue" VisibilityTimeoutSeconds: !Ref {{timeout}} # CloudWatch Log Group LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub "/aws/lambda/${AWS::StackName}-function" RetentionInDays: 14 Outputs: FunctionName: Description: Lambda Function Name Value: !Ref {{projectName}}Function Export: Name: !Sub "${AWS::StackName}-FunctionName" FunctionArn: Description: Lambda Function ARN Value: !GetAtt {{projectName}}Function.Arn Export: Name: !Sub "${AWS::StackName}-FunctionArn" S3BucketName: Condition: HasS3Trigger Description: S3 Trigger Bucket Name Value: !Ref S3Bucket Export: Name: !Sub "${AWS::StackName}-S3Bucket" SQSQueueUrl: Condition: HasSQSTrigger Description: SQS Queue URL Value: !Ref SQSQueue Export: Name: !Sub "${AWS::StackName}-SQSQueue" .cfn-forge.yaml: | project: name: {{projectName}} description: {{description}} type: basic-lambda environments: dev: stackName: "{{projectName}}-dev" template: cloudformation.yaml region: us-east-1 parameters: Environment: dev staging: stackName: "{{projectName}}-staging" template: cloudformation.yaml region: us-east-1 parameters: Environment: staging prod: stackName: "{{projectName}}-prod" template: cloudformation.yaml region: us-east-1 parameters: Environment: prod deployment: packagingBucket: "{{projectName}}-deployment-artifacts" createBucket: true git: watchBranches: ["main", "develop"] deployOnPush: true package.json: | { "name": "{{projectName}}", "version": "1.0.0", "description": "{{description}}", "main": "src/index.js", "scripts": { "start": "sam local start-lambda", "invoke": "sam local invoke", "build": "sam build", "deploy": "cfn-forge deploy", "watch": "cfn-forge watch", "validate": "cfn-forge validate", "test": "jest", "test:watch": "jest --watch", "lint": "eslint src/", "logs": "sam logs -n {{projectName}}Function --stack-name {{projectName}}-dev" }, "dependencies": { "aws-sdk": "^2.1490.0" }, "devDependencies": { "jest": "^29.0.0", "eslint": "^8.0.0" }, "keywords": ["lambda", "aws", "serverless"], "author": "{{author}}", "license": "MIT" } src/index.js: | // Basic Lambda function handler for Node.js exports.handler = async (event, context) => { console.log('Event:', JSON.stringify(event, null, 2)); console.log('Context:', JSON.stringify(context, null, 2)); try { // Your business logic here const result = { message: 'Hello from {{projectName}}!', timestamp: new Date().toISOString(), environment: process.env.ENVIRONMENT, eventType: event.Records ? 'triggered' : 'direct', requestId: context.awsRequestId }; console.log('Result:', JSON.stringify(result, null, 2)); return { statusCode: 200, body: JSON.stringify(result) }; } catch (error) { console.error('Error:', error); return { statusCode: 500, body: JSON.stringify({ message: 'Internal server error', error: error.message }) }; } }; src/handler.py: | # Basic Lambda function handler for Python import json import logging import os from datetime import datetime # Configure logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): logger.info(f"Event: {json.dumps(event)}") logger.info(f"Context: {vars(context)}") try: # Your business logic here result = { 'message': 'Hello from {{projectName}}!', 'timestamp': datetime.now().isoformat(), 'environment': os.environ.get('ENVIRONMENT'), 'eventType': 'triggered' if 'Records' in event else 'direct', 'requestId': context.aws_request_id } logger.info(f"Result: {json.dumps(result)}") return { 'statusCode': 200, 'body': json.dumps(result) } except Exception as error: logger.error(f"Error: {str(error)}") return { 'statusCode': 500, 'body': json.dumps({ 'message': 'Internal server error', 'error': str(error) }) } tests/test-handler.js: | const { handler } = require('../src/index'); describe('Lambda Handler', () => { const mockContext = { awsRequestId: 'test-request-id', getRemainingTimeInMillis: () => 30000 }; test('should handle direct invocation', async () => { const event = { test: 'data' }; const result = await handler(event, mockContext); expect(result.statusCode).toBe(200); expect(JSON.parse(result.body).message).toContain('Hello from {{projectName}}'); }); test('should handle S3 event', async () => { const event = { Records: [{ eventSource: 'aws:s3', s3: { bucket: { name: 'test-bucket' }, object: { key: 'test-key' } } }] }; const result = await handler(event, mockContext); expect(result.statusCode).toBe(200); expect(JSON.parse(result.body).eventType).toBe('triggered'); }); }); README.md: | # {{projectName}} {{description}} ## Quick Start 1. Install dependencies: ```bash npm install ``` 2. Deploy to AWS: ```bash cfn-forge deploy ``` 3. Test locally: ```bash npm run invoke ``` ## Function Details - **Runtime**: {{runtime}} - **Memory**: {{memorySize}} MB - **Timeout**: {{timeout}} seconds - **Trigger**: {{triggerType}} ## Project Structure ``` {{projectName}}/ src/ index.js # Node.js handler handler.py # Python handler tests/ test-handler.js # Unit tests cloudformation.yaml # AWS infrastructure .cfn-forge.yaml # CFN-Forge configuration package.json ``` ## Local Development ```bash # Start Lambda locally npm run start # Invoke function locally npm run invoke # Run tests npm test # Watch for changes npm run test:watch ``` ## Deployment ### Environments - **dev**: Development environment - **staging**: Staging environment - **prod**: Production environment ### Commands - `cfn-forge deploy` - Deploy to default environment - `cfn-forge deploy --env prod` - Deploy to production - `cfn-forge watch` - Watch for changes and auto-deploy - `cfn-forge validate` - Validate CloudFormation template ## Monitoring ```bash # View logs npm run logs # View CloudWatch metrics in AWS Console aws logs describe-log-groups --log-group-name-prefix "/aws/lambda/{{projectName}}" ``` ## Triggers This template supports multiple trigger types: - **manual**: Invoke directly or via API - **s3**: Triggered by S3 object creation - **eventbridge**: Triggered by EventBridge rules - **sqs**: Triggered by SQS messages hooks: postInstall: - type: npm command: install - type: message content: "Lambda function template created! Choose the appropriate handler file for your runtime."