serverless/lib/plugins/aws/deploy-list.js
2024-05-19 23:22:40 -07:00

155 lines
4.9 KiB
JavaScript

import utils from '@serverlessinc/sf-core/src/utils.js';
import validate from './lib/validate.js';
import findAndGroupDeployments from './utils/find-and-group-deployments.js';
import setBucketName from './lib/set-bucket-name.js';
import ServerlessError from '../../serverless-error.js';
const { log, progress, writeText } = utils;
class AwsDeployList {
constructor(serverless, options, pluginUtils) {
this.serverless = serverless;
this.options = options || {};
this.provider = this.serverless.getProvider('aws');
this.logger = pluginUtils.log
this.progress = pluginUtils.progress
Object.assign(this, validate, setBucketName);
this.hooks = {
'before:deploy:list:log': () => this.validate(),
'before:deploy:list:functions:log': () => this.validate(),
'deploy:list:log': async () => {
await this.setBucketName();
await this.listDeployments();
},
'deploy:list:functions:log': async () => this.listFunctions(),
};
}
async listDeployments() {
this.progress.notice('Fetching deployments');
const service = this.serverless.service.service;
const stage = this.provider.getStage();
const prefix = this.provider.getDeploymentPrefix();
let response;
try {
response = await this.provider.request('S3', 'listObjectsV2', {
Bucket: this.bucketName,
Prefix: `${prefix}/${service}/${stage}`,
});
} catch (err) {
if (err.code === 'AWS_S3_LIST_OBJECTS_V2_ACCESS_DENIED') {
throw new ServerlessError(
'Could not list objects in the deployment bucket. Make sure you have sufficient permissions to access it.',
err.code
);
}
throw err;
}
const directoryRegex = new RegExp('(.+)-(.+-.+-.+)');
const deployments = findAndGroupDeployments(response, prefix, service, stage);
if (deployments.length === 0) {
log.aside(
"No deployments found, if that's unexpected ensure that stage and region are correct"
);
return;
}
this.progress.remove()
deployments.forEach((deployment) => {
const match = deployment[0].directory.match(directoryRegex);
const date = new Date(Date.parse(match[2]));
this.logger.notice(`${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1)
.padStart(2, 0)}-${String(date.getUTCDate()).padStart(2, 0)} ${String(date.getUTCHours()).padStart(2, 0)}:${String(date.getUTCMinutes())
.padStart(2, 0)}:${String(date.getUTCSeconds()).padStart(2, 0)} UTC`)
this.logger.aside(`Timestamp: ${match[1]}`);
this.logger.aside('Files:')
deployment.forEach((entry) => {
this.logger.aside(` - ${entry.file}`);
});
// If this is not the last item in the array, show blank line
if (deployment !== deployments[deployments.length - 1]) this.logger.blankLine();
});
}
// list all functions and their versions
async listFunctions() {
const funcs = await this.getFunctions();
const funcsVersions = await this.getFunctionVersions(funcs);
this.displayFunctions(funcsVersions);
}
async getFunctions() {
const funcs = this.serverless.service.getAllFunctionsNames();
const result = await Promise.all(
funcs.map((funcName) => {
const params = {
FunctionName: funcName,
};
return this.provider.request('Lambda', 'getFunction', params);
})
);
return result.map((item) => item.Configuration);
}
async getFunctionPaginatedVersions(params, totalVersions) {
const response = await this.provider.request('Lambda', 'listVersionsByFunction', params);
const Versions = (totalVersions || []).concat(response.Versions);
if (response.NextMarker) {
return this.getFunctionPaginatedVersions(
{ ...params, Marker: response.NextMarker },
Versions
);
}
return { Versions };
}
async getFunctionVersions(funcs) {
return Promise.all(
funcs.map((func) => {
const params = {
FunctionName: func.FunctionName,
};
return this.getFunctionPaginatedVersions(params);
})
);
}
displayFunctions(funcs) {
this.progress.remove()
funcs.forEach((func) => {
let name = func.Versions[0].FunctionName;
name = name.replace(`${this.serverless.service.service}-`, '');
name = name.replace(`${this.provider.getStage()}-`, '');
this.logger.notice(name);
const versionsLength = func.Versions.length;
const versions = func.Versions.map((funcEntry) => funcEntry.Version).slice(
Math.max(0, func.Versions.length - 5)
);
if (versionsLength < 6) this.logger.aside(` All Versions: ${versions.join(', ')}`);
else this.logger.aside(` Latest Versions: ${versions.join(', ')}`);
// If this is not the last item in the array, show blank line
if (func !== funcs[funcs.length - 1]) this.logger.blankLine();
});
}
}
export default AwsDeployList;