apostrophedottilde
apostrophedottilde

Reputation: 877

API gateway - how to split nested REST resources across different terraform deployments

I am making an HTTP API in AWS. Most of my logic is handled in lambda functions. I use terraform to describe and deploy my infrastructure. So far this is going well.

I have a single project that has lambdas for CRUD operations

GET /journal
POST /journal
GET /journal/{id}
PUT /journal/{id}
DELETE /journal/{id}

The code and infrastructure are all currently inside a monorepo.

Its now time to add endpoints for nested resources

for example...

/journals/{id}/sentence/{id} 

and

/journals/{id}/sentence/{id}/correction

I really want the code and terraform for these sub-resources to be in a separate project because it's going to get very, very big.

I am really struggling to figure out how to make sub-resources for API gateway that exist in multiple separately deployed projects.

I want to avoid exporting the ARNs for the api-gateway resources and using them in other projects as I don't think it's a great idea to create dependencies between separate deployments.

I would really appreciate hearing any advice on how this could be managed as I am sure many people have faced this issue.

Is it possible to use route53 to route all API calls on a domain to lots of separate API gateways? If this is possible then this make life much easier. I am really struggling to find documentation or literature that explains anything beyond creating an API with single resource endpoints.

Edit: I had one other idea that maybe all my lambda projects could be completely ignorant of the api-gateway and just have their ARNs exported as outputs. Then I could have a completely separate project which defines the whole api-gateway and creates lambda integrations which simply use the function ARNs exported by the function in the other projects. This would prevent each lambda project from needing to reference the api_gateway_resource of the corresponding parent resource. I feel like this may not be a good idea though.

Upvotes: 0

Views: 1619

Answers (1)

TaiT's
TaiT's

Reputation: 3216

I want to avoid exporting the ARNs for the api-gateway resources and using them in other projects as I don't think it's a great idea to create dependencies between separate deployments.

I am not sure about that statement. Independently of the way you go, you will have dependencies anyway between your project that creates the API GW and the lambda sub project.

So far I understood the question is in which direction you should create this dependency:

  • export the apigw and reuse it in the lambda project
  • export the lambda and reuse it in the apigw project

I think it makes sense for the lambda to be considered as independent piece of infrastructure in your terraform project and not create any kind of apigw related resource in it. First of all because in such case it already creates a strong implicit dependency and constraint on the usage of your lambda. And secondly you can think this way: what if your project grow more and more and you need to add more and more lambdas to your API. In such scenario you probably don't want to create each time new methods/resources and it's probably more convenient to use something like for_each in terraform and write your code one single time and automatically creates new integrations when you add new lambda.

Hence I would avoid the first choice and go for the second option which is way cleaner from an architectural stand point. Everything that deals with API GW stays in the same project. Your edits point it out to the right direction. You could have one repo for the "Infrastructure" (call it whatever you want) and one for "Lambda". You could output the lambda ARNs as a list (or a custom map with other key parameters) and use remote state from the apigw project to loop through your lambda and create the needed resource in one single place with for_each.

For example, use the remote state from apigw project:

data "terraform_remote_state" "lambda" {
  backend = "s3"
  config = {
    bucket = "my-bucket"
    key    = "my/key/state/for/lambda"
    region = "region"
  }
}

And use the outputs like this:

resource "aws_api_gateway_integration" "lambda" {
  for_each = data.terraform_remote_state.lambda.outputs.lambdas
  ...
  uri = each.value
}

Is it possible to use route53 to route all API calls on a domain to lots of separate API gateways? If this is possible then this make life much easier. .

Sorry I am not sure to understand that point but I will still try to detail a bit the topic. The "link" API gateway provides you to call your api is just a DNS. When you create an API, behind the scenes AWS creates a CloudFront distribution for you in us-east-1 region. You don't have access to it through the console because it's managed by AWS. When you map an API to a domain name, you actually map the domain to the CloudFront distribution of your API. When you add methods or resources to your API (this is what you do with your lambda), you actually don't create new APIs each time.

Upvotes: 1

Related Questions