我正在为我的Azure函数设置一个ARM模板。我有CCD_ 1;主";模板,并将用于其他发布管道。
然后会有项目特定的参数模板,比如:
- counter_function_arm.parameters.test.json
- counter_function_arm.parameters.acceptance.json
- weather_function_arm.parameters.test.json
等。
但我一直停留在这一部分,它在functions_app.json
模板中创建了实际的Function资源:
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('resourceName'))]"
}
]
}
}
}
为了简洁起见,我省略了一些内容。导入部分是appSettings
部分。
我最初的想法是把array
放在variables
中。这些将是";默认";设置。然后,从我的counter_function_arm.parameters.test.json
文件中,我会添加另一个特定于该应用程序的数组,然后将union
这两个数组放在一起,以便配置所有AppSettings
。
类似这样的东西:
counter_function_arm.parameters.test.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"customAppSettings":{
"value": [
{
"name": "CustomProperty",
"value": "some value"
}
]
}
}
}
函数_app.json
"variables": {
"defaultAppSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('resourceName'))]"
}
]
},
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(variables('defaultAppSettings'), parameters('customAppSettings'))]"
}
}
}
所以在这种情况下,我union
将变量functions_app.json
0和parameters('customAppSettings')
放在一起。
但是,问题是我不能在variables
部分中使用listKeys
。我也不能将其移动到parameters
部分并将其设置为defaultValue
,因为那里也不允许使用listKeys
。
向union
添加硬编码数组也不起作用:
"appSettings": "[union([1,2,3], parameters('customAppSettings'))]"
所以我没有主意了。
有办法做到这一点吗?
我已经找到了解决这个问题的方法,它不漂亮,但它有效。。。基本上,我有一个纯静态应用程序设置的数组(在您的例子中是FUNCTIONS_EEXTENSION_VERSION、FUNCTIONS_WORKER_RUNTIME、WEBSITE_CONTENTSHARE(,您可以在变量中创建它,一个来自参数的customAppSettings数组,以及另一个我必须作为原始JSON编写的数组。这里有一个例子:
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(variables('staticAppSettings'), parameters('customAppSettings'), json(concat('[{"name": "AzureWebJobsStorage","value": "', concat('DefaultEndpointsProtocol=https;AccountName=', parameters('azureFunctionParameters').functionStorageName,';AccountKey=', listKeys(resourceId(parameters('azureFunctionParameters').mainStorageResourceGroup, 'Microsoft.Storage/storageAccounts', parameters('azureFunctionParameters').functionStorageName), '2021-08-01').keys[1].value, ';EndpointSuffix=core.windows.net'),'"}]')))]"
}
}
}
]
遗憾的是,这是我能想到的最好的方法,它很容易出现语法错误,但如果你使用多行字符串,你可以用一种避免错误的方式对它进行格式化(但要小心,如果你使用Azure Devops,它是不兼容的(。
编辑:还有另一种方法可能更适合你,那就是使用linkedTemplate:
主模板
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "yourResourceDeployment",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('blobBaseUrl'), '/', parameters('resourceGroupName'), '/azurefunctions/baseazurefunction.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"azureFunctionParameters": {
"value": "[parameters('baseAzureFunctionParameters')]"
},
"appSettings": {
"value" : "[union(variables('staticAppSettings'), parameters('customAppSettings'))]"
},
"someMoreAppSettings": {
"value" : [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
}
]
}
}
}
}
]
在baseazurerefunction.json linkedTemplate中,您可以只使用
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(parameters('appSettings'), parameters('moreAppSettings'))]"
}
}
}
如果你对将连接字符串作为参数发送到其他模板有安全顾虑,你可以将你的appsettings包装在一个名为array的安全对象中,该属性将包含你的所有设置,然后像这样使用它来代替
"appSettings": {
"type": "secureobject",
"metadata": {
"description": "Secure object with an array property which contains the appsettings"
}
},
"moreAppSettings": {
"type": "secureobject",
"metadata": {
"description": "Secure object with an array property which contains more appsettings"
}
}
.
.
.
"appSettings": "[union(parameters('appSettings').array, parameters('moreAppSettings').array)]"