Reputation: 5159
I try to create kubernetes_config_map
using for_each
loop, when all of the data is inside a variable:
variables.tf
:
variable "extra_configmaps" {
type = list(object({
name = string
namespace = string
data = object({})
}))
default = []
}
terraform.tfvars
:
extra_configmaps = [
{
name = "common"
namespace = "production"
data = {
"somekey" = "somevalue"
}
}
]
main.tf
:
resource "kubernetes_config_map" "extra_configmaps" {
for_each = { for record in var.extra_configmaps : record.name => record }
metadata {
name = each.key
namespace = each.value.namespace
}
data = tomap(each.value.data)
}
However, the configmap is created with no data!
# kubernetes_config_map.extra_configmaps["common"] will be created
+ resource "kubernetes_config_map" "extra_configmaps" {
+ id = (known after apply)
+ metadata {
+ generation = (known after apply)
+ name = "common"
+ namespace = "production"
+ resource_version = (known after apply)
+ self_link = (known after apply)
+ uid = (known after apply)
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
I know data
expects a map, but the plan doesn't show it even thoughI have provided it.
How do I create dynamic configmaps for Kubernetes without empty data? How do I create dynamic configmaps for Kubernetes without empty data?
Upvotes: 0
Views: 1898
Reputation: 74574
You've specified that the type constraint of the data
attribute is object({})
, which is an object type with no attributes at all. Object type constraints require that at least the given attributes are present, but since you didn't specify any attributes this constraint will match any object value but it will also discard all its attributes during type conversion, because none are specified in the type constraint.
This behavior for a totally-empty object type is, of course, a bit weird. It's a natural but perhaps awkward consequence of the rule that allows declaring an object type constraint that is a subset of an object type defined by a provider's resource type, to allow callers the convenience of passing the whole resource in without having to write out all of the attributes that the module doesn't actually need or care about:
variable "aws_vpc" {
type = object({
id = string
cidr_block = string
# aws_vpc's object type has many other attributes,
# but this module only needs the two above so it
# will accept and silently discard all of the
# others. Caller can therefore do this:
# aws_vpc = aws_vpc.example
})
}
The data
attribute of kubernetes_config_map
is defined with the type constraint map(string)
, so I think the best way to get the result you were looking for here is to echo that same type constraint in your variable, like this:
variable "extra_configmaps" {
type = list(object({
name = string
namespace = string
data = map(string)
}))
default = []
}
There's more information about Terraform's type conversion rules in Conversion of Complex Types, which is part of the documentation on Type Constraints.
Upvotes: 2