首页 文章

将来自CloudFormation的ARN引用传递给Swagger

提问于
浏览
2

我们正在尝试使用Amazon CloudFormation和Swagger自动部署AWS lambda和API网关 . 为此,我们创建了一个CloudFormation模板来创建APIGateway所需的Lambda和其他资源(包括 endpoints ) . 我们想从外部swagger文件导入API定义,以便相同的CloudFormation模板可用于多个lambda和APIGateways . 有没有办法可以在外部swagger文件(在同一个CloudFormation模板中引用)中引用由CloudFormation模板创建的lambda的ARN,该文件包含API定义?

Swagger内容:

"x-amazon-apigateway-integration": {
              "uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:TestSimpleProxy/invocations",
              "passthroughBehavior": "when_no_match",
              "httpMethod": "POST",
              "type": "aws_proxy"
            }

在上面的集成方法中,我需要从 Cloud 形成模板中动态替换uri的值 .

我的 Cloud 形成脚本如下:

"myApi":{
      "Type" : "AWS::ApiGateway::RestApi",
      "Properties" : {
        "BodyS3Location" : S3Location of the swagger definition file,
        ..,
        ..
      }
    }

4 回答

  • 0

    New solution:

    现在可以使用新的AWS::Include Transform直接从CloudFormation模板引用上传的模板:

    Api:
      Type: AWS::ApiGateway::RestApi
      Properties:
        Body:
          Fn::Transform:
            Name: AWS::Include
            Parameters:
              Location: !Sub s3://${ArtifactsBucket}/swagger.yaml
    

    其中 ArtifactsBucket 指的是在创建或更新堆栈之前上载Swagger规范的存储桶 . 然后,在Swagger模板中,您可以使用内在函数,例如

    x-amazon-apigateway-integration:
      type: aws_proxy
      httpMethod: POST
      uri:
        Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations
    

    这里我使用的是长 Fn::Sub 符号而不仅仅是 !Sub ,因为Swagger本身并不支持后者,也因为 AWS::Include Transform上的文档说不支持缩写形式 .

    如果使用SAM,也可以使用 AWS::Serverless::ApiDefinitionBody .

    Old workaround:

    另一个(有点hacky,但很简单)解决方案是将Api列为CloudFormation模板中的最后一个资源,并在末尾指定一个带有 : !Sub |- 的空Body .

    然后,您可以将此模板与实际的Swagger文件连接,并使用该文件中的标准 ${} 语法引用任何参数 .

    唯一的一个小问题是,当你为JSON模板工作时,你必须正确地缩进Swagger文件;如果你使用这些,你将不得不用 jq 替换Body .

  • 6

    我只是碰到了同样的障碍......这不是一个简单的答案,而是一种解决方法,可以自动解决你在招摇模板中使用的Lambda ARN的问题;它对我有用 . 开始...

    创建Lambda的

    • Export the Lambda ARN in the CF template 以及稍后要在swagger模板中使用的内容,例如
    Outputs:
      MyLambdaARN:
        Value: !Ref "LambdaFuncThatIsDefinedInTheTemplate"
        Export:
          Name: !Sub "${AWS::StackName}-LambdaARN"
    
    • Refer to the Lambda ARN Export within the swagger template - 代替lambda的ARN,输入包含步骤1中的导出名称的可替换标记,例如"MyLambdaStack-LambdaARN",如果您将步骤1中的堆栈创建为"MyLambdaStack" .

    • 对于令牌语法,让我们使用 wish 实际工作的内容ImportValue function,这样我们的令牌变为 !ImportValue(MyLambdaStack-LambdaARN) .

    • 在我们的招摇模板中,集成扩展使用我们的令牌,如下所示:

    x-amazon-apigateway-integration:
      passthroughBehavior: "when_no_match"
      uri: "!ImportValue(MyLambdaStack-LambdaARN)"
      httpMethod": "POST"
      type: "AWS-PROXY"
    
    • Replace Token with Actual Lambda ARN - 我们将使用以下脚本将 !ImportValue(MyLambdaStack-LambdaARN) 标记替换为我们需要的实际Lambda ARN .
    #!/bin/bash
    SWAGGER_FILE=$1
    
    REPLACEMENTS=$( \
        aws cloudformation list-exports --query 'Exports[*].[Name,Value]'\
        | awk '{print "s/!ImportValue(" $1 ")/" $2 "/g"}' ORS='; '\
    )
    
    sed "$REPLACEMENTS" "$SWAGGER_FILE"
    

    这是这个脚本的作用

    • 使用 aws cloudformation list-exports 抓取堆栈导出列表

    • 使用 --query 'Exports[*].[Name,Value]' 参数过滤到导出名称和值

    • 将导出格式化为一串sed替换,将使用 awk '{print "s/!ImportValue(" $1 ")/" $2 "/g"}' ORS='; ' 替换实际导出值的标记值

    • 最后,使用 sed 将swagger文件中的替换作为脚本的第一个参数传入 .

    例如,如果您将此脚本创建为 resolve-arns.sh ,则可以按如下方式调用它:

    ./resolve-arns.sh swagger.yml > resolved-swagger.yml
    
    • Reference the Resolved Swagger definition - 最后,您将在您用于创建API的CF模板中引用 resolved-swagger.yml 文件,例如 BodyS3Location: resolved-swagger.yml

    CAVEATS:

    • 当然 aws 命令行工具需要可用和配置

    • 此实现不够复杂,无法处理AWS区域参数......但可以对其进行修改

    • 这是一个bash脚本......如果你're on a different OS like windows the same approach should work but the implementation would be different (I'从PowerShell开始可能......)

  • 1

    这是 "x-amazon-apigateway-integration" 您的CloudFormation模板的一部分吗?

    如果是这样,那么按照https://blog.jayway.com/2016/09/18/introduction-swagger-cloudformation-api-gateway/中的示例,我认为您可以使用Ref函数来传递该信息 .

  • 0

    还有另一种方法,即 less complicated 方法 . 如果使用 Body 属性而不是 BodyS3Location AWS::ApiGateway::RestApi ,则可以使用Cloud Formation Instrinsic Functions在swagger模板中引用或动态构建所需的ARN .

    ...当然缺点是你的招摇模板嵌入在CF脚本中而不是单独的文件中 .

相关问题