web-dev-qa-db-fra.com

Puis-je avoir un ARM ressource modèle avec un tableau COPY de à N

Je déploie un modèle ARM qui utilise un bloc de ressources de copie pour déployer un ou plusieurs disques de données sur une machine virtuelle. Ce que j'aimerais faire, c'est changer ceci en 0 ou plus. 

Le paramètre que j'utilise est 

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

Qui est ensuite appelé dans une ressource:

   "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') )]"
                            }
                        }
                    }
                ]
            }
        }
    },

Cependant, lorsque je passe dans un tableau de disques de données avec 0 élément, le message d'erreur suivant s'affiche:

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.

Je voudrais essayer de contourner cela en quelque sorte - j'ai essayé d'ajouter une condition sur la copie: 

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

Mais cela a renvoyé la même erreur.

Je recherche des modèles imbriqués, mais cela ne semble pas bon pour une section d'une ressource.

9

La façon la plus simple de contourner ce problème consiste à utiliser ceci:

{
    "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"
                    }
                }
            ]
        }
    }
}

cela contournera le fait que vous transmettez 0 disque de données et que vous ne déploierez pas en même temps cette machine virtuelle. tout ce que vous avez à faire est d’ajouter une autre ressource vm. Mais il doit porter un nom différent (sinon le modèle échouera) ou vous pouvez utiliser un modèle imbriqué pour déployer une machine virtuelle portant le même nom.

ceci peut être amélioré avec les correctifs récents de la fonction if(), vous pouvez toujours contourner le problème en utilisant également des déploiements imbriqués

8
4c74356b41

Donc, dans le Intérêt du temps, j'ai changé mon approche, mais je ne l'aime pas vraiment ... 

J'ai maintenant deux fichiers JSON de déploiement, VMDeploy.json et VMDeploy-NoDataDisks.json.

Ils sont identiques, à l'exception de la section storageProfile de la ressource VM:

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": []
}

Et j'ai un bloc Powershell qui permute entre les deux fichiers JSON:

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

Je vais utiliser cette réponse pour utiliser une référence dans mes recherches sur les modèles imbriqués.

En regardant ici je peux voir une approche qui aurait deux modèles imbriqués, un comme celui-ci:

"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') )]"
                        }
                    }
                }
            ]
        }
    }
}
]

et un comme ça:

"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": []
        }
    }
}
] 

Et référencez-les à partir d'un modèle parent: 

"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')]"
    }
     . . .
  }
 }
]
}

Cependant, je ne crois pas que cela soit meilleur/plus facile que ce que j’ai fait dans ma réponse "Intérêt du temps" parce que

  1. La section qui m'intéresse (dataDisks) est entourée d'un tas d'autres fichiers json que ne change pas, ce qui me laisse le même problème de devoir synchroniser manuellement le code entre deux fichiers.
  2. Je dois maintenant non seulement gérer deux fichiers JSON pour les ressources imbriquées, mais aussi les publier via une URL accessible au public.

Donc, en gros, à moins que je puisse avoir une copie de 0-N d’une section (plutôt que 1-N) ou imbriquer juste une section, mes deux fichiers piratés avec le commutateur powershell semblent être les moins lourds.

1

En ce qui concerne Disksize, je peux vous aider… .. Ce que j’ai fait est une référence à un fichier de modèle JSON dans lequel la taille, le nom et la mise en cache sont définis pour la création de disques.

Ceux-ci peuvent facilement être analysés au déploiement

"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"
        }
      }],

Le problème qui fait partie du déploiement VM reste donc, il n'y a donc pas d'option pour sélectionner une valeur Null si vous souhaitez déployer un VM sans disques supplémentaires.

J'ai essayé de déplacer la création de disque vers la section variables du modèle, mais il n'est pas possible d'utiliser le VMName dans le cadre du nom des disques que vous souhaitez créer. Cela est dû au fait que la boucle de copie pour la VM n'est pas encore initialisée, elle donnera donc un nom incorrect.

0
user9860446

Je voudrais partager notre solution basée sur plusieurs des réponses déjà ici. Ceci est un exemple simple pour avoir un tableau en entrée de disques (les valeurs étant leurs tailles) et créer avec ceux avec votre vm. fonctionne de 0 à n. n doit être plus petit que les disques pris en charge de votre taille VM et autres limites Azure :) Cela devrait également aider avec ce commentaire

{
    "$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": {
    }
}
0
Klaas

Exemple de travail https://github.com/mariuszdotnet/Azure-resource-manager-tutorial/blob/master/azuredeploy.json

Voici le résumé:

  • Déplacez les disques dans une variable et utilisez la variable itération.
  • Si numDisks = 0 alors diskLoop = 1 (cela évite une erreur dans la copie de variable)
  • Créer un objet de copie variable avec count = diskLoop
"copy": [
  {
      "name": "dataDisks",
      "count": "[if(equals(parameters('numberOfDataDisks'),0),1, parameters('numberOfDataDisks'))]",
      "input": {
        "lun": "[copyIndex('dataDisks')]",
        "createOption": "Empty",
        "diskSizeGB": "1023"
      }
  }   ]
  • Sur la ressource VM pour les disques de données.
  • Sur la ressource VM, si numDisk = 0 alors datadisks = json (‘null’) sinon datadisks = variable
"dataDisks": 
                "[if(equals(parameters('numberOfDataDisks'),0),json('null'),variables('dataDisks'))]"

            },
0
Mariusz Kolodziej