如何在文件存在时读取文件,但如果文件不存在则不抛出致命错误

27次阅读
没有评论

问题描述

在使用Terraform时,有一个需求是希望在读取文件时,如果文件存在则读取,但如果文件不存在则不抛出致命错误。用户尝试使用data.local_sensitive_file来读取文件,但当文件不存在时,会导致编译错误。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

在Terraform中,你可以使用fileexists函数来检查文件是否存在,然后再尝试使用它。这个函数返回一个布尔值,指示指定的文件是否存在。
在你的情况下,你可以使用以下代码来处理文件可能不存在的情况:

filename = fileexists("/tmp/foo") ? "/tmp/foo" : "/tmp/whateverfile_you_want_if_foo_doesn't_exist"

如果文件存在,filename将为/tmp/foo,如果文件不存在,filename将为/tmp/whateverfile_you_want_if_foo_doesn't_exist

方案2

在这种特殊情况下,如果路径是已知的,我通常会使用file函数而不是local_sensitive_file数据源,因为数据源主要用于在Terraform运行时动态生成的文件。
以下是使用file函数的示例代码:

locals {
  filename = "${path.module}/whatever.txt"
  example  = fileexists(local.filename) ? sensitive(file(local.filename)) : null
}

如果在你的实际配置中,这是一个来自Terraform配置之外的文件或者是由你的配置动态生成的文件,你可以通过告诉Terraform,如果文件不存在,则不应该有此数据资源的实例,来达到类似的效果:

locals {
  filename = "${path.module}/whatever.txt"
}

data "local_sensitive_file" "example" {
  count    = fileexists(local.filename) ? 1 : 0
  filename = local.filename
}

locals {
  file_content = one(data.local_sensitive_file.example[*].content)
}

上面的代码中,使用one函数的最后一个表达式是一种简洁的方式,可以获取content的一个值,如果没有此资源的实例,则返回null。因此,local.file_content将是文件的内容,如果文件不存在,则为null

需要注意的是,如果应用此Terraform配置可能会改变文件是否存在,那么声明”仅在文件存在时使用”的规则可能会有问题。因为在规划阶段,Terraform会做出一些假设,而这些假设在应用阶段可能不成立,从而导致Terraform表现出未指定的行为。因此,建议明确指定文件是否应该存在,以便Terraform可以立即告诉你是否做出了错误的假设。

例如,你可以声明一个输入变量,其存在明确表示文件应该存在,但在不需要存在时可以省略:

variable "filename" {
  type    = string
  default = null
}

data "local_sensitive_file" "example" {
  count    = var.filename != null ? 1 : 0
  filename = var.filename
}

locals {
  file_content = one(data.local_sensitive_file.example[*].content)
}

这与前面的示例基本相同,只是现在决定是否读取文件的谓词是是否指定了文件名,因此,如果调用此模块的用户在编写文件名时出现拼写错误,或者假设文件存在但实际上不存在,Terraform可以快速给出反馈。

请注意,以上解决方案中的代码仅供参考,具体实现可能需要根据实际情况进行调整。

正文完