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

发布于 2025-02-13 01:30:16 字数 1662 浏览 0 评论 0原文

我们正在通过Terraform创建API管理实例和关联的端点。我们所有的API端点(接近一百个)共享相同的策略逻辑,以将请求路由到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,以便我们仅存储在一个位置中?

我已经查看了文件()函数的各种用途,但看不到任何可以完成我需要的事情。

谢谢

We are creating our API management instance and associated endpoints through Terraform. All our API endpoints (close to a hundred) share the same policy logic for routing the request to an Azure function.

An example policy is like so -

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>

So we have the same XML_content being used on every API endpoint, only the variables get set differently depending what function app is going to be routed to.

Is there a way this xml content could be moved into a file where parameters can be passed through to then generate the XML for every API policy so we have the logic stored in only one place?

I have looked at a variety of uses of the file() function but can't see anything that could be done to achieve what I need here.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

脱离于你 2025-02-20 01:30:16

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

templatefile(路径,vars)

其中路径表示文件位置,而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>

请注意,我删除了密码值,并且数据源输出中的数据源输出> url 。这些现在将期望使用名称passwordhostname_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. 使用当前设置,“ $ {其他route-variable}”将在templatefile 函数调用中提供,否则会失败。


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

    中内置的

从理论上讲,如果要创建一个模块以使其更便宜,那么您只需要将path更改为文件,以便可以通过变量提供。


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

[2] https://www.terraform.io/lage.io/lage.io/lageage/lageions/expressions/refress@references# Filesystem-and-workspace-Info

Yes, you can use the templatefile function for that [1]. The templatefile function works in the following way:

templatefile(path, vars)

Where the path represents the file location and the vars are a map of variables that will be used to replace the placeholders in the file itself. I will give an example based on the XML file you have. You would first create the template file inside of the same directory probably (e.g., 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>

Notice that I removed the password value and the data source output in url. Those will now expect variables with names password and hostname_url to be provided when using the templatefile function:

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

Whenever this is called, it will look for the placeholder values and replace them. Two additional things to note:

  1. With the current setup, the "${other-route-variable}" would be required to be provided in the templatefile function call, otherwise it would fail.

  2. The path.root option is built-in in Terraform [2].

In theory, if you were to create a module from this to make it more portable, then you would just have to change the path to the file so it can be provided through a variable probably.


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

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

那伤。 2025-02-20 01:30:16

模板文件需要将var放入括号中。从上面的示例遵循:

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

The templatefile requires the vars to be put into brackets. Following the example from above:

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
  })
} 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文