如何使用 terraform 在模块功能中创建模块?

How to make a module in module feature with terraform?

对于这个 terraform 项目结构

|- common-modules
|---- development               # Call common-modules/common to use and act as a new module
|-------- main.tf
|-------- variables.tf
|-------- outputs.tf
|---- staging                   # Call common-modules/common to use and act as a new module
|-------- main.tf
|-------- variables.tf
|-------- outputs.tf
|---- production                # Call common-modules/common to use and act as a new module
|-------- main.tf
|-------- variables.tf
|-------- outputs.tf
|---- common                    # Common resources for all the environments
|-------- main.tf
|-------- variables.tf
|-------- outputs.tf
|- development                  # Call common-modules/development to use
|---- main.tf
|---- variables.tf
|---- outputs.tf
|- staging                      # Call common-modules/staging to use
|---- main.tf
|---- variables.tf
|---- outputs.tf
|- production                   # Call common-modules/production to use
|---- main.tf
|---- variables.tf
|---- outputs.tf

common-modules/common/main.tf 中,类似于

resource "XXX" "example" {
    # hoge
}

common-modules/development/main.tf中调用common-modules/common

module "XXX" "YYY" {
    source "../common"
    
    # hoge
}

common-modules/stagingcommon-modules/production 相同。

development/main.tf

module "XXX" "ZZZ" {
    source "../common-modules/development"
    
    # hoge
}

development下运行terraform apply时,发现对common-modules/common中的内容执行了两次。也许 common-modules/development/main.tf 运行 一次,然后 development/main.tf 运行 一次。

那如何做到运行只创建一次资源呢?

现在使用 atlantis 自动 运行 工作流程。其中一些设置为

version: 3
projects:
  - dir: common-modules/development
    autoplan:
      enabled: true
      when_modified: [ "*.tf" ]

  - dir: development
    autoplan:
      enabled: true
      when_modified: ["*.tf"]
    apply_requirements: [mergeable]

是否可以在第一个设置中避免自动申请common-modules/development

解决您在此处描述的问题的典型方法是 module composition,其中不是将一个模块嵌入另一个模块,而是将从一个模块返回的数据(通过输出值)传递到另一个模块的输入变量模块。

这意味着您的根模块将包含所有 module 块,其中一些块的结果将传递给其他块。我不确定如何将你在问题中分享的内容改编成一个工作示例,因为你没有显示你的模块输出值或输入变量,但这是一个通用示例:

module "common" {
  source = "../common-modules/common"
}

module "development" {
  source = "../common-modules/development"

  something = module.common.something
}

当您使用这些配置时,您应该只在 developmentstagingproduction 目录中 运行 Terraform,永远不要在任何 common-modules 目录,因为 common-modules 将仅用作根配置的一部分。我不太熟悉 Atlantis,但我认为这意味着您应该将 common-modules/development 作为 Atlantis 中的“项目”删除,因为它不是独立配置,只是用作 development配置。