【问题标题】:How to extend terraform module input variable schema without breaking existing clients?如何在不破坏现有客户端的情况下扩展 terraform 模块输入变量模式?
【发布时间】:2020-05-30 15:57:43
【问题描述】:

我有一个带有以下输入变量的模块:

variable "apsvc_map" {
  description = "The App Services sharing the same App Service Plan. Maps an App Service name to its properties."
  type        = map(object({ 
    identity_ids = list(string),
    disabled = bool
  }))
}

现在我想在架构中添加一个新属性 - no_custom_hostname_binding。新版本是:

variable "apsvc_map" {
  description = "The App Services sharing the same App Service Plan. Maps an App Service name to its properties."
  type        = map(object({ 
    identity_ids = list(string),
    disabled = bool
    no_custom_hostname_binding = bool
  }))
}

并且可以借助 try 函数在模块代码中使此更改向后兼容,因为省略新属性等同于为其提供 false 值。

但是,terraform 会严格处理此架构,并且不允许在没有新字段的情况下传递输入:

2020-05-30T15:34:20.8061749Z Error: Invalid value for module argument
2020-05-30T15:34:20.8062005Z 
2020-05-30T15:34:20.8062205Z   on ..\..\modules\web\main.tf line 47, in module "web":
2020-05-30T15:34:20.8062336Z   47:   apsvc_map = {
2020-05-30T15:34:20.8062484Z   48:     dfhub = {
2020-05-30T15:34:20.8062727Z   49:       disabled     = false
2020-05-30T15:34:20.8065156Z   50:       identity_ids = [local.identity_id]
2020-05-30T15:34:20.8065370Z   51:     }
2020-05-30T15:34:20.8065459Z   52:   }
2020-05-30T15:34:20.8065538Z 

我从 terraform 抱怨的错误中了解到,因为我没有在输入中指定新属性的值。

所以,有三种解决方案:

  1. 更新所有现有代码以添加新属性 - 不可能。
  2. 给新版本的模块打上不同的标签,让新代码引用新标签,而旧代码继续引用旧标签——从长远来看会导致标签泛滥,产生各种奇怪的笛卡尔乘法标签名称中的特征。最终 - 不可能。
  3. 通过注释掉可选属性来放松输入变量架构并在代码中使用try

最后一个选项并不理想,因为模块的文档不会列出可选属性。但从代码管理的角度来看 - 它是最好的。

所以问题是 - 可以将输入对象属性定义为可选的吗?理想情况下,它应该包含默认值,但我现在可以使用 try 方法。

编辑 1

我实际上认为我可以在对象中传递未知属性,但没有。一旦给出了模式,它就没什么了。因此,在我的情况下,唯一向后兼容的解决方案是使用 map(any)

【问题讨论】:

  • 加入俱乐部:github.com/hashicorp/terraform/issues/19898 +1,并给他们留言为什么你需要它,希望这将很快实施......这是他们回购中最受好评的问题跨度>
  • 真糟糕。请宣传您的评论以回答,所以我可以相信你。

标签: terraform


【解决方案1】:

已为 Terraform 建议对象变量中的可选参数:
https://github.com/hashicorp/terraform/issues/19898

很遗憾,截至 2020 年 5 月 30 日,这方面没有任何进展。
这是他们回购中投票最多的问题,我们所能做的就是继续投票,希望很快就会实施。

您是对的

【讨论】:

    【解决方案2】:

    鉴于您的选择、偏好以及Terraform 0.12 doesn't support and Terraform 0.13 likely won't support optional or default values on objects 的事实,我认为您还有第四个选择:

    variable "apsvc_map" {
      description = "The App Services sharing the same App Service Plan. Maps an App Service name to its properties."
      default = {}
      type        = map(object({ 
        identity_ids = list(string),
        disabled = bool
      }))
    }
    
    variable "no_custom_hostname_binding" {
      description = "Whether or not an App Service should disable hostname binding. Maps an App Service name to an override of the no_custom_hostname_binding property."
      type        = map(bool)
    }
    

    从那里,您可以像这样使用它:

    lookup(var.no_custom_hostname_binding[local.awsvpc_map_key], null)
    

    并像这样声明覆盖:

    no_custom_hostname_binding = {
      "vpc_key" = true
    }
    

    在您需要知道该参数的表达式中。这不是超级优雅,但是没有可选参数,你没有很多好的选择。

    您可以按照此模式根据需要添加任意数量的可选覆盖,并在以后添加更多内容而不会破坏客户端。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 2019-06-28
    • 2022-08-06
    • 2021-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多