【问题标题】:Cloud formation custom resource creation failsCloudformation 自定义资源创建失败
【发布时间】:2021-04-06 02:56:45
【问题描述】:

我正在尝试创建一个指向 lambda 函数的自定义资源,然后调用它来生成随机优先级或我的 ELB 侦听器。

Lambda函数代码如下。

[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"

【问题讨论】:

  • CF 为您的自定义资源创建 lambda 函数。此 lambda 在 cloudwatch 中创建日志组,您可以检查错误
  • @OleksiiDonoha 感谢您的意见。尝试了日志,但奇怪的是没有发现,我认为这意味着该函数根本没有被调用。虽然我在经历了这个page 之后找到了解决方案。我们需要严格遵守自定义资源的 lambda 函数格式。如果这对我有用,我会将其发布为答案。

标签: amazon-web-services .net-core aws-lambda amazon-cloudformation


【解决方案1】:

以前方法的问题在于数据格式。当我们使用自定义资源时,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",
                    Reason = string.Empty,
                    PhysicalResourceId = Guid.NewGuid().ToString(),
                    StackId = crfRequest.StackId,
                    RequestId = crfRequest.RequestId,
                    LogicalResourceId = crfRequest.LogicalResourceId,
                    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, 0, 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 块。最佳做法是尝试捕获块并发送失败响应。

更多详情可参考以下网址:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-02
    • 2018-03-10
    • 2018-03-02
    • 2020-10-09
    • 1970-01-01
    • 2019-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多