Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bin/node-lambda
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dotenv.load();

var AWS_ENVIRONMENT = process.env.AWS_ENVIRONMENT || '';
var CONFIG_FILE = process.env.CONFIG_FILE || '';
var EXCLUDE_GLOBS = process.env.EXCLUDE_GLOBS || '';
var AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
var AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
var AWS_SESSION_TOKEN = process.env.AWS_SESSION_TOKEN || '';
Expand Down Expand Up @@ -45,6 +46,8 @@ program
.option('-v, --version [' + AWS_FUNCTION_VERSION + ']', 'Lambda Function Version', AWS_FUNCTION_VERSION)
.option('-f, --configFile [' + CONFIG_FILE + ']',
'Path to file holding secret environment variables (e.g. "deploy.env")', CONFIG_FILE)
.option('-x, --excludeGlobs [' + EXCLUDE_GLOBS + ']',
'Space-separated glob pattern(s) for additional exclude files (e.g. "event.json dotenv.sample")', EXCLUDE_GLOBS)
.action(function (prg) {
lambda.deploy(prg);
});
Expand Down
1 change: 1 addition & 0 deletions lib/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ AWS_MEMORY_SIZE=128
AWS_TIMEOUT=3
AWS_DESCRIPTION=
AWS_RUNTIME=nodejs
EXCLUDE_GLOBS="deploy.env event.json"
122 changes: 76 additions & 46 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,16 @@ Lambda.prototype._zipfileTmpPath = function (program) {
};

Lambda.prototype._rsync = function (program, codeDirectory, callback) {
exec('rsync -r --exclude=.git --exclude=*.log --exclude=node_modules . ' + codeDirectory, function (err) {
var extraExcludes = '';

if (program.excludeGlobs) {
var excludes = program.excludeGlobs.split(' ');
excludes.forEach(function(exclude) {
extraExcludes += '--exclude=' + exclude + ' ';
});
}

exec('rsync -r --exclude=.git --exclude=*.env --exclude=*.log --exclude=node_modules ' + extraExcludes + ' . ' + codeDirectory, function (err) {
if (err) {
throw err;
}
Expand Down Expand Up @@ -162,6 +171,22 @@ Lambda.prototype._codeDirectory = function (program) {
return os.tmpDir() + '/' + program.functionName + '-' + epoch_time;
};

Lambda.prototype._cleanDirectory = function (codeDirectory, callback) {
exec('rm -rf ' + codeDirectory, function (err) {
if (err) {
throw err;
}

fs.mkdir(codeDirectory, function(err) {
if (err) {
throw err;
}

return callback(null, true);
});
});
};

Lambda.prototype._setEnvironmentVars = function (program, codeDirectory) {
console.log('=> Setting "environment variables" for Lambda from %s', program.configFile);
// Which file is the handler?
Expand Down Expand Up @@ -200,72 +225,77 @@ Lambda.prototype.deploy = function (program) {
var regions = program.region.split(',');
var codeDirectory = _this._codeDirectory(program);

console.log('=> Moving files to temporary directory');
// Move all files to tmp folder (except .git, .log, event.json and node_modules)

_this._rsync(program, codeDirectory, function (err) {
_this._cleanDirectory(codeDirectory, function (err) {
if (err) {
console.error(err);
return;
}
console.log('=> Running npm install --production');
_this._npmInstall(program, codeDirectory, function (err) {
console.log('=> Moving files to temporary directory');
// Move all files to tmp folder (except .git, .log, event.json and node_modules)

_this._rsync(program, codeDirectory, function (err) {
if (err) {
console.error(err);
return;
}

// Add custom environment variables if program.configFile is defined
if (program.configFile) {
_this._setEnvironmentVars(program, codeDirectory);
}
console.log('=> Zipping deployment package');

var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
archive = archive.bind(_this);

archive(program, codeDirectory, function (err, buffer) {
console.log('=> Running npm install --production');
_this._npmInstall(program, codeDirectory, function (err) {
if (err) {
console.error(err);
return;
}

console.log('=> Reading zip file to memory');
var params = _this._params(program, buffer);
// Add custom environment variables if program.configFile is defined
if (program.configFile) {
_this._setEnvironmentVars(program, codeDirectory);
}
console.log('=> Zipping deployment package');

async.map(regions, function (region, cb) {
console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:');
console.log(params);
var archive = process.platform !== 'win32' ? _this._nativeZip : _this._zip;
archive = archive.bind(_this);

var aws_security = {
accessKeyId: program.accessKey,
secretAccessKey: program.secretKey,
region: region
};
archive(program, codeDirectory, function (err, buffer) {
if (err) {
console.error(err);
return;
}

if (program.sessionToken){
aws_security.sessionToken = program.sessionToken;
};
console.log('=> Reading zip file to memory');
var params = _this._params(program, buffer);

aws.config.update(aws_security);
async.map(regions, function (region, cb) {
console.log('=> Uploading zip file to AWS Lambda ' + region + ' with parameters:');
console.log(params);

var lambda = new aws.Lambda({
apiVersion: '2014-11-11'
});
var aws_security = {
accessKeyId: program.accessKey,
secretAccessKey: program.secretKey,
region: region
};

lambda.uploadFunction(params, function (err, data) {
cb(err, data);
});
if (program.sessionToken){
aws_security.sessionToken = program.sessionToken;
};

}, function (err, results) {
if (err) {
console.error(err);
} else {
console.log('=> Zip file(s) done uploading. Results follow: ');
console.log(results);
}
});
aws.config.update(aws_security);

var lambda = new aws.Lambda({
apiVersion: '2014-11-11'
});

lambda.uploadFunction(params, function (err, data) {
cb(err, data);
});

}, function (err, results) {
if (err) {
console.error(err);
} else {
console.log('=> Zip file(s) done uploading. Results follow: ');
console.log(results);
}
});
});
});
});
});
Expand Down
62 changes: 55 additions & 7 deletions test/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,67 @@ describe('node-lambda', function () {
});

describe('_rsync', function () {
beforeEach(function (done) {
lambda._cleanDirectory(codeDirectory, done);
});

it('rsync an index.js as well as other files', function (done) {
lambda._rsync(program, codeDirectory, function (err, result) {
var contents = fs.readdirSync(codeDirectory);

result = _.includes(contents, 'index.js');
result = _.includes(contents, 'index.js') ||
_.includes(contents, 'package.json');
assert.equal(result, true);

done();
});
});

describe("when there are excluded files", function (done) {
beforeEach(function (done) {
program.excludeGlobs="*.png test"
done();
});

it('rsync an index.js as well as other files', function (done) {
lambda._rsync(program, codeDirectory, function (err, result) {
var contents = fs.readdirSync(codeDirectory);

result = _.includes(contents, 'index.js') ||
_.includes(contents, 'package.json');
assert.equal(result, true);

done();
});
});

it('rsync excludes files matching excludeGlobs', function (done) {
lambda._rsync(program, codeDirectory, function (err, result) {
var contents = fs.readdirSync(codeDirectory);

result = _.includes(contents, 'node-lambda.png') ||
_.includes(contents, 'test');
assert.equal(result, false);

done();
});
});
});
});

describe('_npmInstall', function () {
beforeEach(function (done) {
lambda._rsync(program, codeDirectory, function (err) {
lambda._cleanDirectory(codeDirectory, function (err) {
if (err) {
return done(err);
}
done();

lambda._rsync(program, codeDirectory, function (err) {
if (err) {
return done(err);
}
done();
});
});
});

Expand All @@ -92,7 +134,7 @@ describe('node-lambda', function () {
lambda._npmInstall(program, codeDirectory, function (err, result) {
var contents = fs.readdirSync(codeDirectory);

result = _.includes(contents, 'index.js');
result = _.includes(contents, 'node_modules');
assert.equal(result, true);

done();
Expand All @@ -103,15 +145,21 @@ describe('node-lambda', function () {
describe('_zip', function () {
beforeEach(function (done) {
this.timeout(30000); // give it time to build the node modules
lambda._rsync(program, codeDirectory, function (err) {
lambda._cleanDirectory(codeDirectory, function (err) {
if (err) {
return done(err);
}
lambda._npmInstall(program, codeDirectory, function (err) {

lambda._rsync(program, codeDirectory, function (err) {
if (err) {
return done(err);
}
done();
lambda._npmInstall(program, codeDirectory, function (err) {
if (err) {
return done(err);
}
done();
});
});
});
});
Expand Down