首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Terraform:如何删除从数组/列表中创建的用户资源?

Terraform:如何删除从数组/列表中创建的用户资源?
EN

Stack Overflow用户
提问于 2019-08-01 15:01:51
回答 1查看 2.3K关注 0票数 2

我有一个文件users.tf文件,它为aws创建管理用户。它通过定义一个列表(例如users = ["bob", "john", "tom"])来做到这一点。

然后使用terraform中的aws_iam_user功能遍历它们,如下所示:

代码语言:javascript
运行
复制
resource "aws_iam_user" "user" {
  count = length(local.users)
  name  = local.users[count.index]
}

这里的问题是,如果从上面的示例中删除数组的第一个元素(从上面的示例中移除“bob”),那么terraform在发出terraform plan之后建议做什么,而不是删除bob,而是将bob更改为john,将john更改为tom,并删除tom。

就像这样:

代码语言:javascript
运行
复制
  # aws_iam_user.user[0] will be updated in-place
  ~ resource "aws_iam_user" "user" {
        arn           = "arn:aws:iam::5555555:user/bob"
        force_destroy = false
        id            = "bob"
      ~ name          = "bob" -> "john"
        path          = "/"
        tags          = {}
        unique_id     = "BLABLABLA11111"
    }

  # aws_iam_user.user[1] will be updated in-place
  ~ resource "aws_iam_user" "user" {
        arn           = "arn:aws:iam::5555555:user/john"
        force_destroy = false
        id            = "john"
      ~ name          = "john" -> "tom"
        path          = "/"
        tags          = {}
        unique_id     = "BLABLABLA22222"
    }

  # aws_iam_user.user[2] will be destroyed
  - resource "aws_iam_user" "user" {
      - arn           = "arn:aws:iam::5555555:user/tom" -> null
      - force_destroy = false -> null
      - id            = "tom" -> null
      - name          = "tom" -> null
      - path          = "/" -> null
      - tags          = {} -> null
      - unique_id     = "BLABLABLA3333" -> null

这将导致约翰得到鲍勃的arn,而汤姆得到约翰的arn。这是不可取的。

我尝试使用for_each循环的for_each循环(在编写这个问题前19小时发布)代替count,并将键定义为原始索引号,希望terraform将它们视为相同的资源。

是啊,没那么幸运:

代码语言:javascript
运行
复制
...
# aws_iam_user.user[1] will be destroyed
...
# aws_iam_user.user["1"] will be created
...

我将总结我的问题:

是否有任何方法删除资源(特别是aws_iam_user),当该资源是通过迭代列表来创建的,这样所有剩余的资源都保持原样吗?

EN

Stack Overflow用户

回答已采纳

发布于 2019-08-01 17:08:09

您在这里看到的是文档在其最后一段中警告的情况:

请注意,count创建的独立资源实例仍然由其索引来标识,而不是由给定列表中的字符串值标识。这意味着,如果从列表的中间删除一个元素,那么在它看到元素的subnet_id值发生变化之后,所有索引实例都会发生变化,这将导致可能比预期更多的远程对象更改。从列表中生成多个实例的做法应该谨慎使用,并适当注意如果列表稍后更改会发生什么。

幸运的是,这正是for_each特性想要解决的问题。但是,为了有效地使用它,在传递给for_each的映射中选择有意义的唯一键是很重要的

代码语言:javascript
运行
复制
resource "aws_iam_user" "user" {
  for_each = { for name in local.users : name => name }

  name  = each.value
}

这将导致Terraform跟踪像aws_iam_user.user["john"]这样的实例标识符,而不是aws_iam_user.user[1]

但是,您的状态中有现有的count-based实例,因此需要采取一些迁移步骤才能实现。不幸的是,Terraform没有足够的信息来自动将现有的基于索引的地址与新的基于名称的地址关联起来,但是通过使用现有列表和单独的一次性脚本,您可以告诉Terraform如何通过对列表中的每个条目运行这样的命令来翻译这些地址:

代码语言:javascript
运行
复制
terraform state mv 'aws_iam_user.user[1]' 'aws_iam_user.user["john"]'

之后,Terraform将通过名称跟踪这些对象,因此添加和删除名称只会影响与您更改的名称相关的对象。

如果您现在还没有准备好完全切换到for_each,可以使用类似的策略和一次性脚本来“修复”从列表中删除项目所造成的漏洞:

代码语言:javascript
运行
复制
# First, Terraform must "forget" the user that you removed
terraform state rm 'aws_iam_user.user[0]'

# Then renumber the subsequent items to correlate with their new
# positions in the list.
terraform state mv 'aws_iam_user.user[1]' 'aws_iam_user.user[0]'
terraform state mv 'aws_iam_user.user[2]' 'aws_iam_user.user[1]'
# etc, etc

当然,这将是一个相当繁琐,容易出错的过程,如果您有超过少数用户,所以最好编写一个小程序来生成脚本。

票数 9
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57311928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档