【问题标题】:ARM template parameter object array into template arrayARM模板参数对象数组转化为模板数组
【发布时间】:2017-11-02 16:34:06
【问题描述】:

我们正在尝试使用参数对象创建模板,因此可以选择在不同资源中具有多个值,即部署一个事件中心命名空间,该命名空间可能具有多个授权规则和 eventthub,但参数中的另一个对象一秒钟可能只有一个的事件中心命名空间。

模板如下:

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "eventhubs": {
      "type": "object",
      "metadata": {
        "description": "JSON object that describes the deployment. see example parameters file"
      }
    }
  },
  "variables": {
      "resourceNamePrefix": "[substring(resourceGroup().name, 0, 8)]",
      "datacenterCode": "[substring(resourceGroup().name, 0, 3)]",
      "productCode": "[substring(resourceGroup().name, 3, 3)]",
      "environmentLevel": "[substring(resourceGroup().name, 6, 2)]"
  },
"resources": [
  {
    "type": "Microsoft.EventHub/namespaces",
    "name": "[concat(variables('resourceNamePrefix'), parameters('eventhubs').instances[copyIndex()].name)]",
    "apiVersion": "2015-08-01",
    "location": "[resourceGroup().location]",
    "sku": {
      "name": "[concat(variables('resourceNamePrefix'), parameters('eventhubs').instances[copyIndex()].sku.name)]",
      "tier": "[parameters('eventhubs').instances[copyIndex()].sku.tier]",
      "capacity": "[parameters('eventhubs').instances[copyIndex()].sku.capacity]"
    },
    "copy": {
      "name": "eventHubCopy",
      "count": "[length(parameters('eventhubs').instances)]"
    },
    "properties": {
      "serviceBusEndpoint": "[concat('https://',variables('resourceNamePrefix'), parameters('eventhubs').instances[copyIndex()].name,'.servicebus.windows.net:443/')]",
      "enabled": "[parameters('eventhubs').instances[copyIndex()].properties.enabled]"
    },
    "resources": [
        *** PARAMETER OBJECT ***
    ]
    "dependsOn": []
      }
    ],
    "outputs": {}
  }

还有参数文件:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
  "parameters": {
    "eventhubs": {
      "value": {
        "instances": [
          {
            "name": "EVT001",
            "sku": {
              "name": "Standard",
              "tier": "Standard",
              "capacity": 4
            },
            "scale": null,
            "properties": {
              "enabled": "true"
            },
            "resources": [
              {
                "type": "AuthorizationRules",
                "name": "SendKey",
                "apiVersion": "2015-08-01",
                "properties": {
                  "rights": [
                    "Send"
                  ]
                }
              },
              {
                "type": "AuthorizationRules",
                "name": "ListenKey",
                "apiVersion": "2015-08-01",
                "properties": {
                  "rights": [
                    "Listen"
                  ]
                }
              },
              {
                "type": "EventHub",
                "name": "TestHub",
                "apiVersion": "2015-08-01",
                "properties": {
                  "messageRetentionInDays": 7,
                  "status": "Active",
                  "partitionCount": 4
                }
              }
            ]
          },
          {
            "name": "EVT002",
            "sku": {
              "name": "Standard",
              "tier": "Standard",
              "capacity": 4
            },
            "scale": null,
            "properties": {
              "enabled": "true"
            },
            "resources": [
              {
                "type": "AuthorizationRules",
                "name": "SendKey",
                "apiVersion": "2015-08-01",
                "properties": {
                  "rights": [
                    "Send"
                  ]
                }
              },
              {
                "type": "EventHub",
                "name": "TestHub",
                "apiVersion": "2015-08-01",
                "properties": {
                  "messageRetentionInDays": 7,
                  "status": "Active",
                  "partitionCount": 4
                }
              },
              {
                "type": "EventHub",
                "name": "SecondHub",
                "apiVersion": "2015-08-01",
                "properties": {
                  "messageRetentionInDays": 7,
                  "status": "Active",
                  "partitionCount": 4
                }
              }
            ]
          }
        ]
      }
    }
  }
}

我正在尝试做的是将参数文件中资源数组的内容移动到模板文件中的嵌套资源数组中。将数组移入对象时这是可能的,但我在将数组移入数组时遇到以下问题:

"resources": "[parameters('eventhubs').instances[copyIndex()].properties]", <--- value must be of type array
"resources": [ { "[parameters('eventhubs').instances[copyIndex()].properties]" } ],  <--- expecting a name and value as it's in an object 
 "resources": [ "[parameters('eventhubs').instances[copyIndex()].properties]" ], <--- value must be of the following types: object

在参数文件的数组中的对象周围添加另一组方括号也无济于事。

使用 createArray 函数时出现同样的错误。

我的解决方法是做

    "resources": [
  {
    "type": "AuthorizationRules",
    "name": "[parameters('eventhubs').instances[copyIndex()].resources[0].name]",
    "apiversion": "[parameters('eventhubs').instances[copyIndex()].resources[0].apiversion]",
    "properties": "[parameters('eventhubs').instances[copyIndex()].resources[0].properties]",
    "dependsOn": [ "[concat(variables('resourceNamePrefix'), parameters('eventhubs').instances[copyIndex()].name)]" ]
  }
],

但 type 属性不能是表达式,因此不适用于我们的模板的消费和使用方式。

有可能做我正在尝试的事情吗?

【问题讨论】:

  • 我怀疑你能否实现你想要的 + 你的参数文件看起来已经像一个模板,这没有任何意义。你应该重新考虑你在做什么。你故意让你过得更艰难,为什么?
  • 这些参数文件将被我们公司的其他团队使用。我们希望在模板中定义某些不可更改的标准值,并在参数文件中定义可配置的值。这也意味着我们不需要管理和重新使用可能具有不同属性和布局的其他模板文件的负载,只需要(应该)都使用固定模板文件的参数文件。如果我按照自己的方式行事,我们甚至不会为此使用 ARM,而是 wcyd
  • 在 Azure 中不使用 arm 模板进行大型\复杂部署实际上是您能做的最愚蠢的事情。无论如何,你可以实现你的最终目标,只是不是用这种方法
  • 你有什么建议?使用对象是 MS 文档中针对大型部署的建议之一,在这种部署中,您可能会用完参数,并且模板本身需要由多个不同的项目使用,因此很难调整 T 恤大小。这在理论上应该有效,因为它可以将数组转换为对象,只是验证失败,因为它在从参数表达式替换它之前需要一个数组

标签: azure azure-resource-manager azure-template


【解决方案1】:

这不会真正适合答案(遗憾的是,我没有时间输入所有解释),但您基本上希望将配置和实现分开(这是明智的做法),但是ARM 模板并不像您想象的那么简单。我将尝试创建一个 mcve。它会很抽象,但你只需要这个想法。

所以前提:你需要部署X个不同属性的资源。

您的配置数据如下所示:

"eventhubs": [
    {
        "name": "EVT001",
        "sku": skuobject,
        "scale": null,
        "properties": propertiesobject,
        "resources": [
            nestedobject,
            nestedobject,
            nestedobject
        ]
    },
    parentobject,
]

这个对象是嵌套在数组内的对象在数组内的父对象内(我建议你删除最外面的对象,因为它没有用,除了增加复杂性之外什么都不做)。您的行动方案,在复制循环中迭代最外层(父对象)数组并尝试在资源属性中迭代最内层(嵌套对象)数组。这不适用于 ARM 模板。

使用 arm 模板,您只能迭代一层深度(使用循环,使用硬代码,您可以根据需要进行任意深度),因此您需要做的是将配置对象拆分为 1 层深度的对象。您的对象是 2 级深(父对象数组和嵌套对象数组)。您可以使用嵌套部署来做到这一点。

你需要做的是这样的:

{
    "name": "[concat('nested-', copyIndex())]",
    "type": "Microsoft.Resources/deployments",
    "apiVersion": "2016-06-01",
    "copy": {
        "name": "eventHubLoop",
        "count": "[length(parameters('eventhubs'))]" (this should be an array)
    },
    "properties": {
        "mode": "Incremental",
        "templateLink": {
            "uri": "xxx",
            "contentVersion": "1.0.0.0"
        },
        "parameters": {
            "currentIteration": {
                "value": "[parameters('eventhubs')[copyIndex()]]"
            }
        }
    }
}

并且您的嵌套模板应该是父资源(没有副本,因为它始终是单个资源,我们通过上面的循环处理了这一点)和属性\资源循环。不幸的是,我没有一个方便的例子(nda),但我希望你能明白。您需要创建 2 个不同的循环,这样您就可以处理嵌套级别,如果您有 3 个嵌套级别,则需要 3 个不同的循环(您可以通过相同的方式实现)

当然,您可以使这变得更复杂,并参数化几乎任何东西(位置、不同的资源组、不同的附加属性),但我觉得这种复杂程度不会给表格添加任何东西,而是让您创建一个属性文件完全像一个模板(如果你问我,这就是它变得无用的地方)。

【讨论】:

  • 感谢您抽出宝贵时间回复。我会调查一下。我唯一要指出的是“......尝试在资源的属性中迭代最内层(嵌套对象)数组。”不太正确。我不想迭代最里面的循环,只是将该数组替换为模板中的资源数组。最外层的循环将处理迭代。我们对其他模板执行相同的操作,将对象数组替换为对象(例如 keyvault 中的访问策略)
  • 是的,抱歉,您不是在尝试迭代它,但我相信这是唯一的方法,就是迭代。我找不到直接将 object\arrays 传递给 resources 节点的方法。您可以使用属性或资源(密钥库中的访问策略)来执行此操作,但不能使用整个节点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多