ID已存在的Terraform资源

时间:2020-04-24 22:05:38

标签: azure terraform devops

当Terraform运行任务在azure devops发布管道中执行时,出现错误“具有ID的资源已存在”。 该资源存在于Azure中,但是如果资源已经存在,为什么它会抱怨该资源。这应该忽略这一部分。请帮我需要在代码中添加的内容,以解决此错误! 我是否只是在使用这个错误的Terraform工具来部署Azure资源? Terraform帮助太糟糕了!

resource "azurerm_resource_group" "test_project" {
  name = "${var.project_name}-${var.environment}-rg"
  location = "${var.location}"
  tags = {  
    application = "${var.project_name}" 
  }
}

3 个答案:

答案 0 :(得分:6)

Terraform旨在允许您使用特定的Terraform配置仅管理基础结构的一个子集,以防某些对象由其他工具管理,或者如果您已分解基础结构以由许多单独的配置进行管理合作以产生预期的结果。

作为该设计的一部分,Terraform区分了远程系统中存在的对象和由当前Terraform配置管理的对象。在基础API的技术约束允许的情况下,Terraform提供商将避免隐式获得该特定Terraform配置未创建的内容的所有权。您在这里看到的错误消息是Azure提供程序的实现,它在进行预检查以确保您给它提供的名称是唯一的,这样它就不会覆盖(并因此隐式拥有)在其他地方创建的对象。 / p>

要继续此处,您有两个主要选择,具体取决于您的预期目标:

  • 如果该对象以前是由其他系统管理的,而现在您希望仅通过此Terraform配置来管理它,则可以告诉Terraform将现有对象与您编写的resource块相关联因此,就好像该对象最初是由该资源块创建的一样:

    terraform import azurerm_resource_group.test_project /subscriptions/YOUR-SUBSCRIPTION-ID/resourceGroups/PROJECTNAME-ENVIRONMENTNAME-rg
    

    运行terraform import后,必须确保以前管理该对象的所有内容都不再与该对象关联。现在,此对象归此Terraform配置所有,并且不得由任何其他系统更改。

  • 如果此对象是由其他系统管理的,并且您希望以这种方式继续进行管理,则可以使用data块来检索有关该现有对象的信息可以在配置中的其他地方使用而无需Terraform拥有所有权:

    data "azurerm_resource_group" "example" {
      name = "${var.project_name}-${var.environment}-rg"
    }
    

    例如,如果您在模块的其他位置需要资源组的位置名称,则可以使用data.azurerm_resource_group.example.location来访问它。如果您以后想要对该资源组进行任何更改,则将继续使用您环境中被认为是该资源所有者的其他系统来进行此操作。

这两种方法之间的主要区别是Terraform如何在状态快照中记录对象。 terraform import使Terraform在您编写的资源配置和您在命令行上提供其ID的远程对象之间创建绑定,此后与Terraform在创建该对象并在第一个对象中记录了绑定本身之间就没有区别地点。对于数据资源,Terraform只是读取有关现有对象的数据,并将其缓存保存在状态中,以便它可以确定该值在以后的运行中是否已更改;它永远不会计划对与data块一起使用的对象进行任何修改。

答案 1 :(得分:0)

为了未来的自己: 今天我偶然发现了同样的问题,因为我重命名了一些资源,terraform 无法跟踪它们。我发现了 terraform state mv ...,它使您能够重命名状态文件中的资源,以便它可以跟踪远程资源。真的很有用。

答案 2 :(得分:-3)

尝试将${terraform.workspace}添加到资源名称。

resource "azurerm_resource_group" "test_project" {
  name = "${terraform.workspace}-${var.project_name}-${var.environment}-rg"
  location = "${var.location}"
  tags = {  
    application = "${var.project_name}" 
  }
}