Skip to content
This repository has been archived by the owner on Jun 15, 2024. It is now read-only.

Commit

Permalink
Merge pull request #157 from agutoli/bug-fix/look-for-matching-layer
Browse files Browse the repository at this point in the history
Bug fix/look for matching layer
  • Loading branch information
agutoli authored Mar 8, 2024
2 parents 4fe97ad + 3c7c21a commit 660829b
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:

strategy:
matrix:
node-version: [12.x]
node-version: [16.x]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "serverless-layers",
"version": "2.8.3",
"version": "2.8.4",
"description": "",
"main": "lib/index.js",
"bugs": {
Expand Down
51 changes: 49 additions & 2 deletions src/aws/LayersService.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
const AbstractService = require('../AbstractService');

class LayersService extends AbstractService {
async publishVersion() {

descriptionWithVersionKey(versionKey) {
return 'created by serverless-layers plugin (' + versionKey + ')'
}

async publishVersion(versionKey) {
const params = {
Content: {
S3Bucket: this.bucketName,
S3Key: this.zipFileKeyName
},
LayerName: this.layerName,
Description: 'created by serverless-layers plugin',
Description: this.descriptionWithVersionKey(versionKey),

CompatibleRuntimes: this.plugin.settings.compatibleRuntimes,
CompatibleArchitectures: this.plugin.settings.compatibleArchitectures
Expand All @@ -22,6 +27,48 @@ class LayersService extends AbstractService {
});
}


async findVersionChecksumInList(versionKey, marker) {
const params = {
LayerName: this.layerName,
// TODO: Question: is layer name specific enough? Is there a way to deploy multiple runtime architectures per name?
// CompatibleRuntime: this.plugin.settings.compatibleRuntimes,
// CompatibleArchitecture: this.plugin.settings.compatibleArchitectures
};

if (marker) {
params.Marker = marker;
}

const result = await this.awsRequest('Lambda:listLayerVersions', params, { checkError: true });

const description = this.descriptionWithVersionKey(versionKey);

const matchingLayerVersion = result.LayerVersions.find((layer) => layer.Description === description);
if (matchingLayerVersion) {
return matchingLayerVersion.LayerVersionArn;
} else if (result.NextMarker) {
return this.findVersionChecksumInList(versionKey, result.NextMarker);
} else {
return null;
}
}

async checkLayersForVersionKey(versionKey) {
this.plugin.log('Looking for version with "' + versionKey + '"');
const layerVersionArn = await this.findVersionChecksumInList(versionKey);

if (layerVersionArn) {
return layerVersionArn;
// TODO: double-check to confirm layer content is as expected
// const params = { arn: layerVersionArn }
// const matchingLayerWithContent = await this.awsRequest('Lambda:getLayerVersionByArn', params, { checkError: true });
// if (matchingLayerWithContent) {
// matchingLayerWithContent.Content.Location // A link to the layer archive in Amazon S3 that is valid for 10 minutes.
// }
}
}

async cleanUpLayers(retainVersions = 0) {
const params = {
LayerName: this.layerName
Expand Down
18 changes: 13 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,16 @@ class ServerlessLayers {
// merge package default options
this.mergePackageOptions();

// It returns the layer arn if exists.
const existentLayerArn = await this.getLayerArn();
let existentLayerArn = '';
const versionKey =
(this.runtimes.getDependenciesChecksum()) +
(this.settings.customHash ? '.' + this.settings.customHash : '');

// If nothing has changed, confirm layer with same checksum
if (!verifyChanges) {
this.log('Checking if layer already exists...')
existentLayerArn = await this.layersService.checkLayersForVersionKey(versionKey);
}

// It improves readability
const skipInstallation = (
Expand Down Expand Up @@ -338,7 +346,7 @@ class ServerlessLayers {

await this.zipService.package();
await this.bucketService.uploadZipFile();
const version = await this.layersService.publishVersion();
const version = await this.layersService.publishVersion(versionKey);
await this.bucketService.putFile(this.dependencies.getDepsPath());

this.relateLayerWithFunctions(version.LayerVersionArn);
Expand Down Expand Up @@ -563,7 +571,7 @@ class ServerlessLayers {
let pattern = /arn:aws:lambda:([^:]+):([0-9]+):layer:([^:]+):([0-9]+)/g;
let region = chalk.bold('$1');
let name = chalk.magenta('$3');
let formated = chalk.white(`arn:aws:lambda:${region}:*********:${name}:$4`);
let formatted = chalk.white(`arn:aws:lambda:${region}:*********:${name}:$4`);

let text = "";
switch (typeof arn) {
Expand All @@ -580,7 +588,7 @@ class ServerlessLayers {
text = String(arn);
break;
}
return text.replace(pattern, formated);
return text.replace(pattern, formatted);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/runtimes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ class Runtimes {
hasDependenciesChanges() {
return this._runtime.hasDependenciesChanges();
}

getDependenciesChecksum() {
return this._runtime.getDependenciesChecksum();
}
}

module.exports = Runtimes;
7 changes: 6 additions & 1 deletion src/runtimes/nodejs.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const path = require('path');
const crypto = require('crypto');

class NodeJSRuntime {
constructor(parent, runtime, runtimeDir) {
Expand All @@ -9,7 +10,7 @@ class NodeJSRuntime {
runtime,
runtimeDir,
libraryFolder: 'node_modules',
packageManager: 'npm',
packageManager: 'npm',
packageManagerExtraArgs: '',
dependenciesPath: 'package.json',
compatibleRuntimes: [runtimeDir],
Expand Down Expand Up @@ -123,6 +124,10 @@ class NodeJSRuntime {

return isDifferent;
}

getDependenciesChecksum() {
return crypto.createHash('md5').update(JSON.stringify(this.localPackage.dependencies)).digest('hex');
}
}

module.exports = NodeJSRuntime;
7 changes: 6 additions & 1 deletion src/runtimes/python.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

class PythonRuntime {
constructor(parent, runtime, runtimeDir) {
Expand All @@ -10,7 +11,7 @@ class PythonRuntime {
runtime,
runtimeDir,
libraryFolder: 'site-packages',
packageManager: 'pip',
packageManager: 'pip',
packageManagerExtraArgs: '',
dependenciesPath: 'requirements.txt',
compatibleRuntimes: [runtime],
Expand Down Expand Up @@ -78,6 +79,10 @@ class PythonRuntime {

return isDifferent;
}

getDependenciesChecksum() {
return crypto.createHash('md5').update(JSON.stringify(this.localPackage)).digest('hex');
}
}

module.exports = PythonRuntime;
8 changes: 6 additions & 2 deletions src/runtimes/ruby.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fs = require('fs');
const path = require('path');

const crypto = require('crypto');

class RubyRuntime {
constructor(parent, runtime, runtimeDir) {
Expand All @@ -11,7 +11,7 @@ class RubyRuntime {
runtime,
runtimeDir,
libraryFolder: 'gems',
packageManager: 'bundle',
packageManager: 'bundle',
packageManagerExtraArgs: '',
dependenciesPath: 'Gemfile',
compatibleRuntimes: [runtime],
Expand Down Expand Up @@ -86,6 +86,10 @@ class RubyRuntime {

return isDifferent;
}

getDependenciesChecksum() {
return crypto.createHash('md5').update(JSON.stringify(this.localPackage)).digest('hex');
}
}

module.exports = RubyRuntime;

0 comments on commit 660829b

Please sign in to comment.