使用 terragrunt 生成提供者块会导致与模块中的 require 提供者块发生冲突

Ale*_*lex 4 terraform terragrunt terraform-provider-aws terraform0.12+

我正在使用 Terragrunt 和 Terraform 版本 0.14.8。

\n

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

\n

文件夹结构:

\n
project root:\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 environments\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 prd\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 rds-cluster\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 terragrunt.hcl\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 terragrunt.hcl\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 modules\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 rds-cluster\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.tf\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 output.tf\n    \xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 variables.tf\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 secretsmanager-secret\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.tf\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 output.tf\n        \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 variables.tf\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
remote_state {\n  backend = "s3"\n  ...\n}\n\ngenerate "provider" {\n  path = "provider.tf"\n  if_exists = "overwrite_terragrunt"\n\n  contents = <<EOF\nterraform {\n  required_providers {\n    aws = {\n      source = "hashicorp/aws"\n      version = "~> 3.0"\n    }\n  }\n}\n\nprovider "aws" {\n  region = "ca-central-1"\n}\nEOF\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在environments/prd/rds-cluster/terragrunt.hcl中,我定义了以下内容:

\n
include {\n  path = find_in_parent_folders()\n}\n\nterraform {\n  source = "../../../modules//rds-cluster"\n}\n\ninputs = {\n ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在modules/rds-cluster/main.tf中,我定义了以下内容:

\n
terraform {\n  required_providers {\n    aws = {\n      source  = "hashicorp/aws"\n      version = ">= 3.0"\n    }\n  }\n}\n\n// RDS related resources...\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
Error: Duplicate required providers configuration\n\n  on provider.tf line 3, in terraform:\n   3:   required_providers {\n\nA module may have only one required providers configuration. The required\nproviders were previously configured at main.tf:2,3-21.\n
Run Code Online (Sandbox Code Playgroud)\n

我可以通过在提供程序块中声明版本来解决此问题,如此处所示但是, Terraform 0.13 中已弃用提供程序块中的版本属性;Terraform 建议改用 terraform 块下的 required_providers 子块。

\n

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

\n

Mar*_*ins 12

正如您所看到的,Terraform 希望每个模块对其所需的提供程序只有一个定义,这是为了避免出现以下情况:当声明分布在多个文件中时,Terraform 为何检测到特定的特定内容。

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

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

如果required_providers设置了参数,则其值将在逐个元素的基础上合并,这允许覆盖块调整单个提供程序的约束,而不影响其他提供程序的约束。

required_versionrequired_providers设置中,每个覆盖约束完全替换原始块中同一组件的约束。如果基本块和覆盖块都设置了 required_version,则基本块中的约束将被完全忽略。

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

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