如何为AWS API Gateway动态创建子资源?避免代码重复
Absolutely! You can dynamically create AWS API Gateway resources and methods in Terraform to avoid repetitive hardcoding—using structured configuration (like lists or maps) with Terraform's for_each meta-argument is exactly the right approach here.
Step 1: Define Structured Path Configuration
First, create a local value (or variable) that maps out all your API path segments, including their parent relationships. This makes it easy to add/remove paths later without rewriting resource blocks:
locals { api_path_hierarchy = [ { resource_name = "customers" parent_ref = "" # Empty string means root resource path_part = "customers" }, { resource_name = "single-customer" parent_ref = "customers" path_part = "{customerId}" }, { resource_name = "customers-accounts" parent_ref = "single-customer" path_part = "accounts" }, { resource_name = "single-account" parent_ref = "customers-accounts" path_part = "{accountId}" } ] }
Step 2: Dynamically Create API Gateway Resources
Use for_each to loop through your path hierarchy and create each resource. The key here is dynamically resolving the parent resource ID—either the API root ID or the ID of the parent resource we just created:
resource "aws_api_gateway_rest_api" "my-api" { name = "MyCustomerAPI" description = "API for customer account management" } resource "aws_api_gateway_resource" "dynamic_paths" { for_each = { for path in local.api_path_hierarchy : path.resource_name => path } rest_api_id = aws_api_gateway_rest_api.my-api.id # Resolve parent ID: use root if parent_ref is empty, else reference the parent resource parent_id = each.value.parent_ref == "" ? aws_api_gateway_rest_api.my-api.root_resource_id : aws_api_gateway_resource.dynamic_paths[each.value.parent_ref].id path_part = each.value.path_part }
Step 3: Dynamically Add API Methods
You can extend this pattern to create methods (like your GET example) too. Define another structured config for methods, then loop through it:
locals { api_method_configs = [ { resource_name = "customers-accounts" http_method = "GET" authorization = "NONE" }, { resource_name = "single-account" http_method = "GET" authorization = "NONE" } ] } resource "aws_api_gateway_method" "dynamic_methods" { for_each = { for method in local.api_method_configs : "${method.resource_name}-${method.http_method}" => method } rest_api_id = aws_api_gateway_rest_api.my-api.id resource_id = aws_api_gateway_resource.dynamic_paths[each.value.resource_name].id http_method = each.value.http_method authorization = each.value.authorization }
Key Notes for Success
- Ensure
parent_refvalues inapi_path_hierarchyexactly match theresource_nameof the parent path—this is how Terraform links the resources together. - If you want to parse full path strings (like
/customers/{customerId}/accounts) directly, you can split the string into segments and generate the hierarchy programmatically (using Terraform'ssplit()function) for even less manual configuration. for_eachis preferred overcounthere because it uses meaningful resource names instead of numeric indices, which prevents accidental resource destruction/recreation if you reorder your path list.
内容的提问来源于stack exchange,提问作者shadow

