terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
    digitalocean = {
      source = "digitalocean/digitalocean"
    }
  }
}

provider "coder" {
}

variable "step1_do_project_id" {
  type        = string
  description = <<-EOF
    Enter project ID

      $ doctl projects list
  EOF
  sensitive   = true

  validation {
    # make sure length of alphanumeric string is 36
    condition     = length(var.step1_do_project_id) == 36
    error_message = "Invalid Digital Ocean Project ID."
  }

}

variable "step2_do_admin_ssh_key" {
  type        = number
  description = <<-EOF
    Enter admin SSH key ID (some Droplet images require an SSH key to be set):

    Can be set to "0" for no key.

    Note: Setting this to zero will break Fedora images and notify root passwords via email.

      $ doctl compute ssh-key list
  EOF
  sensitive   = true

  validation {
    condition     = var.step2_do_admin_ssh_key >= 0
    error_message = "Invalid Digital Ocean SSH key ID, a number is required."
  }
}

data "coder_parameter" "droplet_image" {
  name         = "droplet_image"
  display_name = "Droplet image"
  description  = "Which Droplet image would you like to use?"
  default      = "ubuntu-22-04-x64"
  type         = "string"
  mutable      = false
  option {
    name  = "AlmaLinux 9"
    value = "almalinux-9-x64"
    icon  = "/icon/almalinux.svg"
  }
  option {
    name  = "AlmaLinux 8"
    value = "almalinux-8-x64"
    icon  = "/icon/almalinux.svg"
  }
  option {
    name  = "Fedora 39"
    value = "fedora-39-x64"
    icon  = "/icon/fedora.svg"
  }
  option {
    name  = "Fedora 38"
    value = "fedora-38-x64"
    icon  = "/icon/fedora.svg"
  }
  option {
    name  = "CentOS Stream 9"
    value = "centos-stream-9-x64"
    icon  = "/icon/centos.svg"
  }
  option {
    name  = "CentOS Stream 8"
    value = "centos-stream-8-x64"
    icon  = "/icon/centos.svg"
  }
  option {
    name  = "Debian 12"
    value = "debian-12-x64"
    icon  = "/icon/debian.svg"
  }
  option {
    name  = "Debian 11"
    value = "debian-11-x64"
    icon  = "/icon/debian.svg"
  }
  option {
    name  = "Debian 10"
    value = "debian-10-x64"
    icon  = "/icon/debian.svg"
  }
  option {
    name  = "Rocky Linux 9"
    value = "rockylinux-9-x64"
    icon  = "/icon/rockylinux.svg"
  }
  option {
    name  = "Rocky Linux 8"
    value = "rockylinux-8-x64"
    icon  = "/icon/rockylinux.svg"
  }
  option {
    name  = "Ubuntu 22.04 (LTS)"
    value = "ubuntu-22-04-x64"
    icon  = "/icon/ubuntu.svg"
  }
  option {
    name  = "Ubuntu 20.04 (LTS)"
    value = "ubuntu-20-04-x64"
    icon  = "/icon/ubuntu.svg"
  }
}

data "coder_parameter" "droplet_size" {
  name         = "droplet_size"
  display_name = "Droplet size"
  description  = "Which Droplet configuration would you like to use?"
  default      = "s-1vcpu-1gb"
  type         = "string"
  icon         = "/icon/memory.svg"
  mutable      = false
  # s-1vcpu-512mb-10gb is unsupported in tor1, blr1, lon1, sfo2, and nyc3 regions
  # s-8vcpu-16gb access requires a support ticket with Digital Ocean
  option {
    name  = "1 vCPU, 1 GB RAM"
    value = "s-1vcpu-1gb"
  }
  option {
    name  = "1 vCPU, 2 GB RAM"
    value = "s-1vcpu-2gb"
  }
  option {
    name  = "2 vCPU, 2 GB RAM"
    value = "s-2vcpu-2gb"
  }
  option {
    name  = "2 vCPU, 4 GB RAM"
    value = "s-2vcpu-4gb"
  }
  option {
    name  = "4 vCPU, 8 GB RAM"
    value = "s-4vcpu-8gb"
  }
}

data "coder_parameter" "home_volume_size" {
  name         = "home_volume_size"
  display_name = "Home volume size"
  description  = "How large would you like your home volume to be (in GB)?"
  type         = "number"
  default      = "20"
  mutable      = false
  validation {
    min = 1
    max = 100 # Sizes larger than 100 GB require a support ticket with Digital Ocean
  }
}

data "coder_parameter" "region" {
  name         = "region"
  display_name = "Region"
  description  = "This is the region where your workspace will be created."
  icon         = "/emojis/1f30e.png"
  type         = "string"
  default      = "ams3"
  mutable      = false
  # nyc1, sfo1, and ams2 regions were excluded because they do not support volumes, which are used to persist data while decreasing cost
  option {
    name  = "Canada (Toronto)"
    value = "tor1"
    icon  = "/emojis/1f1e8-1f1e6.png"
  }
  option {
    name  = "Germany (Frankfurt)"
    value = "fra1"
    icon  = "/emojis/1f1e9-1f1ea.png"
  }
  option {
    name  = "India (Bangalore)"
    value = "blr1"
    icon  = "/emojis/1f1ee-1f1f3.png"
  }
  option {
    name  = "Netherlands (Amsterdam)"
    value = "ams3"
    icon  = "/emojis/1f1f3-1f1f1.png"
  }
  option {
    name  = "Singapore"
    value = "sgp1"
    icon  = "/emojis/1f1f8-1f1ec.png"
  }
  option {
    name  = "United Kingdom (London)"
    value = "lon1"
    icon  = "/emojis/1f1ec-1f1e7.png"
  }
  option {
    name  = "United States (California - 2)"
    value = "sfo2"
    icon  = "/emojis/1f1fa-1f1f8.png"
  }
  option {
    name  = "United States (California - 3)"
    value = "sfo3"
    icon  = "/emojis/1f1fa-1f1f8.png"
  }
  option {
    name  = "United States (New York - 1)"
    value = "nyc1"
    icon  = "/emojis/1f1fa-1f1f8.png"
  }
  option {
    name  = "United States (New York - 3)"
    value = "nyc3"
    icon  = "/emojis/1f1fa-1f1f8.png"
  }
}

# Configure the DigitalOcean Provider
provider "digitalocean" {
  # Recommended: use environment variable DIGITALOCEAN_TOKEN with your personal access token when starting coderd
  # alternatively, you can pass the token via a variable.
}

data "coder_workspace" "me" {}

resource "coder_agent" "main" {
  os   = "linux"
  arch = "amd64"

  metadata {
    key          = "cpu"
    display_name = "CPU Usage"
    interval     = 5
    timeout      = 5
    script       = "coder stat cpu"
  }
  metadata {
    key          = "memory"
    display_name = "Memory Usage"
    interval     = 5
    timeout      = 5
    script       = "coder stat mem"
  }
  metadata {
    key          = "home"
    display_name = "Home Usage"
    interval     = 600 # every 10 minutes
    timeout      = 30  # df can take a while on large filesystems
    script       = "coder stat disk --path /home/${lower(data.coder_workspace.me.owner)}"
  }
}

resource "digitalocean_volume" "home_volume" {
  region                   = data.coder_parameter.region.value
  name                     = "coder-${data.coder_workspace.me.id}-home"
  size                     = data.coder_parameter.home_volume_size.value
  initial_filesystem_type  = "ext4"
  initial_filesystem_label = "coder-home"
  # Protect the volume from being deleted due to changes in attributes.
  lifecycle {
    ignore_changes = all
  }
}

resource "digitalocean_droplet" "workspace" {
  region = data.coder_parameter.region.value
  count  = data.coder_workspace.me.start_count
  name   = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
  image  = data.coder_parameter.droplet_image.value
  size   = data.coder_parameter.droplet_size.value

  volume_ids = [digitalocean_volume.home_volume.id]
  user_data = templatefile("cloud-config.yaml.tftpl", {
    username          = lower(data.coder_workspace.me.owner)
    home_volume_label = digitalocean_volume.home_volume.initial_filesystem_label
    init_script       = base64encode(coder_agent.main.init_script)
    coder_agent_token = coder_agent.main.token
  })
  # Required to provision Fedora.
  ssh_keys = var.step2_do_admin_ssh_key > 0 ? [var.step2_do_admin_ssh_key] : []
}

resource "digitalocean_project_resources" "project" {
  project = var.step1_do_project_id
  # Workaround for terraform plan when using count.
  resources = length(digitalocean_droplet.workspace) > 0 ? [
    digitalocean_volume.home_volume.urn,
    digitalocean_droplet.workspace[0].urn
    ] : [
    digitalocean_volume.home_volume.urn
  ]
}

resource "coder_metadata" "workspace-info" {
  count       = data.coder_workspace.me.start_count
  resource_id = digitalocean_droplet.workspace[0].id

  item {
    key   = "region"
    value = digitalocean_droplet.workspace[0].region
  }
  item {
    key   = "image"
    value = digitalocean_droplet.workspace[0].image
  }
}

resource "coder_metadata" "volume-info" {
  resource_id = digitalocean_volume.home_volume.id

  item {
    key   = "size"
    value = "${digitalocean_volume.home_volume.size} GiB"
  }
}
