Trying to create a kubernetes_manifest for a CRD.
It is specifically for the Cloud SQL Auth Proxy Operator for GCP. The manifest sets up a cloud sql auth proxy sidecar that gets injected into matching k8s pods.
The problem I am facing is how to not set the proxy port attribute in the manifest, if it is omitted in the object variable…
The reason I want to do this is that the optional value is null, it is still recognized as a change in TF which causes an update to the resource.
variable looks like this:
variable "sidecar_definitions" {
description = "Map of workloads to add Cloud SQL Proxy sidecar to, with configuration details..."
type = map(object({
workload_namespace = string
workload_selector_kind = string
workload_selector_name = string
connections = list(object({
connection_string = string
port = optional(number)
hostEnvName = optional(string, "CSAP_HOSTNAME")
portEnvName = optional(string, "CSAP_PORT")
}))
telemetry = bool
}))
validation {
condition = length(var.sidecar_definitions) > 0
error_message = "must provide at least 1 entry"
}
nullable = false
}```
data looks like this:
"application_with_port" = {
workload_namespace = "namespace1",
workload_selector_kind = "StatefulSet",
workload_selector_name = "application_1",
connections = [
{ connection_string = "sample_project_abc:northamerica-northeast1:sample_db_1",
hostEnvName = "DBHOST",
portEnvName = "DBPORT",
port = 54320,
}
],
telemetry = false
},
"application_without_port" = {
workload_namespace = "namespace1",
workload_selector_kind = "StatefulSet",
workload_selector_name = "application_2",
connections = [
{ connection_string = "sample_project_abc:northamerica-northeast1:sample_db_1",
hostEnvName = "DBHOST",
portEnvName = "DBPORT",
}
],
telemetry = false
},
At the moment, my locals and resource definition looks like this:
```locals {
# flatten ensures that this local value is a flat list of objects, rather
# than a list of lists of objects.
flattened_sidecar_defn = flatten([
for sidecar_key, sidecar in var.sidecar_definitions : [
for connection_key, connection in sidecar.connections : {
sidecar_key = sidecar_key
connection_key = connection_key
connection_string = connection.connection_string
connection_port = connection.port
hostEnvName = connection.hostEnvName
portEnvName = connection.portEnvName
}
]
])
}
resource "kubernetes_manifest" "auth_proxy_workload" {
for_each = var.sidecar_definitions
manifest = {
"apiVersion" = "cloudsql.cloud.google.com/v1"
"kind" = "AuthProxyWorkload"
"metadata" = {
"name" = "cloud-sql-auth-proxy-operator--workload--${each.key}"
"namespace" = each.value["workload_namespace"]
}
"spec" = {
"instances" = [
/*
"autoIAMAuthN" = true
"connectionString" = each.value["db_connection_string"]
"hostEnvName" = each.value["hostEnvName"]
"portEnvName" = each.value["portEnvName"]
"privateIP" = true
*/
for conn_key, conn in local.flattened_sidecar_defn : {
"autoIAMAuthN" = true
"privateIP" = true
"connectionString" = conn.connection_string
"hostEnvName" = conn.hostEnvName
"portEnvName" = conn.portEnvName
# "port" = conn.connection_port
"port" = (conn.connection_port == null || conn.connection_port == 0) ? null : conn.connection_port
# %{ if conn.connection_port != null }"port" = conn.connection_port %{ endif }
} if conn.sidecar_key == each.key
]
"workloadSelector" = {
"kind" = each.value["workload_selector_kind"]
"name" = each.value["workload_selector_name"]
}
}
}
}
The error I see in TF plan is this:
~ resource "kubernetes_manifest" "auth_proxy_workload" {
~ object = {
~ spec = {
~ instances = [
~ {
+ port = (known after apply)
# (7 unchanged attributes hidden)
},
]
# (2 unchanged attributes hidden)
}
# (3 unchanged attributes hidden)
}
# (1 unchanged attribute hidden)
}
because port is being recognized as being changed, TF is pushing the new value (ie null) into the resource definition and recreating it…
+ port = (known after apply)
I need a hint how to make the port attribute optional if the value of conn.connection_port is null…
Thanks for any suggestions!