Azure Resource Manager模板网站应用程序设置来自参数阵列



我正在尝试使用一系列参数 - 特别是电子邮件收件人列表 - 并将其写入我的Web应用程序的应用程序设置。

以下模板有效,但是 - 显然 - 仅写入数组中的第一项和第二个项目。

我已经研究了复制功能,但这似乎只能处理对象的创建,但我需要添加到键值对的现有列表中。

{
  "$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]]",
            ...
          }
        }
  ]
}

我的用例非常相似:我希望用户指定要用于碎片的存储帐户的数量存储帐户,然后每个人都将连接字符串与我所有其他应用程序设置一起以:

以及我所有其他应用程序设置并肩设置添加连接字符串。
<other app settings>
...
"STORAGE_CONNECTION_STRING_00": "<connectionString00>",
"STORAGE_CONNECTION_STRING_01": "<connectionString01>",
...

我意识到我可能为时已晚,无法帮助您,但是希望这会帮助别人。

解决方案的关键是,而不是将应用程序设置指定为Microsoft.Web/sites资源的子资源,而是在属性部分中指定它们内联。至关重要的是,这使您可以将它们指定为一个对象数组,每个对象都具有namevalue属性,而不是作为一个大对象,如您的问题:

{
  "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'))]"
    }
  },
  ...
}

不幸的是,模板变量热切地评估,这意味着您无法参考任何资源属性。这是评估连接字符串的问题,也是我的其他应用程序设置,其中包含我在模板中部署的其他资源的引用。

研究这个问题会导致查看嵌套模板,尤其是此堆栈溢出答案,用于在数组中使用嵌套模板上的copy在数组中构建动态评估的对象列表。

这种方法看起来很有希望,直到我达到了另一个手臂模板的限制:

对于嵌套模板,您不能使用嵌套模板中定义的参数或变量。

解决方案是使用链接模板,但这是一个巨大的过度杀伤,应该是一个琐碎的问题。

在刮擦一些头后,我最终找出了一种适应它仅使用输出参数的方法,从而使其可以使用嵌套模板进行工作:

...
{
  "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数组作为空数组输出。
  • 输出第一个连接字符串应用程序设置对象。
  • 输出Web应用程序要求的所有其他应用程序设置对象的数组。

然后,使用copyreferenceN部署用于循环,我想部署的每个碎片之一(或在您的情况下,每个电子邮件接收者)。每个人都执行以下操作:

  • 输出新的storageAppSettings数组作为storageAppSettings数组的串联和上一个迭代referenceN-1中生成的storageAppSetting对象。
  • 输出Nth storageAppSetting对象。

请注意,在最终的referenceN中,我们不需要输出storageAppSetting,因为第一个是在reference0中创建的,因此,为了整洁,我们有一个condition来停止它。不幸的是,即使存在conditionvalue仍会被评估,除非您使用诸如min(variables('maximumShardIndex'), copyIndex(1))之类的内容来防止端口错误,否则将变量maximumShardIndex定义为[sub(parameters('resultsShardCount'), 1)]。另一个解决方法,但随之而来的是它可以正常工作。

最终referencestorageAppSettings数组输出是我们的完整连接字符串应用程序设置对象的完整数组,而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)]"
    }
  },
  ...
}

我已经对此进行了测试,并且已经成功部署了一个针对N个存储帐户的数据,如resultsShardCount模板参数。

我认为,您的解决方案看起来会大致相同,除非建立连接字符串name/value对象,您会从接收器列表中构建一个类似的数组,从而传递给模板。

您可以在属性对象中使用复制函数 - 请参阅:https://learn.microsoft.com/en-us/azure/azure-resource-resource-manager/Resource-Group--创建#property-ititeration

将其视为部署模板之前的复制/糊状操作类型。

最新更新