mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
141 lines
4.4 KiB
JavaScript
141 lines
4.4 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('crypto');
|
|
const BbPromise = require('bluebird');
|
|
const _ = require('lodash');
|
|
const path = require('path');
|
|
|
|
class AwsCompileLayers {
|
|
constructor(serverless, options) {
|
|
this.serverless = serverless;
|
|
this.options = options;
|
|
const servicePath = this.serverless.config.servicePath || '';
|
|
this.packagePath =
|
|
this.serverless.service.package.path || path.join(servicePath || '.', '.serverless');
|
|
|
|
this.provider = this.serverless.getProvider('aws');
|
|
|
|
this.hooks = {
|
|
'package:compileLayers': () => BbPromise.bind(this).then(this.compileLayers),
|
|
};
|
|
}
|
|
|
|
compileLayer(layerName) {
|
|
const newLayer = this.cfLambdaLayerTemplate();
|
|
const layerObject = this.serverless.service.getLayer(layerName);
|
|
layerObject.package = layerObject.package || {};
|
|
|
|
const artifactFileName = this.provider.naming.getLayerArtifactName(layerName);
|
|
const artifactFilePath =
|
|
layerObject.package && layerObject.package.artifact
|
|
? layerObject.package.artifact
|
|
: path.join(this.serverless.config.servicePath, '.serverless', artifactFileName);
|
|
|
|
if (this.serverless.service.package.deploymentBucket) {
|
|
newLayer.Properties.Content.S3Bucket = this.serverless.service.package.deploymentBucket;
|
|
}
|
|
|
|
const s3Folder = this.serverless.service.package.artifactDirectoryName;
|
|
const s3FileName = artifactFilePath.split(path.sep).pop();
|
|
newLayer.Properties.Content.S3Key = `${s3Folder}/${s3FileName}`;
|
|
|
|
newLayer.Properties.LayerName = layerObject.name || layerName;
|
|
if (layerObject.description) {
|
|
newLayer.Properties.Description = layerObject.description;
|
|
}
|
|
if (layerObject.licenseInfo) {
|
|
newLayer.Properties.LicenseInfo = layerObject.licenseInfo;
|
|
}
|
|
if (layerObject.compatibleRuntimes) {
|
|
newLayer.Properties.CompatibleRuntimes = layerObject.compatibleRuntimes;
|
|
}
|
|
|
|
let layerLogicalId = this.provider.naming.getLambdaLayerLogicalId(layerName);
|
|
if (layerObject.retain) {
|
|
const sha = crypto
|
|
.createHash('sha1')
|
|
.update(JSON.stringify(_.omit(newLayer, ['Properties.Content.S3Key'])))
|
|
.digest('hex');
|
|
layerLogicalId = `${layerLogicalId}${sha}`;
|
|
newLayer.DeletionPolicy = 'Retain';
|
|
}
|
|
const newLayerObject = {
|
|
[layerLogicalId]: newLayer,
|
|
};
|
|
|
|
if (layerObject.allowedAccounts) {
|
|
layerObject.allowedAccounts.map(account => {
|
|
let parsedAccount = account;
|
|
// cast to string if account is number
|
|
if (typeof account === 'number' && !isNaN(account)) {
|
|
parsedAccount = `${account}`;
|
|
}
|
|
const newPermission = this.cfLambdaLayerPermissionTemplate();
|
|
newPermission.Properties.LayerVersionArn = { Ref: layerLogicalId };
|
|
newPermission.Properties.Principal = parsedAccount;
|
|
const layerPermLogicalId = this.provider.naming.getLambdaLayerPermissionLogicalId(
|
|
layerName,
|
|
parsedAccount
|
|
);
|
|
newLayerObject[layerPermLogicalId] = newPermission;
|
|
return newPermission;
|
|
});
|
|
}
|
|
|
|
_.merge(
|
|
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
|
newLayerObject
|
|
);
|
|
|
|
// Add layer to Outputs section
|
|
const layerOutputLogicalId = this.provider.naming.getLambdaLayerOutputLogicalId(layerName);
|
|
const newLayerOutput = this.cfOutputLayerTemplate();
|
|
|
|
newLayerOutput.Value = { Ref: layerLogicalId };
|
|
|
|
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, {
|
|
[layerOutputLogicalId]: newLayerOutput,
|
|
});
|
|
}
|
|
|
|
compileLayers() {
|
|
const allLayers = this.serverless.service.getAllLayers();
|
|
return BbPromise.each(allLayers, layerName => this.compileLayer(layerName));
|
|
}
|
|
|
|
cfLambdaLayerTemplate() {
|
|
return {
|
|
Type: 'AWS::Lambda::LayerVersion',
|
|
Properties: {
|
|
Content: {
|
|
S3Bucket: {
|
|
Ref: 'ServerlessDeploymentBucket',
|
|
},
|
|
S3Key: 'S3Key',
|
|
},
|
|
LayerName: 'LayerName',
|
|
},
|
|
};
|
|
}
|
|
|
|
cfLambdaLayerPermissionTemplate() {
|
|
return {
|
|
Type: 'AWS::Lambda::LayerVersionPermission',
|
|
Properties: {
|
|
Action: 'lambda:GetLayerVersion',
|
|
LayerVersionArn: 'LayerVersionArn',
|
|
Principal: 'Principal',
|
|
},
|
|
};
|
|
}
|
|
|
|
cfOutputLayerTemplate() {
|
|
return {
|
|
Description: 'Current Lambda layer version',
|
|
Value: 'Value',
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = AwsCompileLayers;
|