如何通过资源类型和标识符在ARM模板中识别Azure资源是否存在
如何通过资源类型和标识符在ARM模板中识别Azure资源是否存在
事实上,这是有可能的。您可以使用资源组标记来标记当前已部署的版本并跳过部署(如果设置了该标记)。所有这些都可以通过链接的模板实现。
请注意,我们不会检查资源是否存在,但仍允许编写包含一次性初始化模板的 ARM 模板。最后一个模板将在资源组被删除并且资源丢失的情况下恢复资源(前提是您重新创建了资源组)。您可以将其扩展以支持每个资源的标记,在某些情况下更加有用。
启动部署的模板可能如下所示:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"DeploymentTemplateLink": {
"type": "string"
},
"DeploymentVersion": {
"defaultValue": 1,
"type": "int"
}
},
"variables": {
"rgWithDefaultVersion": {
"tags": {
"Version": "0"
}
}
},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2017-05-10",
"name": "DeploymentTemplate",
"condition": "[less(int(union(variables('rgWithDefaultVersion'), resourceGroup()).tags['Version']), parameters('DeploymentVersion'))]",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[parameters('DeploymentTemplateLink')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"DeploymentVersion": {
"value": "[parameters('DeploymentVersion')]"
}
}
}
}
]
}
链接模板的条件检查标签,仅当当前版本(存储在标签中)小于请求的版本时返回true。实际上,您不必维护版本:只需不设置DeploymentVersion参数即可仅首次部署。如果您决定重新部署,则始终可以选择增加版本,这将导致链接模板(又名“主部署”)的部署。{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"DeploymentVersion": {
"defaultValue": 1,
"type": "int"
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/tags",
"name": "default",
"apiVersion": "2019-10-01",
"dependsOn": [],
"properties": {
"tags": {
"Version": "[string(parameters('DeploymentVersion'))]"
}
}
}
]
}
注意:对于那些不理解union()和rgWithDefaultVersion的人来说,ARM模板部署将会失败,如果所引用的对象不包含一个属性。在我们的情况下,我们有两个这样的属性:'tags' 和 'Version'。'Tags' 只在特定资源组具有或曾经具有标签时存在。'Version'只在我们已经写入它一次后才存在(在主部署中)。因此,在访问它们之前,我们使用一个适当的默认值执行union()操作,以确保我们可以安全地访问这些属性。
union
的技巧真是太棒了。 - Vladislavmerge
,而不是replace
)
当将多个资源作为RG标记保持状态时,如果并行运行ARM模板步骤而不是顺序,则维护标记会成为一个问题,因为由于某些竞争条件而丢失一些标记。 - johni在 ARM 模板中无法实现此操作。您可以使用一些外部源(如 PowerShell)来确定并传递适当值的参数,或者您可以使用标记来找出 (具有资源存在\不存在的标记)。
{
...
"condition": "[empty(resourceId('[resourceGroup().id]', 'Microsoft.SQL/servers', parameters('serverName')))]",
...
}
您可以针对任何资源类型执行此操作。
resourceId
函数实际上并没有检查资源是否存在,它只是返回给定资源组、类型和名称的ID。请参阅文档以获取更多信息-https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#resourceid - David Gard