UNPKG

7.99 kBJavaScriptView Raw
1/**
2 * Defines the ServerlessConfigGenerator class.
3 *
4 * @author Luke Chavers <luke@c2cschools.com>
5 * @author Kevin Sanders <kevin@c2cschools.com>
6 * @since 5.1.15
7 * @license See LICENSE.md for details about licensing.
8 * @copyright 2017 C2C Schools, LLC
9 */
10
11"use strict";
12
13const BaseGenerator = require( "../util/BaseGenerator" );
14
15/**
16 * This class is used for the automatic generation of a Serverless config file
17 * which is consumed by Serverless during the deployment of services and other
18 * Serverless Framework powered operations.
19 *
20 * @memberOf Serverless
21 * @extends Util.BaseGenerator
22 */
23class ServerlessConfigGenerator extends BaseGenerator {
24
25 // noinspection JSMethodCanBeStatic
26 /**
27 * Defines a static mapping that this generator uses to create each part of
28 * the exported Serverless config. This variable/property is used,
29 * exclusively, by the `configExports` property.
30 *
31 * @see configExports
32 * @private
33 * @type {Object}
34 * @readonly
35 */
36 get _configMethodMap() {
37
38 return [
39 {
40 property : "custom",
41 methodName : "buildCustomConfig",
42 },
43 {
44 property : "package",
45 methodName : "buildPackageConfig",
46 },
47 {
48 property : "plugins",
49 methodName : "buildPluginsConfig",
50 },
51 {
52 property : "provider",
53 methodName : "buildProviderConfig",
54 },
55 {
56 property : "functions",
57 methodName : "buildFunctionsConfig",
58 },
59 ];
60 }
61
62 /**
63 * The object that should be exported by implementing scripts in order to
64 * allow the Serverless Framework access to the configuration data generated
65 * by this generator.
66 *
67 * @example
68 * ```
69 * module.exports = configGenerator.configExports;
70 * ```
71 *
72 * @see https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-variables-in-javascript-files
73 * @public
74 * @type {Object}
75 * @readonly
76 */
77 get configExports() {
78
79 const me = this;
80
81 // Dependencies
82 const _ = me.$dep( "lodash" );
83
84 let fnMap = me._configMethodMap;
85
86 // Init Return
87 let ret = {};
88
89 // Create each export property
90 _.each( fnMap, function ( mapping ) {
91
92 ret[ mapping.property ] = me[ mapping.methodName ].bind( me );
93 } );
94
95 // Finished
96 return ret;
97 }
98
99 /**
100 * A debugging function that can be used to dump the configuration data that
101 * is being generated by this config generator.
102 *
103 * @public
104 * @returns {void}
105 */
106 dumpConfigExports() {
107
108 const me = this;
109
110 // Dependencies
111 const _ = me.$dep( "lodash" );
112
113 let resolvedConfig = {};
114
115 // Create a "DebugHelper"...
116 let deb = me.$spawn( "commonLib", "util/DebugHelper" );
117
118 // Resolve all config data...
119 _.each( me.configExports, function ( val, key ) {
120
121 if ( _.isFunction( val ) ) {
122
123 resolvedConfig[ key ] = val();
124
125 } else {
126
127 resolvedConfig[ key ] = val;
128 }
129 } );
130
131 // Dump the config data
132 deb.dbg( resolvedConfig, true, 1 );
133 }
134
135 /**
136 * Generates the entire serverless config and returns it as an object.
137 *
138 * @returns {Promise<Object>} Serverless config.
139 */
140 buildConfig() {
141
142 const me = this;
143
144 // Dependencies
145 const BB = me.$dep( "bluebird" );
146
147 return BB.props( {
148 service : me.buildServiceConfig(),
149 provider : me.buildProviderConfig(),
150 package : me.buildPackageConfig(),
151 plugins : me.buildPluginsConfig(),
152 custom : me.buildCustomConfig(),
153 functions : me.buildFunctionsConfig(),
154 } );
155 }
156
157 /**
158 * A specialist method that generates the 'service:' portion of the
159 * Serverless config (`serverless.yml`).
160 *
161 * This method will simply load a common Serverless config file
162 * (e.g. `serverless/config/default/provider.yml`) and return it.
163 *
164 * @public
165 * @returns {Object} The 'service:' portion of the Serverless config.
166 */
167 buildServiceConfig() {
168
169 const me = this;
170
171 return {
172 name: me.serviceName,
173 };
174 }
175
176 /**
177 * A specialist method that generates the 'custom:' portion of the
178 * Serverless config (`serverless.yml`).
179 *
180 * This method will simply load a common Serverless config file
181 * (e.g. `serverless/config/default/custom.yml`) and return it.
182 *
183 * Note: Although, in theory, this type of 'common config loading' could be
184 * skipped using the `${file:...}` syntax that Serverless allows, the
185 * specific, absolute, path is not always known to Serverless. So, this
186 * generator allows the Node.js `require` function to assist in the
187 * resolution of paths...
188 *
189 * @public
190 * @returns {Object} The 'custom:' portion of the Serverless config.
191 */
192 buildCustomConfig() {
193
194 const me = this;
195
196 return me._loadCommonConfigFile( "custom.yml", "custom" );
197 }
198
199 /**
200 * A specialist method that generates the 'plugins:' portion of the
201 * Serverless config (`serverless.yml`).
202 *
203 * This method will simply load a common Serverless config file
204 * (e.g. `serverless/config/default/plugins.yml`) and return it.
205 *
206 * See the note in {@link Serverless#buildCustomConfig} which also applies
207 * to this method.
208 *
209 * @public
210 * @returns {Object} The 'plugins:' portion of the Serverless config.
211 */
212 buildPluginsConfig() {
213
214 const me = this;
215
216 return me._loadCommonConfigFile( "plugins.yml", "plugins" );
217 }
218
219 /**
220 * A specialist method that generates the 'package:' portion of the
221 * Serverless config (`serverless.yml`).
222 *
223 * This method will simply load a common Serverless config file
224 * (e.g. `serverless/config/default/package.yml`) and return it.
225 *
226 * See the note in {@link Serverless#buildCustomConfig} which also applies
227 * to this method.
228 *
229 * @public
230 * @returns {Object} The 'package:' portion of the Serverless config.
231 */
232 buildPackageConfig() {
233
234 const me = this;
235
236 return me._loadCommonConfigFile( "package.yml", "package" );
237 }
238
239 /**
240 * A specialist method that generates the 'provider:' portion of the
241 * Serverless config (`serverless.yml`).
242 *
243 * This method will load a common Serverless config file
244 * (e.g. `serverless/config/default/provider.yml`) and then apply decrypted
245 * environment variables from KmsCrypt to the provider object and return it.
246 *
247 * See the note in {@link Serverless#buildCustomConfig} which also applies
248 * to this method.
249 *
250 * @public
251 * @returns {Object} The 'provider:' portion of the Serverless config.
252 */
253 buildProviderConfig() {
254
255 const me = this;
256
257 // Dependencies
258 const _ = me.$dep( "lodash" );
259 const BB = me.$dep( "bluebird" );
260 const YAML = me.$dep( "js-yaml" );
261 const KmsCrypt = me.$dep( "util/kms-crypt" );
262
263 let providerConfig;
264
265 return BB.try( function () {
266
267 return me._loadCommonConfigFile( "provider.yml", "provider" );
268
269 } ).then( function ( _providerConfig ) {
270
271 providerConfig = _providerConfig;
272
273 return KmsCrypt.decryptFromS3( me.kmsCryptConfig );
274
275 } ).then( function ( decryptedData ) {
276
277 let config = YAML.safeLoad( decryptedData );
278
279 // TODO: determine correct deployment environment (production/development).
280 let deploymentEnvironment = "production";
281
282 _.assign( providerConfig.environment, config[ deploymentEnvironment ].environment );
283
284 return providerConfig;
285 } );
286 }
287
288 /**
289 * A specialist method that generates the 'functions:' portion of the
290 * Serverless config (`serverless.yml`).
291 *
292 * This method will concatenate the function configuration data, defined
293 * in each endpoint's `config/serverless-function.yml` file, from
294 * all endpoints in the target service and return the resulting object.
295 *
296 * @public
297 * @returns {Object} The 'functions:' portion of the Serverless config.
298 */
299 buildFunctionsConfig() {
300
301 const me = this;
302
303 // Dependencies
304 const _ = me.$dep( "lodash" );
305
306 // Build information about all endpoints
307 // in the target service...
308 let eps = me.getServiceEndpoints();
309
310 // Init the return object
311 let ret = {};
312
313 // Iterate over each endpoint and add its
314 // function config to the return
315 _.each( eps, function ( epData, epName ) {
316
317 ret[ epName ] = epData.functionConfig;
318 } );
319
320 // All done
321 return ret;
322 }
323}
324
325module.exports = ServerlessConfigGenerator;