以数组为参数的 Azure ARM 模板

我正在尝试在 Azure ARM 模板中使用用户复制循环功能,以下是我拥有的资源块

{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceGroupsName": {
  "type": "string"
},
"clusterName": {
  "type": "string"
},
"clusterLoginUserName": {
  "type": "string"
},
"clusterLoginPassword": {
  "type": "securestring"
},
"sshUserName": {
  "type": "string"
},
"sshPassword": {
  "type": "securestring"
},
"location": {
  "type": "string"
},
"clusterType": {
  "type": "string",
  "defaultValue": "spark"
},
"clusterVersion": {
  "type": "string"
},
"sparkVersion": {
  "type": "string"
},
"clusterWorkerNodeCount": {
  "type": "int",
  "defaultValue": 2
},
"virtualNetworkName": {
  "type": "string"
},
"subnetName": {
  "type": "string"
},
"vnetResourceGroupName": {
  "type": "string"
},
"clusterStorageAccountName": {
  "type": "string"
},
"dataStorageAccountName": {
  "type": "string"
},
"clusterStorageContainerName": {
  "type": "string"
},
"externalStorageAccounts": {
  "type": "array"
},
"storageAccountResourceGroupName": {
  "type": "string"
},
"headNodeSize": {
  "type": "string"
},
"workerNodeSize": {
  "type": "string"
},
"edgeNodeSize": {
  "type": "string"
},
"dbServerName": {
  "type": "string"
},
"hivedbName": {
  "type": "string",
  "metadata": { "description": "Name of the database where metadata will be stored" }
},
"ooziedbName": {
  "type": "string",
  "metadata": { "description": "Name of the database where metadata will be stored" }
},
"dbuser": {
  "type": "string",
  "metadata": { "description": "User Name of the database server where metadata will be stored" }
},
"dbpassword": {
  "type": "securestring",
  "metadata": { "description": "Password of the database where metadata will be stored" }
},
"collation": {
  "type": "string",
  "defaultValue": "SQL_Latin1_General_CP1_CI_AS",
  "metadata": {
    "description": "The database collation for governing the proper use of characters."
  }
},
"edition": {
  "type": "string",
  "defaultValue": "Standard",
  "allowedValues": [
    "Basic",
    "Standard",
    "Premium"
  ],
  "metadata": {
    "description": "The type of database to create."
  }
},
"maxSizeBytes": {
  "type": "string",
  "defaultValue": "1073741824",
  "metadata": {
    "description": "The maximum size, in bytes, for the database"
  }
},
"requestedServiceObjectiveName": {
  "type": "string",
  "defaultValue": "S1",
  "allowedValues": [
    "Basic",
    "S0",
    "S1",
    "S2",
    "P1",
    "P2",
    "P3"
  ],
  "metadata": {
    "description": "Describes the performance level for Edition"
  }
},
"omsWorkspace": {
  "type": "string",
  "metadata": {
    "description": "OMS Workspace ID"
  }
},
"omsResourceGroup": {
  "type": "string",
  "metadata": {
    "description": "OMS Workspace Key"
  }
},
"Environment": {
  "type": "string",
  "allowedValues": [
    "dev",
    "qa",
    "stage",
    "prod"
  ],
  "metadata": {
    "description": "The environment that the resources will be tagged with (dev, test, stage, prod)."
  }
},
"ProjectName": {
  "type": "string",
  "metadata": {
    "description": "A name for the project or company that this template is being provisioned for (used for tagging)."
  }
}
},
"variables": {
"dbServerName": "[concat(parameters('dbServerName'),'.database.windows.net')]",
"defaultApiVersion": "2015-05-01-preview",
"clusterApiVersion": "2015-03-01-preview",
"vnetID": "[concat(resourceId(parameters('vnetResourceGroupName'),'Microsoft.Network/virtualNetworks', parameters('virtualNetworkName')))]",
"subnet1Ref": "[concat(variables('vnetID'),'/subnets/', parameters('subnetName'))]",
"applicationName": "[concat('edgenode')]"
},
"resources": [
  {
    "name": "[parameters('clusterName')]",
    "type": "Microsoft.HDInsight/clusters",
    "location": "[resourceGroup().location]",
    "apiVersion": "[variables('clusterApiVersion')]",
    "dependsOn": [],
    "tags": {
      "Environment": "[parameters('Environment')]",
      "Project": "[parameters('ProjectName')]"
    },
    "properties": {
      "clusterVersion": "[parameters('clusterVersion')]",
      "osType": "Linux",
      "tier": "standard",
      "clusterDefinition": {
        "kind": "[parameters('clusterType')]",
        "componentVersion": {
                "Spark": "[parameters('sparkVersion')]"
        },
        "configurations": {
          "gateway": {
            "restAuthCredential.isEnabled": true,
            "restAuthCredential.username": "[parameters('clusterLoginUserName')]",
            "restAuthCredential.password": "[parameters('clusterLoginPassword')]"
          },
          "core-site": {
          },
          "hive-site": {
            "javax.jdo.option.ConnectionDriverName": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
            "javax.jdo.option.ConnectionURL": "[concat('jdbc:sqlserver://', variables('dbServerName'),';database=', parameters('hivedbName'),';encrypt=true;trustServerCertificate=true;create=false;loginTimeout=300')]",
            "javax.jdo.option.ConnectionUserName": "[parameters('dbuser')]",
            "javax.jdo.option.ConnectionPassword": "[parameters('dbpassword')]"
          },
          "hive-env": {
            "hive_database": "Existing MSSQL Server database with SQL authentication",
            "hive_database_name": "[parameters('hivedbName')]",
            "hive_database_type": "mssql",
            "hive_existing_mssql_server_database": "[parameters('hivedbName')]",
            "hive_existing_mssql_server_host": "[variables('dbServerName')]",
            "hive_hostname": "[variables('dbServerName')]"
          },
          "oozie-site": {
            "oozie.service.JPAService.jdbc.driver": "com.microsoft.sqlserver.jdbc.SQLServerDriver",
            "oozie.service.JPAService.jdbc.url": "[concat('jdbc:sqlserver://', variables('dbServerName'),';database=', parameters('ooziedbName'),';encrypt=true;trustServerCertificate=true;create=false;loginTimeout=300')]",
            "oozie.service.JPAService.jdbc.username": "[parameters('dbuser')]",
            "oozie.service.JPAService.jdbc.password": "[parameters('dbpassword')]",
            "oozie.db.schema.name": "oozie"
          },
          "oozie-env": {
            "oozie_database": "Existing MSSQL Server database with SQL authentication",
            "oozie_database_name": "[parameters('ooziedbName')]",
            "oozie_database_type": "mssql",
            "oozie_existing_mssql_server_database": "[parameters('ooziedbName')]",
            "oozie_existing_mssql_server_host": "[variables('dbServerName')]",
            "oozie_hostname": "[variables('dbServerName')]"
          }
        }
      },
      "storageProfile": {
        "copy": [
            {
                "name": "storageaccounts",
                "count": "[length(parameters('externalStorageAccounts'))]",
                "input": {
                    "name": "[concat(parameters('externalStorageAccounts')[copyIndex('storageaccounts')].name,'.blob.core.windows.net')]",
                    "isDefault": "[parameters('externalStorageAccounts')[copyIndex('storageaccounts')].isDefault]",
                    "container": "[parameters('externalStorageAccounts')[copyIndex('storageaccounts')].container]",
                    "key": "[listKeys(resourceId(parameters('externalStorageAccounts')[copyIndex('storageaccounts')].resourceGroupsName,'Microsoft.Storage/storageAccounts', parameters('externalStorageAccounts')[copyIndex('storageaccounts')].name), variables('defaultApiVersion')).key1]",
                }
            }
        ]
      },
    "computeProfile": {
        "roles": [
          {
            "name": "headnode",
            "targetInstanceCount": "2",
            "hardwareProfile": {
              "vmSize": "[parameters('headNodeSize')]"
            },
            "osProfile": {
              "linuxOperatingSystemProfile": {
                "username": "[parameters('sshUserName')]",
                "password": "[parameters('sshPassword')]"
              }
            },
            "virtualNetworkProfile": {
              "id": "[variables('vnetID')]",
              "subnet": "[variables('subnet1Ref')]"
            },
            "scriptActions": []
          },
          {
            "name": "workernode",
            "targetInstanceCount": "[parameters('clusterWorkerNodeCount')]",
            "hardwareProfile": {
              "vmSize": "[parameters('workerNodeSize')]"
            },
            "osProfile": {
              "linuxOperatingSystemProfile": {
                "username": "[parameters('sshUserName')]",
                "password": "[parameters('sshPassword')]"
              }
            },
            "virtualNetworkProfile": {
              "id": "[variables('vnetID')]",
              "subnet": "[variables('subnet1Ref')]"
            },
            "scriptActions": []
          }
        ]
      }
    }
  }
],
"outputs": {
"cluster": {
  "type": "object",
  "value": "[reference(resourceId('Microsoft.HDInsight/clusters',parameters('clusterName')))]"
 }
}
}

带参数文件: https://gist.github.com/anonymous/fa27714ea74bbcecafbbfa1380b2308a

我将参数 externalStorageAccounts 作为数组传递,其中包含以下详细信息

"externalStorageAccounts": {
  "value": [
    { "name": "sparkstg", "container": "sparkdata", "isDefault": "true","resourceGroupsName": "Spark" },
    { "name": "s1rg", "container": "blank", "isDefault": "false","resourceGroupsName": "s1rg" },
    { "name": "s2rg", "container": "blank", "isDefault": "false","resourceGroupsName": "s2rg" },
    { "name": "s3rg", "container": "blank", "isDefault": "false","resourceGroupsName": "s3rg" },
    { "name": "s4rg", "container": "blank", "isDefault": "false","resourceGroupsName": "s3rg" }
  ]
}

但是得到无效的模板错误

试图了解我在这里做错了什么。

stack overflow Azure ARM template with array as parameter
原文答案

答案:

作者头像

您需要从资源定义中删除 copy 并创建以下 json:

"storageProfile": {
    "copy": [
        {
            "name": "storageaccounts",
            "count": "[length(parameters('externalStorageAccounts'))]",
            "input": {
                "name": "[concat(parameters('externalStorageAccounts')[copyIndex('storageaccounts')].name,'.blob.core.windows.net')]",
                "isDefault": "[parameters('externalStorageAccounts')[copyIndex('storageaccounts')].isDefault]",
                "container": "[parameters('externalStorageAccounts')[copyIndex('storageaccounts')].container]",
                "key": "[listKeys(resourceId(parameters('externalStorageAccounts')[copyIndex('storageaccounts')].resourceGroupsName,'Microsoft.Storage/storageAccounts', parameters('externalStorageAccounts')[copyIndex('storageaccounts')].name), variables('defaultApiVersion')).key1]"
            }
        }
    ]
}

而不是你现有的 storageProfile

基本上你在做什么 - 尝试创建相同的资源 X 次,你需要做的是复制单个属性 X 次

好的,在稍微修改后,我可以向你保证这是不可能的,因为 listkeys 是一个运行时函数,而属性副本是一个编译时函数。所以这不可能奏效(起初我并没有想到这一点)。

您的解决方法可能是预先提取键并将它们直接添加到数组中,因此您的数组将如下所示:

"externalStorageAccounts": {
  "value": [
    { "name": "salsbx01sparkstg", "container": "dlid01spk21", "isDefault": "true","key": "xxx" },
    ...
    { "name": "s4rg", "container": "blank", "isDefault": "false","key": "xxx" }
  ]
},
作者头像

我认为这可能与我们正在跨数据中心推出的修复有关 - 您可以尝试部署到 westus(如果可能,我知道您有一些先决条件)并看看是否有效?我可以在那里验证模板(上周不能)。

作者头像

这个解决方案对我很有效

{
  "type": "Microsoft.Compute/disks",
  "name": "[concat(parameters('VmName'), copyIndex(), '-dataDisk')]",
  "apiVersion": "2017-03-30",
  "location": "[resourceGroup().location]",
  "sku": {
    "name": "Standard_LRS"
  },
  "copy": {
    "name": "VMDataDisksLoop",
    "count": "[parameters('numberOfNodes')]"
  },
  "properties": {
    "creationData": {
      "createOption": "Empty"
    },
    "diskSizeGB": 128
  }
}

它创建指定数量的磁盘,每个节点一个