【问题标题】:Can terraform have 2 main files with second running after first is applied?terraform 可以在应用第一个文件后有 2 个主文件并在第二个文件中运行吗?
【发布时间】:2021-07-13 06:35:11
【问题描述】:

terraform 可以有 2 个主文件,一个接一个地运行吗?

我需要在调用 main2 之前完全运行 main1,因为我的 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_LISTVPN_ASSO_LIST等vars会在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.

【问题讨论】:

    标签: amazon-web-services terraform terraform-provider-aws


    【解决方案1】:

    很遗憾,您不能这样做。构建代码的正确方法是放入modules。因此,您必须将main1main2 转换为子模块,然后创建顶级main.tf。在main 中创建main1main2 模块将确保正确的顺序。

    .
    ├── 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
    }
    

    【讨论】:

    • 感谢 cmets @Marcin 。我的代码中已经有模块。我重新提出了我的问题。让我知道这是否有帮助。
    【解决方案2】:

    对于一个如此人为的例子,很难给出具体的建议,所以只能给出一些一般性的意见:

    • “要一起创建/修改的一组基础架构”的主要分解单元是单独的配置,而不是同一配置中的单独模块。如果您将配置拆分为两部分并使用Data Sources 以便第二部分可以读取第一部分的结果,那么您可以分两步应用整个系统,从而确保正确的顺序。

    • 话虽如此,对于在规划期间未知的for_each 值的问题,通常(但不总是)有不同的方式来构建事物,以便 Terraform 至少可以在规划中看到地图的键时间。只要 keys 是已知的,值就可以是未知的。

      如果您想了解更多相关信息,那么我建议您在 Stack Overflow 上提出一个新问题,您可以在其中分享更真实的配置版本并描述潜在问题,因为那时回答者可以建议特定的重构或重组可能会带来可行的解决方案。

    • depends_on 的大量使用,特别是在 module 块中,通常是 Terraform 中的 code smell,因为它表明模块没有正确封装,因此它们依赖外部注释才能正确运行。

      这并不总是正确的,而且如果没有真实的例子也很难具体说明,但是有更好的技术可以告诉 Terraform 不同模块中的对象之间的关系,这通常可以使模块在默认情况下正常运行,而无需额外的注释像这样。

    【讨论】:

    • 感谢 cmets @Martin。说得通。我重新提出了我的问题。让我知道这是否有帮助。 – 维尼塔沙阿
    【解决方案3】:

    您可以使用 -target 执行此操作。 你在做什么并不理想。

    terraform plan -target=module.mymodule.aws_instance.myinstance ```
    
    terraform apply
    
    This might help: https://stackoverflow.com/questions/46762047/i-would-like-to-run-terraform-only-for-a-specific-resource
    

    【讨论】:

      【解决方案4】:

      我的 if 循环中有 if rt_att_id.rt_id != null 条件。

      For each 不能引用未知的资源,这就是它出错的原因。

      我通过数据获取路由表 ID 并使用特定名称而不是遍历整个路由表来修改我的循环。

      感谢大家的帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-01
        • 2021-10-16
        • 2014-07-06
        • 1970-01-01
        • 2011-03-13
        • 2018-02-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多