locals { service_hostname = format("%s.localdomain", var.application_name) at_least_one_port = length(var.ports) > 0 ? 1 : 0 ports_map = { for index, port in var.ports : format("port-%s", index) => port } exposed_ports_map = { for index, port in var.ports : format("port-%s", index) => port if port.expose == true } certificate_secret_name = format("%s-certificate", var.application_name) at_least_one_port_exposed = length(local.exposed_ports_map) > 0 } resource "kubernetes_service_v1" "service" { count = local.at_least_one_port metadata { name = var.application_name namespace = var.namespace labels = { "app.kubernetes.io/part-of" = var.application_name "app.kubernetes.io/managed-by" = "terraform" } } spec { type = "ClusterIP" dynamic port { for_each = local.ports_map content { name = format("service-%s", port.key) port = port.value.container_port target_port = port.key } } selector = { "app.kubernetes.io/name" = local.label_name } } } resource "kubernetes_manifest" "certificate" { # at_least_one_port_exposed is_test result # 0 0 0 # 0 1 0 # 1 0 1 # 1 1 0 count = local.at_least_one_port_exposed && !var.is_test ? 1 : 0 manifest = { apiVersion = "cert-manager.io/v1" kind = "Certificate" metadata = { name = var.application_name namespace = var.namespace labels = { "app.kubernetes.io/part-of" = var.application_name "app.kubernetes.io/managed-by" = "terraform" } } spec = { secretName = local.certificate_secret_name dnsNames = [ local.service_hostname, format("*.%s", local.service_hostname) ] issuerRef = { kind = "ClusterIssuer" name = "localdomain-issuer" group = "cfssl-issuer.wikimedia.org" } } } } resource "kubernetes_ingress_v1" "ingress" { for_each = local.exposed_ports_map metadata { name = var.application_name namespace = var.namespace labels = { "app.kubernetes.io/part-of" = var.application_name "app.kubernetes.io/managed-by" = "terraform" } annotations = { "traefik.ingress.kubernetes.io/router.middlewares" = "kube-ingress-gzip-compress@kubernetescrd" "traefik.ingress.kubernetes.io/router.entrypoints" = "websecure" } } spec { dynamic rule { for_each = concat( var.additional_ingress_host, [local.service_hostname] ) content { host = rule.value http { path { path = "/" backend { service { name = kubernetes_service_v1.service[0].metadata.0.name port { name = format("service-%s", each.key) } } } } } } } tls { hosts = concat( var.additional_ingress_host, [local.service_hostname] ) secret_name = local.certificate_secret_name } } } # {{ application_name }}.localdomain IN CNAME internal-lb resource "kubernetes_manifest" "record" { # at_least_one_port_exposed is_test result # 0 0 0 # 0 1 0 # 1 0 1 # 1 1 0 count = local.at_least_one_port_exposed && !var.is_test ? 1 : 0 manifest = { apiVersion = "externaldns.k8s.io/v1alpha1" kind = "DNSEndpoint" metadata = { name = var.application_name namespace = var.namespace labels = { "app.kubernetes.io/part-of" = var.application_name "app.kubernetes.io/managed-by" = "terraform" } } spec = { endpoints = [ { dnsName = local.service_hostname recordTTL = "180" recordType = "CNAME" targets = [ "internal-lb.localdomain" ] } ] } } }