Skip to content

Instantly share code, notes, and snippets.

@iconifyit
Created April 26, 2021 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iconifyit/772a3b9537033bd811440d09291c0249 to your computer and use it in GitHub Desktop.
Save iconifyit/772a3b9537033bd811440d09291c0249 to your computer and use it in GitHub Desktop.
Example serverless file
app: aws-pdf-merge
org: iconify
service: pdf-workflow
custom: ${file(./yml/custom.yml)}
# ================================================================================================
# PROVIDER
# ================================================================================================
provider:
name: aws
runtime: nodejs12.x
profile: default
timeout: 10
iamRoleStatements:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource:
- arn:aws:lambda:us-east-1::*:*
- arn:aws:states:us-east-1::*:*
- Effect: Allow
Action:
- sts:StartExecution
Resource:
- arn:aws:states:us-east-1::*:*
- Effect: Allow
Action:
- cloudwatch:*
Resource:
- arn:aws:cloudwatch:us-east-1::*:*
- Effect: Allow
Action:
- s3:*
Resource: '*'
# ================================================================================================
# PLUGINS
# ================================================================================================
plugins:
- serverless-step-functions
- serverless-pseudo-parameters
- serverless-vpc-plugin
layers:
commonLibs:
path: layer
compatibleRuntimes:
- nodejs12.x
# ================================================================================================
# LAMBDAS
# ================================================================================================
functions:
getLatestCursor:
handler: getLatestCursor.handler
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
getStoredCursor:
handler: getStoredCursor.handler
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
getFileList:
handler: getFileList.handler
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
downloadFile:
handler: downloadFile.handler
timeout: 900
memorySize: 3008
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
compressFile:
handler: compressFile.handler
timeout: 900
memorySize: 3008
layers:
- {Ref: CommonLibsLambdaLayer}
- arn:aws:lambda:us-east-1:764866452798:layer:ghostscript:8
# https://github.com/shelfio/ghostscript-lambda-layer
environment:
s3BucketName: ${self:custom.s3BucketName}
clearBucket:
handler: clearBucket.handler
timeout: 300
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
mergePdfs:
handler: mergePdfs.handler
timeout: 900
memorySize: 3008
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
uploadToDropbox:
handler: uploadToDropbox.handler
timeout: 900
memorySize: 3008
layers:
- {Ref: CommonLibsLambdaLayer}
environment:
s3BucketName: ${self:custom.s3BucketName}
# ================================================================================================
# STEP FUNCTIONS
# ================================================================================================
stepFunctions:
stateMachines:
getLatestCursor:
name: sfGetLatestCursor
definition:
Comment: 'Get the latest cursor'
StartAt: Get_Latest_Cursor
States:
Get_Latest_Cursor:
Type: Task
Resource:
Fn::GetAtt: [getLatestCursor, Arn]
TimeoutSeconds: 120
HeartbeatSeconds: 30
Catch:
- ErrorEquals: [States.ALL]
ResultPath: $.error
Next: Send_Cursor_Error_Message
Next : Send_Cursor_Success_Message
Send_Cursor_Success_Message:
Type: Task
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[SUCCESS] Saved Latest Cursor'
Message:
- Input.$ : $
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: End_Cursor_Process
Send_Cursor_Error_Message:
Type: Task
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[FAILED] Get Latest Cursor Error'
Message:
- Input.$: $.error
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: End_Cursor_Process
End_Cursor_Process:
Type: Pass
End: true
Merge_File_List:
name: sfMergeFileList
definition:
Comment: 'Get the stored cursor'
StartAt: Send_Merge_Started_Message
States:
Send_Merge_Started_Message:
Type: Task
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: 'PDF Merge Started'
Message: '[START] GoodHumans.co.uk PDF merge has started. You will be notified via email when the process is complete'
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: Get_Stored_Cursor
Get_Stored_Cursor:
Type: Task
Resource:
Fn::GetAtt: [getStoredCursor, Arn]
Catch:
- ErrorEquals : [States.ALL]
ResultPath : $.error
Next : Send_Error_Message
Next : Clear_PDF_Bucket
Clear_PDF_Bucket:
Type: Task
Resource:
Fn::GetAtt: [clearBucket, Arn]
Catch:
- ErrorEquals : [States.ALL]
ResultPath : $.error
Next : Send_Error_Message
Next : Get_File_List
Get_File_List:
Type: Task
Resource:
Fn::GetAtt: [getFileList, Arn]
Catch:
- ErrorEquals : [States.ALL]
ResultPath : $.error
Next : Send_Error_Message
Next : Has_Files_To_Download
Has_Files_To_Download:
Type: Choice
Choices :
- Variable : $.body.has_files
BooleanEquals : true
Next : Download_Files
Default : Send_No_Files_Message
Download_Files :
Type : Map
InputPath : $.body
ItemsPath : $.files
Parameters :
'Index.$' : $$.Map.Item.Index
'Value.$' : $$.Map.Item.Value
MaxConcurrency : 3
Iterator :
StartAt : Download_File
States :
Download_File:
Type: Task
Resource: !Join [':', ['arn:aws:lambda', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'function:pdf-workflow-downloadFile']]
TimeoutSeconds : 900
HeartbeatSeconds : 30
Retry:
- ErrorEquals: [ States.ALL ]
IntervalSeconds: 1
BackoffRate: 2
MaxAttempts: 3
Next: Cool_Down_1
Cool_Down_1:
Type : Wait
Seconds : 2
Next : Compress_File
Compress_File:
Type: Task
Resource: !Join [':', ['arn:aws:lambda', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'function:pdf-workflow-compressFile']]
Parameters:
'Key.$': $.body.Key
TimeoutSeconds: 900
HeartbeatSeconds: 30
Retry:
- ErrorEquals: [ States.ALL ]
IntervalSeconds: 1
BackoffRate: 2
MaxAttempts: 3
Next : Cool_Down_2
Cool_Down_2:
Type : Wait
Seconds : 2
End : true
Catch:
- ErrorEquals : [States.ALL]
ResultPath : $
Next : Send_Error_Message
Next : Merge_PDFs_in_Parallel
Merge_PDFs_in_Parallel:
Type: Parallel
Next : End_Process
Branches:
- StartAt: Merge_HR_PDFs
States:
Merge_HR_PDFs:
Type: Task
Parameters:
Resolution: 'HR'
Resource:
Fn::GetAtt: [mergePdfs, Arn]
Catch:
- ErrorEquals: [States.ALL]
ResultPath: $
Next: Send_HR_Process_Error_Message
Next: Merge_PDFs_Cool_Down_1
Merge_PDFs_Cool_Down_1:
Type: Wait
Seconds: 3
Next : Upload_HR_PDF_to_Dropbox
Upload_HR_PDF_to_Dropbox:
Type: Task
Resource:
Fn::GetAtt: [uploadToDropbox, Arn]
Catch:
- ErrorEquals: [States.ALL]
ResultPath: $
Next: Send_HR_Process_Error_Message
Next: Send_HR_Process_Finished_Message
Send_HR_Process_Finished_Message:
Type: Task
InputPath: $
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[SUCCESS] `03 Final Artwork` PDFs Merged'
Message:
- Input.$: $.body.message
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: End_HR_Process
Send_HR_Process_Error_Message:
Type: Task
InputPath: $
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[FAILED] Merge HR File List Error'
Message:
- Input.$: $
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: Exit_HR_Process_with_Failure
Exit_HR_Process_with_Failure:
Type: Fail
Cause: 'Merge `03 Final Artwork` PDFs Error'
Error: $
End_HR_Process:
Type: Pass
End: true
- StartAt: Merge_LR_PDFs
States:
Merge_LR_PDFs:
Type: Task
Parameters:
Resolution: 'LR'
ResultPath: $
Resource:
Fn::GetAtt: [mergePdfs, Arn]
Catch:
- ErrorEquals: [States.ALL]
ResultPath: $
Next: Send_LR_Process_Error_Message
Next: Upload_LR_PDF_to_Dropbox
Upload_LR_PDF_to_Dropbox:
Type: Task
Resource:
Fn::GetAtt: [uploadToDropbox, Arn]
Catch:
- ErrorEquals: [States.ALL]
ResultPath: $
Next: Send_LR_Process_Error_Message
Next: Send_LR_Process_Finished_Message
Send_LR_Process_Finished_Message:
Type: Task
InputPath: $
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[SUCCESS] `Proofs` PDFs Merged'
Message:
- Input.$: $.body.message
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: End_LR_Process
Send_LR_Process_Error_Message:
Type: Task
InputPath: $
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: '[FAILED] Merge LR File List Error'
Message:
- Input.$: $
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: Exit_LR_Process_with_Failure
Exit_LR_Process_with_Failure:
Type: Fail
Cause: 'Merge `Proofs` PDFs Error'
Error: $
End_LR_Process:
Type: Pass
End: true
Send_No_Files_Message:
Type: Task
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject: 'No Files to Download'
Message: '[EXITED] This is not an error, it simply means there were no files found to merge since the last time we checked.'
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: End_Process
Send_Error_Message:
Type: Task
Resource:
arn:aws:states:::sns:publish
Parameters:
Subject : '[FAILED] Merge File List Error'
Message:
- Input.$ : $
TopicArn:
!Join [':', ['arn:aws:sns', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'GoodHumansNotifications']]
Next: Exit_With_Failure
Exit_With_Failure:
Type : Fail
Cause : 'Merge File List Error'
Error : ''
End_Process:
Type: Pass
End : true
# ================================================================================================
# RESOURCES
# ================================================================================================
resources:
Resources:
TriggerGetLatestCursor:
Type: AWS::Events::Rule
Properties:
Name: 'Trigger-Get-Latest-Cursor'
Description : 'Triggers getLatestCursor step function'
ScheduleExpression : 'cron(30 5 ? * 1-6 *)'
State : 'ENABLED'
Targets :
- Arn : !Join [ ':', [ 'arn:aws:states', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'stateMachine:sfGetLatestCursor' ]]
Id : TriggerGetLatestCursorStepFunction
RoleArn : !Join [ ':', [ 'arn:aws:iam:', !Ref 'AWS::AccountId', 'role/pdf-workflow-SfGetLatestCursorRole-1GXNYMTHZZLNX' ] ]
TriggerMergePdfs:
Type: AWS::Events::Rule
Properties:
Name: 'Trigger-Merge-PDFs'
Description : 'Triggers mergePdfs step function'
ScheduleExpression : 'cron(0 15 ? * 1-5 *)'
State : 'ENABLED'
Targets :
- Arn : !Join [ ':', [ 'arn:aws:states', !Ref 'AWS::Region', !Ref 'AWS::AccountId', 'stateMachine:sfMergeFileList' ]]
Id : TriggerMergePdfsStepFunction
RoleArn : !Join [ ':', [ 'arn:aws:iam:', !Ref 'AWS::AccountId', 'role/pdf-workflow-SfMergeFileListRole-12UIYA0MAZF0R' ] ]
errorMessages:
Type: AWS::SNS::Topic
Properties:
DisplayName: 'Good Humans Workflow Notifications'
TopicName: GoodHumansNotifications
Subscription:
- Endpoint: scott@atomiclotus.net
Protocol: email
storageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: ${self:custom.s3BucketName}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment