【问题标题】:How to check the resource exists in the arm template如何检查arm模板中是否存在资源
【发布时间】:2019-07-08 09:28:38
【问题描述】:

如何通过资源类型和标识符识别 ARM 模板中是否存在 azure 资源

【问题讨论】:

  • ARM 模板本质上是声明性的(所以理论上这不是必需的) - 你的情况是什么,可能有另一种方法来做你在想的事情......

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


【解决方案1】:

实际上是有可能的。您可以使用资源组标签来标记当前部署的版本,如果设置了标签则跳过部署。所有这些都可以通过链接模板来实现。
请注意,我们不检查资源本身是否存在,但我们仍然允许编写可能包含一次性初始化模板的 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 参数,它只会在第一次部署。如果您决定重新部署,您始终可以选择增加版本,这将导致链接模板的部署(也称为“主部署”)。

主要部署模板在你身上,但它应该包含一个 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() 操作,以确保我们可以安全地访问所提到的属性。

【讨论】:

  • 非常好,正是我今天所需要的......而且我什至不是问这个问题的人。谢谢!
  • 这是一个很好的解决方法,谢谢! union 的诀窍太棒了
  • 很好的答案本尼!有没有办法修补标签? (即merge,而不是replace)当有多个受状态影响的资源保留为RG标签时,在并行运行ARM模板步骤而不是运行ARM模板步骤时,维护标签而不丢失一些标签就成了一个问题。序列。
  • 伙计,你是否意识到你所做的方式是无用的复杂性?您是否要将条件应用于 ARM 模板中的每个资源?其次,如果真实资源有配置漂移,如果该资源的版本标签没有更改,则永远不会回滚。
  • 我的意思是,这几乎就是我在回答中提到的,但是(类似于@BMW)我不鼓励这种方法。模板并不真正关心现在存在的状态。他们应该“做到这一点”。你有 git 来跟踪以前的状态。
【解决方案2】:

在 arm 模板中无法做到这一点。您可以使用一些外部源(如powershell)来确定并传入具有适当值的参数,或者您可以使用标签来解决这个问题(有一个代表资源存在\不存在的标签)。

【讨论】:

    【解决方案3】:

    资源管理器提供以下函数来获取资源值:Resource functions for Azure Resource Manager templates

    您可以用一块 powershell\whatever 包装您的模板,这将确定资源是否存在,并根据该参数传入参数值,并在模板中使用条件语句来决定根据输入(但输入必须来自其他地方)

    【讨论】:

      【解决方案4】:

      您可能会发现 https://docs.microsoft.com/en-us/azure/developer/terraform/overview 这对于解决您的问题很有用。
      Hashicorp Terraform 是一种用于配置和管理云基础设施的开源工具。它将基础设施编入描述云资源拓扑的配置文件中。这些资源包括虚拟机、存储帐户和网络接口。 Terraform CLI 提供了一种将配置文件部署到 Azure 并对其进行版本控制的简单机制。

      但这将要求您远离 ARM 模板。

      【讨论】:

        【解决方案5】:

        我最近需要一个解决方案来基本上对 SQL 服务器进行增量更新。既然你不能这样做;模板将因 NameAlreadyExists 错误而失败。 所以我需要检查资源不存在,如果不存在才创建。

        添加“条件”检查 azure 资源 id 是否存在;如果有,请不要创建。

        {
         ...
         "condition": "[empty(resourceId('[resourceGroup().id]', 'Microsoft.SQL/servers', parameters('serverName')))]",
         ...
        }
        

        您可以对任何资源类型执行此操作。

        【讨论】:

        • 这不起作用,因为resourceId 函数实际上并不检查资源是否存在,它只是返回给定资源组、类型和名称的 ID。有关更多信息,请参阅文档 - docs.microsoft.com/en-us/azure/azure-resource-manager/…
        • 这个答案是完全错误的。谁赞成这个?
        • 需要注意的是,这种做法之所以错误,是因为在找不到资源ID的时候,会报错,而不是空字符串。如果返回一个空字符串,那么它看起来会起作用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 2018-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-02
        相关资源
        最近更新 更多