I am trying to create the aws_api_gateway resources using terraform, to avoid the hassle of adding the same code again and again, am trying to create a loop which create multiple resources for me in the order i specify. But, I am facing difficulties as I am new to this and it is always complaining of cyclic dependency.
The cyclic dependency is caused in "parent_id" while creating resources
Any Help would be greatly appreciated.
Here's what I have coded:
locals {
api_endpoints = [
{
path = "v0"
http_method = "GET"
integration_uri = "${uri_path}/v0"
},
{
path = "v0/expert/gen/btags"
http_method = "POST"
integration_uri = "${uri_path}/v0/expert/gen/btags"
},
{
path = "v0/expert/generate/tags"
http_method = "POST"
integration_uri = "${uri_path}/v0/expert/gen/tags"
},
{
path = "v0/expert/search"
http_method = "POST"
integration_uri = "${uri_path}/v0/expert/search"
},
]
resources_hierarchy = {
"v0" = aws_api_gateway_rest_api.gatewayh.root_resource_id
"expert" = "v0"
"gen" = "expert"
"search" = "expert"
"btags" = "gen"
"tags" = "gen"
}
}
resource "aws_api_gateway_resource" "api_resource" {
for_each = local.resources_hierarchy
rest_api_id = aws_api_gateway_rest_api.gatewayh.id
parent_id = each.value == aws_api_gateway_rest_api.gatewayh.root_resource_id ? each.value : aws_api_gateway_resource.api_resource[each.value].id
path_part = each.key
}
The full Amazon API Gateway schema is challenging to construct dynamically in Terraform because it ends up requiring resources that depend on themselves. Dependencies in Terraform are between
resource
blocks as a whole rather than the individual instances of them, because Terraform must evaluatefor_each
orcount
before knowing which instances exist and those expressions can themselves have dependencies.However, you can avoid that problem by using the OpenAPI-based method for describing your API, which follows a flat structure similar to what you've shown as your input. The API Gateway API internally transforms that into the corresponding individual resources, resource methods, integration methods, etc, so the result is the same but constructed in a way that doesn't involve as many resources and doesn't involve any dependencies between the objects.
For example:
The above uses
for
expressions to derive a data structure that follows the OpenAPI spec for describing methods associated with paths, and uses thex-amazon-apigateway-integration
extension, specific to Amazon API Gateway, to describe what each operation integrates with. It then usesjsonencode
to encode that resulting data structure into a form that API Gateway can parse and analyze.When you define an API Gateway REST API with a
body
argument, you don't need to use any other resources to describe the schema; the information inbody
describes the same tree of resources in a different way. You will still need resources for the deployment, stages, etc, though, because they are independent of the actual API definition.OpenAPI uses a flat structure -- all paths listed together as a single map, rather than resources nested inside one another -- and so that's a better fit both for the way your input data is structured and for describing this in a form that doesn't cause problems for Terraform's dependency graph.
References:
aws_api_gateway_rest_api
resource type in thehashicorp/aws
provider (and in particular, the OpenAPI example)jsonencode
functionfor
expressions in Terraform, which allow you to project collection values from one shape to another, so you can reshape your input into a valid OpenAPI schema as API Gateway requires.