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

时间:2016-12-21 15:34:40

标签: amazon-web-services swagger aws-lambda aws-api-gateway amazon-cloudformation

我们正在尝试使用Amazon CloudFormation和Swagger自动部署AWS lambda和API网关。为此,我们创建了一个CloudFormation模板来创建APIGateway所需的Lambda和其他资源(包括端点)。我们希望从外部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"
            }

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

我的云形成脚本如下:

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

4 个答案:

答案 0 :(得分:6)

新解决方案:

现在可以使用新的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上的文档变换说不支持速记形式。

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

旧的解决方法:

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

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

唯一的小问题是,当你使用YAML连接时,你必须正确缩进Swagger文件(这种方法不适用于JSON模板;你必须替换如果您使用这些内容,请使用jq之类的内容。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

我遇到了同样的障碍......这是 NOT 一个简单的答案,但是一种解决方法可以自动解决你想要使用的Lambda ARN招摇模板;它对我有用。这就是......

  1. 导出创建Lambda的CF模板中的Lambda ARN,以及稍后要在swagger模板中使用的内容,例如

    Outputs:
      MyLambdaARN:
        Value: !Ref "LambdaFuncThatIsDefinedInTheTemplate"
        Export:
          Name: !Sub "${AWS::StackName}-LambdaARN"
    
  2. 请参阅招摇模板中的Lambda ARN导出 - 代替lambda的ARN ,输入可替换令牌包括步骤1中的导出名称,例如“MyLambdaStack-LambdaARN”,如果您将步骤1中的堆栈创建为“MyLambdaStack”。

    • 对于令牌语法,让我们使用希望实际工作的内容ImportValue function,以便我们的令牌变为!ImportValue(MyLambdaStack-LambdaARN)
    • 在我们的招摇模板中,集成扩展程序使用我们的令牌:

      x-amazon-apigateway-integration:
        passthroughBehavior: "when_no_match"
        uri: "!ImportValue(MyLambdaStack-LambdaARN)"
        httpMethod": "POST"
        type: "AWS-PROXY" 
      
  3. 用实际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"
    

    这是这个脚本的作用

    1. 使用aws cloudformation list-exports
    2. 获取堆栈导出列表
    3. 使用--query 'Exports[*].[Name,Value]'参数
    4. 过滤到导出名称和值
    5. 将导出格式化为一系列sed替换,将使用awk '{print "s/!ImportValue(" $1 ")/" $2 "/g"}' ORS='; '
    6. 的实际导出值替换标记值
    7. 最后,使用sed将swagger文件中的替换作为脚本的第一个参数传入。
    8. 例如,如果您将此脚本创建为resolve-arns.sh,则可以按如下方式调用它:

      ./resolve-arns.sh swagger.yml > resolved-swagger.yml
      
    9. 引用已解决的Swagger定义 - 最后,您将引用您用于创建API的CF模板中的resolved-swagger.yml文件,例如BodyS3Location: resolved-swagger.yml

    10. <强>注意事项:

      1. 当然,aws命令行工具需要可用且已配置
      2. 此实现不够复杂,无法处理AWS区域参数......但可以针对该
      3. 进行修改
      4. 这是一个bash脚本...如果你在不同的操作系统上像windows一样,同样的方法应该可以工作,但实现方式会有所不同(我可能会从powershell开始......)