首页 > 解决方案 > “列表”参数的值无效:列表元素类型不正确:需要字符串

问题描述

应用配置时出现以下错误:

Error: Invalid function argument
│ 
│   on modules/kubernetes_cluster/main.tf line 53, in resource "local_file" "kubespray_inventory":
│   53:     k8s_node_host              = replace(join("\", \"\n", local.all_nodes), "\", \"", "") 
│     ├────────────────
│     │ local.all_nodes is a list of object, known only after apply
│ 
│ Invalid value for "lists" parameter: incorrect list element type: string required.

这是我的本地人块的样子:

locals {
   all_nodes_verbose_etcd = [for k, v in var.node_hosts:
                               format("%s ip=%s etcd_instance=%s", v.name, v.ipv4_address, v.etcd_instance)
                               if length(v.etcd_instance) > 0]

   all_nodes_verbose      = [for k, v in var.node_hosts:
                               format("%s ip=%s", v.name, v.ipv4_address)
                               if length(v.etcd_instance) == 0]

   master_nodes           = [for k, v in var.node_hosts:
                               v.name
                               if v.compute_node != true]

   etcd_nodes             = [for k, v in var.node_hosts:
                               v.name
                               if length(v.etcd_instance) > 0]

   all_nodes              = values(var.node_hosts)[*].name

   kubernetes_conf_file = format("%s/kubespray/inventory/%s/group_vars/k8s-cluster/k8s-cluster.yml", pathexpand("~"), var.kubespray_inventory)
   kubespray_inv_file   = format("%s/kubespray/inventory/%s/inventory.ini", pathexpand("~"), var.kubespray_inventory)
   context_artifact     = format("%s/kubespray/inventory/%s/artifacts/admin.conf", pathexpand("~"), var.kubespray_inventory)
}

kubespray_invenotory.tpl 模板:

[all]
${k8s_node_host_verbose_etcd}
${k8s_node_host_verbose}

[kube-master]
${k8s_master_host}

[etcd]
${k8s_etcd_host}

[kube-node]
${k8s_node_host}

[calico-rr]

[k8s-cluster:children]
kube-master
kube-node
calico-rr

这是引发错误的 local_file 资源:

resource "local_file" "kubespray_inventory" {
  content = templatefile("${path.module}/templates/var.kubespray_inventory.tpl", {
    k8s_node_host_verbose_etcd = replace(join("\", \"\n", local.all_nodes_verbose_etcd), "\", \"", "")
    k8s_node_host_verbose      = replace(join("\", \"\n", local.all_nodes_verbose), "\", \"", "")
    k8s_master_host            = replace(join("\", \"\n", local.master_nodes), "\", \"", "")
    k8s_etcd_host              = replace(join("\", \"\n", local.etcd_nodes), "\", \"", "")
    k8s_node_host              = replace(join("\", \"\n", local.all_nodes), "\", \"", "")
  })
  filename = local.kubespray_inv_file

  depends_on = [
    null_resource.kubespray
  ]
}

这是我的 variables.tf 文件中 node_hosts 的定义:

variable "node_hosts" {
  type = map(map(object({
      name          = string
      compute_node  = bool
      etcd_instance = string
      ipv4_address  = string
    })))
}

这就是我的 tfvars 文件中 node_hosts 的样子:

node_hosts = {
  default = {
    z-ca-arc-control1 = {
      name          = "z-ca-arc-control1"
      compute_node  = false
      etcd_instance = "etcd1"
      ipv4_address  = "10.123.456.01"
    },
    z-ca-arc-control2 =  {
      name          = "z-ca-arc-control2"
      compute_node  = false
      etcd_instance = "etcd2"
      ipv4_address  = "10.123.456.02"
    },
    z-ca-arc-compute1 = {
      name          = "z-ca-arc-compute1"
      compute_node  = true
      etcd_instance = "etcd3"
      ipv4_address  = "10.123.456.03"
    },
    z-ca-arc-compute2 = {
      name          = "z-ca-arc-compute2"
      compute_node   = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.04"
    },
    z-ca-arc-compute3 = {
      name          = "z-ca-arc-compute3"
      compute_node  = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.05"
    }
  }
}

我试图通过将嵌套映射最底层的名称元素更改为列表来解决此问题,但这只会导致不同的错误。奇怪的是,当我在变量文件中取消 node_hosts 的定义并使用:

variable node_hosts = {
  default = {
    z-ca-arc-control1 = {
      name          = "z-ca-arc-control1"
      compute_node  = false
      etcd_instance = "etcd1"
      ipv4_address  = "10.123.456.01"
    },
    z-ca-arc-control2 =  {
      name          = "z-ca-arc-control2"
      compute_node  = false
      etcd_instance = "etcd2"
      ipv4_address  = "10.123.456.02"
    },
    z-ca-arc-compute1 = {
      name          = "z-ca-arc-compute1"
      compute_node  = true
      etcd_instance = "etcd3"
      ipv4_address  = "10.123.456.03"
    },
    z-ca-arc-compute2 = {
      name          = "z-ca-arc-compute2"
      compute_node   = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.04"
    },
    z-ca-arc-compute3 = {
      name          = "z-ca-arc-compute3"
      compute_node  = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.05"
    }
  }
}

该代码有效,我想知道在我的 tfvars 文件中使用 default = 是否不正确。

标签: terraform

解决方案


一切似乎都很好,除了你的default和变量node_hosts不匹配。在我看来,如果您按如下方式制作它们,它将起作用:

variable "node_hosts" {
  type = map(object({
      name          = string
      compute_node  = bool
      etcd_instance = string
      ipv4_address  = string
    }))
}

tfvars中它将是:

node_hosts =  {
    z-ca-arc-control1 = {
      name          = "z-ca-arc-control1"
      compute_node  = false
      etcd_instance = "etcd1"
      ipv4_address  = "10.123.456.01"
    },
    z-ca-arc-control2 =  {
      name          = "z-ca-arc-control2"
      compute_node  = false
      etcd_instance = "etcd2"
      ipv4_address  = "10.123.456.02"
    },
    z-ca-arc-compute1 = {
      name          = "z-ca-arc-compute1"
      compute_node  = true
      etcd_instance = "etcd3"
      ipv4_address  = "10.123.456.03"
    },
    z-ca-arc-compute2 = {
      name          = "z-ca-arc-compute2"
      compute_node   = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.04"
    },
    z-ca-arc-compute3 = {
      name          = "z-ca-arc-compute3"
      compute_node  = true
      etcd_instance = ""
      ipv4_address  = "10.123.456.05"
    }
  } 

推荐阅读