Terraform:将模块变量作为对象

3

以下是我的模块片段:

inputs.tf

variable "namespace" {
    type = object({
        metadata = object({
            name = string
        })
    })
}

main.tf:

resource "helm_release" "spark" {
    name       = "spark"
    repository = "https://charts.bitnami.com/bitnami" 
    chart      = "spark"
    version    = "1.2.21"
    namespace  = var.namespace.metadata.name
}

正如您所见,我正在尝试访问之前创建的 kubernetes_namespace

进入我的环境工作区:

resource "kubernetes_namespace" "this" {
    metadata {
        name = var.namespace
    }
}

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

    namespace = kubernetes_namespace.this
    workers = 1
}

当我尝试获取计划时,我收到了这个消息:

➜  development terraform plan | xclip -selection clipboard

Error: Invalid value for module argument

  on main.tf line 14, in module "spark":
  14:     namespace = kubernetes_namespace.this

The given value is not suitable for child module variable "namespace" defined
at ../modules/spark/inputs.tf:1,1-21: attribute "metadata": object required.

有什么想法吗?

2个回答

2
这句话的意思是:“报错显示你给变量`namespace`赋值的类型与其约束类型不兼容。”
另外一句话的意思是:“`kubernetes_namespace`的`metadata`属性似乎被定义为对象列表而不是一个单独的对象,因此在这里无法进行自动类型转换。你可以通过改变变量的类型以匹配资源类型架构来解决此问题,像这样:”
variable "namespace" {
    type = object({
        metadata = list(object({
            name = string
        }))
    })
}

我们可以在提供者实现中看到,该块被定义为具有MaxItems: 1,只要这个条件保持不变(这似乎很可能),您可以预期var.namespace.metadata将是一个空列表或单项列表,您可以在模块的其他地方编写一个本地变量以便更轻松地使用它:
locals {
  namespace_name = var.namespace.metadata[0].name
}

以上操作将使local.namespace_name引用给定的命名空间名称,如果给定的命名空间没有metadata块,则该表达式将失败,因为在这种情况下不会有元素[0]
以上是为了访问命名空间 name 而需要的复杂性。如果您预计将来需要使用 kubernetes_namespace 对象的其他属性,那么上述结构可能会有用,但如果您只需要名称,那么将其简化为仅一个字符串变量并直接使用命名空间名称可能会更有帮助。
variable "namespace_name" {
  type = string
}

"...而您可以让呼叫者自行担心如何获取那个名称:"
resource "kubernetes_namespace" "this" {
    metadata {
        name = var.namespace
    }
}

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

    namespace_name = kubernetes_namespace.this.metadata.name
    workers        = 1
}

1
你应该能够将kubernetes_namespace.this.metadata.0.name传递给模块,让模块变量接受一个字符串即可。这样做可以满足所需的依赖关系链,并且还能稍微简化一些事情。
因此,你的模块的inputs.tf应该包含:
variable "namespace" {
  type = string
}

然后你像这样调用它:
resource "kubernetes_namespace" "this" {
    metadata {
        name = var.namespace
    }
}

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

    namespace = kubernetes_namespace.this.metadata.0.name
    workers   = 1
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接