Reputation: 9763
I have a CloudFormation template that creates an APIGateway, but when I deploy again to add APIGateway methods (running update stack) I get:
Method already exists for this resource (Service: AmazonApiGateway; Status Code: 409;
Error Code: ConflictException; Request ID: 7058deed-14e1-46bc-863d-efba23cd668b; Proxy: null)
I attempted to add an update/delete policy to all resources but that doesn't seem to have worked:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
I have a hunch it may be caused by not specifying the resources correctly, do I have something wrong with my resource paths? Are both resources being created at the root resource or something?
My End Goal
To declare two separate resources (with seperate URLS) eg
https://xxx/post-note
https://xxx/deleteNote
that are both tied to lambda functions
My template:
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
# above two lines necessary to convert SAM template to CloudFormation template
Description: Resource definitions for my site
Globals: # any parameters you want available to all your resources
Api:
Cors:
AllowMethods: "'OPTIONS,POST,GET'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
AllowOrigin: "'*'"
Function:
Runtime: nodejs14.x # language used at runtime
Timeout: 35 # timeout seconds for a given lambda function execution
Environment:
Variables: # these will be important later
DYNAMO_TABLE: !Ref DynamoNotesTable
DB_ENDPOINT: http://dynamodb.us-east-1.amazonaws.com
REGION_NAME: us-east-1
Resources:
# #############################################################################
# # BACK END LAMBDAS
# #############################################################################
postNote:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::Serverless::Function
Properties:
Handler: backend/dynamo/postNote.postNote
CodeUri: s3://backend/xxx
Policies:
- AmazonDynamoDBFullAccess
deleteNote:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::Serverless::Function
Properties:
Handler: backend/dynamo/deleteNote.deleteNote
CodeUri: s3://backend/xxx
Policies:
- AmazonDynamoDBFullAccess
#############################################################################
# api-gateway (with cognito auth)
# https://bl.ocks.org/magnetikonline/c314952045eee8e8375b82bc7ec68e88
#############################################################################
apiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Description: API Gateway
EndpointConfiguration:
Types:
- REGIONAL
Name: my-api
postNoteGatewayMethod:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt postNote.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
deleteNoteGatewayMethod:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt deleteNote.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
apiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- postNoteGatewayMethod
- deleteNoteGatewayMethod
Properties:
RestApiId: !Ref apiGateway
StageName: Prod
lambdaApiGatewayInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt postNote.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/Prod/POST/PATH_PART
Upvotes: 3
Views: 4763
Reputation: 10333
Both cloudformation resources AWS::ApiGateway::Method
pointing to same api gateway resource with same method POST.
We have two options
Option 1: Change Method Name for one of the methods.
deleteNoteGatewayMethod:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::ApiGateway::Method
Properties:
HttpMethod: POST <--- should be DELETE
AuthorizationType: "NONE"
Option 2: have a different root resource for each methods. so, if we need two POST endpoints /postNote and /deleteNote, we must have two separate resources from the root path and use these resources for the lambdas.
Ex:
/postNote
with Parent as root resource.
noteResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt apiGateway.RootResourceId
PathPart: "postNote"
RestApiId: !Ref apiGateway
and method ResourceId
pointing to !Ref noteResource
postNoteGatewayMethod:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::ApiGateway::Method
DependsOn:
- noteResource
Properties:
HttpMethod: POST
AuthorizationType: NONE
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt postNote.Arn
ResourceId: !Ref noteResource
RestApiId: !Ref apiGateway
Similarly we need to add delete resource.
deleteResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId: !GetAtt apiGateway.RootResourceId
PathPart: "deleteNote"
RestApiId: !Ref apiGateway
deleteNoteGatewayMethod:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::ApiGateway::Method
DependsOn:
- deleteResource
Properties:
HttpMethod: POST
AuthorizationType: "NONE"
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt deleteNote.Arn
ResourceId: !Ref deleteResource
RestApiId: !Ref apiGateway
Upvotes: 3