diff --git a/.icons/exoscale.svg b/.icons/exoscale.svg
new file mode 100644
index 0000000..c56a615
--- /dev/null
+++ b/.icons/exoscale.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/.images/exoscale-custom.png b/.images/exoscale-custom.png
new file mode 100644
index 0000000..3646c8c
Binary files /dev/null and b/.images/exoscale-custom.png differ
diff --git a/.images/exoscale-exclude.png b/.images/exoscale-exclude.png
new file mode 100644
index 0000000..40683c1
Binary files /dev/null and b/.images/exoscale-exclude.png differ
diff --git a/.images/exoscale-instance-custom.png b/.images/exoscale-instance-custom.png
new file mode 100644
index 0000000..04373e3
Binary files /dev/null and b/.images/exoscale-instance-custom.png differ
diff --git a/.images/exoscale-instance-exclude.png b/.images/exoscale-instance-exclude.png
new file mode 100644
index 0000000..1261b24
Binary files /dev/null and b/.images/exoscale-instance-exclude.png differ
diff --git a/.images/exoscale-instance-types.png b/.images/exoscale-instance-types.png
new file mode 100644
index 0000000..9158830
Binary files /dev/null and b/.images/exoscale-instance-types.png differ
diff --git a/.images/exoscale-zones.png b/.images/exoscale-zones.png
new file mode 100644
index 0000000..b78cd01
Binary files /dev/null and b/.images/exoscale-zones.png differ
diff --git a/code-server/README.md b/code-server/README.md
index 302a1ea..ca076df 100644
--- a/code-server/README.md
+++ b/code-server/README.md
@@ -63,6 +63,18 @@ module "settings" {
}
```
+### Install multiple extensions
+
+Just run code-server in the background, don't fetch it from GitHub:
+
+```hcl
+module "settings" {
+ source = "https://registry.coder.com/modules/code-server"
+ agent_id = coder_agent.example.id
+ extensions = [ "dracula-theme.theme-dracula", "ms-azuretools.vscode-docker" ]
+}
+```
+
### Offline Mode
Just run code-server in the background, don't fetch it from GitHub:
diff --git a/code-server/main.tf b/code-server/main.tf
index 837f0db..86afdd0 100644
--- a/code-server/main.tf
+++ b/code-server/main.tf
@@ -62,6 +62,15 @@ variable "install_version" {
default = ""
}
+variable "share" {
+ type = string
+ default = "owner"
+ validation {
+ condition = var.share == "owner" || var.share == "authenticated" || var.share == "public"
+ error_message = "Incorrect value. Please set either 'owner', 'authenticated', or 'public'."
+ }
+}
+
resource "coder_script" "code-server" {
agent_id = var.agent_id
display_name = "code-server"
@@ -85,7 +94,7 @@ resource "coder_app" "code-server" {
url = "http://localhost:${var.port}/${var.folder != "" ? "?folder=${urlencode(var.folder)}" : ""}"
icon = "/icon/code.svg"
subdomain = false
- share = "owner"
+ share = var.share
healthcheck {
url = "http://localhost:${var.port}/healthz"
diff --git a/code-server/run.sh b/code-server/run.sh
index 6676aaa..552ced1 100755
--- a/code-server/run.sh
+++ b/code-server/run.sh
@@ -25,7 +25,8 @@ printf "🥳 code-server has been installed in ${INSTALL_PREFIX}\n\n"
CODE_SERVER="${INSTALL_PREFIX}/bin/code-server"
# Install each extension...
-for extension in "$${EXTENSIONS[@]}"; do
+IFS=',' read -r -a EXTENSIONLIST <<< "$${EXTENSIONS}"
+for extension in "$${EXTENSIONLIST[@]}"; do
if [ -z "$extension" ]; then
continue
fi
@@ -46,4 +47,4 @@ fi
echo "👷 Running code-server in the background..."
echo "Check logs at ${LOG_PATH}!"
-$CODE_SERVER --auth none --port ${PORT} >${LOG_PATH} 2>&1 &
+$CODE_SERVER --auth none --port ${PORT} >${LOG_PATH} 2>&1 &
\ No newline at end of file
diff --git a/exoscale-instance-type/README.md b/exoscale-instance-type/README.md
new file mode 100644
index 0000000..e1031e4
--- /dev/null
+++ b/exoscale-instance-type/README.md
@@ -0,0 +1,109 @@
+---
+display_name: exoscale-instance-type
+description: A parameter with human readable exoscale instance names
+icon: ../.icons/exoscale.svg
+maintainer_github: WhizUs
+verified: false
+tags: [helper, parameter, instances, exoscale]
+---
+
+# exoscale-instance-type
+
+A parameter with all Exoscale instance types. This allows developers to select
+their desired virtuell machine for the workspace.
+
+Customize the preselected parameter value:
+
+```hcl
+module "exoscale-instance-type" {
+ source = "https://registry.coder.com/modules/exoscale-instance-type"
+ default = "standard.medium"
+}
+
+resource "exoscale_compute_instance" "instance" {
+ type = module.exoscale-instance-type.value
+ ...
+}
+
+resource "coder_metadata" "workspace_info" {
+ item {
+ key = "instance type"
+ value = module.exoscale-instance-type.name
+ }
+}
+```
+
+
+
+## Examples
+
+### Customize type
+
+Change the display name a type using the corresponding maps:
+
+```hcl
+module "exoscale-instance-type" {
+ source = "https://registry.coder.com/modules/exoscale-instance-type"
+ default = "standard.medium"
+ custom_names = {
+ "standard.medium": "Mittlere Instanz" # German translation
+ }
+ custom_descriptions = {
+ "standard.medium": "4 GB Arbeitsspeicher, 2 Kerne, 10 - 400 GB Festplatte" # German translation
+ }
+}
+
+resource "exoscale_compute_instance" "instance" {
+ type = module.exoscale-instance-type.value
+ ...
+}
+
+resource "coder_metadata" "workspace_info" {
+ item {
+ key = "instance type"
+ value = module.exoscale-instance-type.name
+ }
+}
+```
+
+
+
+### Use category and exlude type
+
+Show only gpu1 types
+
+```hcl
+module "exoscale-instance-type" {
+ source = "https://registry.coder.com/modules/exoscale-instance-type"
+ default = "gpu.large"
+ type_category = ["gpu"]
+ exclude = [
+ "gpu2.small",
+ "gpu2.medium",
+ "gpu2.large",
+ "gpu2.huge",
+ "gpu3.small",
+ "gpu3.medium",
+ "gpu3.large",
+ "gpu3.huge"
+ ]
+}
+
+resource "exoscale_compute_instance" "instance" {
+ type = module.exoscale-instance-type.value
+ ...
+}
+
+resource "coder_metadata" "workspace_info" {
+ item {
+ key = "instance type"
+ value = module.exoscale-instance-type.name
+ }
+}
+```
+
+
+
+## Related templates
+
+A related exoscale template will be provided soon.
diff --git a/exoscale-instance-type/main.test.ts b/exoscale-instance-type/main.test.ts
new file mode 100644
index 0000000..eeb6745
--- /dev/null
+++ b/exoscale-instance-type/main.test.ts
@@ -0,0 +1,34 @@
+import { describe, expect, it } from "bun:test";
+import {
+ runTerraformApply,
+ runTerraformInit,
+ testRequiredVariables,
+} from "../test";
+
+describe("exoscale-instance-type", 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("");
+ });
+
+ it("customized default", async () => {
+ const state = await runTerraformApply(import.meta.dir, {
+ default: "gpu3.huge",
+ type_category: `["gpu", "cpu"]`,
+ });
+ expect(state.outputs.value.value).toBe("gpu3.huge");
+ });
+
+ it("fails because of wrong categroy definition", async () => {
+ expect(async () => {
+ await runTerraformApply(import.meta.dir, {
+ default: "gpu3.huge",
+ // type_category: ["standard"] is standard
+ });
+ }).toThrow('default value "gpu3.huge" must be defined as one of options');
+ });
+});
diff --git a/exoscale-instance-type/main.tf b/exoscale-instance-type/main.tf
new file mode 100644
index 0000000..f7c8998
--- /dev/null
+++ b/exoscale-instance-type/main.tf
@@ -0,0 +1,279 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ coder = {
+ source = "coder/coder"
+ version = ">= 0.12"
+ }
+ }
+}
+
+variable "display_name" {
+ default = "Exoscale instance type"
+ description = "The display name of the parameter."
+ type = string
+}
+
+variable "description" {
+ default = "Select the exoscale instance type to use for the workspace. Check out the pricing page for more information: https://www.exoscale.com/pricing"
+ description = "The description of the parameter."
+ type = string
+}
+
+variable "default" {
+ default = ""
+ description = "The default instance type to use if no type is specified. One of [\"standard.micro\", \"standard.tiny\", \"standard.small\", \"standard.medium\", \"standard.large\", \"standard.extra\", \"standard.huge\", \"standard.mega\", \"standard.titan\", \"standard.jumbo\", \"standard.colossus\", \"cpu.extra\", \"cpu.huge\", \"cpu.mega\", \"cpu.titan\", \"memory.extra\", \"memory.huge\", \"memory.mega\", \"memory.titan\", \"storage.extra\", \"storage.huge\", \"storage.mega\", \"storage.titan\", \"storage.jumbo\", \"gpu.small\", \"gpu.medium\", \"gpu.large\", \"gpu.huge\", \"gpu2.small\", \"gpu2.medium\", \"gpu2.large\", \"gpu2.huge\", \"gpu3.small\", \"gpu3.medium\", \"gpu3.large\", \"gpu3.huge\"]"
+ 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 instance type IDs."
+ type = map(string)
+}
+variable "custom_descriptions" {
+ default = {}
+ description = "A map of custom descriptions for instance type IDs."
+ type = map(string)
+}
+
+variable "type_category" {
+ default = ["standard"]
+ description = "A list of instance type categories the user is allowed to choose. One of [\"standard\", \"cpu\", \"memory\", \"storage\", \"gpu\"]"
+ type = list(string)
+}
+
+variable "exclude" {
+ default = []
+ description = "A list of instance type IDs to exclude. One of [\"standard.micro\", \"standard.tiny\", \"standard.small\", \"standard.medium\", \"standard.large\", \"standard.extra\", \"standard.huge\", \"standard.mega\", \"standard.titan\", \"standard.jumbo\", \"standard.colossus\", \"cpu.extra\", \"cpu.huge\", \"cpu.mega\", \"cpu.titan\", \"memory.extra\", \"memory.huge\", \"memory.mega\", \"memory.titan\", \"storage.extra\", \"storage.huge\", \"storage.mega\", \"storage.titan\", \"storage.jumbo\", \"gpu.small\", \"gpu.medium\", \"gpu.large\", \"gpu.huge\", \"gpu2.small\", \"gpu2.medium\", \"gpu2.large\", \"gpu2.huge\", \"gpu3.small\", \"gpu3.medium\", \"gpu3.large\", \"gpu3.huge\"]"
+ type = list(string)
+}
+
+locals {
+ # https://www.exoscale.com/pricing/
+
+ standard_instances = [
+ {
+ value = "standard.micro",
+ name = "Standard Micro",
+ description = "512 MB RAM, 1 Core, 10 - 200 GB Disk"
+ },
+ {
+ value = "standard.tiny",
+ name = "Standard Tiny",
+ description = "1 GB RAM, 1 Core, 10 - 400 GB Disk"
+ },
+ {
+ value = "standard.small",
+ name = "Standard Small",
+ description = "2 GB RAM, 2 Cores, 10 - 400 GB Disk"
+ },
+ {
+ value = "standard.medium",
+ name = "Standard Medium",
+ description = "4 GB RAM, 2 Cores, 10 - 400 GB Disk"
+ },
+ {
+ value = "standard.large",
+ name = "Standard Large",
+ description = "8 GB RAM, 4 Cores, 10 - 400 GB Disk"
+ },
+ {
+ value = "standard.extra",
+ name = "Standard Extra",
+ description = "rge",
+ description = "16 GB RAM, 4 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "standard.huge",
+ name = "Standard Huge",
+ description = "32 GB RAM, 8 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "standard.mega",
+ name = "Standard Mega",
+ description = "64 GB RAM, 12 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "standard.titan",
+ name = "Standard Titan",
+ description = "128 GB RAM, 16 Cores, 10 - 1.6 TB Disk"
+ },
+ {
+ value = "standard.jumbo",
+ name = "Standard Jumbo",
+ description = "256 GB RAM, 24 Cores, 10 - 1.6 TB Disk"
+ },
+ {
+ value = "standard.colossus",
+ name = "Standard Colossus",
+ description = "320 GB RAM, 40 Cores, 10 - 1.6 TB Disk"
+ }
+ ]
+ cpu_instances = [
+ {
+ value = "cpu.extra",
+ name = "CPU Extra-Large",
+ description = "16 GB RAM, 8 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "cpu.huge",
+ name = "CPU Huge",
+ description = "32 GB RAM, 16 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "cpu.mega",
+ name = "CPU Mega",
+ description = "64 GB RAM, 32 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "cpu.titan",
+ name = "CPU Titan",
+ description = "128 GB RAM, 40 Cores, 0.1 - 1.6 TB Disk"
+ }
+ ]
+ memory_instances = [
+ {
+ value = "memory.extra",
+ name = "Memory Extra-Large",
+ description = "16 GB RAM, 2 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "memory.huge",
+ name = "Memory Huge",
+ description = "32 GB RAM, 4 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "memory.mega",
+ name = "Memory Mega",
+ description = "64 GB RAM, 8 Cores, 10 - 800 GB Disk"
+ },
+ {
+ value = "memory.titan",
+ name = "Memory Titan",
+ description = "128 GB RAM, 12 Cores, 0.1 - 1.6 TB Disk"
+ }
+ ]
+ storage_instances = [
+ {
+ value = "storage.extra",
+ name = "Storage Extra-Large",
+ description = "16 GB RAM, 4 Cores, 1 - 2 TB Disk"
+ },
+ {
+ value = "storage.huge",
+ name = "Storage Huge",
+ description = "32 GB RAM, 8 Cores, 2 - 3 TB Disk"
+ },
+ {
+ value = "storage.mega",
+ name = "Storage Mega",
+ description = "64 GB RAM, 12 Cores, 3 - 5 TB Disk"
+ },
+ {
+ value = "storage.titan",
+ name = "Storage Titan",
+ description = "128 GB RAM, 16 Cores, 5 - 10 TB Disk"
+ },
+ {
+ value = "storage.jumbo",
+ name = "Storage Jumbo",
+ description = "225 GB RAM, 24 Cores, 10 - 15 TB Disk"
+ }
+ ]
+ gpu_instances = [
+ {
+ value = "gpu.small",
+ name = "GPU1 Small",
+ description = "56 GB RAM, 12 Cores, 1 GPU, 100 - 800 GB Disk"
+ },
+ {
+ value = "gpu.medium",
+ name = "GPU1 Medium",
+ description = "90 GB RAM, 16 Cores, 2 GPU, 0.1 - 1.2 TB Disk"
+ },
+ {
+ value = "gpu.large",
+ name = "GPU1 Large",
+ description = "120 GB RAM, 24 Cores, 3 GPU, 0.1 - 1.6 TB Disk"
+ },
+ {
+ value = "gpu.huge",
+ name = "GPU1 Huge",
+ description = "225 GB RAM, 48 Cores, 4 GPU, 0.1 - 1.6 TB Disk"
+ },
+ {
+ value = "gpu2.small",
+ name = "GPU2 Small",
+ description = "56 GB RAM, 12 Cores, 1 GPU, 100 - 800 GB Disk"
+ },
+ {
+ value = "gpu2.medium",
+ name = "GPU2 Medium",
+ description = "90 GB RAM, 16 Cores, 2 GPU, 0.1 - 1.2 TB Disk"
+ },
+ {
+ value = "gpu2.large",
+ name = "GPU2 Large",
+ description = "120 GB RAM, 24 Cores, 3 GPU, 0.1 - 1.6 TB Disk"
+ },
+ {
+ value = "gpu2.huge",
+ name = "GPU2 Huge",
+ description = "225 GB RAM, 48 Cores, 4 GPU, 0.1 - 1.6 TB Disk"
+ },
+ {
+ value = "gpu3.small",
+ name = "GPU3 Small",
+ description = "56 GB RAM, 12 Cores, 1 GPU, 100 - 800 GB Disk"
+ },
+ {
+ value = "gpu3.medium",
+ name = "GPU3 Medium",
+ description = "120 GB RAM, 24 Cores, 2 GPU, 0.1 - 1.2 TB Disk"
+ },
+ {
+ value = "gpu3.large",
+ name = "GPU3 Large",
+ description = "224 GB RAM, 48 Cores, 4 GPU, 0.1 - 1.6 TB Disk"
+ },
+ {
+ value = "gpu3.huge",
+ name = "GPU3 Huge",
+ description = "448 GB RAM, 96 Cores, 8 GPU, 0.1 - 1.6 TB Disk"
+ }
+ ]
+}
+
+data "coder_parameter" "instance_type" {
+ name = "exoscale_instance_type"
+ display_name = var.display_name
+ description = var.description
+ default = var.default == "" ? null : var.default
+ mutable = var.mutable
+ dynamic "option" {
+ for_each = [for k, v in concat(
+ contains(var.type_category, "standard") ? local.standard_instances : [],
+ contains(var.type_category, "cpu") ? local.cpu_instances : [],
+ contains(var.type_category, "memory") ? local.memory_instances : [],
+ contains(var.type_category, "storage") ? local.storage_instances : [],
+ contains(var.type_category, "gpu") ? local.gpu_instances : []
+ ) : v if !(contains(var.exclude, v.value))]
+ content {
+ name = try(var.custom_names[option.value.value], option.value.name)
+ description = try(var.custom_descriptions[option.value.value], option.value.description)
+ value = option.value.value
+ }
+ }
+}
+
+output "value" {
+ value = data.coder_parameter.instance_type.value
+}
diff --git a/exoscale-zone/README.md b/exoscale-zone/README.md
new file mode 100644
index 0000000..91097c8
--- /dev/null
+++ b/exoscale-zone/README.md
@@ -0,0 +1,93 @@
+---
+display_name: exoscale-zone
+description: A parameter with human zone names and icons
+icon: ../.icons/exoscale.svg
+maintainer_github: WhizUs
+verified: false
+tags: [helper, parameter, zones, regions, exoscale]
+---
+
+# exoscale-zone
+
+A parameter with all Exoscale zones. This allows developers to select
+the zone closest to them.
+
+Customize the preselected parameter value:
+
+```hcl
+module "exoscale-zone" {
+ source = "https://registry.coder.com/modules/exoscale-zone"
+ default = "ch-dk-2"
+}
+
+
+data "exoscale_compute_template" "my_template" {
+ zone = module.exoscale-zone.value
+ name = "Linux Ubuntu 22.04 LTS 64-bit"
+}
+
+resource "exoscale_compute_instance" "instance" {
+ zone = module.exoscale-zone.value
+ ....
+}
+```
+
+
+
+## Examples
+
+### Customize zones
+
+Change the display name and icon for a zone using the corresponding maps:
+
+```hcl
+module "exoscale-zone" {
+ source = "https://registry.coder.com/modules/exoscale-zone"
+ default = "at-vie-1"
+ custom_names = {
+ "at-vie-1": "Home Vienna"
+ }
+ custom_icons = {
+ "at-vie-1": "/emojis/1f3e0.png"
+ }
+}
+
+data "exoscale_compute_template" "my_template" {
+ zone = module.exoscale-zone.value
+ name = "Linux Ubuntu 22.04 LTS 64-bit"
+}
+
+resource "exoscale_compute_instance" "instance" {
+ zone = module.exoscale-zone.value
+ ....
+}
+```
+
+
+
+### Exclude regions
+
+Hide the Switzerland zones Geneva and Zurich
+
+```hcl
+module "exoscale-zone" {
+ source = "https://registry.coder.com/modules/exoscale-zone"
+ exclude = [ "ch-gva-2", "ch-dk-2" ]
+}
+
+data "exoscale_compute_template" "my_template" {
+ zone = module.exoscale-zone.value
+ name = "Linux Ubuntu 22.04 LTS 64-bit"
+}
+
+resource "exoscale_compute_instance" "instance" {
+ zone = module.exoscale-zone.value
+ ....
+}
+```
+
+
+
+## Related templates
+
+An exoscale sample template will be delivered soon.
diff --git a/exoscale-zone/main.test.ts b/exoscale-zone/main.test.ts
new file mode 100644
index 0000000..7c423e7
--- /dev/null
+++ b/exoscale-zone/main.test.ts
@@ -0,0 +1,25 @@
+import { describe, expect, it } from "bun:test";
+import {
+ executeScriptInContainer,
+ runTerraformApply,
+ runTerraformInit,
+ testRequiredVariables,
+} from "../test";
+
+describe("exoscale-zone", 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("");
+ });
+
+ it("customized default", async () => {
+ const state = await runTerraformApply(import.meta.dir, {
+ default: "at-vie-1",
+ });
+ expect(state.outputs.value.value).toBe("at-vie-1");
+ });
+});
diff --git a/exoscale-zone/main.tf b/exoscale-zone/main.tf
new file mode 100644
index 0000000..01f1467
--- /dev/null
+++ b/exoscale-zone/main.tf
@@ -0,0 +1,110 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ coder = {
+ source = "coder/coder"
+ version = ">= 0.12"
+ }
+ }
+}
+
+variable "display_name" {
+ default = "Exoscale 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 = ""
+ description = "The default region to use if no region is specified."
+ 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 "exclude" {
+ default = []
+ description = "A list of region IDs to exclude."
+ type = list(string)
+}
+
+
+locals {
+ # This is a static list because the zones don't change _that_
+ # frequently and including the `exoscale_zones` data source requires
+ # the provider, which requires a zone.
+ # https://www.exoscale.com/datacenters/
+ zones = {
+ "de-fra-1" = {
+ name = "Frankfurt - Germany"
+ icon = "/emojis/1f1e9-1f1ea.png"
+ }
+ "at-vie-1" = {
+ name = "Vienna 1 - Austria"
+ icon = "/emojis/1f1e6-1f1f9.png"
+ }
+ "at-vie-2" = {
+ name = "Vienna 2 - Austria"
+ icon = "/emojis/1f1e6-1f1f9.png"
+ }
+ "ch-gva-2" = {
+ name = "Geneva - Switzerland"
+ icon = "/emojis/1f1e8-1f1ed.png"
+ }
+ "ch-dk-2" = {
+ name = "Zurich - Switzerland"
+ icon = "/emojis/1f1e8-1f1ed.png"
+ }
+ "bg-sof-1" = {
+ name = "Sofia - Bulgaria"
+ icon = "/emojis/1f1e7-1f1ec.png"
+ }
+ "de-muc-1" = {
+ name = "Munich - Germany"
+ icon = "/emojis/1f1e9-1f1ea.png"
+ }
+ }
+}
+
+data "coder_parameter" "zone" {
+ name = "exoscale_zone"
+ display_name = var.display_name
+ description = var.description
+ default = var.default == "" ? null : var.default
+ mutable = var.mutable
+ dynamic "option" {
+ for_each = { for k, v in local.zones : k => v if !(contains(var.exclude, k)) }
+ content {
+ name = try(var.custom_names[option.key], option.value.name)
+ icon = try(var.custom_icons[option.key], option.value.icon)
+ value = option.key
+ }
+ }
+}
+
+output "value" {
+ value = data.coder_parameter.zone.value
+}
\ No newline at end of file
diff --git a/filebrowser/main.tf b/filebrowser/main.tf
index f479488..27790a2 100644
--- a/filebrowser/main.tf
+++ b/filebrowser/main.tf
@@ -43,6 +43,15 @@ variable "folder" {
default = "~"
}
+variable "share" {
+ type = string
+ default = "owner"
+ validation {
+ condition = var.share == "owner" || var.share == "authenticated" || var.share == "public"
+ error_message = "Incorrect value. Please set either 'owner', 'authenticated', or 'public'."
+ }
+}
+
resource "coder_script" "filebrowser" {
agent_id = var.agent_id
display_name = "File Browser"
@@ -64,5 +73,5 @@ resource "coder_app" "filebrowser" {
url = "http://localhost:${var.port}"
icon = "https://raw.githubusercontent.com/filebrowser/logo/master/icon_raw.svg"
subdomain = true
- share = "owner"
+ share = var.share
}
diff --git a/git-clone/main.tf b/git-clone/main.tf
index c5a6d29..110232f 100644
--- a/git-clone/main.tf
+++ b/git-clone/main.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
coder = {
source = "coder/coder"
- version = ">= 0.11"
+ version = ">= 0.12"
}
}
}
diff --git a/git-commit-signing/README.md b/git-commit-signing/README.md
new file mode 100644
index 0000000..38a02c0
--- /dev/null
+++ b/git-commit-signing/README.md
@@ -0,0 +1,24 @@
+---
+display_name: Git commit signing
+description: Configures Git to sign commits using your Coder SSH key
+icon: ../.icons/git.svg
+maintainer_github: phorcys420
+verified: false
+tags: [helper, git]
+---
+
+# git-commit-signing
+
+This module downloads your SSH key from Coder and uses it to sign commits with Git.
+It requires `curl` and `jq` to be installed inside your workspace.
+
+Please observe that using the SSH key that's part of your Coder account for commit signing, means that in the event of a breach of your Coder account, or a malicious admin, someone could perform commit signing pretending to be you.
+
+This module has a chance of conflicting with the user's dotfiles / the personalize module if one of those has configuration directives that overwrite this module's / each other's git configuration.
+
+```hcl
+module "git-commit-signing" {
+ source = "https://registry.coder.com/modules/git-commit-signing"
+ agent_id = coder_agent.example.id
+}
+```
diff --git a/git-commit-signing/main.tf b/git-commit-signing/main.tf
new file mode 100644
index 0000000..9be7bac
--- /dev/null
+++ b/git-commit-signing/main.tf
@@ -0,0 +1,25 @@
+terraform {
+ required_version = ">= 1.0"
+
+ required_providers {
+ coder = {
+ source = "coder/coder"
+ version = ">= 0.12"
+ }
+ }
+}
+
+variable "agent_id" {
+ type = string
+ description = "The ID of a Coder agent."
+}
+
+resource "coder_script" "git-commit-signing" {
+ display_name = "Git commit signing"
+ icon = "https://raw.githubusercontent.com/coder/modules/main/.icons/git.svg"
+
+ script = file("${path.module}/run.sh")
+ run_on_start = true
+
+ agent_id = var.agent_id
+}
diff --git a/git-commit-signing/run.sh b/git-commit-signing/run.sh
new file mode 100755
index 0000000..57c5139
--- /dev/null
+++ b/git-commit-signing/run.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env sh
+
+if ! command -v git > /dev/null; then
+ echo "git is not installed"
+ exit 1
+fi
+
+if ! command -v curl > /dev/null; then
+ echo "curl is not installed"
+ exit 1
+fi
+
+if ! command -v jq > /dev/null; then
+ echo "jq is not installed"
+ exit 1
+fi
+
+mkdir -p ~/.ssh/git-commit-signing
+
+echo "Downloading SSH key"
+
+ssh_key=$(curl --request GET \
+ --url "${CODER_AGENT_URL}api/v2/workspaceagents/me/gitsshkey" \
+ --header "Coder-Session-Token: ${CODER_AGENT_TOKEN}")
+
+jq --raw-output ".public_key" > ~/.ssh/git-commit-signing/coder.pub < ~/.ssh/git-commit-signing/coder <