listKeys使用内部变量或参数在ARM模板中出现问题



我正在为我的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.json0和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)]"

最新更新