我是否可以拥有COPY数组为0到N

时间:2017-08-28 16:50:19

标签: azure azure-resource-manager

我部署了一个ARM模板,该模板使用复制资源块将一个或多个数据磁盘部署到VM。我想做的是将其更改为0或更多。

我使用的参数是

    "VirtualMachineDiskSizeArray": {
        "type": "array",
        "defaultValue": [ "100" ]
    },

然后在资源中调用:

   "resources": [
    {
        "name": "[parameters('virtualMachineName')]",
        "type": "Microsoft.Compute/virtualMachines",
        "apiVersion": "2016-04-30-preview",
        "location": "[parameters('rgLocation')]",
        "dependsOn": [
            "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]"
        ],
        "properties": {
            "osProfile": { ... },
            "hardwareProfile": { ... },
            "storageProfile": {
                "imageReference": { ... },
                "osDisk": { ... },
                "copy": [
                    {
                        "name": "dataDisks",
                        "count": "[length(parameters('VirtualMachineDiskSizeArray'))]",
                        "input": {
                            "lun": "[copyIndex('dataDisks')]",
                            "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]",
                            "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]",
                            "createOption": "Empty",
                            "vhd": {
                                "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'),  add(copyIndex('dataDisks'),1), '.vhd') )]"
                            }
                        }
                    }
                ]
            }
        }
    },

但是,当我传入一个包含0个元素的数据磁盘数组时,我得到了这个错误,正如预期的那样:

Validation returned the following errors:
: Deployment template validation failed: 'The template 'copy' definition at line '0' and column '0' has an invalid copy count. The co
py count must be a postive integer value and cannot exceed '800'. Please see https://aka.ms/arm-copy for usage details.'.

Template is invalid.

我想尝试以某种方式解决这个问题 - 我尝试在副本上添加一个条件:

"condition": "[  greater(length(parameters('VirtualMachineDiskSizeArray')), 0)]",

但是返回了相同的错误。

我正在研究嵌套模板,但这对资源的部分来说并不好看。

7 个答案:

答案 0 :(得分:9)

解决这个问题的最简单方法是使用它:

{
    "condition": "[if(equals(parameters('numberOfDataDisks'), 0), bool('false'), bool('true'))]",
    "apiVersion": "2017-03-30",
    "type": "Microsoft.Compute/virtualMachines",
    "name": "[variables('vmName')]",
    "location": "[resourceGroup().location]",
    "properties": {
        "storageProfile": {
            "imageReference": { xxx },
            "osDisk": { xxx },
            "copy": [
                {
                    "name": "dataDisks",
                    "count": "[if(equals(parameters('numberOfDataDisks'), 0), 1, parameters('numberOfDataDisks'))]",
                    "input": {
                        "diskSizeGB": "1023",
                        "lun": "[copyIndex('dataDisks')]",
                        "createOption": "Empty"
                    }
                }
            ]
        }
    }
}

这将解决您传递0个数据磁盘并同时不会部署此虚拟机的问题。您需要做的就是添加另一个vm资源。但它必须使用不同的名称(否则模板将失败),或者您可以使用嵌套模板来部署具有相同名称的虚拟机。

这可以通过最近对if()函数的修复来改进,您也可以通过使用嵌套部署来解决这个问题

答案 1 :(得分:3)

所以在时间的利益中,我已经改变了我的方法,但并不是真的喜欢它......

我现在有两个部署json文件,VMDeploy.jsonVMDeploy-NoDataDisks.json

除了VM资源的storageProfile部分之外,它们是相同的:

VMDeploy.json

"storageProfile": {
  "imageReference": { ... },
  "osDisk": { ... },
  "copy": [
    {
    "name": "dataDisks",
    "count": "[length(parameters('VirtualMachineDiskSizeArray'))]",
    "input": {
      "lun": "[copyIndex('dataDisks')]",
      "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]",
      "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]",
      "createOption": "Empty",
      "vhd": {
        "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'),  add(copyIndex('dataDisks'),1), '.vhd') )]"
        }
      }
    }
  ]
}

VMDeploy-NoDataDisks.json

"storageProfile": {
  "imageReference": { ... },
  "osDisk": { ... },
  "dataDisks": []
}

我在两个json文件之间有一个Powershell块切换:

if ($DriveArray.Count -eq 0) {
    $TemplateFile = $TemplateFile.Replace('.json','-NoDataDisks.json')
}

答案 2 :(得分:1)

我将使用这个答案来使用我对嵌套模板的研究参考。

here我可以看到一种方法,它有两个嵌套模板,一个像这样:

"resources": [
{
    "name": "MultiDataDisk",
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2016-04-30-preview",
    "location": "[parameters('rgLocation')]",
    "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]"
    ],
    "properties": {
        "osProfile": { ... },
        "hardwareProfile": { ... },
        "storageProfile": {
            "imageReference": { ... },
            "osDisk": { ... },
            "copy": [
                {
                    "name": "dataDisks",
                    "count": "[length(parameters('VirtualMachineDiskSizeArray'))]",
                    "input": {
                        "lun": "[copyIndex('dataDisks')]",
                        "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]",
                        "diskSizeGB": "[parameters('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]",
                        "createOption": "Empty",
                        "vhd": {
                            "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'),  add(copyIndex('dataDisks'),1), '.vhd') )]"
                        }
                    }
                }
            ]
        }
    }
}
]

和这样的一个:

"resources": [
{
    "name": "ZeroDataDisk",
    "type": "Microsoft.Compute/virtualMachines",
    "apiVersion": "2016-04-30-preview",
    "location": "[parameters('rgLocation')]",
    "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]"
    ],
    "properties": {
        "osProfile": { ... },
        "hardwareProfile": { ... },
        "storageProfile": {
            "imageReference": { ... },
            "osDisk": { ... },
             "dataDisks": []
        }
    }
}
] 

从父模板中引用它们:

"parameters": {
 "nestedType": {
  "type": "string",
  "defaultValue": "ZeroDataDisk",
  "allowedValues": [
   "ZeroDataDisk",
   "MultiDataDisk"
  ],
 }
},
"resources": [
 {
 "name": "[concat("nested-",parameters('virtualMachineName')]",
 "type": "Microsoft.Resources/deployments",
 "apiVersion": "2015-01-01",
 "properties": {
  "mode": "Incremental",
  "templateLink": {
   "uri": "[concat('https://someplace.on.the.internet/nested/',parameter('nestedType'),".json")],
   "contentVersion": "1.0.0.0"
   },
   "parameters": {
    "rgStorageAccountName": {
     "value": "[parameters(rgStorageAccountName)]"
    },
    "OtherParms": {
     "value": "[parameters('otherParms')]"
    }
     . . .
  }
 }
]
}

然而,我不相信这比我在“时间的兴趣”答案中所做的更好/更容易,因为

  1. 我感兴趣的部分(dataDisks)周围是一堆其他json,没有更改让我遇到了必须在两个文件之间手动同步代码的蹩脚问题
  2. 我现在不仅需要为嵌套资源维护两个json文件,而且还必须通过可公开访问的URL发布它们。
  3. 所以基本上,除非我可以拥有一个0-N的一个部分(而不是1-N)的副本或只是一个部分,我的两个文件hack与powershell开关似乎是最少的开销。

答案 3 :(得分:1)

关于Disksize我可以帮到你。 我实际上做的是引用一个JSON模板文件,其中为磁盘创建定义了大小,名称和缓存。

可以轻松地将这些解析为部署

"storageProfile": {
      "copy": [{
        "name": "dataDisks",
        "count": "[length(parameters('dataDiskArray'))]",
        "input": {
          "name": "[concat(parameters('vmName'), if(less(copyindex(1), 10), concat('0', copyindex(1)), concat(copyindex(1))), '-datadisk-', parameters('dataDiskArray')[copyIndex('dataDisks')].name)]",
          "diskSizeGB": "[parameters('dataDiskArray')[copyIndex('dataDisks')].size]",
          "caching": "[parameters('dataDiskArray')[copyIndex('dataDisks')].cache]",
          "lun": "[copyIndex('dataDisks')]",
          "createOption": "Empty"
        }
      }],

问题仍然是VM部署的一部分,因此如果要在没有额外磁盘的情况下部署VM,则无法选择Null值。

我尝试将磁盘创建移动到模板的变量部分,但是不能将VMName用作要创建的磁盘名称的一部分。这是因为VM的复制循环尚未初始化,因此它将给出错误的名称。

答案 4 :(得分:0)

工作样本https://github.com/mariuszdotnet/azure-resource-manager-tutorial/blob/master/azuredeploy.json

以下是摘要:

  • 将磁盘移动到变量中并使用变量迭代。
  • 如果numDisks = 0则diskLoop = 1(这可以防止变量副本出错)
  • 使用count = diskLoop
  • 创建变量复制对象
"copy": [
  {
      "name": "dataDisks",
      "count": "[if(equals(parameters('numberOfDataDisks'),0),1, parameters('numberOfDataDisks'))]",
      "input": {
        "lun": "[copyIndex('dataDisks')]",
        "createOption": "Empty",
        "diskSizeGB": "1023"
      }
  }   ]
  • 在数据磁盘的VM资源上。
  • 在VM资源上,如果numDisk = 0则datadisks = json('null')else datadisks = variable
"dataDisks": 
                "[if(equals(parameters('numberOfDataDisks'),0),json('null'),variables('dataDisks'))]"

            },

答案 5 :(得分:0)

我想在此分享基于许多答案的解决方案。这是一个简单的示例,其中有一个磁盘输入数组-值是它们的大小-并与您的vm一起创建。从0-n开始工作。 n必须小于您的VM大小和其他天蓝色限制的支持磁盘:)这也应有助于this comment

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        [...]
        "dataDiskArray": {
            "type": "array",
            "defaultValue": [
                "100",
                "50"
            ]
        }
    },
    "variables": {
        "copy": [
            {
                "name": "dataDisks",
                "count": "[if(equals(length(parameters('dataDiskArray')),0),1, length(parameters('dataDiskArray')))]",
                "input": {
                    "lun": "[if(equals(length(parameters('dataDiskArray')),0),0, copyIndex('dataDisks'))]",
                    "createOption": "Empty",
                    "diskSizeGB": "[if(equals(length(parameters('dataDiskArray')),0),10,parameters('dataDiskArray')[copyIndex('dataDisks')])]"
                }
            }
        ]
    },
    "resources": [
        {
            "name": "[parameters('virtualMachineName')]",
            "type": "Microsoft.Compute/virtualMachines",
            [...]
            "properties": {
                [...]
                "storageProfile": {
                    [...]
                    "dataDisks": "[if(equals(length(parameters('dataDiskArray')),0),json('null'),variables('dataDisks'))]"
                },
                [...]
                }
            }
    ],
    "outputs": {
    }
}

答案 6 :(得分:0)

我自己使用的解决方法不需要链接模板或复杂的逻辑;基于此:

如果该数组为空,则创建另一个仅包含一个值为"EMPTY_ARRAY_INDICATOR"的项的数组。

此外,在我的copy循环中,添加了以下条件:"condition": "[not(equals(variables('input')[0]), "EMPTY_ARRAY_INDICATOR")]",以便在数组的第一个元素为"EMPTY_ARRAY_INDICATOR"时它不会部署。

看看您的模板,我想我可以这样重写它:

   "parameters": [
      "VirtualMachineDiskSizeArray": {
        "type": "array",
        "defaultValue": []
      }
   ],
   "variables": [
      "VirtualMachineDiskSizeArray": "[if(empty(parameters('VirtualMachineDiskSizeArray')), array('EMPTY_ARRAY_INDICATOR'), parameters('VirtualMachineDiskSizeArray'))]"
   ],
   "resources": [
    {
        "name": "[parameters('virtualMachineName')]",
        "type": "Microsoft.Compute/virtualMachines",
        "apiVersion": "2016-04-30-preview",
        "location": "[parameters('rgLocation')]",
        "dependsOn": [
            "[concat('Microsoft.Storage/storageAccounts/', parameters('rgStorageAccountName'))]"
        ],
        "properties": {
            "osProfile": { ... },
            "hardwareProfile": { ... },
            "storageProfile": {
                "imageReference": { ... },
                "osDisk": { ... },
                "copy": [
                    {
                        "name": "dataDisks",
                        "condition": "[not(equals(variables('VirtualMachineDiskSizeArray')[0], 'EMPTY_ARRAY_INDICATOR'))]"
                        "count": "[length(variables('VirtualMachineDiskSizeArray'))]",
                        "input": {
                            "lun": "[copyIndex('dataDisks')]",
                            "name": "[concat(parameters('vmDataDiskNameStub'), add(copyIndex('dataDisks'),1), '.vhd')]",
                            "diskSizeGB": "[variables('VirtualMachineDiskSizeArray')[copyIndex('dataDisks')]]",
                            "createOption": "Empty",
                            "vhd": {
                                "uri": "[concat(concat(reference(resourceId(parameters('rgName'), 'Microsoft.Storage/storageAccounts', parameters('rgStorageAccountName')), '2015-06-15').primaryEndpoints['blob'], 'vhds/'), concat(parameters('vmDataDiskNameStub'),  add(copyIndex('dataDisks'),1), '.vhd') )]"
                            }
                        }
                    }
                ]
            }
        }
    },

请注意condition循环中的copy,以及variables('VirtualMachineDiskSizeArray')而不是parameters(VirtualMachineDiskSizeArray)的用法。

我已经针对自己的模板对其进行了测试,但是尚未运行您的模板。请让我知道它是否有效。