我正在使用无服务器版本1.29.2
我创建了一个初始cloudformation脚本,该脚本创建了一个API GateWay REST API,该API将被其他服务使用。这是负责它的cloudformation脚本。
{
"AWSTemplateFormatVersion":"2010-09-09",
"Description":"API",
"Resources":{
"APIGw":{
"Type":"AWS::ApiGateway::RestApi",
"Properties":{
"Name":"API-GW"
}
}
},
"Outputs":{
"ApiGwRestApiId":{
"Value":{
"Ref":"APIGw"
},
"Export":{
"Name":"apigw-restApiId"
}
},
"eyesApiGwRestApiRootResourceId":{
"Value":{
"Fn::GetAtt":[
"APIGw",
"RootResourceId"
]
},
"Export":{
"Name":"apigw-rootResourceId"
}
}
}
}
这里是我尝试部署的应用程序的serverless.yml。
service: template-test-service
provider:
name: aws
runtime: python3.6
region: eu-central-1
stage: ${self:custom.environment.stage}
environment:
stage: ${self:custom.environment.stage}
apiGateway:
restApiId:
'Fn::ImportValue': apigw-restApiId
restApiRootResourceId:
'Fn::ImportValue': apigw-rootResourceId
当我执行sls deploy --stage dev
时一切正常,但是当我执行另一次部署到sls deploy --stage prod
出现此错误。
Another resource with the same parent already has this name
答案 0 :(得分:0)
我已经为这个问题苦苦了一个星期,而问题是与从资源和方法中构造API网关的方式有关。从文档中
在Amazon API Gateway中,您将REST API构建为称为API Gateway资源的可编程实体的集合。例如,您使用RestApi资源表示可以包含Resource实体集合的API。每个资源实体又可以具有一个或多个方法资源。在请求参数和主体中表示的方法定义了客户端访问公开资源的应用程序编程接口,并表示客户端提交的传入请求。
当具有通过http事件触发的功能时,无服务器CLI将为您创建所有资源/方法。
functions:
GetScenesInGame:
handler: handler.hello
layers: arn:aws:lambda:eu-west-1:xxxxxxxxx:layer:pynamodb-layer:1
events:
- http:
method: GET
path: api/v1/game/{gameId}/scene
在上面的示例中,这将创建五个资源(api,v1,game,gameIdParam,场景),最后在最终资源上添加一个GET方法。
不幸的是,如果您有两个单独的堆栈(如您在微服务设置中可能的那样),如果它们是上述方法的一部分,则会出现错误,具有相同父级的另一个资源已经具有此名称 < / p>
本文从无服务器deploy serverless microservice on aws着重介绍了该解决方案,尽管该解决方案不是很明确,也很容易遗漏。
首先,有一个用于配置所需资源的顶级cloudformation模板。
对于要添加无服务器微服务的资源,请将该资源的ID导出为堆栈中的输出变量。
然后在serverless.yml文件中导入api网关引用和apigateway资源ID。
然后您可以部署每个服务,而不会在api结构中出现资源名称冲突。
下面的模板显示了一组顶级资源。
api/v1/game/{gameId}/page
api/v1/game/{gameId}/scene
然后将 PageService 附加到 page 资源和 SceneService 附加到 scene 资源。
AWSTemplateFormatVersion: "2010-09-09"
Description: "S3 template for deploying S3 to be used by ACS s3 connector."
Resources:
TestApiGw:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub 'test-apigw-throwaway'
ApiResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !GetAtt
- TestApiGw
- RootResourceId
PathPart: "api"
VersionResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !Ref ApiResource
PathPart: "v1"
GameResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !Ref VersionResource
PathPart: "game"
GameParamResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !Ref GameResource
PathPart: "{gameId}"
SceneResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !Ref GameParamResource
PathPart: "scene"
PageResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref TestApiGw
ParentId: !Ref GameParamResource
PathPart: "page"
Outputs:
ApiRestApiId:
Value: !Ref TestApiGw
Export:
Name: !Sub ${AWS::StackName}-TestApiId
ApiRootResourceId:
Value:
Fn::GetAtt:
- TestApiGw
- RootResourceId
Export:
Name: !Sub ${AWS::StackName}-ApiRootResourceVar
ApiSceneResourceVar:
Value: !Ref SceneResource
Export:
# variable names are global so this will need more work to make it unique across stages.
Name: !Sub ${AWS::StackName}-ApiSceneResourceVar
ApiPageResourceVar:
Value: !Ref PageResource
Export:
# variable names are global so this will need more work to make it unique across stages.
Name: !Sub ${AWS::StackName}-ApiPageResourceVar
service: scrap-page-service
provider:
name: aws
runtime: python2.7
apiGateway:
restApiId:
"Fn::ImportValue": throw-stack-1-TestApiId
restApiRootResourceId:
"Fn::ImportValue": throw-stack-1-ApiPageResourceVar
functions:
hello:
handler: handler.hello
events:
- http:
path: ""
method: get
service: scrap-scene-service
provider:
name: aws
runtime: python2.7
apiGateway:
restApiId:
"Fn::ImportValue": throw-stack-1-TestApiId
restApiRootResourceId:
"Fn::ImportValue": throw-stack-1-ApiSceneResourceVar
functions:
hello:
handler: handler.hello
events:
- http:
path: ""
method: get
希望这可以帮助其他人解决此问题,如果有人有更好的解决方法,我很想知道:-)
答案 1 :(得分:-1)
看看Serverless documentation on sharing API Gateway吗?
看来您必须创建的通用资源路径组件是CloudFormed对象