Skip to content
87 changes: 87 additions & 0 deletions registry/umair/modules/digitalocean-region/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
display_name: DigitalOcean Region
description: A parameter with human region names and icons
icon: ../../../../.icons/digital-ocean.svg
verified: true
tags: [helper, parameter, digitalocean, regions]
---

# DigitalOcean Region

This module adds DigitalOcean regions to your Coder template with automatic GPU filtering. You can customize display names and icons using the `custom_names` and `custom_icons` arguments.

The simplest usage is:

```tf
module "digitalocean-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/digitalocean-region/coder"
version = "1.0.0"
default = "ams3"
}
```

## Examples

### Basic usage

```tf
module "digitalocean-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/digitalocean-region/coder"
version = "1.0.0"
}
```

### With custom configuration

```tf
module "digitalocean-region" {
count = data.coder_workspace.me.start_count
source = "registry.coder.com/coder/digitalocean-region/coder"
version = "1.0.0"
default = "ams3"
mutable = true

custom_icons = {
"ams3" = "/emojis/1f1f3-1f1f1.png"
}

custom_names = {
"ams3" = "Europe - Amsterdam (Primary)"
}
}
```

### GPU-only toggle (internal parameter)

This module automatically exposes a "GPU-only regions" checkbox in the template UI. When checked, it shows only GPU-capable regions and auto-selects the first one. When unchecked, it shows all available regions.

## Available Regions

Refer to DigitalOcean’s official availability matrix for the most up-to-date information.

- GPU availability: currently only in `nyc2` and `tor1` (per DO docs). Others are non-GPU.
- See: https://docs.digitalocean.com/platform/regional-availability/

### All datacenters (GPU status)

- `nyc2` - New York, United States (Legacy) - **GPU available**
- `tor1` - Toronto, Canada - **GPU available**
- `nyc3` - New York, United States
- `ams3` - Amsterdam, Netherlands
- `sfo3` - San Francisco, United States
- `sgp1` - Singapore
- `lon1` - London, United Kingdom
- `fra1` - Frankfurt, Germany
- `blr1` - Bangalore, India
- `syd1` - Sydney, Australia
- `atl1` - Atlanta, United States
- `nyc1` - New York, United States (Legacy)
- `sfo2` - San Francisco, United States (Legacy)
- `sfo1` - San Francisco, United States (Legacy)
- `ams2` - Amsterdam, Netherlands (Legacy)

## Associated template

Also see the Coder template registry for a [DigitalOcean Droplet template](https://registry.coder.com/templates/digitalocean-droplet) that provisions workspaces as DigitalOcean Droplets.
46 changes: 46 additions & 0 deletions registry/umair/modules/digitalocean-region/main.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, expect, it } from "bun:test";
import {
runTerraformApply,
runTerraformInit,
testRequiredVariables,
} from "~test";

describe("digitalocean-region", async () => {
await runTerraformInit(import.meta.dir);

testRequiredVariables(import.meta.dir, {});


it("default output", async () => {
const state = await runTerraformApply(import.meta.dir, {});
expect(state.outputs.value.value).toBe("ams2");
});

it("customized default", async () => {
const state = await runTerraformApply(import.meta.dir, {
regions: '["nyc1","ams3"]',
default: "ams3",
});
expect(state.outputs.value.value).toBe("ams3");
});

it("gpu only invalid default", async () => {
const state = await runTerraformApply(import.meta.dir, {
regions: '["nyc1"]',
default: "nyc1",
gpu_only: "true",
});
expect(state.outputs.value.value).toBe("nyc1");
});

it("gpu only valid default", async () => {
const state = await runTerraformApply(import.meta.dir, {
regions: '["tor1"]',
default: "tor1",
gpu_only: "true",
});
expect(state.outputs.value.value).toBe("tor1");
});

// Add more tests as needed for coder_parameter_order or other features
});
187 changes: 187 additions & 0 deletions registry/umair/modules/digitalocean-region/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
terraform {
required_version = ">= 1.0"

required_providers {
coder = {
source = "coder/coder"
version = ">= 0.11"
}
}
}

variable "display_name" {
default = "DigitalOcean Region"
description = "The display name of the parameter."
type = string
}

variable "description" {
default = "The region to deploy workspace infrastructure."
description = "The description of the parameter."
type = string
}

variable "default" {
default = null
description = "Default region"
type = string
}



variable "mutable" {
default = false
description = "Whether the parameter can be changed after creation."
type = bool
}

variable "custom_names" {
default = {}
description = "A map of custom display names for region IDs."
type = map(string)
}

variable "custom_icons" {
default = {}
description = "A map of custom icons for region IDs."
type = map(string)
}

variable "single_zone_per_region" {
default = true
description = "Whether to only include a single zone per region."
type = bool
}

variable "coder_parameter_order" {
type = number
description = "The order determines the position of a template parameter in the UI/CLI presentation. The lowest order is shown first and parameters with equal order are sorted by name (ascending order)."
default = null
}

data "coder_parameter" "gpu_only" {
name = "digitalocean_gpu_only"
display_name = "GPU-only regions"
description = "Show only regions with GPUs"
type = "bool"
form_type = "checkbox"
default = false
mutable = var.mutable
order = var.coder_parameter_order
}

locals {
zones = {
# Active datacenters (recommended for new workloads)
"nyc1" = {
gpu = false
name = "New York City, USA (NYC1)"
icon = "/emojis/1f1fa-1f1f8.png"
}
"nyc3" = {
gpu = false
name = "New York City, USA (NYC3)"
icon = "/emojis/1f1fa-1f1f8.png"
}
"ams3" = {
gpu = false
name = "Amsterdam, Netherlands"
icon = "/emojis/1f1f3-1f1f1.png"
}
"sfo3" = {
gpu = false
name = "San Francisco, USA"
icon = "/emojis/1f1fa-1f1f8.png"
}
"sgp1" = {
gpu = false
name = "Singapore"
icon = "/emojis/1f1f8-1f1ec.png"
}
"lon1" = {
gpu = false
name = "London, United Kingdom"
icon = "/emojis/1f1ec-1f1e7.png"
}
"fra1" = {
gpu = false
name = "Frankfurt, Germany"
icon = "/emojis/1f1e9-1f1ea.png"
}
"tor1" = {
gpu = true
name = "Toronto, Canada"
icon = "/emojis/1f1e8-1f1e6.png"
}
"blr1" = {
gpu = false
name = "Bangalore, India"
icon = "/emojis/1f1ee-1f1f3.png"
}
"syd1" = {
gpu = false
name = "Sydney, Australia"
icon = "/emojis/1f1e6-1f1fa.png"
}
"atl1" = {
gpu = false
name = "Atlanta, USA"
icon = "/emojis/1f1fa-1f1f8.png"
}
# Legacy/Restricted datacenters (not recommended for new workloads)
"nyc2" = {
gpu = true # GPU available but restricted to existing users
name = "New York City, USA (Legacy)"
icon = "/emojis/1f1fa-1f1f8.png"
}
"sfo2" = {
gpu = false # No GPU available per current regional availability
name = "San Francisco, USA (Legacy SFO2)"
icon = "/emojis/1f1fa-1f1f8.png"
}
"sfo1" = {
gpu = false # No GPU in legacy datacenter
name = "San Francisco, USA (Legacy SFO1)"
icon = "/emojis/1f1fa-1f1f8.png"
}
"ams2" = {
gpu = false # No GPU in legacy datacenter
name = "Amsterdam, Netherlands (Legacy)"
icon = "/emojis/1f1f3-1f1f1.png"
}
}
}

locals {
allowed_regions = data.coder_parameter.gpu_only.value ? [for k, v in local.zones : k if v.gpu] : keys(local.zones)
default_region = data.coder_parameter.gpu_only.value ? (length([for k, v in local.zones : k if v.gpu]) > 0 ? [for k, v in local.zones : k if v.gpu][0] : null) : (var.default != null && var.default != "" ? var.default : keys(local.zones)[0])
}

data "coder_parameter" "region" {
name = "digitalocean_region"
display_name = var.display_name
description = var.description
icon = "/icon/digital-ocean.svg"
mutable = var.mutable
form_type = "radio"
default = local.default_region
order = var.coder_parameter_order
dynamic "option" {
for_each = {
for k, v in local.zones : k => v
if contains(local.allowed_regions, k)
}
content {
icon = try(var.custom_icons[option.key], option.value.icon)
name = try(var.custom_names[option.key], option.value.name)
description = option.key
value = option.key
}
}


}
output "value" {
description = "DigitalOcean region identifier."
value = data.coder_parameter.region.value
}
Loading