Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

105 changes: 73 additions & 32 deletions registry/Excellencedev/templates/hetzner-linux/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ terraform {
coder = {
source = "coder/coder"
}
http = {
source = "hashicorp/http"
version = "~> 3.0"
}
}
}

Expand All @@ -17,36 +21,42 @@ provider "hcloud" {
token = var.hcloud_token
}

data "http" "hcloud_locations" {
url = "https://api.hetzner.cloud/v1/locations"

request_headers = {
Authorization = "Bearer ${var.hcloud_token}"
Accept = "application/json"
}
}

data "http" "hcloud_server_types" {
url = "https://api.hetzner.cloud/v1/server_types"

request_headers = {
Authorization = "Bearer ${var.hcloud_token}"
Accept = "application/json"
}
}
Comment on lines +24 to +40
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTTP data sources will be fetched during every Terraform plan/apply operation, which could lead to performance issues and potential API rate limiting. Consider the following:

  1. These API calls execute during the plan phase, adding latency to workspace operations
  2. Frequent workspace operations could trigger Hetzner API rate limits
  3. Network failures would block workspace provisioning

Consider documenting this behavior and potential limitations, or explore caching mechanisms if supported by the Coder platform.

Copilot uses AI. Check for mistakes.

# Available locations: https://docs.hetzner.com/cloud/general/locations/
data "coder_parameter" "hcloud_location" {
name = "hcloud_location"
display_name = "Hetzner Location"
description = "Select the Hetzner Cloud location for your workspace."
type = "string"
default = "fsn1"
option {
name = "DE Falkenstein"
value = "fsn1"
}
option {
name = "US Ashburn, VA"
value = "ash"
}
option {
name = "US Hillsboro, OR"
value = "hil"
}
option {
name = "SG Singapore"
value = "sin"
}
option {
name = "DE Nuremberg"
value = "nbg1"
}
option {
name = "FI Helsinki"
value = "hel1"

dynamic "option" {
for_each = local.hcloud_locations
content {
name = format(
"%s (%s, %s)",
upper(option.value.name),
option.value.city,
option.value.country
)
value = option.value.name
}
}
}
Comment on lines 43 to 61
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The location parameter now lacks a default value, which was previously set to "fsn1". Without a default, users will be required to select a location explicitly when creating a workspace. Consider adding a default value to improve the user experience. You could either:

  1. Set a static default value (e.g., default = "fsn1")
  2. Use the first available location from the API response dynamically

Copilot uses AI. Check for mistakes.

Expand Down Expand Up @@ -109,17 +119,48 @@ resource "hcloud_volume_attachment" "home_volume_attachment" {
locals {
username = lower(data.coder_workspace_owner.me.name)

# Data source: local JSON file under the module directory
# Check API for latest server types & availability: https://docs.hetzner.cloud/reference/cloud#server-types
hcloud_server_types_data = jsondecode(file("${path.module}/hetzner_server_types.json"))
hcloud_server_type_meta = local.hcloud_server_types_data.type_meta
hcloud_server_types_by_location = local.hcloud_server_types_data.availability
# --------------------
# Locations
# --------------------
hcloud_locations = [
for loc in jsondecode(data.http.hcloud_locations.response_body).locations : {
name = loc.name
city = loc.city
country = loc.country
description = loc.description
Comment on lines +127 to +130
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The locations data transformation extracts a 'description' field that is never used. The description field is captured in the local variable but not utilized in the dynamic options or elsewhere in the configuration. Consider removing this unused field to keep the code clean and focused, or document its purpose if it's intended for future use.

Suggested change
name = loc.name
city = loc.city
country = loc.country
description = loc.description
name = loc.name
city = loc.city
country = loc.country

Copilot uses AI. Check for mistakes.
}
]
Comment on lines +125 to +132
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The jsondecode() operations on API responses lack error handling. If the API returns an error response (e.g., due to invalid token, rate limiting, or network issues), the jsondecode will fail with an unhelpful error message. Consider adding validation or try-catch logic to provide clearer error messages, or at minimum add comments documenting the expected response structure for troubleshooting purposes.

Copilot uses AI. Check for mistakes.

# --------------------
# Server Types
# --------------------
hcloud_server_types = {
for st in jsondecode(data.http.hcloud_server_types.response_body).server_types :
st.name => {
cores = st.cores
memory_gb = st.memory
disk_gb = st.disk
locations = [for l in st.locations : l.name]
deprecated = st.deprecated
}
if st.deprecated == false
}

hcloud_server_type_options_for_selected_location = [
for type_name in lookup(local.hcloud_server_types_by_location, data.coder_parameter.hcloud_location.value, []) : {
name = format("%s (%d vCPU, %dGB RAM, %dGB)", upper(type_name), local.hcloud_server_type_meta[type_name].cores, local.hcloud_server_type_meta[type_name].memory_gb, local.hcloud_server_type_meta[type_name].disk_gb)
value = type_name
for name, meta in local.hcloud_server_types : {
name = format(
"%s (%d vCPU, %dGB RAM, %dGB)",
upper(name),
meta.cores,
meta.memory_gb,
meta.disk_gb
)
value = name
}
if contains(
meta.locations,
data.coder_parameter.hcloud_location.value
)
]
}

Expand Down