Terraform Apply Error: Code="InvalidResourceName" Message="Resource name is invalid" When creating VPN-GW Module
Terraform Apply Error: Code="InvalidResourceName" Message="Resource name is invalid" When creating VPN-GW Module
我在执行 Terraform 应用命令时收到以下错误。
│ Error: Creating/Updating Virtual Network Gateway: (Name "VPN-GW-HUB-dev" / Resource Group "RG-HUB-dev"): network.VirtualNetworkGatewaysClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidResourceName" Message="Resource name is invalid. The name can be up to 80 characters long. It must begin with a word character, and it must end with a word character or with '_'. The name may contain word characters or '.', '-', '_'." Details=[]
│
│ with module.MOD-VPN-GW.azurerm_virtual_network_gateway.vpngw,
│ on Modules/10.VPN-GW/main.tf line 31, in resource "azurerm_virtual_network_gateway" "vpngw":
│ 31: resource "azurerm_virtual_network_gateway" "vpngw" {
我想做什么?
我的 Terraform 代码在 Azure 中创建了一个完整的 Hub-and-Spoke 基础结构。在我决定模块化 VPN GW 部分之前,它工作得很好。
我的Terraform代码结构是通常的格式:
--Modules/{module-name}/main.tf
--main.tf
所以在 {module-name} 中 - 我有一个名为的文件夹:
10.VPN-GW\main.tf
我尝试了什么?
好吧,我已经尝试重新格式化代码,我针对所有其他工作正常的模块仔细检查了它。我不知道为什么会出现这个错误,现在已经 3 天不停地调试了。
模块文件在这里:
#------------------------------
# VPN GW MODULE FILE - ALso contains GW SUBNET
#-------------------------------
resource "azurerm_subnet" "gwSubnet" {
name = var.subnet_name
resource_group_name = var.subnet_resource_group_name
virtual_network_name = var.subnet_virtual_network_name
address_prefixes = var.subnet_address_prefixes
}
variable "subnet_name" {
type = string
}
variable "subnet_resource_group_name" {
type = string
}
variable "subnet_virtual_network_name" {
type = string
}
variable "subnet_address_prefixes" {
type = list(string)
}
output "outSubnetIDVPNGW" {
value = azurerm_subnet.gwSubnet.id
}
resource "azurerm_virtual_network_gateway" "vpngw" {
name = "${var.vpn-gw-name}"
location = "${var.vpn-gw-location}"
resource_group_name = "${var.vpngw_resource_group_name}"
type = "Vpn"
vpn_type = "RouteBased"
active_active = false
enable_bgp = false
sku = "VpnGw1"
ip_configuration {
name = "${var.ip_configuration_name}"
public_ip_address_id = "${var.ip_configuration_public_ip_address_id}"
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.gwSubnet.id
}
vpn_client_configuration {
address_space = "${var.vpn_client_configuration_address_space}"
root_certificate {
name = "${var.root_certificate_name}"
public_cert_data = "${var.cert}"
}
revoked_certificate {
name = "${var.revoked_certificate_name}"
thumbprint = "${var.revoked_certificate_thumbprint}"
}
}
}
variable "vpn-gw-name" {
type = string
//default = ""
}
variable "vpn-gw-location" {
//default = ""
type = string
}
variable "vpngw_resource_group_name" {
default = ""
}
variable "ip_configuration_name" {
default = ""
}
variable "ip_configuration_public_ip_address_id" {
default = ""
}
/*
variable "ip_configuration_private_ip_address_allocation" {
//default = ""
// type = string
}
*/
variable "vpn_client_configuration_address_space" {
default = []
}
variable "root_certificate_name" {
default = ""
}
variable "cert" {
default = ""
}
variable "revoked_certificate_name" {
default = ""
}
variable "revoked_certificate_thumbprint" {
default = ""
}
variable "ip_configuration" {
type = map(string)
}
variable "vpn_client_configuration" {
type = object({
address_space = list(string)
root_certificate = map(string)
revoked_certificate = map(string)
})
}
/*
variable "revoked_certificate" {
type = map(string)
}
*/
main.tf 文件——调用每个模块,如下所示——(我只是为导致错误的部分添加代码片段)——即创建 VPN GW
#-----------------------------------------
# Create GW SUBNET & VPN GW
#-----------------------------------------
module "MOD-VPN-GW" {
source = "./Modules/10.VPN-GW"
subnet_name = "GatewaySubnet"
subnet_resource_group_name = "RG-HUB-${var.environmentCode}"
subnet_virtual_network_name = "VNET-HUB-${var.environmentCode}"
subnet_address_prefixes = ["10.0.1.0/27"]
vpn-gw-name = "VPN-GW-HUB-${var.environmentCode}"
vpn-gw-location = "westeurope"
vpngw_resource_group_name = "RG-HUB-${var.environmentCode}"
ip_configuration = {
name = "VNetGatewayConfig"
public_ip_address_id = "${module.MOD-VPNGW-PIP.id}"
private_ip_address_allocation = "Dynamic"
subnet_id = module.MOD-VPN-GW.outSubnetIDVPNGW
}
vpn_client_configuration = {
address_space = ["172.16.10.0/24"]
root_certificate = {
name = "dev.vpn.macos.com"
public_cert_data = data.azurerm_key_vault_certificate.akv-certificate.certificate_data_base64
}
revoked_certificate = {
name = "Verizon-Global-Root-CA"
thumbprint = "912198EEF23DCAC40939312FEE97DD560BAE49B1"
}
}
depends_on = [
module.MOD-RG-HUB, module.MOD-VNET-HUB, azurerm_linux_virtual_machine.label-vm-spoke-01
]
}
我搜索了什么?
我似乎无法在 google 搜索中找到这个特定的错误代码。它没有告诉我给我的 VPN GW 的名称不正确 - 它给我名称(在错误消息中)并告诉我没有给出名称。这很奇怪。还是我误解了错误信息?
terraform init 命令成功。
terraform 验证命令成功。
terraform plan 命令成功。
申请时失败
root
模块和 VPN GW
模块之间存在问题。 Terraform 中模块的工作方式类似于其他编程语言中的函数:它们需要特定的输入变量,然后这些变量会被提供给它们的值替换。 [1].
中有关模块的更多信息
要重构此代码,我将在 root
模块中执行以下操作:
source = "./Modules/10.VPN-GW"
subnet_name = "GatewaySubnet"
subnet_resource_group_name = "RG-HUB-${var.environmentCode}"
subnet_virtual_network_name = "VNET-HUB-${var.environmentCode}"
subnet_address_prefixes = ["10.0.1.0/27"]
vpn-gw-name = "VPN-GW-HUB-${var.environmentCode}"
vpn-gw-location = "westeurope"
vpngw_resource_group_name = "RG-HUB-${var.environmentCode}"
ip_configuration_name = "VNetGatewayConfig"
ip_configuration_public_ip_address_id = module.MOD-VPNGW-PIP.id
vpn_client_configuration_address_space = ["172.16.10.0/24"]
root_certificate_name = "dev.vpn.macos.com"
cert = data.azurerm_key_vault_certificate.akv-certificate.certificate_data_base64
revoked_certificate_name = "Verizon-Global-Root-CA"
revoked_certificate_thumbprint = "912198EEF23DCAC40939312FEE97DD560BAE49B1"
}
如您所见,我所做的唯一更改是将值分配给 VPN GW
模块所需的变量。它的工作方式是当模块被调用时,它会被提供变量的值并且它会知道如何处理它们。不需要在调用(root
)和被调用模块(VPN GW
)中定义相同的块。因此,将 root
模块视为一段调用函数的代码,例如:
MOD_VPN_GW(subnet_name, subnet_resource_group_name, subnet_virtual_network_name, subnet_address_prefixes, vpn-gw-name, vpn-gw-location, vpngw_resource_group_name, ip_configuration_name, ip_configuration_public_ip_address_id, vpn_client_configuration_address_space, root_certificate_name, cert, revoked_certificate_name, revoked_certificate_thumbprint)
至于您关于如何访问 subnet_id
的问题,这是简单的部分。在 VPN GW
模块中有一个资源块用于 azurerm_subnet
:
resource "azurerm_subnet" "gwSubnet" {
name = var.subnet_name
resource_group_name = var.subnet_resource_group_name
virtual_network_name = var.subnet_virtual_network_name
address_prefixes = var.subnet_address_prefixes
}
此资源在创建后提供的属性之一是子网 ID [2]。这意味着您可以通过使用此语法 [3]:[=32= 引用结果值来分配属性值]
<resource type>.<resource_name>.<attribute>
你的情况是:
azurerm_subnet.gwSubnet.id
此值已在 azurerm_virtual_network_gateway
资源的 subnet_id
参数中引用:
subnet_id = azurerm_subnet.gwSubnet.id
这意味着它不需要作为模块的输入变量之一。好处是 VPN GW
模块会知道创建资源的顺序,因为这是隐式依赖。
[1] https://www.terraform.io/language/modules/develop
[2] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet#id
[3]https://www.terraform.io/language/expressions/references#references-to-resource-attributes
我在执行 Terraform 应用命令时收到以下错误。
│ Error: Creating/Updating Virtual Network Gateway: (Name "VPN-GW-HUB-dev" / Resource Group "RG-HUB-dev"): network.VirtualNetworkGatewaysClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="InvalidResourceName" Message="Resource name is invalid. The name can be up to 80 characters long. It must begin with a word character, and it must end with a word character or with '_'. The name may contain word characters or '.', '-', '_'." Details=[]
│
│ with module.MOD-VPN-GW.azurerm_virtual_network_gateway.vpngw,
│ on Modules/10.VPN-GW/main.tf line 31, in resource "azurerm_virtual_network_gateway" "vpngw":
│ 31: resource "azurerm_virtual_network_gateway" "vpngw" {
我想做什么?
我的 Terraform 代码在 Azure 中创建了一个完整的 Hub-and-Spoke 基础结构。在我决定模块化 VPN GW 部分之前,它工作得很好。
我的Terraform代码结构是通常的格式:
--Modules/{module-name}/main.tf
--main.tf
所以在 {module-name} 中 - 我有一个名为的文件夹:
10.VPN-GW\main.tf
我尝试了什么?
好吧,我已经尝试重新格式化代码,我针对所有其他工作正常的模块仔细检查了它。我不知道为什么会出现这个错误,现在已经 3 天不停地调试了。
模块文件在这里:
#------------------------------
# VPN GW MODULE FILE - ALso contains GW SUBNET
#-------------------------------
resource "azurerm_subnet" "gwSubnet" {
name = var.subnet_name
resource_group_name = var.subnet_resource_group_name
virtual_network_name = var.subnet_virtual_network_name
address_prefixes = var.subnet_address_prefixes
}
variable "subnet_name" {
type = string
}
variable "subnet_resource_group_name" {
type = string
}
variable "subnet_virtual_network_name" {
type = string
}
variable "subnet_address_prefixes" {
type = list(string)
}
output "outSubnetIDVPNGW" {
value = azurerm_subnet.gwSubnet.id
}
resource "azurerm_virtual_network_gateway" "vpngw" {
name = "${var.vpn-gw-name}"
location = "${var.vpn-gw-location}"
resource_group_name = "${var.vpngw_resource_group_name}"
type = "Vpn"
vpn_type = "RouteBased"
active_active = false
enable_bgp = false
sku = "VpnGw1"
ip_configuration {
name = "${var.ip_configuration_name}"
public_ip_address_id = "${var.ip_configuration_public_ip_address_id}"
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.gwSubnet.id
}
vpn_client_configuration {
address_space = "${var.vpn_client_configuration_address_space}"
root_certificate {
name = "${var.root_certificate_name}"
public_cert_data = "${var.cert}"
}
revoked_certificate {
name = "${var.revoked_certificate_name}"
thumbprint = "${var.revoked_certificate_thumbprint}"
}
}
}
variable "vpn-gw-name" {
type = string
//default = ""
}
variable "vpn-gw-location" {
//default = ""
type = string
}
variable "vpngw_resource_group_name" {
default = ""
}
variable "ip_configuration_name" {
default = ""
}
variable "ip_configuration_public_ip_address_id" {
default = ""
}
/*
variable "ip_configuration_private_ip_address_allocation" {
//default = ""
// type = string
}
*/
variable "vpn_client_configuration_address_space" {
default = []
}
variable "root_certificate_name" {
default = ""
}
variable "cert" {
default = ""
}
variable "revoked_certificate_name" {
default = ""
}
variable "revoked_certificate_thumbprint" {
default = ""
}
variable "ip_configuration" {
type = map(string)
}
variable "vpn_client_configuration" {
type = object({
address_space = list(string)
root_certificate = map(string)
revoked_certificate = map(string)
})
}
/*
variable "revoked_certificate" {
type = map(string)
}
*/
main.tf 文件——调用每个模块,如下所示——(我只是为导致错误的部分添加代码片段)——即创建 VPN GW
#-----------------------------------------
# Create GW SUBNET & VPN GW
#-----------------------------------------
module "MOD-VPN-GW" {
source = "./Modules/10.VPN-GW"
subnet_name = "GatewaySubnet"
subnet_resource_group_name = "RG-HUB-${var.environmentCode}"
subnet_virtual_network_name = "VNET-HUB-${var.environmentCode}"
subnet_address_prefixes = ["10.0.1.0/27"]
vpn-gw-name = "VPN-GW-HUB-${var.environmentCode}"
vpn-gw-location = "westeurope"
vpngw_resource_group_name = "RG-HUB-${var.environmentCode}"
ip_configuration = {
name = "VNetGatewayConfig"
public_ip_address_id = "${module.MOD-VPNGW-PIP.id}"
private_ip_address_allocation = "Dynamic"
subnet_id = module.MOD-VPN-GW.outSubnetIDVPNGW
}
vpn_client_configuration = {
address_space = ["172.16.10.0/24"]
root_certificate = {
name = "dev.vpn.macos.com"
public_cert_data = data.azurerm_key_vault_certificate.akv-certificate.certificate_data_base64
}
revoked_certificate = {
name = "Verizon-Global-Root-CA"
thumbprint = "912198EEF23DCAC40939312FEE97DD560BAE49B1"
}
}
depends_on = [
module.MOD-RG-HUB, module.MOD-VNET-HUB, azurerm_linux_virtual_machine.label-vm-spoke-01
]
}
我搜索了什么?
我似乎无法在 google 搜索中找到这个特定的错误代码。它没有告诉我给我的 VPN GW 的名称不正确 - 它给我名称(在错误消息中)并告诉我没有给出名称。这很奇怪。还是我误解了错误信息?
terraform init 命令成功。 terraform 验证命令成功。 terraform plan 命令成功。
申请时失败
root
模块和 VPN GW
模块之间存在问题。 Terraform 中模块的工作方式类似于其他编程语言中的函数:它们需要特定的输入变量,然后这些变量会被提供给它们的值替换。 [1].
要重构此代码,我将在 root
模块中执行以下操作:
source = "./Modules/10.VPN-GW"
subnet_name = "GatewaySubnet"
subnet_resource_group_name = "RG-HUB-${var.environmentCode}"
subnet_virtual_network_name = "VNET-HUB-${var.environmentCode}"
subnet_address_prefixes = ["10.0.1.0/27"]
vpn-gw-name = "VPN-GW-HUB-${var.environmentCode}"
vpn-gw-location = "westeurope"
vpngw_resource_group_name = "RG-HUB-${var.environmentCode}"
ip_configuration_name = "VNetGatewayConfig"
ip_configuration_public_ip_address_id = module.MOD-VPNGW-PIP.id
vpn_client_configuration_address_space = ["172.16.10.0/24"]
root_certificate_name = "dev.vpn.macos.com"
cert = data.azurerm_key_vault_certificate.akv-certificate.certificate_data_base64
revoked_certificate_name = "Verizon-Global-Root-CA"
revoked_certificate_thumbprint = "912198EEF23DCAC40939312FEE97DD560BAE49B1"
}
如您所见,我所做的唯一更改是将值分配给 VPN GW
模块所需的变量。它的工作方式是当模块被调用时,它会被提供变量的值并且它会知道如何处理它们。不需要在调用(root
)和被调用模块(VPN GW
)中定义相同的块。因此,将 root
模块视为一段调用函数的代码,例如:
MOD_VPN_GW(subnet_name, subnet_resource_group_name, subnet_virtual_network_name, subnet_address_prefixes, vpn-gw-name, vpn-gw-location, vpngw_resource_group_name, ip_configuration_name, ip_configuration_public_ip_address_id, vpn_client_configuration_address_space, root_certificate_name, cert, revoked_certificate_name, revoked_certificate_thumbprint)
至于您关于如何访问 subnet_id
的问题,这是简单的部分。在 VPN GW
模块中有一个资源块用于 azurerm_subnet
:
resource "azurerm_subnet" "gwSubnet" {
name = var.subnet_name
resource_group_name = var.subnet_resource_group_name
virtual_network_name = var.subnet_virtual_network_name
address_prefixes = var.subnet_address_prefixes
}
此资源在创建后提供的属性之一是子网 ID [2]。这意味着您可以通过使用此语法 [3]:[=32= 引用结果值来分配属性值]
<resource type>.<resource_name>.<attribute>
你的情况是:
azurerm_subnet.gwSubnet.id
此值已在 azurerm_virtual_network_gateway
资源的 subnet_id
参数中引用:
subnet_id = azurerm_subnet.gwSubnet.id
这意味着它不需要作为模块的输入变量之一。好处是 VPN GW
模块会知道创建资源的顺序,因为这是隐式依赖。
[1] https://www.terraform.io/language/modules/develop
[2] https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet#id
[3]https://www.terraform.io/language/expressions/references#references-to-resource-attributes