codepipeline.putJobSuccessResult() 从 VPC 调用 Lambda 时挂起
codepipeline.putJobSuccessResult() Hanging when Invoking a Lambda from VPC
更新:
经过多次试验和磨难,我确定 [nodejs8.1 运行time] 下面的代码是一个基本的 CodePipeline 设置,没有额外的代码,在正常调用 Lambda 时工作正常,但如果有人尝试从 VPC 中调用 Lambda,codepipeline.putJobSuccessResult()
挂起并且 Lambda 超时。在调用 运行 之前出现的任何代码都很好,但它不会 运行 codepipeline.putJobSuccessResult()
并给 CodePipeline 一个适当的 return 值,尽管代码管道和 Lambda具有具有各种策略和信任关系的角色,并且 VPC 具有许多端点以及 NAT 网关和 Internet 网关。这导致 CodePipeline 不断重试,直到超时期限(~15 分钟)。
另请注意,在将 Lambda 添加到 CodePipeline 并添加端点之前,我手动 运行 设置了 Lambda 并通过 NAT => Internet 网关成功利用静态 IP(https://medium.com/@matthewleak/aws-lambda-functions-with-a-static-ip-89a3ada0b471 ) 再一次,即使在 CodePipeline 中,Lambda 运行 也很好,直到它使用 AWS SDK aws.CodePipeline.putJobSuccessResult()
/aws.CodePipeline.putJobFailureResult()
函数;所有其他代码都已成功执行。
理论上,要重现,只需使用下面的代码创建一个 Lambda,按照上文所述设置一个 VPC,设置一个基本的 CodePipeline 并将 Lambda 作为管道的一部分调用。第一个 运行 通过应该工作正常。然后将 Lambda 分配给 VPC 和子网,然后再次 运行 管道并查看它在尝试 putJobSuccessResult 时是否没有挂起。
挂起的行为意味着它是一个网络问题,但是如果 CodePipeline 有一个到 VPC 的端点并且能够成功调用 Lambda,为什么 Lambda 不能与 CodePipeline 对话 putJobSuccessResult/putJobFailureResult?我的猜测是我在 VPC 方面遗漏了一些东西,或者 CodePipeline 无法正常工作 and/or 正确利用其端点 -- 但我想弄明白。
// Working Base response code for CodePipeline
'use strict';
const aws = require('aws-sdk');
const codepipeline = new aws.CodePipeline();
let environment = 'dev';
let callback;
let context = {
invokeid: ''
}
exports.handler = async (event, context, callback) => {
context = context;
callback = callback;
console.log('Inside deploy-website Lambda');
if (!('CodePipeline.job' in event)) {
return Promise.resolve();
}
// Retrieve the Job ID from the Lambda action
let jobId;
if (event["CodePipeline.job"]) {
jobId = event["CodePipeline.job"].id;
// Retrieve the value of UserParameters from the Lambda action configuration in AWS CodePipeline, in this case the environment
// to deploy to from this function
environment = event["CodePipeline.job"].data.actionConfiguration.configuration.UserParameters || environment;
}
console.log(`Envrionment: ${environment}`);
console.log('Copy Successful');
console.log('Entering Results');
return await putJobSuccess('Copy Successful', jobId);
}
// Notify AWS CodePipeline of a successful job
async function putJobSuccess(message, jobId) {
console.log(`Post Job Success For JobID: ${jobId}`);
const params = {
jobId: jobId
};
console.log(`Job Success Params: ${JSON.stringify(params)}`);
await codepipeline.putJobSuccessResult(params).promise();
console.log('Job Success: Successfully reported hook results');
return callback(null, 'Job Success: Successfully reported hook results');
}
使用 Lambda 的 Node 6/8 运行时,使用 Promises(甚至 async/await
语法)会更容易。
旧的 context.succeed()
/context.fail()
语法适用于旧的 Node 版本,并且已被弃用。
// Leave this outside your handler so you don't instantiate in every invocation.
const codepipeline = new aws.CodePipeline();
exports.handler = event => {
if (!('CodePipeline.job' in event)) {
return Promise.resolve();
}
const jobId = event['CodePipeline.job'].id;
const environment = event['CodePipeline.job'].data.actionConfiguration.configuration.UserParameters;
return doStuff
.then(() => putJobSuccess(message, jobId));
}
function putJobSuccess(message, jobId) {
console.log('Post Job Success For JobID: '.concat(jobId));
const params = {
jobId: jobId
};
return codepipeline.putJobSuccessResult(params).promise()
.then(() => {
console.log(`Post Job Success Succeeded Message: ${message}`);
return message;
})
.catch((err) => {
console.log(`Post Job Failure Message: ${message}`);
throw err;
});
}
原来是网络问题。看来是 VPC 路由 tables 吸引了我。当您创建一个路由 table 时,它会让您选择一个名称和一个 VPC 来关联它。我忘记做的是转到子网并将它们关联到 "Route Table" 选项卡 and/or 下的正确路由 table 我没有在其中一个上选择正确的路由,因为当你选择一个路由 table 与之关联,它不显示逻辑名称,只显示路由 table ID,这使得它更容易出错。因此,虽然这绝对是一个 "Newb" 错误 [如此愚蠢的错误造成如此多的痛苦],但我认为在关联路由 table 时的用户体验方面还有一些不足之处。
更新:
经过多次试验和磨难,我确定 [nodejs8.1 运行time] 下面的代码是一个基本的 CodePipeline 设置,没有额外的代码,在正常调用 Lambda 时工作正常,但如果有人尝试从 VPC 中调用 Lambda,codepipeline.putJobSuccessResult()
挂起并且 Lambda 超时。在调用 运行 之前出现的任何代码都很好,但它不会 运行 codepipeline.putJobSuccessResult()
并给 CodePipeline 一个适当的 return 值,尽管代码管道和 Lambda具有具有各种策略和信任关系的角色,并且 VPC 具有许多端点以及 NAT 网关和 Internet 网关。这导致 CodePipeline 不断重试,直到超时期限(~15 分钟)。
另请注意,在将 Lambda 添加到 CodePipeline 并添加端点之前,我手动 运行 设置了 Lambda 并通过 NAT => Internet 网关成功利用静态 IP(https://medium.com/@matthewleak/aws-lambda-functions-with-a-static-ip-89a3ada0b471 ) 再一次,即使在 CodePipeline 中,Lambda 运行 也很好,直到它使用 AWS SDK aws.CodePipeline.putJobSuccessResult()
/aws.CodePipeline.putJobFailureResult()
函数;所有其他代码都已成功执行。
理论上,要重现,只需使用下面的代码创建一个 Lambda,按照上文所述设置一个 VPC,设置一个基本的 CodePipeline 并将 Lambda 作为管道的一部分调用。第一个 运行 通过应该工作正常。然后将 Lambda 分配给 VPC 和子网,然后再次 运行 管道并查看它在尝试 putJobSuccessResult 时是否没有挂起。
挂起的行为意味着它是一个网络问题,但是如果 CodePipeline 有一个到 VPC 的端点并且能够成功调用 Lambda,为什么 Lambda 不能与 CodePipeline 对话 putJobSuccessResult/putJobFailureResult?我的猜测是我在 VPC 方面遗漏了一些东西,或者 CodePipeline 无法正常工作 and/or 正确利用其端点 -- 但我想弄明白。
// Working Base response code for CodePipeline
'use strict';
const aws = require('aws-sdk');
const codepipeline = new aws.CodePipeline();
let environment = 'dev';
let callback;
let context = {
invokeid: ''
}
exports.handler = async (event, context, callback) => {
context = context;
callback = callback;
console.log('Inside deploy-website Lambda');
if (!('CodePipeline.job' in event)) {
return Promise.resolve();
}
// Retrieve the Job ID from the Lambda action
let jobId;
if (event["CodePipeline.job"]) {
jobId = event["CodePipeline.job"].id;
// Retrieve the value of UserParameters from the Lambda action configuration in AWS CodePipeline, in this case the environment
// to deploy to from this function
environment = event["CodePipeline.job"].data.actionConfiguration.configuration.UserParameters || environment;
}
console.log(`Envrionment: ${environment}`);
console.log('Copy Successful');
console.log('Entering Results');
return await putJobSuccess('Copy Successful', jobId);
}
// Notify AWS CodePipeline of a successful job
async function putJobSuccess(message, jobId) {
console.log(`Post Job Success For JobID: ${jobId}`);
const params = {
jobId: jobId
};
console.log(`Job Success Params: ${JSON.stringify(params)}`);
await codepipeline.putJobSuccessResult(params).promise();
console.log('Job Success: Successfully reported hook results');
return callback(null, 'Job Success: Successfully reported hook results');
}
使用 Lambda 的 Node 6/8 运行时,使用 Promises(甚至 async/await
语法)会更容易。
旧的 context.succeed()
/context.fail()
语法适用于旧的 Node 版本,并且已被弃用。
// Leave this outside your handler so you don't instantiate in every invocation.
const codepipeline = new aws.CodePipeline();
exports.handler = event => {
if (!('CodePipeline.job' in event)) {
return Promise.resolve();
}
const jobId = event['CodePipeline.job'].id;
const environment = event['CodePipeline.job'].data.actionConfiguration.configuration.UserParameters;
return doStuff
.then(() => putJobSuccess(message, jobId));
}
function putJobSuccess(message, jobId) {
console.log('Post Job Success For JobID: '.concat(jobId));
const params = {
jobId: jobId
};
return codepipeline.putJobSuccessResult(params).promise()
.then(() => {
console.log(`Post Job Success Succeeded Message: ${message}`);
return message;
})
.catch((err) => {
console.log(`Post Job Failure Message: ${message}`);
throw err;
});
}
原来是网络问题。看来是 VPC 路由 tables 吸引了我。当您创建一个路由 table 时,它会让您选择一个名称和一个 VPC 来关联它。我忘记做的是转到子网并将它们关联到 "Route Table" 选项卡 and/or 下的正确路由 table 我没有在其中一个上选择正确的路由,因为当你选择一个路由 table 与之关联,它不显示逻辑名称,只显示路由 table ID,这使得它更容易出错。因此,虽然这绝对是一个 "Newb" 错误 [如此愚蠢的错误造成如此多的痛苦],但我认为在关联路由 table 时的用户体验方面还有一些不足之处。