-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathindex.js
136 lines (119 loc) · 4.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/**
* @fileOverview Expose a programmatic interface for using Lambda Complex.
*/
// Core.
var util = require('util');
// NPM.
var async = require('async');
var Janitor = require('cloudwatch-logs-janitor');
var fs = require('fs-extra');
// Local.
var common = require('./lib/build/common');
var configValidator = require('./lib/build/configValidator');
var installUtilities = require('./lib/build/installUtilities');
var packageUtilities = require('./lib/build/packageUtilities');
var cloudFormationTemplateUtilities = require('./lib/build/cloudFormationTemplateUtilities');
var cloudFormationUtilities = require('./lib/deploy/cloudFormationUtilities');
var s3Utilities = require('./lib/deploy/s3Utilities');
/**
* Build a Lambda Complex application.
*
* @param {Object} config The application configuration.
* @param {Function} callback Of the form function (error).
*/
exports.build = function (config, callback) {
// Validate the configuration first of all.
var results = configValidator.validate(config);
if (results.length) {
return callback(new Error(util.format(
'Invalid configuration: %s',
JSON.stringify(results, null, ' ')
)));
}
async.series({
// Clear out the build directory for this application.
clean: function (asyncCallback) {
fs.remove(common.getApplicationBuildDirectory(config), asyncCallback);
},
// Download or copy the NPM packages containing Lambda function handlers.
install: function (asyncCallback) {
installUtilities.installLambdaFunctions(config, asyncCallback);
},
// Zip up the NPM packages.
package: function (asyncCallback) {
packageUtilities.packageLambdaFunctions(config, asyncCallback);
},
// Create the CloudFormation template for this application deployment.
generateCloudFormationTemplate: function (asyncCallback) {
cloudFormationTemplateUtilities.generateTemplate(config, asyncCallback);
}
}, callback);
};
/**
* Build and deploy a Lambda Complex application.
*
* @param {Object} config The application configuration.
* @param {Function} callback Of the form function (error, results).
*/
exports.deploy = function (config, callback) {
var startTime = new Date();
var results;
async.series({
// Run the build task.
build: function (asyncCallback) {
exports.build(config, asyncCallback);
},
// Take the packaged Lambda functions and upload them to S3.
uploadLambdaFunctions: function (asyncCallback) {
s3Utilities.uploadLambdaFunctions(config, asyncCallback);
},
// Upload the configuration to S3.
//
// The application doesn't use this config file instance, rather loading
// config files from the packages, but keeping a record of it in S3
// alongside the other files for each deployment seems like a smart idea.
uploadConfig: function (asyncCallback) {
s3Utilities.uploadConfig(config, asyncCallback);
},
// Now on to the actual CloudFormation deployment, including the activities
// needed to switch over resources to use the new application, and deletion
// of old stacks.
deployCloudFormationStack: function (asyncCallback) {
cloudFormationUtilities.deployStack(config, function (error, _results) {
results = _results;
asyncCallback(error);
});
},
// Every Lambda function generates a CloudWatch log group, and this can
// build up clutter pretty quickly during development. Some people may
// prefer to keep the old groups around for production deployments.
deletePriorCloudwatchLogGroups: function (asyncCallback) {
if (config.deployment.skipPriorCloudWatchLogGroupsDeletion) {
return asyncCallback();
}
// This will use AWS config from the environment, like the rest of Lambda
// Complex.
var janitor = new Janitor();
janitor.deleteMatchingLogGroups({
// Using this should be sufficient to avoid deleting log groups for
// the just-deployed Lambda functions.
createdBefore: startTime,
// Lambda function log groups for this application will have names that
// begin with this prefix.
prefix: '/aws/lambda/' + config.name + '-'
}, function (error) {
// Cleaning up old log groups may require a bunch of API requests, and
// these have in the past proven to be somewhat flaky and/or subject to
// very low throttling levels. Failure here isn't critical, as anything
// that is missed will be addressed by the next deployment. So just add
// the error to the results.
if (error) {
results.cloudWatchLogDeletionError = error;
}
asyncCallback();
});
}
}, function (error) {
callback(error, results);
});
};