Terraform:将一组文件的内容存储到单个变量中

Terraform:将一组文件的内容存储到单个变量中,terraform,hcl,Terraform,Hcl,这在TF V0.12中,如果有帮助的话 在一个目录中,我有一个可变数量的单行文件。 我需要以某种方式读取它们的内容,并在它们之间用换行符连接起来,然后将结果存储到单个变量中。不是字符串数组 我知道我可以通过以下方式获取要读取的文件列表: locals{ my files=tolist(fileset("${var.file_path}", "**")) } 如果我只有一个文件,我知道我可以通过使用 locals { file_value=file("${var.file_path}\\

这在TF V0.12中,如果有帮助的话 在一个目录中,我有一个可变数量的单行文件。 我需要以某种方式读取它们的内容,并在它们之间用换行符连接起来,然后将结果存储到单个变量中。不是字符串数组 我知道我可以通过以下方式获取要读取的文件列表:

locals{
  my files=tolist(fileset("${var.file_path}", "**")) }
如果我只有一个文件,我知道我可以通过使用

locals {
  file_value=file("${var.file_path}\\${local.my_files}") # if there was only a single file
}
但是我的大脑转向了棉花,我如何读取倍数,我觉得我应该在一个空资源中使用一个计数和一个串联,但似乎无法计算出逻辑。
这是正确的路径还是我应该怎么做?

在本地连接null\u资源

resource "null_resource" "concatenate_my_files" {
  provisioner "local-exec" {
    working_dir = "${var.file_path}"
    command = <<EOF
      cat "${local.my_files}" > "${var.concatenated_file_name}"
EOF
  }
}

使用null_资源本地连接

resource "null_resource" "concatenate_my_files" {
  provisioner "local-exec" {
    working_dir = "${var.file_path}"
    command = <<EOF
      cat "${local.my_files}" > "${var.concatenated_file_name}"
EOF
  }
}

谢谢你@mon,这提醒了我应该经常接吻

消除了我最终的复杂性

resource "null_resource" "concatenate_my_files" {
  provisioner "local-exec" {
    working_dir = var.file_path
    command = <<EOF
cat * > my_temp_file
EOF
  }
}

然后我可以像前面一样读到这篇文章。

谢谢@mon提醒我应该经常接吻

消除了我最终的复杂性

resource "null_resource" "concatenate_my_files" {
  provisioner "local-exec" {
    working_dir = var.file_path
    command = <<EOF
cat * > my_temp_file
EOF
  }
}

然后我可以像前面一样阅读此内容。

我们可以将此问题分为三个步骤:

枚举与所需模式匹配的文件名。 将每个文件的内容读入内存。 将所有文件内容连接在一起。 我们可以将上述内容重新表述为三个局部值表达式,每个表达式都建立在前一个表达式的基础上:

locals {
  filenames            = fileset(".", "${var.file_path}/**")
  file_contents        = { for fn in local.filenames : fn => file(fn) }
  file_contents_concat = join("\n", local.file_contents)
}
或者,我们可以在一个表达式中同时执行所有这些步骤:

locals {
  file_contents_concat = join("\n", [
    for fn in fileset(".", "${var.file_path}/**") : file(fn)
  ])
}
请注意,在调用中,我将var.file_path包含在pattern参数中,而不是path参数中,因为这样生成的文件路径都将相对于当前工作目录,因此我们可以直接将它们传递到file,而无需在那里重新预加var.file_path


文件集的路径和模式之间的分离有助于将一堆文件镜像到S3中,在S3中,使生成的路径相对于bucket根而不是当前工作目录是很有帮助的,但是这种映射在这里并不重要,因为文件名根本不会出现在结果中。

我们可以将此问题分解为三个步骤:

枚举与所需模式匹配的文件名。 将每个文件的内容读入内存。 将所有文件内容连接在一起。 我们可以将上述内容重新表述为三个局部值表达式,每个表达式都建立在前一个表达式的基础上:

locals {
  filenames            = fileset(".", "${var.file_path}/**")
  file_contents        = { for fn in local.filenames : fn => file(fn) }
  file_contents_concat = join("\n", local.file_contents)
}
或者,我们可以在一个表达式中同时执行所有这些步骤:

locals {
  file_contents_concat = join("\n", [
    for fn in fileset(".", "${var.file_path}/**") : file(fn)
  ])
}
请注意,在调用中,我将var.file_path包含在pattern参数中,而不是path参数中,因为这样生成的文件路径都将相对于当前工作目录,因此我们可以直接将它们传递到file,而无需在那里重新预加var.file_path


文件集的路径和模式之间的分离有助于将一堆文件镜像到S3中,在S3中,使生成的路径相对于bucket根而不是当前工作目录是很有帮助的,但是这种映射在这里并不重要,因为文件名根本不会出现在结果中。

为什么不先使用null resource local_exec并在本地连接文件?为什么不先使用null resource local_exec并在本地连接文件?这样尝试一个测试会得到错误:main.tf第7行的函数调用出错,在局部变量中:7:filenames=fileset.,${var.file\u path}/*|--------------var.file|u path是C:/path/test/Call to function fileset失败:未能修剪匹配的路径:Rel:无法使C:\path\test\test1.test.txt相对于..为糟糕的标记表示歉意我今天似乎无法将其格式化嗯。。。您的var.file_路径是否包括。。?看起来这会导致它失败,因为文件集的约定是在第一个参数中给定的路径下生成路径,但是。。不在。。如果您确实需要在父目录中工作,那么您可能需要按照最初的方式编写它,在path参数中使用var.file_path,然后在文件调用中重新添加它。请注意,Terraform甚至在Windows上对路径使用前斜杠,因此配置可以在平台之间移植。我得到一个错误:file\u contents\u concat=join\n,local.file_contents |------------------local.file_contents是具有2个属性的对象以这种方式执行测试时,我得到错误:main.tf第7行上的函数调用错误,以局部变量表示:7:filenames=fileset.,${var.file_path}/*|--------------var.file|u path是C:/path/test/Call to function fileset失败:未能修剪匹配的路径:Rel:无法使C:\path\test\test1.test.txt相对于..为糟糕的标记表示歉意我今天似乎无法将其格式化嗯。。。您的var.file_路径是否包括。。?看起来这导致了它的失败,因为
文件集的契约是在第一个参数中给出的路径下生成路径,但是。。不在。。如果您确实需要在父目录中工作,那么您可能需要按照最初的方式编写它,在path参数中使用var.file_path,然后在文件调用中重新添加它。请注意,Terraform甚至在Windows上也对路径使用前斜杠,因此配置可以在平台之间移植。我得到一个错误:file_contents_concat=join\n,local.file_contents |------------------local.file_contents是具有2个属性的对象