Terraform 0.15.1多供应商问题-论点;地区“;是必需的,但未设置

Terraform 0.15.1多供应商问题-论点;地区“;是必需的,但未设置,terraform,terraform-provider-aws,Terraform,Terraform Provider Aws,下面是我的项目文件结构: ├── main.tf ├── tunnel │   ├── main.tf │   └── variables.tf └── variables.tf 我正在尝试使用Terraform 0.15.1中的多个提供程序,如下所述-> 在遵循这个例子之后,我无法让它工作。我现在简化了代码,只使用一个提供者别名(尽可能简单)。我得到的错误是: ╷ │ Error: Missing required argument │ │ The argument "regio

下面是我的项目文件结构:

├── main.tf
├── tunnel
│   ├── main.tf
│   └── variables.tf
└── variables.tf
我正在尝试使用Terraform 0.15.1中的多个提供程序,如下所述->

在遵循这个例子之后,我无法让它工作。我现在简化了代码,只使用一个提供者别名(尽可能简单)。我得到的错误是:

╷
│ Error: Missing required argument
│ 
│ The argument "region" is required, but was not set.
╵
根目录中的My main.tf文件:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws.r = aws.requester
  }
}
provider "aws" {
  alias  = "requester"
  region = "ap-southeast-2"
  profile = "benchmark"
}
根目录中的my variables.tf:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws.r = aws.requester
  }
}
provider "aws" {
  alias  = "requester"
  region = "ap-southeast-2"
  profile = "benchmark"
}
my tunnel/variables.tf文件:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
      configuration_aliases = [ aws.r ]
    }
  }
}

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}
my tunnel/main.tf文件:

# Requester's side of the connection.
resource "aws_vpc_peering_connection" "peer" {
  vpc_id        = "vpc-xxxxxxxxxxxxxxxxx"
  peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
  peer_owner_id = data.aws_caller_identity.current.account_id
  peer_region   = data.aws_region.current.name
  auto_accept   = false

  tags = {
    Side = "Requester"
  }
}
我不明白为什么会出现这个错误?这段代码的目标最终是自动化vpc对等的两侧,如下图所示->。但我目前一直在让两个aws提供商使用不同的凭据(上面示例中的一个提供商可以简化工作)

当我从根main.tf中删除
alias=“requester”
时:

provider "aws" {
//  alias  = "requester"
  region = "ap-southeast-2"
  profile = "benchmark"
}
以及根路径中main.tf的提供程序配置:

module "tunnel" {
  source    = "./tunnel"
//  providers = {
//    aws.r = aws.requester
//  }
}
以及tunnel/variables.tf中的别名配置:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
//      configuration_aliases = [ aws.r ]
    }
  }
}
计划很好:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.tunnel.aws_vpc_peering_connection.peer will be created
  + resource "aws_vpc_peering_connection" "peer" {
      + accept_status = (known after apply)
      + auto_accept   = false
      + id            = (known after apply)
      + peer_owner_id = "xxxxxxx"
      + peer_region   = "ap-southeast-2"
      + peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
      + tags          = {
          + "Side" = "Requester"
        }
      + vpc_id        = "vpc-xxxxxxxxxxx"

      + accepter {
          + allow_classic_link_to_remote_vpc = (known after apply)
          + allow_remote_vpc_dns_resolution  = (known after apply)
          + allow_vpc_to_remote_classic_link = (known after apply)
        }

      + requester {
          + allow_classic_link_to_remote_vpc = (known after apply)
          + allow_remote_vpc_dns_resolution  = (known after apply)
          + allow_vpc_to_remote_classic_link = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

此错误消息是Terraform必须使更简单的情况变得更简单的一些自动行为的结果,但不幸的是,这会导致在像您这样更复杂的情况下情况变得相当不清楚

在子模块中,您已经声明它希望在调用方中传递一个替代(别名)提供程序配置,该配置在此模块中称为
aws.r
。但是,您随后声明的数据资源不包含用于指定它们所属的提供程序配置的
提供程序
参数,因此Terraform正在选择默认(未关联的)提供程序配置

不幸的是,您的配置实际上没有默认的提供程序配置,因为根模块也使用了替代的提供程序配置
aws.requester
。因此,Terraform会自动构造一个空配置的提供者,因为这对于像
http
这样不需要任何特殊配置的简单提供者来说是一种有用的行为。但是,这对aws
提供商来说并不起作用,因为它需要设置
区域

至少有两种不同的方法可以更改子模块以使其正常工作。以下哪一项最合适取决于此模块如何适应您更广泛的配置


第一个选项是让子模块根本不声明
aws.r
,只使用其默认的提供程序配置:

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

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}
因为您的根模块没有
hashicorp/aws
的默认配置,所以您仍然需要在模块调用中明确表示模块的默认提供程序是
aws。请求者
提供程序,正如根模块所看到的:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws = aws.requester
  }
}
对于不需要多个AWS提供程序配置的共享模块来说,这种方法是一个很好的选择,因为模块本身可能完全不知道其调用者中的多个配置,而只是希望得到一个默认配置供
hashicorp/AWS
使用

但是,如果您的子模块也需要为
hashicorp/aws
提供多个配置,那么它将无法工作。在这种情况下,您将需要另一个选项,我将在下面介绍


当一个共享模块将使用多个提供者配置时,我们需要为它期望从调用方传递的每个配置声明一个
configuration\u alias
条目。您在示例中只显示了一个名为
r
,我不知道“r”代表什么,因此为了示例起见,我将它们称为“src”(代表“source”)和“dst”(代表(“destination”),只是为了有一些有意义的术语可供参考

我们将从
配置\u别名开始
配置:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
      configuration_aliases = [ aws.src, aws.dst ]
    }
  }
}
configuration\u alias
中给出的每个项都声明了一个配置地址,该地址必须在对该模块的任何调用中的
providers
参数中有相应的条目,我们将在后面看到

由于该模块不希望使用默认(未关联)配置,因此我们现在需要告诉Terraform每个资源块它所属的提供程序配置。从数据资源开始,假设它们属于“源”端:

我怀疑在您的实际系统中,您显示的
aws_vpc_peering_connection
资源在逻辑上可能也属于“源”端,但由于您没有显示任何其他资源,我将随意将其分配给
aws.dst
,以显示其外观:

resource "aws_vpc_peering_connection" "peer" {
  provider = aws.dst

  vpc_id        = "vpc-xxxxxxxxxxxxxxxxx"
  peer_vpc_id   = "vpc-xxxxxxxxxxxxxxxxx"
  peer_owner_id = data.aws_caller_identity.current.account_id
  peer_region   = data.aws_region.current.name
  auto_accept   = false

  tags = {
    Side = "Requester"
  }
}
该模块中的每个
数据
资源
块都需要设置
提供程序
,因为在该模块中默认情况下没有可选择的默认提供程序配置

调用模块时,您需要告诉Terraform调用方中的哪些提供商配置映射到被调用模块中的
src
dst
配置:

module "tunnel" {
  source    = "./tunnel"
  providers = {
    aws.src = aws.requester
    aws.dst = aws.peer
  }
}
正如我前面提到的,对于模块内声明的每个
configuration\u别名
,我们需要在
providers
中输入一个条目。将这些替代提供程序配置视为与输入变量类似可能会有所帮助,但它们具有更专门的声明和定义语法,因为提供程序是Terraform执行模型的基础,需要在正常表达式求值之前进行解析

在这里,我只是任意选择“peer”作为您在根模块中声明的第二个假定配置的名称。将调用者中的默认配置分配给被调用模块中的替代配置也是有效的,例如
aws.src=aws
,但这似乎并不正确