amazon-web-services - 以编程方式将多个事件通知添加到 s3 存储桶

标签 amazon-web-services amazon-s3 aws-lambda aws-cloudformation

我想使用下面的 cloudformation 模板在单个现有 S3 存储桶上创建多个事件通知。但是,即使我在 BucketConfiguration 资源下指定了另一个“LambdaFunctionConfigurations”,我也只能看到在 S3 存储桶上创建的一个事件。我还尝试创建另一个 BucketConfiguration 资源,并配置了单独的事件,但没有任何运气。我正在寻找任何可以帮助我指明正确方向的提示或建议。据我收集的信息,s3.putBucketNotification 方法将清除任何现有的事件通知配置。请记住,CF 模板确实会创建单个事件通知(我希望创建多个事件通知)。

以下模板的模型: Create a Lambda notification in an S3 bucket with CloudFormation

Description: >-
  Create an event notification for an existing S3 bucket
Parameters:
  BucketName:
    Description: S3 Bucket name (must already exist)
    Type: String
Resources:
  BucketConfiguration:
    Type: 'Custom::S3BucketConfiguration'
    DependsOn:
      - BucketPermission
      - NotificationBucketPolicy
    Properties:
      ServiceToken: !GetAtt S3BucketConfiguration.Arn
      Bucket: !Ref BucketName
      NotificationConfiguration:
        LambdaFunctionConfigurations:
          - Events:
              - 's3:ObjectCreated:*'
            LambdaFunctionArn: MyLambdaArn
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 606b322f-42fa-4d20-bae4-53374d7ad7ba
  S3BucketConfiguration:
    Type: 'AWS::Lambda::Function'
    Properties:
      Description: S3 Object Custom Resource
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          var response = require('cfn-response');
          var AWS = require('aws-sdk');
          var s3 = new AWS.S3();
          exports.handler = function(event, context) {
            var respond = (e) => response.send(event, context, e ? response.FAILED : response.SUCCESS, e ? e : {});
            process.on('uncaughtException', e=>failed(e));
            var params = event.ResourceProperties;
            delete params.ServiceToken;
            if (event.RequestType === 'Delete') {
              params.NotificationConfiguration = {};
              s3.putBucketNotificationConfiguration(params).promise()
                .then((data)=>respond())
                .catch((e)=>respond());
            } else {
              s3.putBucketNotificationConfiguration(params).promise()
                .then((data)=>respond())
                .catch((e)=>respond(e));
            }
          };
      Timeout: 30
      Runtime: nodejs6.10
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 1cefd553-f888-4b3b-8184-d96932a29227
  BucketPermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: 'lambda:InvokeFunction'
      Principal: s3.amazonaws.com
      SourceAccount: !Ref 'AWS::AccountId'
      SourceArn: !Sub 'arn:aws:s3:::${BucketName}'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 29f90f84-cfd0-43d2-8c2b-c173ec96c409
  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      Policies:
        - PolicyName: S3Policy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 's3:PutObject'
                  - 'S3:DeleteObject'
                Resource: !Sub 'arn:aws:s3:::${BucketName}'
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 3556f770-b7cd-4ac1-8afa-62a0319721b8
  NotificationBucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref BucketName
      PolicyDocument:
        Statement:
          - Effect: Allow
            Action:
              - 's3:PutBucketNotification'
            Resource: !Sub 'arn:aws:s3:::${BucketName}'
            Principal:
              AWS: !GetAtt LambdaExecutionRole.Arn
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 1f82086e-0d71-4731-8173-e3b8ee0da4dd
Metadata:
  'AWS::CloudFormation::Designer':
    3556f770-b7cd-4ac1-8afa-62a0319721b8:
      size:
        width: 60
        height: 60
      position:
        x: 60
        'y': 90
      z: 1
      embeds: []
    1f82086e-0d71-4731-8173-e3b8ee0da4dd:
      size:
        width: 60
        height: 60
      position:
        x: 180
        'y': 90
      z: 1
      embeds: []
    29f90f84-cfd0-43d2-8c2b-c173ec96c409:
      size:
        width: 60
        height: 60
      position:
        x: 410
        'y': 90
      z: 1
      embeds: []
    1cefd553-f888-4b3b-8184-d96932a29227:
      size:
        width: 60
        height: 60
      position:
        x: 300
        'y': 190
      z: 1
      embeds: []
    606b322f-42fa-4d20-bae4-53374d7ad7ba:
      size:
        width: 60
        height: 60
      position:
        x: 300
        'y': 90
      z: 1
      embeds: []
      dependson:
        - 29f90f84-cfd0-43d2-8c2b-c173ec96c409
        - 1f82086e-0d71-4731-8173-e3b8ee0da4dd

最佳答案

您是正确的,不可能为同一“触发器”定义多个事件。

例如,在 S3 控制台中我成功地定义了:

  • 同一事件有多个规则,但前缀不同
  • 针对相同前缀不同事件的多个规则

但是,我无法相同事件相同前缀定义多个规则。错误消息是:

Configuration is ambiguously defined. Cannot have overlapping suffixes in two rules if the prefixes are overlapping for the same event type.

根据您的问题,您似乎希望在同一前缀(包括“整个存储桶”)内为同一事件触发多个 Lambda 函数。为此,我建议:

  • 创建 Amazon SNS 主题
  • 创建指向 SNS 主题的 S3 事件
  • 订阅每个 Lambda 函数到 SNS 主题

关于amazon-web-services - 以编程方式将多个事件通知添加到 s3 存储桶,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55079923/

相关文章:

ios - 我是否需要将AWS S3或EC2用于我的iOS应用程序的后端?

python - 需要将 lambda 函数(python)加入 YAML 中的 CloudFormation 模板,我怎样才能实现这一点?

amazon-web-services - 使用 AWS Gateway - Lambda - RDS 的长时间运行的作业

node.js - AWS Lambda 开发工作流程

amazon-web-services - 如何连接到 AWS 中的 EC2 实例?

php - AWS AccessDeniedException 与 Laravel for S3

python - 开始使用 Python 进行安全的 AWS CloudFront 流传输

apache-spark - Spark - 读取和写入相同的 S3 位置

amazon-web-services - 错误: Unexpected server response: 502 on trying to connect to a lambda function through Amazon API gateway Websocket API

ruby - 使用aws sdk获取带有特定标签的ec2实例