【问题标题】:listKeys problems in ARM template using inside variables or parametersARM模板中使用内部变量或参数的listKeys问题
【发布时间】:2021-12-15 13:32:30
【问题描述】:

我正在为我的 Azure Functions 设置一个 ARM 模板。我有functions_app.json,它将作为“主”模板,也将用于其他发布管道。

然后会有项目具体的参数模板,比如:

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

functions_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 变量variables('defaultAppSettings')parameters('customAppSettings') 放在一起。

但是,问题是我不能在variables 部分中使用listKeys。我也无法将其移至parameters 部分并将其设置为defaultValue,因为那里也不允许使用listKeys

将硬编码数组添加到union 也不起作用:

"appSettings": "[union([1,2,3], parameters('customAppSettings'))]"

所以我没有想法。

有没有办法做到这一点?

【问题讨论】:

    标签: azure-devops azure-resource-manager arm-template


    【解决方案1】:

    我找到了解决这个问题的方法,它并不漂亮,但它有效......基本上我有一组纯静态应用程序设置(在你的情况下为 FUNCTIONS_EXTENSION_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'),'\"}]')))]"
                }
            }
        }
    ]
    

    遗憾的是,这是我能想到的最好的方法,它很容易出现语法错误,但如果您使用 multi-line strings,您可以将其格式化以避免错误(但如果您使用 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')]"
                            }
                        ]
                    }
                }
            }
        }
    ]
    

    在 baseazurefunction.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 包装在一个安全对象中,该对象具有一个名为数组的属性,该属性将包含您的所有设置,然后像这样使用它

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

    【讨论】:

    • 谢谢,我选择了你的第一个例子。它不漂亮,但它似乎在我的版本中工作。
    猜你喜欢
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多