I have a SAM template deploying three resources: An ApiGateway, a Lambda Function and a ApiGateway BasePathMapping.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
StageName:
Type: String
Resources:
api:
Type: AWS::Serverless::Api
Properties:
DefinitionBody: ...
StageName: !Ref StageName
apidomain:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName: mydomain.com
RestApiId: !Ref api
Stage: !Ref StageName
lambda:
Type: AWS::Serverless::Function
Properties: ...
There is one parameter to the template called StageName, and this is used in two places:
When this stack is deployed, Cloud Formation deploys things in a strange order. It deploys the Api Gateway before the BasePathMapping, which you would expect, but deploying the ApiGateway stage is a separate step. It tries to deploy the BasePathMapping before the ApiGateway Stage, which results in the error:
Invalid stage identifier specified
This is totally underdtandable given it has not been created yet.
I have tried using the DependsOn property on the BasePathMapping resource to force it to get created after the ApiGateway. It does, but not after the ApiGateway stage.
Does anyone know a way around this? It feels like a bug with the AWS::Serverless::Api resource type. It clearly needs to create a Gateway and a Stage, but the should be done sequentially not not allow the BasePathMapping to be created in between.
Work arounds I don't like include:
I got a workaround for this.. Apparently when using SAM (aws cloudformation deploy) it uses the transform (Transform: AWS::Serverless-2016-10-31) rule set in your template to generate all kind of "extra" resources. One of them is a aws::ApiGateway::stage resource. The name of this resource is ServerlessApiStage where ServerlessApi is the name of the AWS::Serverless::Api resource.
This might be a documentation issue. We are using a standard mechanism for constructing resource names. You should be able to use "DependsOn" to chain the resource creation in correct order. I will update the docs to explain how the resource names are created.
I really don't understand why it's trying to redeploy my API gateway stages in the first place. If my function that an API gateway resource is using is pointing to ":Latest" then why do we need to redeploy?
I'm having similar issue.
I tried using DependsOn to specify that the BasePathMapping depends on my AWS::ApiGateway::DomainName and AWS::Serverless::Api resource, but it is still created before Stage is created. I'm guessing that's because Stage is a separate resource outside of AWS::Serverless::Api.
Thanks to @jvanbrunschot-coolblue 's comment, I was able to find a workaround. It looks like ServerlessApiStage is indeed a separate resource outside of AWS::Serverless::Api, and is generated by the transform function. So my workaround is to figure out what the generated resource name would be for the stage and specify that in the DependsOn section of the AWS::ApiGateway::BasePathMapping resource.
Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem.
In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and word Stage: <myApiLogicalName>Stage.
Fixed the problem by adding a DependsOn on AWS::ApiGateway::BasePathMapping as seen below:
# ########################################################################
# Mobile API
apiMobile:
Type: 'AWS::Serverless::Api'
Properties:
Name: mobile-api
StageName: !FindInMap [ApiStage, !Ref Environment, stage]
DefinitionBody:
'Fn::Transform':
Name: 'AWS::Include'
Parameters:
Location: 's3://<redacted>/swagger.yaml'
EndpointConfiguration: REGIONAL
# ###################################################################
# Base Path Mapping
apiBasePathMapping:
Type: 'AWS::ApiGateway::BasePathMapping'
Properties:
BasePath: v1.0
Stage: !FindInMap [ApiStage, !Ref Environment, stage]
DomainName:
'Fn::Sub':
- 'mobile-api${Suffix}.<redacted>'
- Suffix: !FindInMap
- EnvironmentShort
- !Ref Environment
- suffix
RestApiId: !Ref apiMobile
DependsOn:
- apiMobileStage <------ Added explicit dependency
Hi,
I had to add apiStage and not only Stage.
aws-cli/1.15.66
SAM CLI, version 0.5.0
Hi,
So i was stuck in the same scenario and after a lot of help from the above comments and a little trial and error on my end.
The format of the aws::ApiGateway::stage is =>
(name of the serverless api resource)(stage name)Stage
Adding a DomainName property to the AWS::Serverless::API resources which configures this all for you is probably what we want here.
Having Domain and Certificate parameters makes sense to me. If Certificate is not passed AWS::Serverless::API could create AWS::CertificateManager::Certificate resource too.
Any update on this? Would great to make this easier. Ran into this problem again recently.
If need to understand the inner of an abstraction (i.e SAM) in order to use it then surely it's not doing its job?
I added an RFC for this here https://github.com/awslabs/serverless-application-model/issues/783. I'm going to close out this issue as a workaround has been posted, and we have a path forward to a simpler solution.
Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem.
In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and wordStage:<myApiLogicalName>Stage.Fixed the problem by adding a
DependsOnonAWS::ApiGateway::BasePathMappingas seen below:# ######################################################################## # Mobile API apiMobile: Type: 'AWS::Serverless::Api' Properties: Name: mobile-api StageName: !FindInMap [ApiStage, !Ref Environment, stage] DefinitionBody: 'Fn::Transform': Name: 'AWS::Include' Parameters: Location: 's3://<redacted>/swagger.yaml' EndpointConfiguration: REGIONAL # ################################################################### # Base Path Mapping apiBasePathMapping: Type: 'AWS::ApiGateway::BasePathMapping' Properties: BasePath: v1.0 Stage: !FindInMap [ApiStage, !Ref Environment, stage] DomainName: 'Fn::Sub': - 'mobile-api${Suffix}.<redacted>' - Suffix: !FindInMap - EnvironmentShort - !Ref Environment - suffix RestApiId: !Ref apiMobile DependsOn: - apiMobileStage <------ Added explicit dependencyTHIS IS IT THANKS FOR TAKING ME OUT OF MY DESPERATION PIT
For me the solution was:
Resources:
Api:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Auth:
DefaultAuthorizer: NONE
BasePathMapping:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName: !Ref GatewayDomain
RestApiId: !Ref Api
Stage: !Ref Api.Stage
Notice the BasePathMapping.Stage is set to !Ref Api.Stage which creates tight coupling and removes potential user errors such as typos.
@ca0abinary Thanks for the comment! This will be a really good addition to the examples folder. Reopening this issue.
Indeed it seems to be a bug, which disregards the dependencies between these resources. I am using SAM CLI 0.4.0 and AWS CLI 1.11.131 and had the same problem.
In my case the final template generate by Cloudformation produced the stage name as a concatenation of my API logical name and wordStage:<myApiLogicalName>Stage.
Fixed the problem by adding aDependsOnonAWS::ApiGateway::BasePathMappingas seen below:# ######################################################################## # Mobile API apiMobile: Type: 'AWS::Serverless::Api' Properties: Name: mobile-api StageName: !FindInMap [ApiStage, !Ref Environment, stage] DefinitionBody: 'Fn::Transform': Name: 'AWS::Include' Parameters: Location: 's3://<redacted>/swagger.yaml' EndpointConfiguration: REGIONAL # ################################################################### # Base Path Mapping apiBasePathMapping: Type: 'AWS::ApiGateway::BasePathMapping' Properties: BasePath: v1.0 Stage: !FindInMap [ApiStage, !Ref Environment, stage] DomainName: 'Fn::Sub': - 'mobile-api${Suffix}.<redacted>' - Suffix: !FindInMap - EnvironmentShort - !Ref Environment - suffix RestApiId: !Ref apiMobile DependsOn: - apiMobileStage <------ Added explicit dependencyTHIS IS IT THANKS FOR TAKING ME OUT OF MY DESPERATION PIT
Thank you it worked for me SAM 0.22.0 I had the same issue: just refer the object with the same name plus stage. To verify you are referring the right resources compiled by sam, I suggest to run sam validate --debug and verify the name :-) thank you again!
If anyone is using an Http protocol API and the AWS::ApiGatewayV2:ApiMapping I solved this by referencing ServerlessHttpApiApiGatewayDefaultStage for stage.
ApiMapping:
Type: AWS::ApiGatewayV2::ApiMapping
Properties:
ApiId: !Ref ServerlessHttpApi
DomainName: !Ref ApiDomainName
Stage: !Ref ServerlessHttpApiApiGatewayDefaultStage
@ca0abinary
Use "!Ref Api.Stage" as reference works here!!
Thanks!!!
it works perfect for me
Use "!Ref Api.Stage"
Most helpful comment
For me the solution was:
Notice the
BasePathMapping.Stageis set to!Ref Api.Stagewhich creates tight coupling and removes potential user errors such as typos.