Terraform 资源已更改

Terraform resources has changed

使用以下 Terraform 和 aws 提供商

Terraform v1.1.8
on linux_amd64
Installed hashicorp/aws v4.10.0

以及下面的代码

# S3 Bucket Policy
data "aws_iam_policy_document" "lambda-bucket" {
  statement {
    effect = "Allow"

    actions = [
      "s3:*",
    ]

    principals {
      type = "AWS"

      identifiers = [
        "arn:aws:iam::${var.account_ids.account_1}:role/Teamcity-fullaccess",
        "arn:aws:iam::${var.account_ids.account_2}:role/teamcity-poweruser"
      ]
    }

    resources = [
      aws_s3_bucket.lambda-bucket.arn,
      "${aws_s3_bucket.lambda-bucket.arn}/*",
    ]
  }
}

# Bucket
resource "aws_s3_bucket" "lambda-bucket" {
  bucket = "lambdas-${terraform.workspace}"
  tags = merge(var.default_tags, local.env_tag, {
    Name = "lambdas-${terraform.workspace}"
  })
}

resource "aws_s3_bucket_versioning" "lambda-bucket" {
  bucket = aws_s3_bucket.lambda-bucket.bucket
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "lambda-bucket" {
  bucket = aws_s3_bucket.lambda-bucket.bucket

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_s3_bucket_acl" "lambda-bucket" {
  bucket = aws_s3_bucket.lambda-bucket.bucket
  acl    = "private"
}

resource "aws_s3_bucket_policy" "lambda-bucket" {
  bucket = aws_s3_bucket.lambda-bucket.id
  policy = data.aws_iam_policy_document.lambda-bucket.json
}

我不断收到通知说对象在 Terraform 之外发生了变化,据我所知这不是真的

  # aws_s3_bucket.lambda-bucket has changed
  ~ resource "aws_s3_bucket" "lambda-bucket" {
        id                          = "lambdas-dev1"
      ~ policy                      = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Principal = {
                          ~ AWS = [
                              - "arn:aws:iam::xxxx:role/Teamcity-fullaccess",
                                "arn:aws:iam::yyyy:role/teamcity-poweruser",
                              + "arn:aws:iam::xxxx:role/Teamcity-fullaccess",
                            ]
                        }
                        # (3 unchanged elements hidden)
                    },
                ]
                # (1 unchanged element hidden)
            }
        )
        tags                        = {
            "Environment"  = "dev1"
            "Name"         = "lambdas-dev1"
            "Terraform"    = "True"
        }
        # (11 unchanged attributes hidden)



        # (3 unchanged blocks hidden)
    }

如果它有价值,这是我的帐户 ID 变量

# Account IDs
account_ids = {
  "account_1" = "xxxx",
  "account_2" = "yyyy"
}

我是不是漏掉了什么?

每当提供商通过 returning 不同于 return 从最近的基础架构更改中编辑的值来响应“刷新”操作时,Terraform 都会生成此“对象已在 Terraform 之外更改”消息.

在 Terraform 的体系结构中,提供者的部分职责是实施规则来区分暗示功能变化的差异(例如现在具有不同效果的策略)和只是不同方式的差异写下相同的规则,就像您的示例中的情况一样。

远程 APIs 通常允许多种方式来表达相同的意图作为对可用性的让步,并且 Terraform 提供者原则上应该自己实施相应的规则以避免误报这种规范化。然而,在实践中,这些规则通常在 API 文档中没有得到很好的描述,因此不幸的是,提供者开发人员只能从对提供者观察到的行为的反馈中了解它们。

我在上面的评论线程中看到您已经向 AWS 提供商团队提出了一个问题来报告您的问题,这是我在这里推荐的。

与此同时,您可以通过重新排序源策略以匹配 S3 API 正在 returning 的规范化形式来避免噪音,尽管这并不总是可能的,如果例如API 本身在规范化方面并不一致(每个请求的一些 APIs return 不同的顺序,即使基础数据没有改变)或者如果你正在构建数据在 Terraform 中使用一种不决定特定顺序的机制。

如果 aws_iam_policy_document 数据源将 identifiers 指定为一组字符串而不是字符串列表,那么您将无法通过在配置中重新排序来覆盖排序,因为 Terraform 集本质上是无序的。如果这是真的,那么您可能需要直接使用 the jsonencode function 构建预期的 IAM 策略文档,以便您可以准确控制将使用的结构和顺序,因此可以匹配 S3 API 的规范化正在执行,直到更新提供程序以了解此规范化规则并自动处理它。