# Docker images in use
data "docker_registry_image" "netbox" {
  name = "netboxcommunity/netbox:v4.0-2.9.1"
}
data "docker_registry_image" "netbox_postgres" {
  name = "postgres:16-alpine"
}
data "docker_registry_image" "netbox_redis" {
  name = "redis:7-alpine"
}

# Docker Network
resource "docker_network" "netbox" {
  name        = "netbox"
  driver      = "overlay"
  attachable  = true
  ipam_driver = "default"
}

# Docker Volumes
resource "docker_volume" "netbox_config" {
  name = "netbox_config"
}
resource "docker_volume" "netbox_media" {
  name = "netbox_media"
}
resource "docker_volume" "netbox_reports" {
  name = "netbox_reports"
}
resource "docker_volume" "netbox_scripts" {
  name = "netbox_scripts"
}
resource "docker_volume" "netbox_database" {
  name = "netbox_database"
}
resource "docker_volume" "netbox_redis" {
  name = "netbox_redis"
}
resource "docker_volume" "netbox_cache" {
  name = "netbox_cache"
}

# Configs
resource "random_password" "postgres_password" {
  length  = 32
  special = false
}
resource "random_password" "redis_password" {
  length  = 32
  special = false
}
resource "random_password" "redis_cache_password" {
  length  = 32
  special = false
}
resource "random_password" "secret_key" {
  length  = 50
  special = false
}
locals {
  netbox_conf = {
    CORS_ORIGIN_ALLOW_ALL = true

    DB_HOST     = docker_service.netbox_postgres.name
    DB_NAME     = "netbox"
    DB_PASSWORD = nonsensitive(random_password.postgres_password.result)
    DB_USER     = "netbox"

    EMAIL_FROM         = "netbox@bar.com"
    EMAIL_PASSWORD     = ""
    EMAIL_PORT         = 25
    EMAIL_SERVER       = "localhost"
    EMAIL_SSL_CERTFILE = ""
    EMAIL_SSL_KEYFILE  = ""
    EMAIL_TIMEOUT      = 5
    EMAIL_USERNAME     = "netbox"
    # EMAIL_USE_SSL and EMAIL_USE_TLS are mutually exclusive, i.e. they can't both be `true`!
    EMAIL_USE_SSL = "false"
    EMAIL_USE_TLS = "false"

    GRAPHQL_ENABLED       = "true"
    HOUSEKEEPING_INTERVAL = 86400
    MEDIA_ROOT            = "/opt/netbox/netbox/media"
    METRICS_ENABLED       = "false"

    REDIS_DATABASE                 = 0
    REDIS_HOST                     = docker_service.netbox_redis.name
    REDIS_INSECURE_SKIP_TLS_VERIFY = "false"
    //REDIS_PASSWORD                 = nonsensitive(random_password.redis_password.result)
    REDIS_SSL = "false"

    REDIS_CACHE_DATABASE                 = 1
    REDIS_CACHE_HOST                     = docker_service.netbox_redis_cache.name
    REDIS_CACHE_INSECURE_SKIP_TLS_VERIFY = "false"
    //REDIS_CACHE_PASSWORD                 = nonsensitive(random_password.redis_cache_password.result)
    REDIS_CACHE_SSL = "false"

    RELEASE_CHECK_URL = "https://api.github.com/repos/netbox-community/netbox/releases"
    SECRET_KEY        = nonsensitive(random_password.secret_key.result)
    SKIP_SUPERUSER    = "true"
    WEBHOOKS_ENABLED  = "true"
  }
}

# Services
resource "docker_service" "netbox" {
  name = "netbox-app"
  task_spec {
    container_spec {
      image = "${data.docker_registry_image.netbox.name}@${data.docker_registry_image.netbox.sha256_digest}"
      user  = "unit:root"
      env   = local.netbox_conf
      healthcheck {
        test         = ["CMD-SHELL", "curl -f http://localhost:8080/login/ || exit 1"]
        interval     = "15s"
        timeout      = "3s"
        start_period = "2m"
      }
      mounts {
        target = "/etc/netbox/config"
        type   = "volume"
        source = docker_volume.netbox_config.name
      }
      mounts {
        target = "/opt/netbox/netbox/media"
        type   = "volume"
        source = docker_volume.netbox_media.name
      }
      mounts {
        target = "/opt/netbox/netbox/reports"
        type   = "volume"
        source = docker_volume.netbox_reports.name
      }
      mounts {
        target = "/opt/netbox/netbox/scripts"
        type   = "volume"
        source = docker_volume.netbox_scripts.name
      }
    }
    networks_advanced {
      name = docker_network.loadbalancer.id
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  endpoint_spec {
    ports {
      protocol     = "tcp"
      publish_mode = "ingress"
      target_port  = 8080
    }
  }
  converge_config {
    timeout = "2m"
  }
  depends_on = [
    docker_service.netbox_postgres,
    docker_service.netbox_redis,
    docker_service.netbox_redis_cache,
  ]
}
resource "docker_service" "netbox_worker" {
  name = "netbox-worker"
  task_spec {
    container_spec {
      image   = "${data.docker_registry_image.netbox.name}@${data.docker_registry_image.netbox.sha256_digest}"
      user    = "unit:root"
      env     = local.netbox_conf
      command = ["/opt/netbox/venv/bin/python", "/opt/netbox/netbox/manage.py", "rqworker", ]
      healthcheck {
        test         = ["CMD-SHELL", "ps -aux | grep -v grep | grep -q rqworker || exit 1"]
        interval     = "15s"
        timeout      = "3s"
        start_period = "20s"
      }
      mounts {
        target = "/etc/netbox/config"
        type   = "volume"
        source = docker_volume.netbox_config.name
      }
      mounts {
        target = "/opt/netbox/netbox/media"
        type   = "volume"
        source = docker_volume.netbox_media.name
      }
      mounts {
        target = "/opt/netbox/netbox/reports"
        type   = "volume"
        source = docker_volume.netbox_reports.name
      }
      mounts {
        target = "/opt/netbox/netbox/scripts"
        type   = "volume"
        source = docker_volume.netbox_scripts.name
      }
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  converge_config {
    timeout = "2m"
  }
  depends_on = [
    docker_service.netbox
  ]
}
resource "docker_service" "netbox_housekeeping" {
  name = "netbox-housekeeping"
  task_spec {
    container_spec {
      image   = "${data.docker_registry_image.netbox.name}@${data.docker_registry_image.netbox.sha256_digest}"
      user    = "unit:root"
      env     = local.netbox_conf
      command = ["/opt/netbox/housekeeping.sh", ]
      healthcheck {
        test         = ["CMD-SHELL", "ps -aux | grep -v grep | grep -q housekeeping || exit 1"]
        interval     = "15s"
        timeout      = "3s"
        start_period = "20s"
      }
      mounts {
        target = "/etc/netbox/config"
        type   = "volume"
        source = docker_volume.netbox_config.name
      }
      mounts {
        target = "/opt/netbox/netbox/media"
        type   = "volume"
        source = docker_volume.netbox_media.name
      }
      mounts {
        target = "/opt/netbox/netbox/reports"
        type   = "volume"
        source = docker_volume.netbox_reports.name
      }
      mounts {
        target = "/opt/netbox/netbox/scripts"
        type   = "volume"
        source = docker_volume.netbox_scripts.name
      }
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  converge_config {
    timeout = "2m"
  }
  depends_on = [
    docker_service.netbox
  ]
}

# Netbox Postgres Database
resource "docker_service" "netbox_postgres" {
  name = "netbox-postgres"
  task_spec {
    container_spec {
      image = "${data.docker_registry_image.netbox_postgres.name}@${data.docker_registry_image.netbox_postgres.sha256_digest}"
      mounts {
        target = "/var/lib/postgresql/data"
        type   = "volume"
        source = docker_volume.netbox_database.name
      }
      env = {
        POSTGRES_DB       = "netbox"
        POSTGRES_USER     = "netbox"
        POSTGRES_PASSWORD = random_password.postgres_password.result
      }
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  converge_config {
    timeout = "2m"
  }
}

# Netbox Redis
resource "docker_service" "netbox_redis" {
  name = "netbox-redis"
  task_spec {
    container_spec {
      image = "${data.docker_registry_image.netbox_redis.name}@${data.docker_registry_image.netbox_redis.sha256_digest}"
      command = [
        "sh", "-c",
        "redis-server",
        "--appendonly", "yes",
        //"--requirepass", nonsensitive(random_password.redis_password.result),
      ]
      mounts {
        target = "/data"
        type   = "volume"
        source = docker_volume.netbox_redis.name
      }
      healthcheck {
        test     = ["CMD", "sh", "-c", "redis-cli", "PING"]
        interval = "5s"
        timeout  = "3s"
      }
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  converge_config {
    timeout = "2m"
  }
}
resource "docker_service" "netbox_redis_cache" {
  name = "netbox-redis-cache"
  task_spec {
    container_spec {
      image = "${data.docker_registry_image.netbox_redis.name}@${data.docker_registry_image.netbox_redis.sha256_digest}"
      command = [
        "sh", "-c",
        "redis-server",
        //"--requirepass", nonsensitive(random_password.redis_cache_password.result),
      ]
      mounts {
        target = "/data"
        type   = "volume"
        source = docker_volume.netbox_cache.name
      }
      healthcheck {
        test     = ["CMD", "sh", "-c", "redis-cli", "PING"]
        interval = "5s"
        timeout  = "3s"
      }
    }
    networks_advanced {
      name = docker_network.netbox.id
    }
    restart_policy {
      condition = "any"
      delay     = "0s"
      window    = "0s"
    }
  }
  converge_config {
    timeout = "2m"
  }
}

# Set up some nginx bits for it
module "netbox_nginx_config" {
  # tflint-ignore: terraform_module_pinned_source
  source   = "git::https://code.techinc.nl/grey/terraform-nginx.git//nginx-site-available"
  hostname = "netbox.california.ti"
  //certificate   = acme_certificate.ooo_grey["s3"]
  service_name  = docker_service.netbox.name
  upstream_host = "${docker_service.netbox.name}:8080"
  config_prefix = "nginx"
  allow_non_ssl = true
  allow_ssl     = false
  depends_on = [
    docker_service.netbox
  ]
}