Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing ARN reference from CloudFormation to Swagger

We are trying to automate the deployment of AWS lambda and API gateway using Amazon CloudFormation and Swagger. Towards this, we have created a CloudFormation template to create the Lambda and other resources required for APIGateway (including the endpoints). We would like to import the API definitions from an external swagger file so that the same CloudFormation template can be used for multiple lambdas and APIGateways. Is there a way we can refer the ARN of the lambda which has been created by the CloudFormation template in the external swagger file (being referred to in the same CloudFormation template) which holds the API definition?

Swagger content:

"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"
            }

In the above integration method I need to replace the value of the uri dynamically from the cloud formation template.

My cloud formation script is as below:

"myApi":{
      "Type" : "AWS::ApiGateway::RestApi",
      "Properties" : {
        "BodyS3Location" : S3Location of the swagger definition file,
        ..,
        ..
      }
    }
like image 869
Jeffrey M Avatar asked Dec 21 '16 15:12

Jeffrey M


1 Answers

New solution:

It is now possible to use the new AWS::Include Transform to reference the uploaded template directly from a CloudFormation template:

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

where ArtifactsBucket refers to the bucket where you upload Swagger spec before you create or update your stack. Then, in the Swagger template itself you can use the intrinsics, e.g.

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

Here I'm using the long Fn::Sub notation instead of just !Sub, because Swagger doesn't natively support the latter, and also because the docs on AWS::Include Transform say that shorthand forms are not supported yet.

You can also use AWS::Serverless::Api and DefinitionBody if you use SAM.

Old workaround:

Another (somewhat hacky, yet simple) solution is to list the Api as the last resource in the CloudFormation template, and specify an empty Body with : !Sub |- at the end.

You can then concatenate this template with the actual Swagger file, and reference any parameters using the standard ${} syntax in that file.

The only minor complication is that you have to properly indent the Swagger file when concatenating it when you're using YAML (this approach won't work for JSON templates though; you'll have to substitute Body with something like jq if you use these).

like image 165
dinvlad Avatar answered Sep 18 '22 22:09

dinvlad