Azure ARM 模板如何对多个部分使用副本
Azure ARM template how to use copy for multiple parts
我有一个问题找不到解决方案,当我尝试使用复制在我的仪表板 ARM 模板中动态创建多个部分时。
当我尝试在其中一个键中使用“[copyIndex()]”时出现错误,正如我从错误消息中了解到的那样,这是行不通的。但我不确定如何解决这个问题,所以任何想法将不胜感激。
"copy": [
{
"name": "servers",
"count": "[length(parameters('locationKeys'))]",
"input": {
"[copyIndex('servers')]": {
"position": {
"x": "[mul(copyIndex('servers'), 4)]",
"y": 1,
"colSpan": 2,
"rowSpan": 1
}
}
}
}
]
正如您在上面的示例中看到的那样,这就是失败的地方
"[copyIndex('servers')]": {
我收到这个错误
Error: Code=InvalidTemplate; Message=Deployment template validation failed:
'Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.'.
创建仪表板的结构如下所示
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": {
"0": {},
"1": {},
...
而且我在"parts"键下有复制功能
解决这个问题的方法是删除复制功能并复制代码,但是我很难让它与任何给定数量的 "locations" 一起工作,因为我需要对它们进行硬编码.
基本上这就是我最终想要得到的。
还有其他好的解决方案可以解决这个问题吗?
更新
这是我在管道中的 Azure DevOps 任务中引用的两个模板。请注意,我现在需要执行 parameters('locationKeys')[0] 并复制所有块,而不是使用 parameters('locationKeys')[copyIndex()].
进行复制
parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"locationNames": {
"value": "#{locationNames}"
}
}
}
deploy.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"defaultValue" : "myApp"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"dashboardName": "[concat(parameters('appName'), '-dashboard')]"
},
"resources": [
{
"name": "[variables('dashboardName')]",
"type": "Microsoft.Portal/dashboards",
"apiVersion": "2015-08-01-preview",
"location": "westeurope",
"tags": {
"hidden-title": "24/7 Operations"
},
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": {
"0": {
"position": {
"x": 0,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[0])]",
"title": "",
"subtitle": ""
}
}
}
}
},
"1": {
"position": {
"x": 4,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[1])]",
"title": "",
"subtitle": ""
}
}
}
}
},
"2": {
"position": {
"x": 8,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[2])]",
"title": "",
"subtitle": ""
}
}
}
}
}
}
}
}
},
"dependsOn": []
}
],
"outputs": {
"resourceGroupId": {
"type": "string",
"value": "[resourceGroup().id]"
}
}
}
更新 2
这是使用对象而不是数组的工作示例。我通过将 collector.json 和 transform.json 上传到 http://myjson.com 并在 运行 部署时将它们作为属性包括在内,使用 PowerShell 在本地进行了验证。
parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"azureEnvironment": {
"value": "#{azureEnvironment}"
},
"locationKeys": {
"value": "#{locationKeys}"
},
"locationNames": {
"value": "#{locationNames}"
},
"transformTemplateLink": {
"value": "#{transform}"
},
"collectorTemplateLink": {
"value": "#{collector}"
}
}
}
deploy.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"defaultValue": "myApp"
},
"azureEnvironment": {
"type": "string"
},
"locationKeys": {
"type": "array"
},
"locationNames": {
"type": "array"
},
"transformTemplateLink": {
"type": "string",
"defaultValue": "[uri(deployment().properties.templateLink.uri, 'transform.json')]"
},
"collectorTemplateLink": {
"type": "string",
"defaultValue": "[uri(deployment().properties.templateLink.uri, 'collector.json')]"
}
},
"resources": [
{
"apiVersion": "2015-01-01",
"name": "collector",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('collectorTemplateLink')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"transformTemplateUri": {
"value": "[parameters('transformTemplateLink')]"
},
"locationNames": {
"value": "[parameters('locationNames')]"
}
}
}
},
{
"name": "[concat(parameters('appName'), '-dash-', parameters('azureEnvironment'))]",
"type": "Microsoft.Portal/dashboards",
"apiVersion": "2015-08-01-preview",
"location": "westeurope",
"tags": {
"hidden-title": "[concat('24/7 Operations - (', parameters('azureEnvironment'), ')')]"
},
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": "[reference('collector').outputs.result.value]"
}
}
},
"dependsOn": [
"collector"
]
}
],
"outputs": {
"resourceGroupId": {
"type": "string",
"value": "[resourceGroup().id]"
}
}
}
collector.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"transformTemplateUri": {
"type": "string"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"count": "[length(parameters('locationNames'))]"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"name": "loop-0",
"properties": {
"mode": "Incremental",
"parameters": {},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [],
"outputs": {
"collection": {
"type": "object",
"value": {}
}
}
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"name": "[concat('loop-', copyIndex(1))]",
"copy": {
"name": "iterator",
"count": "[variables('count')]",
"mode": "serial"
},
"dependsOn": [
"[concat('loop-', copyIndex())]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('transformTemplateUri')]"
},
"parameters": {
"state": {
"value": "[reference(concat('loop-', copyIndex())).outputs.collection.value]"
},
"index": {
"value": "[copyIndex()]"
},
"locationNames": {
"value": "[parameters('locationNames')]"
}
}
}
}
],
"outputs": {
"result": {
"type": "object",
"value": "[reference(concat('loop-', variables('count'))).outputs.collection.value]"
}
}
}
transform.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"state": {
"type": "object",
"defaultValue": {}
},
"index": {
"type": "int"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"instance": {
"[string(parameters('index'))]": {
"position": {
"x": "[mul(parameters('index'), 4)]",
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[parameters('index')])]",
"title": "",
"subtitle": ""
}
}
}
}
}
}
},
"resources": [],
"outputs": {
"collection": {
"type": "object",
"value": "[union(parameters('state'), variables('instance'))]"
}
}
}
如果您只是在变量部分尝试相同(但经过简化)的方法,您会收到此错误:
The variable name cannot be an expression.
我认为这同样适用于任何地方,你不能使用表达式来计算 属性 名称,只能计算值。话虽如此,如果你想创建一个循环,你需要使用嵌套部署作为迭代器。您将根据输入将需要的部分 inside\assemble 传递到那里并创建结果数组:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"locations": [
"eastus",
"westeurope"
],
"eastus": {
"red": 1
},
"westeurope": {
"blue": 2
},
"empty": []
},
"resources": [
{
"apiVersion": "2017-05-10",
"name": "[concat('iterator-', copyIndex(1))]",
"type": "Microsoft.Resources/deployments",
"copy": {
"name": "someName",
"count": "[length(variables('locations'))]"
},
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://paste.ee/r/t5ca9/0"
},
"parameters": {
"source": {
"value": "[variables(variables('locations')[copyIndex()])]"
},
"state": {
"value": "[if(equals(copyIndex(), 0), variables('empty'), reference(concat('iterator-', copyIndex())).outputs.collection.value)]"
}
}
}
}
],
"outputs": {
"results": {
"type": "array",
"value": "[reference(concat('iterator-', string(length(variables('locations'))))).outputs.collection.value]"
}
} }
您的迭代器如下所示:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"source": {
"type": "object"
},
"state": {
"type": "array",
"defaultValue": []
}
},
"resources": [],
"outputs": {
"collection": {
"type": "array",
"value": "[concat(array(parameters('source')), parameters('state'))]"
}
}
}
ps。 link 是临时的(1 个月),但您可以在任何地方上传迭代器模板并进行硬编码,它不包含 secrets\no 数据。
pps。更简单的方法 - 在模板外构造它 (powershell\python\whatever) 并作为模板内的参数传递
我有一个问题找不到解决方案,当我尝试使用复制在我的仪表板 ARM 模板中动态创建多个部分时。
当我尝试在其中一个键中使用“[copyIndex()]”时出现错误,正如我从错误消息中了解到的那样,这是行不通的。但我不确定如何解决这个问题,所以任何想法将不胜感激。
"copy": [
{
"name": "servers",
"count": "[length(parameters('locationKeys'))]",
"input": {
"[copyIndex('servers')]": {
"position": {
"x": "[mul(copyIndex('servers'), 4)]",
"y": 1,
"colSpan": 2,
"rowSpan": 1
}
}
}
}
]
正如您在上面的示例中看到的那样,这就是失败的地方
"[copyIndex('servers')]": {
我收到这个错误
Error: Code=InvalidTemplate; Message=Deployment template validation failed:
'Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject.'.
创建仪表板的结构如下所示
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": {
"0": {},
"1": {},
...
而且我在"parts"键下有复制功能
解决这个问题的方法是删除复制功能并复制代码,但是我很难让它与任何给定数量的 "locations" 一起工作,因为我需要对它们进行硬编码.
基本上这就是我最终想要得到的。
还有其他好的解决方案可以解决这个问题吗?
更新
这是我在管道中的 Azure DevOps 任务中引用的两个模板。请注意,我现在需要执行 parameters('locationKeys')[0] 并复制所有块,而不是使用 parameters('locationKeys')[copyIndex()].
进行复制parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"locationNames": {
"value": "#{locationNames}"
}
}
}
deploy.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"defaultValue" : "myApp"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"dashboardName": "[concat(parameters('appName'), '-dashboard')]"
},
"resources": [
{
"name": "[variables('dashboardName')]",
"type": "Microsoft.Portal/dashboards",
"apiVersion": "2015-08-01-preview",
"location": "westeurope",
"tags": {
"hidden-title": "24/7 Operations"
},
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": {
"0": {
"position": {
"x": 0,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[0])]",
"title": "",
"subtitle": ""
}
}
}
}
},
"1": {
"position": {
"x": 4,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[1])]",
"title": "",
"subtitle": ""
}
}
}
}
},
"2": {
"position": {
"x": 8,
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[2])]",
"title": "",
"subtitle": ""
}
}
}
}
}
}
}
}
},
"dependsOn": []
}
],
"outputs": {
"resourceGroupId": {
"type": "string",
"value": "[resourceGroup().id]"
}
}
}
更新 2
这是使用对象而不是数组的工作示例。我通过将 collector.json 和 transform.json 上传到 http://myjson.com 并在 运行 部署时将它们作为属性包括在内,使用 PowerShell 在本地进行了验证。
parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"azureEnvironment": {
"value": "#{azureEnvironment}"
},
"locationKeys": {
"value": "#{locationKeys}"
},
"locationNames": {
"value": "#{locationNames}"
},
"transformTemplateLink": {
"value": "#{transform}"
},
"collectorTemplateLink": {
"value": "#{collector}"
}
}
}
deploy.json
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"type": "string",
"defaultValue": "myApp"
},
"azureEnvironment": {
"type": "string"
},
"locationKeys": {
"type": "array"
},
"locationNames": {
"type": "array"
},
"transformTemplateLink": {
"type": "string",
"defaultValue": "[uri(deployment().properties.templateLink.uri, 'transform.json')]"
},
"collectorTemplateLink": {
"type": "string",
"defaultValue": "[uri(deployment().properties.templateLink.uri, 'collector.json')]"
}
},
"resources": [
{
"apiVersion": "2015-01-01",
"name": "collector",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('collectorTemplateLink')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"transformTemplateUri": {
"value": "[parameters('transformTemplateLink')]"
},
"locationNames": {
"value": "[parameters('locationNames')]"
}
}
}
},
{
"name": "[concat(parameters('appName'), '-dash-', parameters('azureEnvironment'))]",
"type": "Microsoft.Portal/dashboards",
"apiVersion": "2015-08-01-preview",
"location": "westeurope",
"tags": {
"hidden-title": "[concat('24/7 Operations - (', parameters('azureEnvironment'), ')')]"
},
"properties": {
"lenses": {
"0": {
"order": 0,
"parts": "[reference('collector').outputs.result.value]"
}
}
},
"dependsOn": [
"collector"
]
}
],
"outputs": {
"resourceGroupId": {
"type": "string",
"value": "[resourceGroup().id]"
}
}
}
collector.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"transformTemplateUri": {
"type": "string"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"count": "[length(parameters('locationNames'))]"
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"name": "loop-0",
"properties": {
"mode": "Incremental",
"parameters": {},
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {},
"resources": [],
"outputs": {
"collection": {
"type": "object",
"value": {}
}
}
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"name": "[concat('loop-', copyIndex(1))]",
"copy": {
"name": "iterator",
"count": "[variables('count')]",
"mode": "serial"
},
"dependsOn": [
"[concat('loop-', copyIndex())]"
],
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('transformTemplateUri')]"
},
"parameters": {
"state": {
"value": "[reference(concat('loop-', copyIndex())).outputs.collection.value]"
},
"index": {
"value": "[copyIndex()]"
},
"locationNames": {
"value": "[parameters('locationNames')]"
}
}
}
}
],
"outputs": {
"result": {
"type": "object",
"value": "[reference(concat('loop-', variables('count'))).outputs.collection.value]"
}
}
}
transform.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"state": {
"type": "object",
"defaultValue": {}
},
"index": {
"type": "int"
},
"locationNames": {
"type": "array"
}
},
"variables": {
"instance": {
"[string(parameters('index'))]": {
"position": {
"x": "[mul(parameters('index'), 4)]",
"y": 0,
"colSpan": 4,
"rowSpan": 1
},
"metadata": {
"inputs": [],
"type": "Extension/HubsExtension/PartType/MarkdownPart",
"settings": {
"content": {
"settings": {
"content": "[concat('# ', parameters('locationNames')[parameters('index')])]",
"title": "",
"subtitle": ""
}
}
}
}
}
}
},
"resources": [],
"outputs": {
"collection": {
"type": "object",
"value": "[union(parameters('state'), variables('instance'))]"
}
}
}
如果您只是在变量部分尝试相同(但经过简化)的方法,您会收到此错误:
The variable name cannot be an expression.
我认为这同样适用于任何地方,你不能使用表达式来计算 属性 名称,只能计算值。话虽如此,如果你想创建一个循环,你需要使用嵌套部署作为迭代器。您将根据输入将需要的部分 inside\assemble 传递到那里并创建结果数组:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"variables": {
"locations": [
"eastus",
"westeurope"
],
"eastus": {
"red": 1
},
"westeurope": {
"blue": 2
},
"empty": []
},
"resources": [
{
"apiVersion": "2017-05-10",
"name": "[concat('iterator-', copyIndex(1))]",
"type": "Microsoft.Resources/deployments",
"copy": {
"name": "someName",
"count": "[length(variables('locations'))]"
},
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "https://paste.ee/r/t5ca9/0"
},
"parameters": {
"source": {
"value": "[variables(variables('locations')[copyIndex()])]"
},
"state": {
"value": "[if(equals(copyIndex(), 0), variables('empty'), reference(concat('iterator-', copyIndex())).outputs.collection.value)]"
}
}
}
}
],
"outputs": {
"results": {
"type": "array",
"value": "[reference(concat('iterator-', string(length(variables('locations'))))).outputs.collection.value]"
}
} }
您的迭代器如下所示:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"source": {
"type": "object"
},
"state": {
"type": "array",
"defaultValue": []
}
},
"resources": [],
"outputs": {
"collection": {
"type": "array",
"value": "[concat(array(parameters('source')), parameters('state'))]"
}
}
}
ps。 link 是临时的(1 个月),但您可以在任何地方上传迭代器模板并进行硬编码,它不包含 secrets\no 数据。 pps。更简单的方法 - 在模板外构造它 (powershell\python\whatever) 并作为模板内的参数传递