Merge branch 'main' into vault
@ -0,0 +1 @@
 | 
			
		||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 68.03 68.03"><defs><style>.cls-1{fill:#da291c;}</style></defs><title>Artboard 1</title><polygon class="cls-1" points="34.02 13.31 11.27 52.72 14.52 52.72 34.02 18.94 34.02 24.57 17.77 52.72 21.02 52.72 34.02 30.2 34.02 35.83 24.27 52.72 27.52 52.72 34.02 41.46 34.02 47.09 30.77 52.72 34.02 52.72 34.02 52.72 56.77 52.72 34.02 13.31"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 427 B  | 
| 
		 After Width: | Height: | Size: 28 KiB  | 
| 
		 After Width: | Height: | Size: 21 KiB  | 
| 
		 After Width: | Height: | Size: 93 KiB  | 
| 
		 After Width: | Height: | Size: 45 KiB  | 
| 
		 After Width: | Height: | Size: 92 KiB  | 
| 
		 After Width: | Height: | Size: 27 KiB  | 
@ -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.
 | 
			
		||||
@ -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');
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
@ -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.
 | 
			
		||||
@ -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");
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
@ -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
 | 
			
		||||
}
 | 
			
		||||
@ -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 <<EOF
 | 
			
		||||
$ssh_key
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
jq --raw-output ".private_key" > ~/.ssh/git-commit-signing/coder <<EOF
 | 
			
		||||
$ssh_key
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
chmod -R 400 ~/.ssh/git-commit-signing/coder
 | 
			
		||||
chmod -R 400 ~/.ssh/git-commit-signing/coder.pub
 | 
			
		||||
 | 
			
		||||
echo "Configuring git to use the SSH key"
 | 
			
		||||
 | 
			
		||||
git config --global gpg.format ssh
 | 
			
		||||
git config --global commit.gpgsign true
 | 
			
		||||
git config --global user.signingkey ~/.ssh/git-commit-signing/coder
 | 
			
		||||