应用第一个后,terraform 可以有 2 个主文件和第二个 运行 吗?
Can terraform have 2 main files with second running after first is applied?
terraform 可以有 2 个主文件,一个 运行ning 一个接一个吗?
我需要 main1 在调用 main2 之前完全 运行,因为我的 main2 有 for_each
,这需要先创建资源。
与 main3 相同。
所以 main1 必须 运行 完全 (terraform plan/apply) 然后是 main2.
我的树结构
├── README.md
├── config
│ ├── prod
│ └── sandbox
│ └── us_east_2
│ ├── nonprod.tfvars
│ └── prod.tfvars
├── init
│ ├── prod
│ └── sandbox
│ └── us_east_2
│ ├── nonprod.tfvars
│ └── prod.tfvars
├── main.tf
├── modules
│ ├── create_transit_gateway
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway_asso_prop
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway_locals
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── vpc
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── output.tf
└── variables.tf
provider "aws" {
region = var.REGION
}
module "create_transit_gateway" {
source = "./modules/create_transit_gateway"
REGION_SHORTHAND = var.REGION_SHORTHAND
TGW_LOCAL = var.TGW_LOCAL
ENV_NAME = var.ENV_NAME
AMAZON_SIDE_ASN = var.AMAZON_SIDE_ASN
}
module "vpc" {
depends_on = [module.create_transit_gateway]
source = "./modules/vpc"
NETWORK_VPC = var.NETWORK_VPC
SUBNETS = var.SUBNETS
ROUTE_TABLES = var.ROUTE_TABLES
ENV_NAME = var.ENV_NAME
TGW_LOCAL = var.TGW_LOCAL
REGION_SHORTHAND = var.REGION_SHORTHAND
}
module "ec2" {
depends_on = [module.create_transit_gateway, module.vpc]
source = "./modules/ec2"
FW_ASNS = var.FW_ASNS
FIREWALLS = var.FIREWALLS
AMI_IMAGE_KEY = var.AMI_IMAGE_KEY
REGION_SHORTHAND = var.REGION_SHORTHAND
ENV_NAME = var.ENV_NAME
VPC_ID = module.vpc.VPC_ID
AWS_SUBNETS = module.vpc.AWS_SUBNETS
}
module "transit_gateway" {
depends_on = [module.create_transit_gateway, module.ec2, module.vpc]
source = "./modules/transit_gateway"
REGION = var.REGION
TGW_LOCAL = var.TGW_LOCAL
ENV_NAME = var.ENV_NAME
SITE_CUSTOMER_GATEWAYS = var.SITE_CUSTOMER_GATEWAYS
EIP_FW1_NICS = module.ec2.EIP_FW1_NICS
EIP_FW2_NICS = module.ec2.EIP_FW2_NICS
AWS_SUBNETS = module.vpc.AWS_SUBNETS
FW_ASNS = var.FW_ASNS
TGW_PEERS = var.TGW_PEERS
VPC_ID = module.vpc.VPC_ID
TGW_ROUTE_TABLES = var.TGW_ROUTE_TABLES
REGION_SHORTHAND = var.REGION_SHORTHAND
AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
}
module "transit_gateway_locals" {
depends_on = [module.create_transit_gateway, module.transit_gateway]
source = "./modules/transit_gateway_locals"
REGION = var.REGION
TGW_PEERS = var.TGW_PEERS
TGA_VPC_ATTACHMENT = module.vpc.TG_VPC_ATTACHMENT
ENV_NAME = var.ENV_NAME
AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
NETWORK_S2S_VPN = module.transit_gateway.NETWORK_S2S_VPN
NETWORK_TGW_RT = module.transit_gateway.NETWORK_TGW_RT
TGW_PEERS_RESOURCE = module.transit_gateway.TGW_PEERS_RESOURCE
PEER_ACCEPTOR_STATUS = module.transit_gateway.PEER_ACCEPTOR_STATUS
}
module "transit_gateway_asso_prop" {
depends_on = [module.transit_gateway_locals]
source = "./modules/transit_gateway_asso_prop"
REGION = var.REGION
VPC_ASSO_LIST = module.transit_gateway_locals.VPC_ASSO_LIST
VPC_PROP_LIST = module.transit_gateway_locals.VPC_PROP_LIST
VPN_ASSO_LIST = module.transit_gateway_locals.VPN_ASSO_LIST
VPN_PROP_LIST = module.transit_gateway_locals.VPN_PROP_LIST
PEER_ASSO_LIST = module.transit_gateway_locals.PEER_ASSO_LIST
SEC_STATIC_LIST = module.transit_gateway_locals.SEC_STATIC_LIST
TGW_PEERS = var.TGW_PEERS
ENV_NAME = var.ENV_NAME
}
在应用上述模块后,我需要模块 transit_gateway_asso_prop
到 运行。
由于 VPN_PROP_LIST
、VPN_ASSO_LIST
等变量将在应用 transit_gateway_locals
和其他上述模块后创建
Error: Invalid for_each argument
on modules/transit_gateway_asso_prop/main.tf line 325, in resource "aws_ec2_transit_gateway_route_table_propagation" "NETWORK-TGW-VPNPROPAGATION":
325: for_each = var.VPN_PROP_LIST
The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.
遗憾的是你不能这样做。构建代码的正确方法是 modules。因此,您必须将 main1
和 main2
转换为子模块,然后创建顶级 main.tf
。在 main
中创建 main1
和 main2
模块将确保正确的顺序。
.
├── main.tf
└── modules
├── main1
│ └── main.tf
└── main2
└── main.tf
然后在 main.tf
中创建两个模块:
module "main1" {
source = "./modules/main1/main"
VAR2 = var.VAR2
}
module "main2" {
source = "./modules/main1/main"
VAR2 = module.main2.id
}
您可以使用 -target 来做到这一点。
你做的不理想。
terraform plan -target=module.mymodule.aws_instance.myinstance ```
terraform apply
This might help:
举一个如此人为的例子,很难给出具体的建议,所以改为一些一般性的观察:
“要created/modified在一起的一组基础设施”的主要分解单元是一个单独的配置,而不是同一配置中的一个单独模块。如果您将配置分成两部分并使用 Data Sources 以便第二部分可以读取第一部分的结果,那么您可以分两步应用整个系统,从而确保正确的顺序。
话虽如此,对于在规划期间未知的 for_each
值的问题,通常(但并非总是)有不同的方式来构建事物,以便 Terraform 可以至少在计划时间看到地图的钥匙。只要键已知,值就可以未知。
如果您想了解更多相关信息,那么我建议您在 Stack Overflow 上开始一个新问题,您可以在其中分享更真实的配置版本并描述潜在问题,此后回答者可以提出具体建议可能允许工作解决方案的重构或重组。
depends_on
的高使用率,特别是在 module
块内,在 Terraform 中通常是 code smell,因为它表明模块没有正确封装和所以他们依赖外部注释才能正确运行。
这并不总是正确的,而且如果没有真实的例子也很难具体说明,但是有更好的技术可以告诉 Terraform 不同模块中对象之间的关系,这通常可以使模块在默认情况下正确运行,而无需像这样的附加注释。
我的 if 循环中有 if rt_att_id.rt_id != null
个条件。
对于每个都不能引用未知的资源,这就是它出错的原因。
我通过数据获取路由 table id 并使用特定名称而不是遍历整个路由 table.
来修改我的循环
谢谢大家的帮助。
terraform 可以有 2 个主文件,一个 运行ning 一个接一个吗?
我需要 main1 在调用 main2 之前完全 运行,因为我的 main2 有 for_each
,这需要先创建资源。
与 main3 相同。
所以 main1 必须 运行 完全 (terraform plan/apply) 然后是 main2.
我的树结构
├── README.md
├── config
│ ├── prod
│ └── sandbox
│ └── us_east_2
│ ├── nonprod.tfvars
│ └── prod.tfvars
├── init
│ ├── prod
│ └── sandbox
│ └── us_east_2
│ ├── nonprod.tfvars
│ └── prod.tfvars
├── main.tf
├── modules
│ ├── create_transit_gateway
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── ec2
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway_asso_prop
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ ├── transit_gateway_locals
│ │ ├── main.tf
│ │ ├── outputs.tf
│ │ └── variables.tf
│ └── vpc
│ ├── main.tf
│ ├── outputs.tf
│ └── variables.tf
├── output.tf
└── variables.tf
provider "aws" {
region = var.REGION
}
module "create_transit_gateway" {
source = "./modules/create_transit_gateway"
REGION_SHORTHAND = var.REGION_SHORTHAND
TGW_LOCAL = var.TGW_LOCAL
ENV_NAME = var.ENV_NAME
AMAZON_SIDE_ASN = var.AMAZON_SIDE_ASN
}
module "vpc" {
depends_on = [module.create_transit_gateway]
source = "./modules/vpc"
NETWORK_VPC = var.NETWORK_VPC
SUBNETS = var.SUBNETS
ROUTE_TABLES = var.ROUTE_TABLES
ENV_NAME = var.ENV_NAME
TGW_LOCAL = var.TGW_LOCAL
REGION_SHORTHAND = var.REGION_SHORTHAND
}
module "ec2" {
depends_on = [module.create_transit_gateway, module.vpc]
source = "./modules/ec2"
FW_ASNS = var.FW_ASNS
FIREWALLS = var.FIREWALLS
AMI_IMAGE_KEY = var.AMI_IMAGE_KEY
REGION_SHORTHAND = var.REGION_SHORTHAND
ENV_NAME = var.ENV_NAME
VPC_ID = module.vpc.VPC_ID
AWS_SUBNETS = module.vpc.AWS_SUBNETS
}
module "transit_gateway" {
depends_on = [module.create_transit_gateway, module.ec2, module.vpc]
source = "./modules/transit_gateway"
REGION = var.REGION
TGW_LOCAL = var.TGW_LOCAL
ENV_NAME = var.ENV_NAME
SITE_CUSTOMER_GATEWAYS = var.SITE_CUSTOMER_GATEWAYS
EIP_FW1_NICS = module.ec2.EIP_FW1_NICS
EIP_FW2_NICS = module.ec2.EIP_FW2_NICS
AWS_SUBNETS = module.vpc.AWS_SUBNETS
FW_ASNS = var.FW_ASNS
TGW_PEERS = var.TGW_PEERS
VPC_ID = module.vpc.VPC_ID
TGW_ROUTE_TABLES = var.TGW_ROUTE_TABLES
REGION_SHORTHAND = var.REGION_SHORTHAND
AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
}
module "transit_gateway_locals" {
depends_on = [module.create_transit_gateway, module.transit_gateway]
source = "./modules/transit_gateway_locals"
REGION = var.REGION
TGW_PEERS = var.TGW_PEERS
TGA_VPC_ATTACHMENT = module.vpc.TG_VPC_ATTACHMENT
ENV_NAME = var.ENV_NAME
AWS_ACCOUNT_ID = var.AWS_ACCOUNT_ID
NETWORK_S2S_VPN = module.transit_gateway.NETWORK_S2S_VPN
NETWORK_TGW_RT = module.transit_gateway.NETWORK_TGW_RT
TGW_PEERS_RESOURCE = module.transit_gateway.TGW_PEERS_RESOURCE
PEER_ACCEPTOR_STATUS = module.transit_gateway.PEER_ACCEPTOR_STATUS
}
module "transit_gateway_asso_prop" {
depends_on = [module.transit_gateway_locals]
source = "./modules/transit_gateway_asso_prop"
REGION = var.REGION
VPC_ASSO_LIST = module.transit_gateway_locals.VPC_ASSO_LIST
VPC_PROP_LIST = module.transit_gateway_locals.VPC_PROP_LIST
VPN_ASSO_LIST = module.transit_gateway_locals.VPN_ASSO_LIST
VPN_PROP_LIST = module.transit_gateway_locals.VPN_PROP_LIST
PEER_ASSO_LIST = module.transit_gateway_locals.PEER_ASSO_LIST
SEC_STATIC_LIST = module.transit_gateway_locals.SEC_STATIC_LIST
TGW_PEERS = var.TGW_PEERS
ENV_NAME = var.ENV_NAME
}
在应用上述模块后,我需要模块 transit_gateway_asso_prop
到 运行。
由于 VPN_PROP_LIST
、VPN_ASSO_LIST
等变量将在应用 transit_gateway_locals
和其他上述模块后创建
Error: Invalid for_each argument
on modules/transit_gateway_asso_prop/main.tf line 325, in resource "aws_ec2_transit_gateway_route_table_propagation" "NETWORK-TGW-VPNPROPAGATION":
325: for_each = var.VPN_PROP_LIST
The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.
遗憾的是你不能这样做。构建代码的正确方法是 modules。因此,您必须将 main1
和 main2
转换为子模块,然后创建顶级 main.tf
。在 main
中创建 main1
和 main2
模块将确保正确的顺序。
.
├── main.tf
└── modules
├── main1
│ └── main.tf
└── main2
└── main.tf
然后在 main.tf
中创建两个模块:
module "main1" {
source = "./modules/main1/main"
VAR2 = var.VAR2
}
module "main2" {
source = "./modules/main1/main"
VAR2 = module.main2.id
}
您可以使用 -target 来做到这一点。 你做的不理想。
terraform plan -target=module.mymodule.aws_instance.myinstance ```
terraform apply
This might help:
举一个如此人为的例子,很难给出具体的建议,所以改为一些一般性的观察:
“要created/modified在一起的一组基础设施”的主要分解单元是一个单独的配置,而不是同一配置中的一个单独模块。如果您将配置分成两部分并使用 Data Sources 以便第二部分可以读取第一部分的结果,那么您可以分两步应用整个系统,从而确保正确的顺序。
话虽如此,对于在规划期间未知的
for_each
值的问题,通常(但并非总是)有不同的方式来构建事物,以便 Terraform 可以至少在计划时间看到地图的钥匙。只要键已知,值就可以未知。如果您想了解更多相关信息,那么我建议您在 Stack Overflow 上开始一个新问题,您可以在其中分享更真实的配置版本并描述潜在问题,此后回答者可以提出具体建议可能允许工作解决方案的重构或重组。
depends_on
的高使用率,特别是在module
块内,在 Terraform 中通常是 code smell,因为它表明模块没有正确封装和所以他们依赖外部注释才能正确运行。这并不总是正确的,而且如果没有真实的例子也很难具体说明,但是有更好的技术可以告诉 Terraform 不同模块中对象之间的关系,这通常可以使模块在默认情况下正确运行,而无需像这样的附加注释。
我的 if 循环中有 if rt_att_id.rt_id != null
个条件。
对于每个都不能引用未知的资源,这就是它出错的原因。
我通过数据获取路由 table id 并使用特定名称而不是遍历整个路由 table.
来修改我的循环谢谢大家的帮助。