如何在Terraform API管理资源中共享xml_content



我们正在通过Terraform创建API管理实例和相关端点。我们所有的API端点(接近100个)共享相同的策略逻辑,将请求路由到Azure函数。

策略示例如下-

resource "azurerm_api_management_api_operation_policy" 
"api_put_policy" {
api_name            = azurerm_api_management_api.my_api.name
resource_group_name = azurerm_resource_group.main.name
api_management_name = azurerm_api_management.my_api.name
operation_id        = azurerm_api_management_api_operation.my_api.operation_id
xml_content = <<XML
<policies>
<inbound>
<base />
<choose>
<when condition="@(context.Request.Headers.GetValueOrDefault("Key") == "password")">
<set-backend-service base-url="${data.azurerm_function_app.MyFunctionApp.default_hostname}" />
</when>
<when condition="@(context.Request.Headers.GetValueOrDefault("Key") != null)">
<return-response>
<set-status code="400" reason="Bad Request" />
<set-body>An incorrect Key header has been passed in the request</set-body>
</return-response>
</when>
<otherwise>
<set-backend-service base-url="${other-route-variable}" />
</otherwise>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>

所以我们在每个API端点上使用相同的XML_content,只是变量的设置不同,这取决于应用程序将被路由到的函数。

是否有一种方法可以将此xml内容移动到一个文件中,其中参数可以通过,然后为每个API策略生成xml,以便我们将逻辑存储在一个地方?

我看了各种各样的文件()函数的使用但什么也看不见,可以实现我所需要的东西。

感谢

是的,您可以使用templatefile函数[1]。templatefile函数的工作方式如下:

templatefile(路径,var)

其中path表示文件位置,vars是将用于替换文件本身中的占位符的变量映射。我将根据您拥有的XML文件给出一个示例。首先,您可能会在同一目录中创建模板文件(例如,xml_content.tpl):

<policies>
<inbound>
<base />
<choose>
<when condition="@(context.Request.Headers.GetValueOrDefault("Key") == ${password})">
<set-backend-service base-url="${hostname_url}" />
</when>
<when condition="@(context.Request.Headers.GetValueOrDefault("Key") != null)">
<return-response>
<set-status code="400" reason="Bad Request" />
<set-body>An incorrect Key header has been passed in the request</set-body>
</return-response>
</when>
<otherwise>
<set-backend-service base-url="${other-route-variable}" />
</otherwise>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>

注意,我删除了password值和url中的数据源输出。那些将现在预期password这样的变量名和hostname_url提供当使用templatefile功能:

resource "azurerm_api_management_api_operation_policy" "api_put_policy" {
api_name            = azurerm_api_management_api.my_api.name
resource_group_name = azurerm_resource_group.main.name
api_management_name = azurerm_api_management.my_api.name
operation_id        = azurerm_api_management_api_operation.my_api.operation_id
xml_content  = templatefile("${path.root}/xml_content.tpl", 
password     = var.password
hostname_url = data.azurerm_function_app.MyFunctionApp.default_hostname
)
}

无论何时调用,它都会查找占位符值并替换它们。还有两件事需要注意:

  1. 在当前的设置中,"${other-route-variable}"需要在templatefile函数调用中提供,否则会失败。

  2. path.root选项是内置在Terraform[2]。

从理论上讲,如果您要以此为基础创建一个模块以使其更具可移植性,那么您只需将path更改为文件,以便可能通过变量提供它。


[1] https://www.terraform.io/language/functions/templatefile

[2] https://www.terraform.io/language/expressions/references filesystem-and-workspace-info

最新更新