feat: add digitalocean region module (#355)
Co-authored-by: Atif Ali <atif@coder.com>
This commit is contained in:
parent
7e53098bea
commit
c4c484089f
87
registry/umair/modules/digitalocean-region/README.md
Normal file
87
registry/umair/modules/digitalocean-region/README.md
Normal file
@ -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.
|
||||
45
registry/umair/modules/digitalocean-region/main.test.ts
Normal file
45
registry/umair/modules/digitalocean-region/main.test.ts
Normal file
@ -0,0 +1,45 @@
|
||||
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
registry/umair/modules/digitalocean-region/main.tf
Normal file
187
registry/umair/modules/digitalocean-region/main.tf
Normal file
@ -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…
x
Reference in New Issue
Block a user