如何检查arm模板中是否存在资源
How to check the resource exists in the arm template
如何通过资源类型和标识符识别 Azure 资源是否存在于 ARM 模板中
资源管理器提供了以下获取资源值的函数:Resource functions for Azure Resource Manager templates
你可以用一段 powershell\whatever 包裹你的模板,这将确定资源是否存在,并根据它传入参数值,并在模板中使用条件语句来决定要做什么根据输入做(但输入必须来自其他地方)
在 arm 模板中无法做到这一点。您可以使用一些外部源(如 powershell)来确定并传递具有适当值的参数,或者您可以使用标签来计算(有一个代表资源的 existence\absence 的标签)。
我最近需要一个解决方案来基本上对 SQL 服务器进行增量更新。因为你不能这样做;该模板将因 NameAlreadyExists 错误而失败。
所以我需要检查资源是否不存在,只有在不存在时才创建。
添加 "condition" 检查 azure 资源 id 是否存在;如果有就不要创建。
{
...
"condition": "[empty(resourceId('[resourceGroup().id]', 'Microsoft.SQL/servers', parameters('serverName')))]",
...
}
您可以对任何资源类型执行此操作。
这实际上是有可能的。您可以使用资源组标签来标记当前部署的版本,如果设置了标签则跳过部署。所有这些都可以通过链接模板实现。
请注意,我们本身不检查资源是否存在,但我们仍然允许编写可以包含一次性初始化模板的 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')]"
}
}
}
}
]
}
链接模板的条件查看标签,returns仅当当前版本(存储在标签中)低于请求的版本时才为真。您实际上不必维护版本控制:只要不设置 DeploymentVersion 参数,它只会在第一次部署时部署。如果您决定重新部署,您始终可以选择增加版本,这将导致部署链接模板(又名 "main deployment")。
主要部署模板在您身上,但它应该包含 tags 资源以维护逻辑。
{
"$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'))]"
}
}
}
]
}
Remark 对于那些不理解 union() 和 rgWithDefaultVersion 的人.如果引用的对象不包含 属性,ARM 模板部署将失败。在我们的例子中,我们有两个这样的属性:'tags' 和 'Version'。 'Tags' 仅当特定资源组具有或曾经具有标签时才会存在。 'Version' 只有在我们已经写过一次之后才会存在(在主部署中)。因此,在我们访问它们之前,我们使用适当的默认对象对返回的对象执行 union() 操作,确保我们可以安全地访问上述属性。
您可能会发现https://docs.microsoft.com/en-us/azure/developer/terraform/overview这对解决您的案件很有用。
Hashicorp Terraform 是一种用于配置和管理云基础设施的开源工具。它在描述云资源拓扑结构的配置文件中对基础架构进行编码。这些资源包括虚拟机、存储帐户和网络接口。 Terraform CLI 提供了一种简单的机制来将配置文件部署到 Azure 并对其进行版本控制。
但这需要您离开 ARM 模板。
如何通过资源类型和标识符识别 Azure 资源是否存在于 ARM 模板中
资源管理器提供了以下获取资源值的函数:Resource functions for Azure Resource Manager templates
你可以用一段 powershell\whatever 包裹你的模板,这将确定资源是否存在,并根据它传入参数值,并在模板中使用条件语句来决定要做什么根据输入做(但输入必须来自其他地方)
在 arm 模板中无法做到这一点。您可以使用一些外部源(如 powershell)来确定并传递具有适当值的参数,或者您可以使用标签来计算(有一个代表资源的 existence\absence 的标签)。
我最近需要一个解决方案来基本上对 SQL 服务器进行增量更新。因为你不能这样做;该模板将因 NameAlreadyExists 错误而失败。 所以我需要检查资源是否不存在,只有在不存在时才创建。
添加 "condition" 检查 azure 资源 id 是否存在;如果有就不要创建。
{
...
"condition": "[empty(resourceId('[resourceGroup().id]', 'Microsoft.SQL/servers', parameters('serverName')))]",
...
}
您可以对任何资源类型执行此操作。
这实际上是有可能的。您可以使用资源组标签来标记当前部署的版本,如果设置了标签则跳过部署。所有这些都可以通过链接模板实现。
请注意,我们本身不检查资源是否存在,但我们仍然允许编写可以包含一次性初始化模板的 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')]"
}
}
}
}
]
}
链接模板的条件查看标签,returns仅当当前版本(存储在标签中)低于请求的版本时才为真。您实际上不必维护版本控制:只要不设置 DeploymentVersion 参数,它只会在第一次部署时部署。如果您决定重新部署,您始终可以选择增加版本,这将导致部署链接模板(又名 "main deployment")。
主要部署模板在您身上,但它应该包含 tags 资源以维护逻辑。
{
"$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'))]"
}
}
}
]
}
Remark 对于那些不理解 union() 和 rgWithDefaultVersion 的人.如果引用的对象不包含 属性,ARM 模板部署将失败。在我们的例子中,我们有两个这样的属性:'tags' 和 'Version'。 'Tags' 仅当特定资源组具有或曾经具有标签时才会存在。 'Version' 只有在我们已经写过一次之后才会存在(在主部署中)。因此,在我们访问它们之前,我们使用适当的默认对象对返回的对象执行 union() 操作,确保我们可以安全地访问上述属性。
您可能会发现https://docs.microsoft.com/en-us/azure/developer/terraform/overview这对解决您的案件很有用。
Hashicorp Terraform 是一种用于配置和管理云基础设施的开源工具。它在描述云资源拓扑结构的配置文件中对基础架构进行编码。这些资源包括虚拟机、存储帐户和网络接口。 Terraform CLI 提供了一种简单的机制来将配置文件部署到 Azure 并对其进行版本控制。
但这需要您离开 ARM 模板。