resource "kubernetes_namespace" "dns" {
  metadata {
    name = "dns"
  }
}

resource "kubernetes_service_account" "dns" {

  metadata {
    name      = "dns-sa"
    namespace = kubernetes_namespace.dns.metadata[0].name
  }

  automount_service_account_token = false
}

resource "kubernetes_config_map" "dns" {
  metadata {
    name      = "dns-config"
    namespace = kubernetes_namespace.dns.metadata[0].name
  }

  data = merge({
    "Corefile" = local.configfile

  }, local.db_files)
}

resource "kubernetes_deployment" "dns" {
  metadata {
    name      = "dns"
    namespace = kubernetes_namespace.dns.metadata[0].name
    labels = {
      dns = "dns"
    }
  }

  spec {
    replicas = 1

    selector {
      match_labels = {
        dns = "dns"
      }
    }

    strategy {
      type = "RollingUpdate"
      rolling_update {
        max_unavailable = 1
      }
    }

    template {
      metadata {
        labels = {
          dns = "dns"
        }
        annotations = {
          "checksum/corefile" = local.configfile_checksum
          "checksum/db-files" = local.db_files_checksum
        }
      }

      spec {
        service_account_name            = kubernetes_service_account.dns.metadata[0].name
        automount_service_account_token = false

        container {
          name              = "dns"
          image             = "docker.io/coredns/coredns:${var.tag}"
          image_pull_policy = "IfNotPresent"
          args = [
            "-conf",
            "/etc/coredns/Corefile",
          ]

          liveness_probe {
            http_get {
              path   = "/health"
              port   = 8080
              scheme = "HTTP"
            }
            initial_delay_seconds = 60
            period_seconds        = 10
            success_threshold     = 1
            timeout_seconds       = 5
          }

          readiness_probe {
            http_get {
              path   = "/ready"
              port   = 8181
              scheme = "HTTP"
            }
            period_seconds    = 10
            success_threshold = 1
            timeout_seconds   = 1
          }

          resources {
            requests = {
              memory = "100Mi"
            }
          }

          security_context {
            allow_privilege_escalation = false
            capabilities {
              drop = ["ALL"]
              add  = ["NET_BIND_SERVICE"]
            }
          }

          port {
            name           = "dns-tcp"
            container_port = 53
            protocol       = "TCP"
          }

          port {
            name           = "dns-udp"
            container_port = 53
            protocol       = "UDP"
          }

          port {
            name           = "metrics"
            container_port = 9153
            protocol       = "TCP"
          }

          volume_mount {
            name       = "config"
            mount_path = "/etc/coredns"
            read_only  = true
          }
        }

        volume {
          name = "config"
          config_map {
            name         = kubernetes_config_map.dns.metadata[0].name
            default_mode = "0644"
            items {
              key  = "Corefile"
              path = "Corefile"
            }
            dynamic "items" {
              for_each = local.db_files
              content {
                key  = items.key
                path = "db.${items.key}"
              }
            }
          }
        }
      }
    }
  }

  lifecycle {
    ignore_changes = [spec[0].template[0].metadata[0].annotations["kubectl.kubernetes.io/restartedAt"]]
  }
}

resource "kubernetes_service" "dns_internal" {
  metadata {
    name      = "dns"
    namespace = kubernetes_namespace.dns.metadata[0].name
  }

  spec {
    selector = {
      dns = "dns"
    }

    port {
      name        = "dns-tcp"
      protocol    = "TCP"
      port        = 53
      target_port = 53
    }

    port {
      name        = "dns-udp"
      protocol    = "UDP"
      port        = 53
      target_port = 53
    }
  }

  lifecycle {
    ignore_changes = [
      metadata[0].annotations
    ]
  }
}
