【问题标题】:Locals depends_on - Terraform当地人depends_on - Terraform
【发布时间】:2021-08-18 22:11:25
【问题描述】:

我在 terraform 中有一个 module a,它创建了一个 text 文件,我需要在另一个 module b 中使用该文本文件,我正在使用 locals 来拉取该文本文件的内容,如下所示 @ 987654325@

locals {
   ports = split("\n", file("ports.txt") ) 
 }

但是terraform 期望这个文件在开始时本身就存在,抛出如下错误

Invalid value for "path" parameter: no file exists at
path/ports.txt; this function works only with files
that are distributed as part of the configuration source code, so if this file
will be created by a resource in this configuration you must instead obtain
this result from an attribute of that resource.

我在这里缺少什么?对此的任何帮助将不胜感激。 locals 有没有 depends_on,我怎样才能做到这一点

【问题讨论】:

  • 这两个模块如何使用?你有任何完整的代码来展示这个问题吗?
  • 抱歉,如果这不是一个真正的答案。 Terraform 非常擅长沿着它的图表找出依赖关系 - 如果你正在写入文件系统然后读取该文件,那么你就是从图表中冲出,然后跳回。如果你可以在图表中做到这一点,你'会有更好的时间。模块a可以将信息传递给模块b而不是通过文件系统传递吗?

标签: terraform terraform-provider-azure


【解决方案1】:

使用模块块从其他模块中调用模块。大多数参数对应于模块定义的输入变量。要引用一个模块的值,需要在该模块中声明输出,然后才能调用其他模块的输出值。

例如,我假设你在模块 a 中有一个文本文件。

模块a中的.tf文件

output "textfile" {
    value = file("D:\\Terraform\\modules\\a\\ports.txt")
}

模块b中的.tf文件

variable "externalFile" {   
}

locals {
   ports = split("\n", var.externalFile) 
 }


#  output "b_test" {
#      value = local.ports
#  }

根模块中的.tf文件

module "a" {
    source = "./modules/a"
}

module "b" {
  source              = "./modules/b"

  externalFile   = module.a.textfile
  depends_on = [module.a]
}


# output "module_b_output" {
#   value = module.b.b_test
# }

更多参考,你可以阅读https://www.terraform.io/docs/language/modules/syntax.html#accessing-module-output-values

【讨论】:

  • 这不起作用,因为它期望output "textfile" { value = file("D:\\Terraform\\modules\\a\\ports.txt") }这个文件在开始时就存在,同样的错误
  • 这是一个例子。如何在模块 a 中生成文本文件?您只需要将文本文件值传递给原始模块 a 中的输出变量。
  • module a通过folderfolder中生成一个text filemodule b需要用到。
  • 上面写着Invalid value for "path" parameter: no file exists at path/ports.txt', but it will get created only after we run the terraform apply`
  • 能否请您显示有关模块的部分代码a通过bash脚本在文件夹中生成文本文件?
【解决方案2】:

正如错误消息报告的那样,file 函数仅适用于作为配置的一部分包含在磁盘上的文件,不适用于在应用阶段动态生成的文件。

我通常建议避免将文件写入本地磁盘作为 Terraform 配置的一部分,因为 Terraform 的主要假设之一是您使用 Terraform 管理的任何对象都会从一次运行到下一次持续存在,但这仅适用于如果您始终在同一台计算机上的同一目录中运行 Terraform,或者如果您使用其他更复杂的方法(例如网络文件系统),则本地文件。但是,由于您没有提及 为什么 要将文件写入磁盘,因此我认为这是一项硬性要求并就如何做到这一点提出建议,即使我认为这是不得已。

The hashicorp/local provider 包含一个名为local_file 的数据源,它将以类似于更典型的数据源从远程 API 端点读取的方式从磁盘读取文件。特别是,它将尊重其配置中反映的任何依赖关系,并在需要时推迟读取文件直到应用步骤。

您可以在模块之间协调这一点,然后通过使返回文件名的输出值也取决于负责创建文件的任何资源。例如,如果文件是使用附加到 aws_instance 资源的配置器创建的,那么您可以在模块中编写如下内容:

output "filename" {
  value      = "D:\\Terraform\\modules\\a\\ports.txt"
  depends_on = [aws_instance.example]
}

然后您可以将该值从一个模块传递到另一个模块,这将带有对aws_instance.example 的隐式依赖,以确保首先实际创建文件:

module "a" {
  source = "./modules/a"
}

module "b" {
  source = "./modules/b"

  filename = module.a.filename
}

最后,在模块内部,声明输入变量并将其用作local_file 数据资源配置的一部分:

variable "filename" {
  type = string
}

data "local_file" "example" {
  filename = var.filename
}

然后,您可以在第二个模块的其他地方使用data.local_file.example.content 来获取该文件的内容。

请注意,除了 output "filename" 块中的显式 depends_on 之外,依赖项会自动传播。模块封装自己的行为是一个很好的做法,以便在调用者使用它时,输出值有用所需的一切都已经发生,因为这样您的配置的其余部分将默认获得正确的行为,而无需需要任何额外的 depends_on 注释。

但是,如果有任何方法可以直接从第一个模块返回 ports.txt 文件中的数据,而无需将其写入磁盘,我建议将其作为一种更强大且不太复杂的方法。

【讨论】:

    猜你喜欢
    • 2023-01-24
    • 1970-01-01
    • 2020-06-02
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多