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 | ;
|
12 |
|
13 | const 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 | */
|
23 | class 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 |
|
325 | module.exports = ServerlessConfigGenerator;
|