ARM资源迭代失败,数组为空



ARM模板中的所有表达式似乎都是预先计算的,因此即使您具有资源的条件false,也会计算该资源中的表达式。

无论condition是显式设置为false,还是计算结果为false的表达式,都会出现这种情况。

在资源迭代的情况下,这种行为是有问题的,因为资源中的表达式可能引用参数或变量的copyIndex()。然而,变量的参数是一个空数组,对这些表达式的求值将失败,并显示类似于以下的消息-

语言表达式属性数组索引"0"越界。。请参阅https://aka.ms/arm-template-expressions了解用法详细信息。

无论是否有任何资源可添加,我是否有任何方法可以修改模板以使其工作?

模板示例

注意,我已经"破解"了copy对象的count参数。如果它是0(表达式length(variables('productsJArray'))可能对其求值(,则模板验证失败,并出现以下错误-

副本计数必须是正整数值,并且不能超过"800"。

我觉得,如果count0,那么就不会添加任何资源,这是一个合理的预期,但这是一种完全不同的主题!

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiManagementServiceName": {
"type": "string",
"metadata": {
"description": "The name of the API Management instance."
}
},
"productsJson": {
"type": "string",
"metadata": {
"description": "A JSON representation of the Products to add."
}
}
},
"variables": {
"productsJArray": "[json(parameters('productsJson'))]"
},
"resources": [
{
"condition": "[greater(length(variables('productsJArray')), 0)]",
"type": "Microsoft.ApiManagement/service/products",
"name": "[concat(parameters('apiManagementServiceName'), '/', variables('productsJArray')[copyIndex()].name)]",
"apiVersion": "2018-06-01-preview",
"properties": {
"displayName": "[variables('productsJArray')[copyIndex()].displayName]",
"description": "[variables('productsJArray')[copyIndex()].description]",
"state": "[variables('productsJArray')[copyIndex()].state]",
"subscriptionRequired": "[variables('productsJArray')[copyIndex()].subscriptionRequired]",
"approvalRequired": "[variables('productsJArray')[copyIndex()].approvalRequired]"
},
"copy": {
"name": "productscopy",
"count": "[if(greater(length(variables('productsJArray')), 0), length(variables('productsJArray')), 1)]"
}
}
]
}

将工作的示例参数文件

请注意,虽然这看起来很好,但在某些情况下,productsJson参数值可能是任何空数组[],这就是我的问题所在。

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiManagementServiceName": {
"value": "my-api-management"
},
"productsJson": {
"value": "[{"name":"my-product","displayName":"My Product","description":"My product is awesome.","state":"published","subscriptionRequired":true,"approvalRequired":false}]"
}
}
}

将失败的参数文件示例

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiManagementServiceName": {
"value": "lmk-bvt-conveyorbot"
},
"productsJson": {
"value": "[]"
}
}
}

更新的模板

源自用户"4c74356b41"的一个建议。

此模板正在生成以下错误-

无法处理第"1"行和第"839"列的资源"/订阅/**********/resourceGroups/**********/providers/Microsoft.Resources/deployments/api管理产品"的模板语言表达式在此位置不应使用模板函数"copyIndex"。该函数只能在指定了副本的资源中使用。

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiManagementServiceName": {
"type": "string",
"metadata": {
"description": "The name of the API Management instance."
}
},
"productsJson": {
"type": "string",
"metadata": {
"description": "A JSON representation of the Products to add."
}
}
},
"variables": {
"productsJArray": "[json(parameters('productsJson'))]"
},
"resources": [
{
"condition": "[greater(length(variables('productsJArray')), 0)]",
"type": "Microsoft.Resources/deployments",
"name": "api-management-products",
"apiVersion": "2017-05-10",
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ApiManagement/service/products",
"name": "[concat(parameters('apiManagementServiceName'), '/', variables('productsJArray')[copyIndex('productscopy')].name)]",
"apiVersion": "2018-06-01-preview",
"properties": {
"displayName": "[variables('productsJArray')[copyIndex('productscopy')].displayName]",
"description": "[variables('productsJArray')[copyIndex('productscopy')].description]",
"state": "[variables('productsJArray')[copyIndex('productscopy')].state]",
"subscriptionRequired": "[variables('productsJArray')[copyIndex('productscopy')].subscriptionRequired]",
"approvalRequired": "[variables('productsJArray')[copyIndex('productscopy')].approvalRequired]"
},
"copy": {
"name": "productscopy",
"count": "[if(greater(length(variables('productsJArray')), 0), length(variables('productsJArray')), 1)]"
}
}
]
}
}
}
]
}

解决此问题的两种方法:

  1. if()破解,所以如果length == 0length = 1。使用这种方法,您需要有一个将要引用的代理对象,因为引用不存在的对象是行不通的
  2. 使用嵌套部署,您可以对部署设置一个条件,这样它就不会在length == 0时启动(并且您在嵌套部署中运行循环(。这样你就不在乎零的长度了

这是我将使用的最后一个模板。这允许我将对象数组或空数组传递给productsJson参数。

{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"apiManagementServiceName": {
"type": "string",
"metadata": {
"description": "The name of the API Management instance."
}
},
"productsJson": {
"type": "string",
"metadata": {
"description": "A JSON representation of the Products to add."
}
}
},
"variables": {
"productsJArray": "[json(parameters('productsJson'))]"
},
"resources": [
{
"condition": "[greater(length(variables('productsJArray')), 0)]",
"type": "Microsoft.Resources/deployments",
"name": "[concat('api-management-products-', copyIndex())]",
"apiVersion": "2017-05-10",
"copy": {
"name": "productscopy",
"count": "[if(greater(length(variables('productsJArray')), 0), length(variables('productsJArray')), 1)]",
"mode": "Serial"
},
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ApiManagement/service/products",
"name": "[concat(parameters('apiManagementServiceName'), '/', variables('productsJArray')[copyIndex()].name)]",
"apiVersion": "2018-06-01-preview",
"properties": {
"displayName": "[variables('productsJArray')[copyIndex()].displayName]",
"description": "[variables('productsJArray')[copyIndex()].description]",
"state": "[variables('productsJArray')[copyIndex()].state]",
"subscriptionRequired": "[variables('productsJArray')[copyIndex()].subscriptionRequired]",
"approvalRequired": "[variables('productsJArray')[copyIndex()].approvalRequired]"
}
}
]
}
}
}
]
}

您也可以在空数组中有一个占位符元素,并使用condition忽略占位符元素。像这个

{
"parameters": {
"yourArray": {
"defaultValue": [
{
"name": "placeholder"
}
],
"type": "array"
}
},
"resources": [
{
"condition": "[not(equals(parameters('yourArray')[copyIndex()].name,'placeholder'))]",
"copy": {
"name": "yourArray",
"count": "[length(parameters('yourArray'))]"
}
}
]
}

最新更新