我试图获取一系列参数 - 特别是电子邮件收件人列表 - 并将这些参数写入我的网络应用程序的应用程序设置。
以下模板可以工作,但显然只会从数组中写入第一个和第二个项目。
我研究了复制功能,但这只能处理对象的创建,但我需要添加到现有的键值对列表中。
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
...
"parameters": {
"Email:Recipients": {
"type": "array"
},
...
"resources": [
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
...
"resources": [
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"properties": {
...
"Email:Recipients:0": "[parameters('Email:Recipients')[0]]",
"Email:Recipients:1": "[parameters('Email:Recipients')[1]]",
...
}
}
]
}
您可以在属性对象中使用复制功能 - 请参阅:https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-create-multiple#property-iteration
在部署模板之前,将此视为复制/粘贴操作类型。
我有一个非常相似的用例:我希望用户指定用于分片的存储帐户数量,并希望模板创建所有存储帐户,然后为每个帐户添加一个连接字符串作为应用程序设置一个Web应用程序以及我的所有其他应用程序设置,格式如下:
<other app settings>
...
"STORAGE_CONNECTION_STRING_00": "<connectionString00>",
"STORAGE_CONNECTION_STRING_01": "<connectionString01>",
...
我意识到我可能来不及帮助你,但希望这会帮助别人。
解决方案的关键是,不要将您的应用程序设置指定为Microsoft.Web/sites
资源的子资源,而是在属性部分中内联指定它们。至关重要的是,这允许您将它们指定为一个对象数组,每个对象都有name
和value
属性,而不是像您的问题中的一个大对象:
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
...
"properties": {
...
"siteConfig": {
"appSettings": [
{
name: "STORAGE_CONNECTION_STRING_00",
value: "<connectionString00>"
},
...
]
},
...
}
对于我的第一次尝试,我尝试使用copy
将所有连接字符串添加到此列表中:
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
...
"properties": {
"siteConfig": {
"copy": [
{
"name": "appSettings",
"count": "[parameters('resultsShardCount')]",
"input": {
"name": "[concat('STORAGE_CONNECTION_STRING_', padLeft(copyIndex('appSettings'), 2, '0'))]",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageDataAccountNames')[copyIndex('appSettings')],';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageDataAccountNames')[copyIndex('appSettings')]), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
}
}
]
}
},
...
}
这有效,但它不允许我在存储连接字符串旁边添加任何其他应用程序设置。
我尝试添加使用单独的appsettings
子资源添加其他应用程序设置,如原始问题,希望它们将被合并,但这只是覆盖了连接字符串。
接下来,我尝试使用copy
定义两个变量,一个是连接字符串对象的数组,另一个是所有其他应用程序设置对象的静态数组。我想我可以使用union
函数来组合它们:
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
...
"properties": {
"siteConfig": {
"appSettings": "[union(variables('additionalAppSettings), variables('storageAppSettings'))]"
}
},
...
}
不幸的是,急切地评估模板变量,这意味着您无法引用任何资源属性。这对于评估连接字符串和我的一些其他应用程序设置都是一个问题,这些设置包含对我在模板中部署的其他资源的引用。
研究该问题导致查看嵌套模板,特别是this Stack Overflow answer,用于在嵌套模板上使用copy
构建数组中动态评估对象的列表。
这个方法看起来很有希望,直到我遇到了ARM模板的another limitation:
对于嵌套模板,您不能使用嵌套模板中定义的参数或变量。
解决方案是使用链接模板,但这对于应该是一个微不足道的问题来说是一个巨大的过度杀伤力。
在经过一番努力之后,我终于找到了一种方法来调整它以仅使用输出参数,允许它使用嵌套模板工作:
...
{
"name": "reference0",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"dependsOn": [
"storageDataAccountCopy"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [],
"outputs": {
"storageAppSettings": {
"type": "array",
"value": []
},
"storageAppSetting": {
"type": "object",
"condition": "[greater(parameters('resultsShardCount'), 0)]",
"value": {
"name": "[concat('STORAGE_CONNECTION_STRING_', padLeft(0, 2, '0'))]",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageDataAccountNames')[0],';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageDataAccountNames')[0]), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
}
},
"additionalAppSettings": {
"type": "array",
"value": [
{
"name": "APPLICATION_INSIGHTS_KEY",
"value": "[reference(concat('Microsoft.Insights/components/', variables('applicationInsightsName'))).InstrumentationKey]"
}
...
]
}
}
}
}
},
{
"name": "[concat('reference', copyIndex(1))]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"copy": {
"name": "storageAppSettings",
"count": "[parameters('resultsShardCount')]"
},
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [],
"outputs": {
"storageAppSettings": {
"type": "array",
"value": "[concat(reference(concat('reference', copyIndex())).outputs.storageAppSettings.value, array(reference(concat('reference', copyIndex())).outputs.storageAppSetting.value))]"
},
"storageAppSetting": {
"type": "object",
"condition": "[less(copyIndex(1), parameters('resultsShardCount'))]",
"value": {
"name": "[concat('STORAGE_CONNECTION_STRING_', padLeft(copyIndex(1), 2, '0'))]",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageDataAccountNames')[min(variables('maximumShardIndex'), copyIndex(1))],';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageDataAccountNames')[min(variables('maximumShardIndex'), copyIndex(1))]), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value)]"
}
}
}
}
}
},
...
解释这是如何工作的:
reference0
部署用于:
storageAppSettings
数组作为空数组。然后使用referenceN
对copy
部署进行循环,每个shard我要部署一个(或者在每种情况下为每个电子邮件收件人一个)。每个人都做到以下几点:
storageAppSettings
数组作为storageAppSettings
数组和前一次迭代storageAppSetting
中生成的referenceN-1
对象的串联。Nth
storageAppSetting
对象。请注意,在最后的referenceN
上,我们不需要输出storageAppSetting
,因为第一个是在reference0
中创建的,所以为了整洁,我们有一个condition
来阻止它。不幸的是,即使condition
存在,value
仍然被评估,导致索引超出界限错误,除非你使用像min(variables('maximumShardIndex'), copyIndex(1))
这样的东西来保护它,其中变量maximumShardIndex
被定义为[sub(parameters('resultsShardCount'), 1)]
。另一个解决方法,但有了它,它工作正常。
因此,最终storageAppSettings
的reference
数组输出是我们完整的连接字符串应用程序设置对象数组,additionalAppSettings
的reference0
数组输出是我们想要的所有其他应用程序设置对象连接字符串。
最后,您可以在Web应用程序中创建appSettings
数组,作为这两个数组的并集:
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
...
"properties": {
"siteConfig": {
"appSettings": "[union(reference('reference0').outputs.additionalAppSettings.value, reference(concat('reference', parameters('resultsShardCount'))).outputs.storageAppSettings.value)]"
}
},
...
}
我已对此进行了测试,并且已成功部署了一个Web应用程序,该应用程序根据resultsShardCount
模板参数指定对N个存储帐户进行数据分片。
我认为你的解决方案看起来大致相同,除了建立一个连接字符串name
/ value
对象的数组,你将从传入模板的收件人列表中建立一个类似的数组。