使用 terragrunt generate provider block 导致与模块中的 require providers 块发生冲突

Using terragrunt generate provider block causes conflicts with require providers block in module

我正在使用 Terrag运行t 和 Terraform 版本 0.14.8。

我的项目使用单存储库结构,因为项目要求将 Terrag运行t 文件和 Terraform 模块打包在一个包中。

文件夹结构:

project root:
├── environments
│   └── prd
│       ├── rds-cluster
│       │   └── terragrunt.hcl
│       └── terragrunt.hcl
└── modules
    ├── rds-cluster
    │   ├── README.md
    │   ├── main.tf
    │   ├── output.tf
    │   └── variables.tf
    └── secretsmanager-secret
        ├── README.md
        ├── main.tf
        ├── output.tf
        └── variables.tf

在 prd/terragrunt.hcl 中,我定义了远程状态块和生成提供程序块。

remote_state {
  backend = "s3"
  ...
}

generate "provider" {
  path = "provider.tf"
  if_exists = "overwrite_terragrunt"

  contents = <<EOF
terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = "ca-central-1"
}
EOF
}

在environments/prd/rds-cluster/terragrunt.hcl中,我定义如下:

include {
  path = find_in_parent_folders()
}

terraform {
  source = "../../../modules//rds-cluster"
}

inputs = {
 ...
}

在modules/rds-cluster/main.tf中,我定义如下:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 3.0"
    }
  }
}

// RDS related resources...

我的问题是,当我尝试 运行 terrag运行t plan under environments/prd/rds-cluster 时,我收到以下错误消息:

Error: Duplicate required providers configuration

  on provider.tf line 3, in terraform:
   3:   required_providers {

A module may have only one required providers configuration. The required
providers were previously configured at main.tf:2,3-21.

我可以通过在 provider 块中声明版本来解决这个问题,如图所示 here. However, the version attribute in provider blocks has been deprecated in Terraform 0.13; Terraform 建议改用 terraform 块下的 required_providers 子块。

有人知道我需要做什么才能为我的 aws 提供商使用新的 required_providers 块吗?

如您所见,Terraform 期望每个模块仅具有其所需提供程序的一个定义,这是为了避免当声明分布在多个文件中时 Terraform 检测特定原因的原因不明确的情况。

但是,为了支持这种零碎的代码生成用例,Terraform 有一个名为 Override Files 的高级功能,它允许您明确标记某些文件以进行不同的处理模式,它们可以选择性地覆盖来自其他文件,而不是创建全新的定义。

此机制的详细信息取决于您覆盖的块类型,但 Merging terraform blocks` 部分讨论了与您的特定情况相关的行为:

If the required_providers argument is set, its value is merged on an element-by-element basis, which allows an override block to adjust the constraint for a single provider without affecting the constraints for other providers.

In both the required_version and required_providers settings, each override constraint entirely replaces the constraints for the same component in the original block. If both the base block and the override block both set required_version then the constraints in the base block are entirely ignored.

上面的实际含义是,如果您有一个包含 AWS 提供商条目的 required_providers 块的覆盖文件,那么 Terraform 会将其视为已存在的任何类似条目的完全替换在非覆盖文件中,但它不会影响根本没有出现在覆盖文件中的其他供应商要求条目。

将所有这些放在一起,您应该能够通过要求 Terragrunt 将此生成的文件命名为 provider_override.tf 而不是仅仅 provider.tf 来获得您正在寻找的结果,这将激活覆盖文件处理行为,从而允许此生成的文件覆盖 AWS 提供商要求的任何现有定义,同时允许配置保留它们可能也在定义的任何其他提供商要求。