vinod827
vinod827

Reputation: 1524

Unable to create an S3 PutObjectEvent for Lambda funtion using SAM Template

I'm new to SAM templates. I have the following snippet of my SAM Template where I used to pass the name of bucket name as a parameter from outside of this SAM YAML file :-

SAM Template:-

MyLambda:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./functions/test/dist/
      Handler: index.lambdaHandler
      Runtime: nodejs12.x
      Events:
        S3PutObjectEvent:
          Type: S3
          Properties:
            Bucket: !Ref S3BucketName
            Events: s3:ObjectCreated:*

Parameter.YAML:-

DeploymentEnvironment:
  default:
     S3BucketName: my-awesome-s3-bucket

Now, I do not create any S3 Bucket using SAM Template or Infrastructure as a code (IaC). Bucket creation is done by Lambda code itself hence there is no S3 Object Type declaration in my SAM Template.

When I execute this command, sam validate to validate the SAM Template then I get this error:-

/template.yaml' was invalid SAM Template. Error: [InvalidResourceException('MyLambda', 'Event with id [S3PutObjectEvent] is invalid. S3 events must reference an S3 bucket in the same template.')] ('MyLambda', 'Event with id [S3PutObjectEvent] is invalid. S3 events must reference an S3 bucket in the same template.')

I really need your help in achieving this as I tried hard in getting it solved. I read various forums, not sure if we can pass the bucket name from outside of the SAM template or not.

Is there any way workaround? This is really critical issue for me. Appreciate your help on this. thanks

Upvotes: 0

Views: 547

Answers (1)

maafk
maafk

Reputation: 6876

Bucket creation is done by Lambda code itself

I'd recommend against this pattern, as your Lambda even source won't get created if the Bucket doesn't already exist.

Try creating the bucket in your SAM template, and pass the bucket name to your function as an environment variable.

Optionally you can set different environment names on your bucket name (addressing comment) using Parameters.

Parameters:
  Env:
    Type: String
    AllowedValues:
      - dev
      - qa
      - prod
    Default: dev
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
      Properties:
        BucketName: !Sub 'My-unique-bucket-name-${Env}'
  MyLambda:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./functions/test/dist/
      Handler: index.lambdaHandler
      Runtime: nodejs12.x
      Environment:
        Variables:
          BUCKET_NAME: !Ref MyBucket  # passed to Lambda as environment variable
      Events:
        S3PutObjectEvent:
          Type: S3
          Properties:
            Bucket: !Ref MyBucket
            Events: s3:ObjectCreated:*

And get the bucket name in your function

const bucket = process.env.BUCKET_NAME

Upvotes: 2

Related Questions