Proper way to deploy on production stage

Hello folks!

I’m new to serverless and it’s so smooth on development stage. Right now, I’m migrating a few stacks to prod environment and I’m facing a common error:

An error occurred: XXXXXX - xxxxx-prod already exists.

If I’m doing a fresh deploy, it works. But when I want to include new functions, I got this error. i.e: only works on first sls deploy --stage prod

My policies are set to Retain on production because I want to keep data save.

How can I deploy new functions and keep my resources without need to change my policy?

1 Like

Hello, no solution but one try!

I’ve the exact same problem with buckets.

I want them to stay what ever happen to the serverless project/function.
So I used
DeletionPolicy: Retain.

Fine for the first run and until you keep the associate CloudFormation stack living.

But when I drop the stack in order to rebuild with a somehow different design but reusing data (thus the bucket)
I can not find any way to do that with serverless.

Try :

  • add a Condition not to create the bucket (will fail because it exists)
  • but now I need this bucket arn to grant permission to the new lambda

Could not find any way to get arn dynamically with serverless
… maybe I can provide input variables an existing arn (for the existing bucket) or the computed expected bucket arn (it is possible with bucket but not for mush resources)
… but for other resources the arn might not be computed in advance

Looks like a simple requirement : I do not want to loose my data.
But can’t figure how to do it with serverless

Code portion to illustrate :

Custom option to disable bucket creation using Conditions

---
service:
...
custom:
  createBucket: ${opt:createBucket, 'true'}
...
resources:
  Conditions:
    CreateBucket:
      Fn::Equals:
      - ${self:custom.createBucket}
      - true
  Resources:
      S3BucketMyProjectIngest:
        Type: 'AWS::S3::Bucket'
        DeletionPolicy: 'Retain'
        Condition: 'CreateBucket'
        Properties:
          BucketName: ${self:custom.IngestBucketName}
  ...

So not creating those buckets can be achieved with
AWS_PROFILE=serverless serverless deploy --createBucket no

But it fails because of the reference in another resource

S3BucketLambdaPermission:
  Type: "AWS::Lambda::Permission"
  Properties:
    FunctionName:
      "Fn::GetAtt":
      - 'ProcessFromS3LambdaFunction'
      - 'Arn'
    ...
    SourceArn:
      "Fn::GetAtt":
      - 'S3BucketMyProjectIngest'
      - 'Arn'

Error is obviously about the missing resource (disable by the condition)

Template format error: Unresolved resource dependencies [S3BucketMyProjectIngest] in the Resources block of the template

Is there a way to achieve this (“I do not want to loose my data”)?

@placplacboom I would expect this happen if you’re removing the stack between deployments but not if you’re only deploying. Serverless uses CloudFormation for deployments and if you tell CloudFormation to create a resource that already exists it will fail. Stack updates, which is what happens if you use sls deploy without doing an sls remove in between will be ok because the stack will continue using the resource it created earlier.

@placplacboom and @smougenot you should think of DeletionPolicy: Retain as a fail safe that stops data from being removed if someone screws up and accidentally deletes the CloudFormation stack. Don’t use it as a way to keep data between deleting and re-creating a stack. If you want to do that then you need to look at putting those resources into their own CloudFormation stack and using cross stack references. See https://serverless.com/framework/docs/providers/aws/guide/variables/#reference-cloudformation-outputs for more information.

1 Like