-
-
Save bubba-h57/48c31940c8ac51b748c9 to your computer and use it in GitHub Desktop.
GULP file for managing AWS LAMBDA node.js functions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| FUNCTION_ROLE="arn:aws:iam::123456789097531:role/lambda_basic_execution" | |
| FUNCTION_TIMEOUT=10 | |
| AWS_REGION=us-east-1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "key3": "value3", | |
| "key2": "value2", | |
| "key1": "value1" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // npm install --save-dev gulp gulp-util del gulp-rename gulp-install gulp-zip aws-sdk fs run-sequence xtend dotenv path | |
| var fs = require('fs'); | |
| var del = require('del'); | |
| var gulp = require('gulp'); | |
| var path = require('path'); | |
| var zip = require('gulp-zip'); | |
| var AWS = require('aws-sdk'); | |
| var gutil = require('gulp-util'); | |
| var extend = require('xtend'); | |
| var p = require('./package.json'); | |
| var install = require('gulp-install'); | |
| var rename = require('gulp-rename'); | |
| var runSequence = require('run-sequence'); | |
| require('dotenv').load(); | |
| /** | |
| * Set up our region | |
| */ | |
| var aws_opts = { | |
| region: 'us-east-1' | |
| }; | |
| /** | |
| * However, if present in the .env file, override | |
| * the values from the package.json | |
| */ | |
| if (typeof process.env.AWS_REGION != 'undefined'){ | |
| aws_opts.region = process.env.AWS_REGION; | |
| } | |
| /** | |
| * Set up our lambda function parameters, prefer to use | |
| * the name and description from package.json | |
| */ | |
| var lambda_params = { | |
| "FunctionName": p.name, | |
| "Description": p.description, | |
| "Role": process.env.FUNCTION_ROLE, | |
| "Timeout": process.env.FUNCTION_TIMEOUT | |
| }; | |
| /** | |
| * However, if present in the .env file, override | |
| * the values from the package.json | |
| */ | |
| if (typeof process.env.FUNCTION_NAME != 'undefined'){ | |
| lambda_params.FunctionName = process.env.FUNCTION_NAME; | |
| } | |
| if (typeof process.env.FUNCTION_DESCRIPTION != 'undefined'){ | |
| lambda_params.Description = process.env.FUNCTION_DESCRIPTION; | |
| } | |
| //Default options | |
| var lambda_options = { | |
| 'handler': 'handler', | |
| 'file_name': 'index.js', | |
| 'event': 'event.json', | |
| 'zip': 'dist.zip', | |
| 'dist_dir': './dist' | |
| }; | |
| // Allow the .env file to override the default options | |
| if (typeof process.env.FUNCTION_HANDLER != 'undefined'){ | |
| lambda_options.handler = process.env.FUNCTION_HANDLER; | |
| } | |
| if (typeof process.env.FUNCTION_FILE_NAME != 'undefined'){ | |
| lambda_options.file_name = process.env.FUNCTION_FILE_NAME; | |
| } | |
| if (typeof process.env.FUNCTION_EVENT != 'undefined'){ | |
| lambda_options.event = process.env.FUNCTION_EVENT; | |
| } | |
| if (typeof process.env.ZIP_FILENAME != 'undefined'){ | |
| lambda_options.zip = process.env.ZIP_FILENAME; | |
| } | |
| if (typeof process.env.DIST_DIR != 'undefined'){ | |
| lambda_options.dist_dir = process.env.DIST_DIR; | |
| } | |
| /** | |
| * Simply runs the function locally for our debug/testing | |
| */ | |
| gulp.task('invoke', function(){ | |
| // Build a context object | |
| var context = { | |
| done: function (error, result) { | |
| if (error === null) { | |
| this.succeed(result); | |
| } else { | |
| this.fail(error); | |
| } | |
| }, | |
| succeed: function (result) { | |
| gutil.log(""); | |
| gutil.log("Success! Message:"); | |
| gutil.log("------------------"); | |
| gutil.log(result); | |
| }, | |
| fail: function (error) { | |
| gutil.log(""); | |
| gutil.log("Failure! Message:"); | |
| gutil.log("------------------"); | |
| gutil.log(error); | |
| }, | |
| awsRequestId: 'LAMBDA_INVOKE', | |
| logStreamName: 'LAMBDA_INVOKE', | |
| clientContext: null, | |
| identity: null | |
| }; | |
| // lets run our code | |
| var lambda = require(path.resolve(lambda_options.file_name)); | |
| var event = JSON.parse(fs.readFileSync(path.resolve(lambda_options.event), "utf8")); | |
| lambda[lambda_options.handler](event, context); | |
| }); | |
| /** | |
| * Clean up the distribution folder, delete the zip package. | |
| */ | |
| gulp.task('clean', function(cb) { | |
| del(lambda_options.dist_dir, | |
| del('./'+lambda_options.zip, cb) | |
| ); | |
| }); | |
| /** | |
| * Copy our function file into the dist folder. | |
| */ | |
| gulp.task('js', function() { | |
| gulp.src(lambda_options.file_name) | |
| .pipe(gulp.dest(lambda_options.dist_dir)) | |
| }); | |
| /** | |
| * Here we want to install npm packages to dist, ignoring devDependencies. | |
| */ | |
| gulp.task('npm', function() { | |
| gulp.src('./package.json') | |
| .pipe(gulp.dest(lambda_options.dist_dir)) | |
| .pipe(install({production: true})); | |
| }); | |
| /** | |
| * Next copy over any environment variables managed outside of source control. | |
| */ | |
| gulp.task('env', function() { | |
| gulp.src('./config.env.production') | |
| .pipe(rename('.env')) | |
| .pipe(gulp.dest(lambda_options.dist_dir)) | |
| }); | |
| /** | |
| * Now the dist directory is ready to go. Zip it. | |
| */ | |
| gulp.task('zip', function() { | |
| gulp.src([lambda_options.dist_dir + '/**/*', '!'+lambda_options.dist_dir+'/package.json', lambda_options.dist_dir+'/.*']) | |
| .pipe(zip(lambda_options.zip)) | |
| .pipe(gulp.dest('./')); | |
| }); | |
| /** | |
| * Uploade the package to AWS Lambda, creating the package if it doesn't | |
| * already exist | |
| */ | |
| gulp.task('upload', function() { | |
| AWS.config.update({ region: aws_opts.region }); | |
| var lambda = new AWS.Lambda(); | |
| var params = lambda_params; | |
| // Updates the Lambda Function Configuration | |
| var updateConfig = function(func_name, func_options, callback) { | |
| if(Object.keys(func_options).length > 0) { | |
| func_options.FunctionName = func_name; | |
| lambda.updateFunctionConfiguration(func_options, function(err, data) { | |
| if (err) { | |
| gutil.log('Could not update config, check that values and permissions are valid'); | |
| } | |
| gutil.log('Config updated.'); | |
| }); | |
| } else { | |
| gutil.log('No config updates to make.'); | |
| return; | |
| } | |
| }; | |
| // Updates the Lambda function code | |
| var updateCode = function(){ | |
| fs.readFile(lambda_options.zip, function (err, data) { | |
| if (err) { | |
| gutil.log('Could not read package file (./dist.zip), verify the lambda package '+ | |
| 'location is correct, and that you have already created the package using lambda_package.'); | |
| } | |
| var codeParams = { | |
| FunctionName: params.FunctionName, | |
| ZipFile: data | |
| } | |
| lambda.updateFunctionCode(codeParams, function (err, data) { | |
| if (err) { | |
| gutil.log('Package upload failed, check you have lambda:UpdateFunctionCode permissions.'); | |
| } | |
| gutil.log('Package deployed.'); | |
| updateConfig(params.FunctionName, params, function(data){ | |
| gutil.log('Configuration Updated.'); | |
| }); | |
| }); | |
| }); | |
| } | |
| // Creates the Lambda function if necessary | |
| var createFunc = function(){ | |
| fs.readFile(path.resolve(lambda_options.zip), function (err, data) { | |
| // Creating a function | |
| lambda.createFunction(extend({ | |
| Handler: path.basename(lambda_options.file_name, path.extname(lambda_options.file_name)) + '.' +lambda_options.handler, | |
| Runtime: 'nodejs' | |
| }, params, {Code: {ZipFile: data} }), function(err, data){ | |
| if (err) { | |
| gutil.log('Could not create the function'); | |
| gutil.log(err); | |
| } | |
| gutil.log('We created the function!'); | |
| updateCode(); | |
| }) ; | |
| }); | |
| } | |
| // Gets the function configuration, if it exists, we don't need to create the function | |
| lambda.getFunctionConfiguration({FunctionName: params.FunctionName}, function(err, data) { | |
| if (err) { | |
| gutil.log('Function does not exist, we will attempt to create it'); | |
| createFunc(); | |
| }else{ | |
| updateCode(); | |
| } | |
| }); | |
| }); | |
| // The key to deploying as a single command is to manage the sequence of events. | |
| gulp.task('default', function(callback) { | |
| gutil.log(lambda_params); | |
| //return; | |
| return runSequence( | |
| ['clean'], | |
| ['js', 'npm', 'env'], | |
| ['zip'], | |
| ['upload'], | |
| callback | |
| ); | |
| }); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Assumes your AWS Credential are setup properly (~/.aws/credentials) and that you are using NPM to manage modules. By default, we will pull the function name and description from the package.json for your project.
You must edit the .env file and update it with your particular role. There are a number of additional settings you can specify in the file, to override the defaults:
Modify event.js to mimic an expected event in the LAMBDA Function.
gulp invoke - Will run your LAMBDA function locally, using the event.js as input for testing.
gulp - Simply packages it all up and pushes it to AWS. If the function doesn't exist, it will attempt to create it.