【问题标题】:Terraform map, return null if key is not foundTerraform 地图,如果找不到键则返回 null
【发布时间】:2023-02-13 18:15:18
【问题描述】:

是否可以从 terraform 地图默认返回 null?

例子:

variable "MY_VAR" {
   type = map(number)
   default = {}
}

并在资源中引用:

var.MY_VAR["someKey"]

如果没有 someKey 的条目,我只想返回 null,而不是抛出“给定的键未标识此集合中的元素”错误。无论如何配置地形图以这种方式运行?是否有某种可以利用的默认功能?

【问题讨论】:

    标签: dictionary variables terraform


    【解决方案1】:

    你可以使用lookup

    lookup(var.MY_VAR, "someKey", null)
    

    【讨论】:

      【解决方案2】:

      有几种不同的方法可以解决这个问题。

      在许多情况下,如果您对模块期望的特定键进行硬编码,则表明您应该使用对象类型而不是映射类型。映射类型适用于键完全受模块调用者控制的情况,例如用于指定要声明的对象的名称。对象类型适用于您的模块需要一组特定的预定义属性的情况。

      如果您声明一个对象类型,其属性的值被标记为可选,那么 Terraform 将自动将其设置为 null 在调用者未设置它的任何情况下:

      variable "example_object" {
        type = object({
          required_thing = string
          optional_thing = optional(string)
        })
      }
      

      通过上述声明,调用者可以提供任何对象至少有一个可以转换为字符串的 required_thing 属性:

      module "example" {
        # ...
      
        example_object = {
          required_thing = "Hello!"
        }
      }
      

      使用此变量的上述值:

      • var.example_object.required_thing 将是 "Hello!"
      • var.example_object.optional_thing 将是一个空值

      在对象类型之间进行转换时,Terraform 保证结果将具有类型约束中提到的所有属性以及指定的类型。如果源值不足以遵守该承诺,则 Terraform 将使用调用者的给定值报告错误。


      在极少数情况下,您打算让调用者控制键,但出于某种原因想要特殊对待某些键仅当它们被设置然后有一些不同的策略来实现这一目标。

      对于以下示例,我将假设以下声明:

      # NOTE: Terraform variable names are conventionally
      # written in lowercase, not in uppercase.
      variable "example_map" {
        type = map(string)
      }
      

      一种方法是让变量的每次单独使用都提供一个回退值,以便在未定义键时使用。在 Terraform 中有两种方法可以做到这一点,这两种方法是等效的,但第一种是更新更通用的方法,而第二种是旧版本 Terraform 的先前设计:

      1. try(var.example_map["specific_key"], null)
      2. lookup(var.example_map, "specific_key", null)

        如果您将在许多不同的地方依赖此值,那么如果您将默认值插入本地值的步骤分解出来,则可能更容易理解和维护:

        locals {
          example_map = tomap(merge(
            {
              specific_key = null
            },
            var.example_map,
          ))
        }
        

        通过该声明,您现在可以在模块的其他地方使用 local.example_map 而不是 var.example_map。通过将调用者提供的映射与默认值映射合并,您可以保证 specific_key 始终出现在映射中,因此您可以安全地在其他地方引用 local.example_map["specific_key"]

        我想强调的是,使用某些键是“特殊”的映射类型是一种非常不寻常的设计,虽然我可以想象在某些情况下它可能是合理的,但我会鼓励尽可能使用对象类型约束,因为这样会更容易让你的模块的未来用户通过阅读类型约束来理解它应该如何使用。

      【讨论】: