mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
141 lines
3.4 KiB
JavaScript
141 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const AWS = require('aws-sdk');
|
|
const https = require('https');
|
|
const url = require('url');
|
|
|
|
const logger = console;
|
|
|
|
function response(event, context, status, data = {}, err) {
|
|
const reason = err ? err.message : '';
|
|
const { StackId, RequestId, LogicalResourceId, PhysicalResourceId, ResponseURL } = event;
|
|
|
|
const body = JSON.stringify({
|
|
StackId,
|
|
RequestId,
|
|
LogicalResourceId,
|
|
PhysicalResourceId,
|
|
Status: status,
|
|
Reason: reason && `${reason} See details in CloudWatch Log: ${context.logStreamName}`,
|
|
Data: data,
|
|
});
|
|
|
|
logger.log(body);
|
|
|
|
const parsedUrl = url.parse(ResponseURL);
|
|
const options = {
|
|
hostname: parsedUrl.hostname,
|
|
port: 443,
|
|
path: parsedUrl.path,
|
|
method: 'PUT',
|
|
headers: {
|
|
'Content-Type': '',
|
|
'Content-Length': body.length,
|
|
},
|
|
};
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const request = https.request(options, resp => {
|
|
logger.log(`STATUS: ${resp.statusCode}`);
|
|
logger.log(`HEADERS: ${JSON.stringify(resp.headers)}`);
|
|
return resolve(data);
|
|
});
|
|
|
|
request.on('error', error => {
|
|
logger.log(`sendResponse Error:\n${error}`);
|
|
return reject(error);
|
|
});
|
|
|
|
request.on('end', () => {
|
|
logger.log('end');
|
|
return resolve();
|
|
});
|
|
|
|
request.write(body);
|
|
request.end();
|
|
});
|
|
}
|
|
|
|
function getLambdaArn(partition, region, accountId, functionName) {
|
|
return `arn:${partition}:lambda:${region}:${accountId}:function:${functionName}`;
|
|
}
|
|
|
|
function getEnvironment(context) {
|
|
const arn = context.invokedFunctionArn.match(
|
|
/^arn:(aws[\w-]*).*:lambda:([\w+-]{2,}\d+):(\d+):function:(.*)$/
|
|
);
|
|
|
|
return {
|
|
LambdaArn: arn[0],
|
|
Partition: arn[1],
|
|
Region: arn[2],
|
|
AccountId: arn[3],
|
|
LambdaName: arn[4],
|
|
};
|
|
}
|
|
|
|
function handlerWrapper(handler, PhysicalResourceId) {
|
|
return (event, context, callback) => {
|
|
// extend the `event` object to include the PhysicalResourceId
|
|
event = Object.assign({}, event, { PhysicalResourceId });
|
|
return Promise.resolve(handler(event, context, callback))
|
|
.then(
|
|
result => response(event, context, 'SUCCESS', result),
|
|
error => response(event, context, 'FAILED', {}, error)
|
|
)
|
|
.then(result => callback(null, result), callback);
|
|
};
|
|
}
|
|
|
|
function wait(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
const MAX_AWS_REQUEST_TRY = (() => {
|
|
const DEFAULT_MAX_AWS_REQUEST_TRY = 8;
|
|
const userValue = Number(process.env.SLS_AWS_REQUEST_MAX_RETRIES);
|
|
return userValue >= 0 ? userValue : DEFAULT_MAX_AWS_REQUEST_TRY;
|
|
})();
|
|
|
|
const getServiceInstance = nameInput => {
|
|
let name;
|
|
let params = {};
|
|
if (typeof nameInput === 'string') {
|
|
name = nameInput;
|
|
} else {
|
|
name = nameInput.name;
|
|
params = nameInput.params;
|
|
}
|
|
return new AWS[name](params);
|
|
};
|
|
|
|
async function awsRequest(service, method, ...args) {
|
|
const serviceInstance = getServiceInstance(service);
|
|
const callAws = async requestTry => {
|
|
try {
|
|
return await serviceInstance[method](...args).promise();
|
|
} catch (error) {
|
|
if (
|
|
requestTry < MAX_AWS_REQUEST_TRY &&
|
|
error &&
|
|
(error.statusCode === 429 || error.retryable)
|
|
) {
|
|
await wait(2000 + Math.random() * 1000);
|
|
return callAws(++requestTry);
|
|
}
|
|
throw error;
|
|
}
|
|
};
|
|
return callAws(1);
|
|
}
|
|
|
|
module.exports = {
|
|
logger,
|
|
response,
|
|
getEnvironment,
|
|
getLambdaArn,
|
|
handlerWrapper,
|
|
wait,
|
|
awsRequest,
|
|
};
|