12

What I am aiming for I'm trying to write a (single) SAM template for obtaining a Lambda function triggered by Api Gateway events.

I want to have multiple API Stages (say "dev", "testing", "prod") and I want each of them to be mapped onto a Lambda alias with the same name.

I'd prefer not to generate a new lambda version at each deployment, and I like manually setting the lambda version to be used by each lambda alias. Of course, "dev" alias is meant to point to $LATEST code version.

What I tried and what I got

I've modified the classic "hello_world" template as follows. Now, when deploying for the first time (say, to "dev") everything seems to work as expected. But if I try to deploy to "testing" stage, the APIs at this new stage respond, while those at "dev" stop responding.

What am I missing?

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  zzzz

  Sample SAM Template for zzzz

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Parameters:
  StageAliasName:
    Description: stage / alias name to be used in this deploy
    Type: String
    AllowedValues:
      - prod
      - stage
      - dev
      - v1
    Default: dev

Resources:
  ApiGatewayApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref StageAliasName

  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      AutoPublishAlias: !Ref StageAliasName
      FunctionName: zzz
      Environment:
        Variables:
          stage: !Ref StageAliasName
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            RestApiId: !Ref ApiGatewayApi
            Path: /hello
            Method: GET
#            Auth:
#              ApiKeyRequired: true



Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
#  HelloWorldApi:
#    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
#    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

cionzo
  • 428
  • 1
  • 5
  • 12
  • 1
    Hello, Did you find a solution to solve this problem without using another tool? – RaKoDev Sep 21 '21 at 07:35
  • 1
    Hi, not yet. Setting the deletion policy to "retain" might work, but I haven't tried yet. – cionzo Oct 20 '21 at 09:17
  • 1
    I think it's sad that there is no evident solution. So far I think I would just duplicate the stack and pass as a parameter the stack name for choosing dev or prod. – Codigo Morsa Nov 27 '21 at 12:35

1 Answers1

0

I had the same question as you, and found this: https://jun711.github.io/aws/deploy-api-gateway-to-multiple-stage-when-aws-sam-replaces-previous-stages/. It looks like SAM replaces the previous stages.

This jun chap does some manual steps to make it work. That's good to know it works, but kind of breaks 'infrastructure as code' I think that I'm going to use ansible to template out different versions of the template for different environments, and then just run off that.

ident
  • 1
  • 1
  • 1
    thanks @ident for your reply. I know how to do it by using other tools, but I think there must be a way of defining this all in the template: that's what I'm looking for. – cionzo Jan 25 '21 at 11:32
  • 1
    I think one can do what you want but resorting to plain Cloudformation, this looks like the solution to me: https://stackoverflow.com/a/58725869/6398014 – Codigo Morsa Nov 27 '21 at 12:31
  • 1
    thank you @CodigoMorsa do you think that setting the deletion policy to "retain" might help? – cionzo Nov 29 '21 at 09:19