【问题标题】:Terraform - Passing type Object as a parameter to Azure Template DeploymentTerraform - 将类型对象作为参数传递给 Azure 模板部署
【发布时间】:2026-01-14 11:45:02
【问题描述】:

我打算通过向 Terraform 提供 Azure ARM 模板来使用 Terraform 配置 Azure AD 域服务,这是因为 Terrafrom 不支持原生配置 Azure AD 域服务。

我已经导出了 ARM 模板及其参数,其中一个参数称为 "notificationSettings",它是 Object 类型,如下所示:

    "notificationSettings": {
        "value": {
            "notifyGlobalAdmins": "Enabled",
            "notifyDcAdmins": "Enabled",
            "additionalRecipients": []
        }
    }

其他参数都是strings,我可以毫无问题地传递它们,例如:

"apiVersion" = "2017-06-01"

我已尝试将此对象传递给如下参数:

"notificationSettings" = [{
                "notifyGlobalAdmins" = "Enabled"
            "notifyDcAdmins" ="Enabled"
            "additionalRecipients" = []
}]

但是,当我执行terrafrom apply 时,terrafrom 抱怨说:

属性“参数”的值不合适:元素 “notificationSettings”:需要字符串。

如何将 Object 的参数类型传递给template body

我还尝试使用parameters_body 选项将整个 ARM json 参数作为文件提供给 terrafrom,如下所示:

parameters_body = "${file("${path.module}/temp/params.json")}"

但是,执行 terrafrom 脚本时出现以下错误:

请求内容无效,无法反序列化:'Error 转换价值 "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#" 输入 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Data.Definitions.DeploymentParameterDefinition'。 路径 'properties.parameters.$schema',第 1 行,位置 2952。'。

下面是params.json 文件:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "apiVersion": {
            "value": "2017-06-01"
        },
        "sku": {
            "value": "Standard"
        "location": {
            "value": "westus"
        },
        "notificationSettings": {
            "value": {
                "notifyGlobalAdmins": "Enabled",
                "notifyDcAdmins": "Enabled",
                "additionalRecipients": []
            }
        },
        "subnetName": {
            "value": "xxxx"
        },
        "vnetName": {
            "value": "xxxx"
        },
        "vnetAddressPrefixes": {
            "value": [
                "10.0.1.0/24"
            ]
        },
        "subnetAddressPrefix": {
            "value": "10.0.1.0/24"
        },
        "nsgName": {
            "value": "xxxxx"
        }
    }
}

【问题讨论】:

    标签: terraform terraform-provider-azure


    【解决方案1】:

    有一种方法可以将任意数据结构从 Terraform 传递到 ARM。

    有两种方法可以在 azure_template_deployment 提供程序中将数据传递到 ARM 模板

    • 使用parameters 块,该块仅限于字符串参数
    • 使用parameters_body 块,这几乎是任意的JSON。

    我发现使用参数块最简单的方法是创建一个具有我需要的结构的局部变量,然后在其上调用jsonencode。我还喜欢将 ARM 模板保存在单独的文件中,并通过 file() 调用将其拉入,从而降低 terraform 的复杂性。

    locals {
      location = "string"
      members = [
        "array",
        "of",
        "members"
      ]
      enabled = true
      tags = {
        "key" = "value",
        "simple" = "store"
      }
    
      # this is the format required by ARM templates
      parameters_body = {
        location = {
          value = "${local.location}"
        },
        properties = {
          value = {
            users = {
              members = "${local.members}"
            }
            boolparameter = "${local.enabled}"
          }
        }
        tags = {
          value = "${module.global.tags}"
        }
      }
    }
    
    resource "azurerm_template_deployment" "sample" {
      name = "sample"
      resource_group_name = "rg"
      deployment_mode = "Incremental"
      template_body = "${file("${path.module}/arm/sample_arm.json")}"
      parameter_body = "${jsonencode(local.parameters_body)}"
    }
    

    我发现的唯一警告是 bool 参数作为字符串传递,因此在 ARM 参数部分将它们声明为字符串,然后使用 ARM 函数转换为 bool

    "parameters: {
      "boolParameter": {
         "type": "string"
      }
    },
    "variables": {
      "boolVariable": "[bool(parameters('boolParameter'))]"
    },
    "resources": [
      ...
      "boolArm": "[variables('boolVariable')]",
      ...
    ]
    

    【讨论】:

    • 而不是使用本地人,我可以只将整个 json 参数提供给 parameter_body ,类似于您为 template_body 读取文件的方式吗?我实际上已经尝试过了,但我遇到了与 api 版本控制和架构相关的错误
    • 是的,如果您的 JSON 没有动态部分,只需从文件系统中提取。您还可以使用heredoc 样式内联。请参阅Ivan Ignatiev 了解他的观点,你的听起来很简单。
    • 谢谢您,您与我分享的文章帮助解决了问题。使用本地人将需要更多的代码行和更多的复杂性。请您更新您的答案好吗?
    • 如何更新答案?这篇文章也使用了heredoc——你想用heredoc而不是本地人来回答吗?似乎是一个小重构。
    • @Leif 您是否找到了另一种传递布尔参数的方法?我现在正在为数字(整数)参数苦苦挣扎,想知道是否有一种在参数部分定义它们的好方法