Dynamic Bucket name Logical ID

I have a question about logical IDs that are created for S3 Buckets. We have bucket names that are suffixed with our stage name media-${opt:stage} . Originally we didn’t have a resource with a matching logical ID needed but we want to add LifecycleConfiguration to expire objects on the bucket so we have created a resource for that like so

    S3BucketMediadevelop:
      Type: "AWS::S3::Bucket"
      Properties:
        BucketName: ${env:MEDIA_STORAGE_BUCKET_PREFIX}-${opt:stage}
        LifecycleConfiguration:
          Rules:
            - Id: "Delayed media expiration"
              Status: "Enabled"
              TagFilters:
                  - Key: "deleted-media"
                    Value: "true"
              ExpirationInDays: 30

But the logical ID won’t match when a stage other than develop is deployed. Is there a way to dynamically create the Resource Logical ID like S3BucketMedia${opt:stage}

1 Like

@justinffs I don’t think it’s possible to have a dynamic Logical ID for your resources.

Can I ask why you need a dynamic Logical ID? I don’t quite understand how the LifecycleConfiguration added that requirement. It’s possible I’m missing something. :slight_smile:

If you deploy to a different stage, it will be to a different CloudFormation stack entirely, so you don’t have to worry about uniqueness. Could you just do this:

    S3BucketMedia:
      Type: "AWS::S3::Bucket"
      Properties:
        BucketName: ${env:MEDIA_STORAGE_BUCKET_PREFIX}-${opt:stage}
        LifecycleConfiguration:
          Rules:
            - Id: "Delayed media expiration"
              Status: "Enabled"
              TagFilters:
                  - Key: "deleted-media"
                    Value: "true"
              ExpirationInDays: 30

where your bucket has the same logical ID in all stacks, regardless of stage?

Thanks Alex,

I might have left out some details.

We deployed previously without specifying the resource just specifying an event so as far as I can tell serverless creates a logical id based on the bucket name, and our bucket name had the stage in it. Adding LifecycleConfiguration need to be done on the resource if I recall.

 resize:
    handler: lambdas/functions/resize/index.handler
    description: 'Creates resized thumbnails once a thumbnail image is uploaded and resizes media when requested resource does not exist in s3.'
    events:
      - s3:
         bucket: media-${opt:stage}
         events:
          - s3:ObjectCreated:Put
          - s3:ObjectCreated:Post
          - s3:ObjectCreated:CompleteMultipartUpload
         rules:
           - suffix: .thumb.jpg
    package:
      exclude:
        - lambdas/**
      include:
        - lambdas/functions/resize/**

The problem is that these buckets already exist and have data in it that can’t be lost. I would like to avoid having to migrate them to a different bucket, but I can’t change the logical id tag in S3 I get an error Your TagKey cannot be prefixed with aws:
Which I think makes sense.

Is there a way around this? Can the bucket specified in the event point to the resource so the bucket logical ID is not dynamically generated?

1 Like

I see. Thanks for that additional context, @justinffs.

I don’t know for sure if this will help, but there is a plugin for using S3 events for an existing bucket. I haven’t used it, and I don’t know for sure that it will play nicely with the CloudFormation you’re trying to do. I’d recommend testing carefully in a staging environment before rolling out to your prod bucket :slight_smile:

1 Like

Did you find a solution to this. I am running into the same problem.

1 Like

Anybody had any solutions to this?

If you have fix number of stages predefined then you can define Conditions block at top on the basis of stages and use that condition to create specific resource.

You need to have all possible stages resources defined using conditions