Skip to content

Commit a796584

Browse files
committed
Added unit tests and slight refactoring
1 parent d095768 commit a796584

File tree

5 files changed

+1054
-38
lines changed

5 files changed

+1054
-38
lines changed

.editorconfig

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
root = true
2+
3+
[*.js]
4+
indent_style = space
5+
indent_size = 2
6+
7+
[Makefile]
8+
indent_style = tab

LayerManagerPlugin.js

+62-37
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
const {
2+
LOG_LEVEL = 'info'
3+
} = process.env;
4+
15
const {execSync} = require('child_process');
26
const pascalcase = require('pascalcase');
37
const fs = require('fs');
@@ -9,71 +13,85 @@ const DEFAULT_CONFIG = {
913
exportPrefix: '${AWS::StackName}-'
1014
};
1115

12-
function getLayers(serverless) {
13-
return serverless.service.layers || {};
14-
}
15-
16-
function getConfig(serverless) {
17-
const custom = serverless.service.custom || {};
18-
19-
return {...DEFAULT_CONFIG, ...custom.layerConfig};
20-
}
16+
const LEVELS = {
17+
none: 0,
18+
info: 1,
19+
verbose: 2
20+
};
2121

2222
function log(...s) {
2323
console.log('[layer-manager]', ...s);
2424
}
2525

2626
function verbose({level}, ...s) {
27-
level === 'verbose' && log(...s);
27+
LEVELS[level] >= LEVELS.verbose && log(...s);
2828
}
2929

3030
function info({level}, ...s) {
31-
log(...s);
31+
LEVELS[level] >= LEVELS.info && log(...s);
3232
}
3333

34+
function getLayers(serverless) {
35+
return serverless.service.layers || {};
36+
}
37+
38+
function getConfig(serverless) {
39+
const custom = serverless.service.custom || {};
40+
41+
return {...DEFAULT_CONFIG, ...custom.layerConfig};
42+
}
3443

3544
class LayerManagerPlugin {
3645
constructor(sls, options = {}) {
37-
this.level = options.v || options.verbose ? 'verbose' : 'info';
46+
this.level = options.v || options.verbose ? 'verbose' : LOG_LEVEL;
47+
this.config = getConfig(sls);
3848

3949
info(this, `Invoking layer-manager plugin`);
50+
verbose(this, `Config: `, this.config);
4051

4152
this.hooks = {
4253
'package:initialize': () => this.installLayers(sls),
4354
'before:deploy:deploy': () => this.transformLayerResources(sls)
4455
};
4556
}
4657

58+
installLayer(path) {
59+
const nodeLayerPath = `${path}/nodejs`;
60+
61+
if (fs.existsSync(nodeLayerPath)) {
62+
verbose(this, `Installing nodejs layer ${path}`);
63+
execSync(`npm install --prefix ${nodeLayerPath}`, {
64+
stdio: 'inherit'
65+
});
66+
return true;
67+
}
68+
69+
return false;
70+
}
71+
4772
installLayers(sls) {
48-
const config = getConfig(sls);
73+
const {installLayers} = this.config;
4974

50-
if (!config.installLayers) {
75+
if (!installLayers) {
76+
verbose(this, `Skipping installation of layers as per config`);
5177
return;
5278
}
5379

5480
const layers = getLayers(sls);
55-
let i = 0;
56-
Object.values(layers).forEach(({path}) => {
57-
const nodeLayerPath = `${path}/nodejs`;
58-
59-
if (fs.existsSync(nodeLayerPath)) {
60-
verbose(this, `Installing nodejs layer ${path}`);
61-
execSync(`npm install --prefix ${nodeLayerPath}`, {
62-
stdio: 'inherit'
63-
});
64-
i++;
65-
}
66-
});
81+
const installedLayers = Object.values(layers)
82+
.filter(({path}) => this.installLayer(path));
83+
84+
info(this, `Installed ${installedLayers.length} layers`);
6785

68-
info(this, `Installed ${i} layers`);
86+
return {installedLayers};
6987
}
7088

7189
transformLayerResources(sls) {
72-
const config = getConfig(sls);
90+
const {exportLayers, exportPrefix, upgradeLayerReferences} = this.config;
7391
const layers = getLayers(sls);
7492
const {compiledCloudFormationTemplate: cf} = sls.service.provider;
7593

76-
Object.keys(layers).forEach(id => {
94+
return Object.keys(layers).reduce((result, id) => {
7795
const name = pascalcase(id);
7896
const exportName = `${name}LambdaLayerQualifiedArn`;
7997
const output = cf.Outputs[exportName];
@@ -82,28 +100,30 @@ class LayerManagerPlugin {
82100
return;
83101
}
84102

85-
if (config.exportLayers) {
103+
if (exportLayers) {
86104
output.Export = {
87105
Name: {
88-
'Fn::Sub': config.exportPrefix + exportName
106+
'Fn::Sub': exportPrefix + exportName
89107
}
90108
};
109+
result.exportedLayers.push(output);
91110
}
92111

93-
if (config.upgradeLayerReferences) {
112+
if (upgradeLayerReferences) {
94113
const resourceRef = `${name}LambdaLayer`;
95114
const versionedResourceRef = output.Value.Ref;
96115

97116
if (resourceRef !== versionedResourceRef) {
98117
info(this, `Replacing references to ${resourceRef} with ${versionedResourceRef}`);
99118

100119
Object.entries(cf.Resources)
101-
.forEach(([id, {Type, Properties: {Layers = []} = {}}]) => {
102-
if (Type === 'AWS::Lambda::Function') {
103-
Layers.forEach(Layer => {
104-
if (Layer.Ref === resourceRef) {
120+
.forEach(([id, {Type: type, Properties: {Layers: layers = []} = {}}]) => {
121+
if (type === 'AWS::Lambda::Function') {
122+
layers.forEach(layer => {
123+
if (layer.Ref === resourceRef) {
105124
verbose(this, `${id}: Updating reference to layer version ${versionedResourceRef}`);
106-
Layer.Ref = versionedResourceRef;
125+
layer.Ref = versionedResourceRef;
126+
result.upgradedLayerReferences.push(layer);
107127
}
108128
})
109129
}
@@ -112,6 +132,11 @@ class LayerManagerPlugin {
112132
}
113133

114134
verbose(this, 'CF after transformation:\n', JSON.stringify(cf, null, 2));
135+
136+
return result;
137+
}, {
138+
exportedLayers: [],
139+
upgradedLayerReferences: []
115140
});
116141
}
117142
}

0 commit comments

Comments
 (0)