Serverless Framework - Create a Lambda and S3 and upload a file in S3. Then, extract to DynamoDB with Lambda

Viewed 2097

It is my first time using serverless framework and my mission is to create a lambda, s3 and dynamodb with serverless and then invoke lambda to transfer from s3 to dynamo. I am trying to get a name generated by serverless to my S3 to use it in my Lambda but I had no luck with that. This is how my serveless.yml looks like:

service: fetch-file-and-store-in-s3

frameworkVersion: ">=1.1.0"

custom:
  bucket: 
    Ref: Outputs.AttachmentsBucketName

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: us-east-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:PutObject
        - s3:PutObjectAcl
      Resource: "arn:aws:s3:::${self:custom.bucket.Ref}/*"

functions:
  save:
    handler: handler.save
    environment:
      BUCKET: ${self:custom.bucket.Ref}

resources:
  # S3
  AttachmentsBucket:
  Type: AWS::S3::Bucket
  Properties:
    # Set the CORS policy
    CorsConfiguration:
      CorsRules:
        -
          AllowedOrigins:
            - '*'
          AllowedHeaders:
            - '*'
          AllowedMethods:
            - GET
            - PUT
            - POST
            - DELETE
            - HEAD
          MaxAge: 3000

  # Print out the name of the bucket that is created
  Outputs:
    AttachmentsBucketName:
      Value:
        Ref: AttachmentsBucket

and here is the part where it creates s3 bucket

Resources:
    # S3
    AttachmentsBucket:
      Type: AWS::S3::Bucket
      Properties:
        # Set the CORS policy
        CorsConfiguration:
          CorsRules:
            - AllowedOrigins:
                - '*'
            - AllowedHeaders:
                - '*'
            - AllowedMethods:
                - GET
                - PUT
                - POST
                - DELETE
                - HEAD
            - MaxAge: 3000
  # Print out the name of the bucket that is created
  Outputs:
    AttachmentsBucketName:
      Value:
        Ref: AttachmentsBucket

and this is the error I am currently getting:

λ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service fetch-file-and-store-in-s3.zip file to S3 (7.32 MB)...
Serverless: Validating template...

  Error --------------------------------------------------

  Error: The CloudFormation template is invalid: Invalid template property or properties [AttachmentsBucket, Type, Properties]
4 Answers

You have some issues with indentation:

resources:
  Resources:
    # S3
    AttachmentsBucket:
      Type: AWS::S3::Bucket
      Properties:
        # Set the CORS policy
        CorsConfiguration:
          CorsRules:
            - AllowedOrigins:
                - '*'
            - AllowedHeaders:
                - '*'
            - AllowedMethods:
                - GET
                - PUT
                - POST
                - DELETE
                - HEAD
            - MaxAge: 3000
  # Print out the name of the bucket that is created
  Outputs:
    AttachmentsBucketName:
      Value:
        Ref: AttachmentsBucket

Indentation is important for serverless.yml file. In this case, AttachmentsBucket is a resource, it should be sub-section under Resources with one tab space, and then Type and Properties should have one tabbed spaces from Resource Name: AttachmentsBucket, while it actually have two in the sample provided. CloudFormation will not be able to process this particular resource since it is not able to identify resource with proper name and properties.

See the updated sample:

Resources:
  AttachmentsBucket:
    Type: AWS::S3::Bucket
    Properties:
    # Set the CORS policy
    CorsConfiguration:
      CorsRules:
        - AllowedOrigins:
            - '*'
        - AllowedHeaders:
            - '*'
        - AllowedMethods:
            - GET
            - PUT
            - POST
            - DELETE
            - HEAD
        - MaxAge: 3000

# Print out the name of the bucket that is created
Outputs:
  AttachmentsBucketName:
    Value: !Ref AttachmentsBucket

You can validate the cloudformation templates by using the aws cli tool here

But your question is regarding how to make lambda and dynamodb load works and in your description you are asking about the deployment part. Can you update your question and tags?

I was able to figure out a solution. As I am very new and it was my first project I wasn't very familiar with the terms in the beginning. what I did was to name my bucket here:

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: ${self:custom.bucket} # Getting the name of table I defined under custom in serverless.yml
  # Make Bucket publicly accessable
  MyBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
        Bucket: !Ref Bucket
        PolicyDocument:
          Statement:
            - Effect: Allow
              Principal: '*' # public access to access the bucket files 
              Action: s3:GetObject
              Resource: 'arn:aws:s3:::${self:custom.bucket}/*'

Then to upload a file with the deploy I found a plugin called serverless-s3bucket-sync And added in the custom attribute and the location of my file under folder:

custom:
  bucket: mybucketuniquename #unique global name it will create for the bucket
  s3-sync: 
      - folder: images
        bucket: ${self:custom.bucket}

And added the IamRole:

iamRoleStatements:
    #S3 Permissions
    - Effect: Allow
      Action:
        - s3:*
      Resource: "arn:aws:s3:::${self:custom.bucket}"
Related