Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
220 views
in Technique[技术] by (71.8m points)

amazon web services - Cloudformation error when deploying serverless.yml

I am following a serverless tutorial and I am trying to send a notification every time an image is uploaded to the s3 bucket. I've created a sendUploadNotifications function under functions and instead of adding an event to the function I've set up the "NotificationsConfiguration" under the AttachmentsBucket, as well as created a new sendUploadNotificationsPermission Resource under resources.

But when I deploy the app I get the following error when I try to deploy my serverless app:

Error: The CloudFormation template is invalid: Template error: instance of Fn::GetAtt references undefined resource sendUploadNotificationsLambdaFunction

The Error seems to stem from the way that I am referencing the FunctionName under the sendUploadNotificationsPermission resource.

I've tried different ways of referencing the function name, but to no avail. I still get the same error.

My serverless.yml file

service: serverless-udagram2

frameworkVersion: '2'

provider:
  name: aws
  runtime: nodejs12.x
  lambdaHashingVersion: 20201221

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'ap-southeast-1'}

  environment:
    GROUPS_TABLE: groups-${self:provider.stage}
    IMAGES_TABLE: images-${self:provider.stage}
    IMAGE_ID_INDEX: ImageIdIndex
    IMAGES_S3_BUCKET: branded-serverless-udagram-images-${self:provider.stage}
    SIGNED_URL_EXPIRATION: 300

  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Scan
        - dynamodb:PutItem
        - dynamodb:GetItem
        - dynamodb:Query
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.GROUPS_TABLE}
    - Effect: Allow
      Action:
        - dynamodb:PutItem
        - dynamodb:Query
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.IMAGES_TABLE}
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:PutItem
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.IMAGES_TABLE}/index/${self:provider.environment.IMAGE_ID_INDEX}
    - Effect: Allow
      Action:
        - s3:PutObject
        - s3:GetObject
      Resource: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}/*


functions:

  getGroups:
    handler: src/lambda/http/getGroups.handler
    events:
      - http:
          path: groups
          method: get
          cors: true

  createGroup:
    handler: src/lambda/http/createGroup.handler
    events:
      - http:
          path: groups
          method: post
          cors: true
          request:
            schema:
              application/json: ${file(models/create-group-request.json)}

  getImages:
    handler: src/lambda/http/getImages.handler
    events:
      - http:
          path: groups/{groupId}/images
          method: get
          cors: true

  getImage:
    handler: src/lambda/http/getImage.handler
    events:
      - http:
          path: images/{imageId}
          method: get
          cors: true

  createImage:
    handler: src/lambda/http/createImage.handler
    events:
      - http:
          path: groups/{groupId}/images
          method: post
          cors: true
          request:
            schema:
              application/json: ${file(models/create-image-request.json)}

  sendUploadNotifications:
    handler: src/lambda/s3/sendNotifications.handler


resources:

  Resources:

    # API gateway validates the request in accordance with json schemas that are identified in the function section under schema
    RequestBodyValidator:
      Type: AWS::ApiGateway::RequestValidator
      Properties:
        Name: 'request-body-validator'
        RestApiId:
          Ref: ApiGatewayRestApi
        ValidateRequestBody: true
        ValidateRequestParameters: true

    GroupsDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.GROUPS_TABLE}

    ImagesDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
            - AttributeName: groupId
              AttributeType: S
            - AttributeName: timestamp
              AttributeType: S
            - AttributeName: imageId
              AttributeType: S
        KeySchema:
          - AttributeName: groupId
            KeyType: HASH #partition key
          - AttributeName: timestamp
            KeyType: RANGE #sort key
        GlobalSecondaryIndexes:
          - IndexName: ${self:provider.environment.IMAGE_ID_INDEX}
            KeySchema:
              - AttributeName: imageId
                KeyType: HASH
            Projection:
              ProjectionType: ALL
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.IMAGES_TABLE}

    #    Bucket for file uploads
    AttachmentsBucket:
        Type: AWS::S3::Bucket
        Properties:
          BucketName: ${self:provider.environment.IMAGES_S3_BUCKET}
          NotificationConfiguration: # Sends notification when image has been uploaded
            LambdaConfigurations: #
              - Event: s3:ObjectCreated:*
                Function: !GetAtt sendUploadNotificationsLambdaFunction.Arn
          CorsConfiguration:
            CorsRules:
              -
                AllowedOrigins:
                  - "*"
                AllowedHeaders:
                  - "*"
                AllowedMethods:
                  - 'GET'
                  - 'PUT'
                  - 'POST'
                  - 'DELETE'
                  - 'HEAD'
                MaxAge: 3000

    sendUploadNotificationsPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: !GetAtt sendUploadNotificationsLambdaFunction.Arn
        Action: lambda:InvokeFunction
        Principal: s3.amazonaws.com
        SourceAccount: !Ref AWS::AccountId #!Ref
        SourceArn: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}

    BucketPolicy:
      Type: AWS::S3::BucketPolicy
      Properties:
        PolicyDocument:
          Id: MyPolicy
          Version: "2012-10-17"
          Statement:
            - Sid: PublicReadForGetBucketObjects
              Effect: Allow
              Principal: '*'
              Action: 's3:GetObject'
              Resource: 'arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}/*'
        Bucket:
          Ref: AttachmentsBucket


I've tried changing the name of the function in both the sendUploadNotificationsPermission and the AttachmentsBucket by appending LamdaFunction to the end of the function name, but still getting the same error.

Any help with this error would be appreciated.

question from:https://stackoverflow.com/questions/65933011/cloudformation-error-when-deploying-serverless-yml

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are trying to reference something which doesn't exist in the template at in the CloudFormation section Resource.

sendUploadNotificationsLambdaFunction

In case you want to reference any of the function you have defined named

sendUploadNotifications

you need to construct the ARN inside the Resources section.

To generate Logical ID for CloudFormation, the plugin transform the specified name in serverless.yml based on the following scheme.

Transform a leading character into uppercase
Transform - into Dash
Transform _ into Underscore

SendUploadNotificationsLambdaFunction in your case.

There are now two ways:

  1. You reference this inside Resource section of the template:
    sendUploadNotificationsPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: !GetAtt SendUploadNotificationsLambdaFunction.Arn
        Action: lambda:InvokeFunction
        Principal: s3.amazonaws.com
        SourceAccount: !Ref AWS::AccountId #!Ref
        SourceArn: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}
  1. You construct the ARN using Fn::Join.
    sendUploadNotificationsPermission:
      Type: AWS::Lambda::Permission
      Properties:
        FunctionName: !Join [":", ['arn:aws:lambda', !Ref 'AWS::Region', !Ref AWS::AccountId, '${self:service}-${self:provider.stage}-sendUploadNotifications']]
        Action: lambda:InvokeFunction
        Principal: s3.amazonaws.com
        SourceAccount: !Ref AWS::AccountId #!Ref
        SourceArn: arn:aws:s3:::${self:provider.environment.IMAGES_S3_BUCKET}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...