如何解决云形成自定义资源创建失败
我正在尝试创建一个指向 lambda 函数的自定义资源,然后调用它来生成随机优先级或我的 ELB 侦听器。
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace aws_listenser_rule_priority_generator {
public class Function {
public async Task<int> FunctionHandler(FunctionParams input,ILambdaContext context) {
AmazonElasticLoadBalancingV2Client elbV2Client = new AmazonElasticLoadBalancingV2Client(RegionEndpoint.EUWest1);
var describeRulesResponse = await elbV2Client.DescribeRulesAsync(new DescribeRulesRequest {
ListenerArn = input.ListenerArn
});
var priority = 0;
var random = new Random();
do {
priority = random.Next(1,50000);
}
while(describeRulesResponse.Rules.Exists(r => r.Priority == priority.ToString()));
return priority;
}
}
public class FunctionParams {
public string ListenerArn { get; set; }
}
}
我已经使用以下参数在 AWS 控制台上测试了这个 lambda,它成功返回。
{
"ListenerArn": "arn:aws:elasticloadbalancing:eu-west-1:706137030892:listener/app/Cumulus/dfcf28e0393cbf77/cdfe928b0285d5f0"
}
但是一旦我尝试将其与 Cloud Formation 结合使用。自定义资源在创建过程中卡住。
Resources:
ListenerPriority:
Type: Custom::Number
Properties:
Servicetoken: "arn:aws:lambda:eu-west-1:706137030892:function:GenerateListenerPriority"
ListenerArn: "arn:aws:elasticloadbalancing:eu-west-1:706137030892:listener/app/Cumulus/dfcf28e0393cbf77/cdfe928b0285d5f0"
解决方法
前一种方法的问题是数据格式。当我们使用自定义资源时,Cloud Formation 会以指定的格式发送请求,并且期望在指定的响应 URL 处异步响应。
我必须对代码进行以下更新:
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace aws_listenser_rule_priority_generator
{
public class Function
{
public async Task FunctionHandler(CustomResourceRequest<CustomResourceRequestProperties> crfRequest,ILambdaContext context)
{
var jsonResponse = string.Empty;
if(crfRequest.RequestType.ToUpperInvariant() != "CREATE") {
jsonResponse = JsonSerializer.Serialize(new CustomResourceResponse<object> {
Status = "SUCCESS",Reason = string.Empty,PhysicalResourceId = Guid.NewGuid().ToString(),StackId = crfRequest.StackId,RequestId = crfRequest.RequestId,LogicalResourceId = crfRequest.LogicalResourceId,Data = new {
Dummy = "Dummy"
}
});
}
else {
AmazonElasticLoadBalancingV2Client elbV2Client = new AmazonElasticLoadBalancingV2Client(RegionEndpoint.EUWest1);
var describeRulesResponse = await elbV2Client.DescribeRulesAsync(new DescribeRulesRequest {
ListenerArn = crfRequest.ResourceProperties.ListenerArn
});
var priority = 0;
var random = new Random();
do {
priority = random.Next(1,50000);
}
while(describeRulesResponse.Rules.Exists(r => r.Priority == priority.ToString()));
jsonResponse = JsonSerializer.Serialize(new CustomResourceResponse<object> {
Status = "SUCCESS",Data = new {
Priority = priority
}
});
}
var byteArray = Encoding.UTF8.GetBytes(jsonResponse);
var webRequest = WebRequest.Create(crfRequest.ResponseURL) as HttpWebRequest;
webRequest.Method = "PUT";
webRequest.ContentType = string.Empty;
webRequest.ContentLength = byteArray.Length;
using(Stream datastream = webRequest.GetRequestStream()) {
await datastream.WriteAsync(byteArray,byteArray.Length);
}
await webRequest.GetResponseAsync();
}
}
public class CustomResourceRequest<T> where T : ICustomResourceRequestProperties {
public string RequestType { get; set; }
public string ResponseURL { get; set; }
public string StackId { get; set; }
public string RequestId { get; set; }
public string ResourceType { get; set; }
public string LogicalResourceId{ get; set; }
public string PhysicalResourceId { get; set; }
public T ResourceProperties { get; set; }
public T OldResourceProperties { get; set; }
}
public class CustomResourceResponse<T> {
public string Status { get; set; }
public string Reason { get; set; }
public string PhysicalResourceId { get; set; }
public string StackId { get; set; }
public string RequestId { get; set; }
public string LogicalResourceId { get; set; }
public bool NoEcho { get; set; }
public T Data { get; set; }
}
public interface ICustomResourceRequestProperties {
public string ServiceToken { get; set; }
}
public class CustomResourceRequestProperties : ICustomResourceRequestProperties
{
string ICustomResourceRequestProperties.ServiceToken { get; set; }
public string ListenerArn { get; set; }
}
}
上面的代码希望一切正常,没有任何问题,并且没有 try catch 块。最佳做法是使用 try catch 块并发送失败响应。
可以参考以下网址了解更多详情:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。