diff --git a/coder/ai.coder.com.tf b/coder/ai.coder.com.tf index 519211f..f7e66c4 100644 --- a/coder/ai.coder.com.tf +++ b/coder/ai.coder.com.tf @@ -250,6 +250,22 @@ module "ai-coder-com-demo" { manual_trigger = var.manual_trigger exclude_from_archive = local.exclude_from_archive } + "universal-sandbox" = { + path = "${path.module}/../deployments/ai.coder.com/demo/universal-sandbox" + description = "General-purpose development workspace. Use this when no language- or repo-specific template fits. +" + display_name = "Universal Sandbox (Generic Dev Environment)" + icon = "/icon/personalize.svg" + default_ttl = 1 + failure_ttl = 24 + time_til_dormant = 1 + time_til_dormant_autodelete = 4 + manual_trigger = var.manual_trigger + exclude_from_archive = local.exclude_from_archive + vars = { + namespace = "coder-ws-demo" + } + } "ec2-win-vm" = { path = "${path.module}/../deployments/ai.coder.com/demo/ec2-win-vm" description = "Work on a Windows VM on AWS EC2!" diff --git a/deployments/ai.coder.com/demo/generic/README.md b/deployments/ai.coder.com/demo/universal-sandbox/README.md similarity index 77% rename from deployments/ai.coder.com/demo/generic/README.md rename to deployments/ai.coder.com/demo/universal-sandbox/README.md index f2ca7ee..17e8c26 100644 --- a/deployments/ai.coder.com/demo/generic/README.md +++ b/deployments/ai.coder.com/demo/universal-sandbox/README.md @@ -1,6 +1,6 @@ -# Generic Dev Template +# Universal Sandbox Template -A general-purpose, Kubernetes-based Coder workspace template designed as the default environment for Coder Agents. This template provides a batteries-included development environment with AI coding agents, IDEs, and a broad set of pre-installed programming languages and tools suitable for most development workflows. +A general-purpose, Kubernetes-based Coder workspace template designed as the default environment for Coder Agents. This template provides a batteries-included development environment with AI coding agents, IDEs, cloud/infrastructure tooling, and a broad set of pre-installed programming languages and tools suitable for most development workflows. **This is the default template.** Unless the user explicitly requests a different template or this template does not suit their specific use-case, this is the one that should be spun up. @@ -10,7 +10,7 @@ The workspace uses a persistent volume mounted at `/home/coder`. Any executables ## Pre-installed Programming Languages and Tools -The default container image (`public.ecr.aws/f7a1d7a4/coder-aidev:1.1.5`) is based on **Ubuntu Noble (24.04)** and comes with the following pre-installed: +The container image is built from `public.ecr.aws/f7a1d7a4/coder-aienv:1.1.6` (based on **Ubuntu Noble 24.04**) with additional tooling layered on top. The full image is defined in `images/aws/dev/Dockerfile.noble`. ### Programming Languages @@ -57,6 +57,55 @@ cursor-agent --version goose session start ``` +### Cloud and Infrastructure Tools + +| Tool | Description | +|------|-------------| +| **AWS CLI** | Amazon Web Services command-line interface | +| **Terraform** | Infrastructure as Code provisioning tool (HashiCorp) | +| **Terragrunt** | Thin wrapper for Terraform providing DRY configurations | +| **AWS CDK** | AWS Cloud Development Kit (via npm) | +| **kubectl** | Kubernetes cluster CLI (v1.35) | +| **Helm** | Kubernetes package manager | +| **K9s** | Terminal-based Kubernetes UI (v0.50.18) | +| **Docker (Podman)** | Container runtime via Podman with Docker CLI symlink | + +```bash +# AWS +aws sts get-caller-identity +aws s3 ls + +# Terraform / Terragrunt +terraform version +terraform init && terraform plan +terragrunt run-all plan + +# CDK +cdk --version +cdk synth + +# Kubernetes +kubectl get pods +helm list +k9s + +# Docker (backed by Podman) +docker ps +docker build -t myimage . +podman-compose up +``` + +### Database Tools + +| Tool | Description | +|------|-------------| +| **PostgreSQL Client** | `psql` CLI and related utilities | + +```bash +psql -h hostname -U user -d database +pg_dump -h hostname -U user database > backup.sql +``` + ### Developer Tools | Tool | Description | @@ -170,9 +219,9 @@ npx @wonderwhy-er/desktop-commander |-----------|-------------|---------| | `Github URL` | Repository URL to clone (optional) | Empty | | `Container Image` | Docker image for the workspace | `public.ecr.aws/f7a1d7a4/coder-aidev:1.1.5` | -| `vCPU Count` | Number of vCPUs to allocate | `2` | -| `Memory` | Amount of memory in Gi to allocate | `2` | -| `Storage` | Persistent volume size in Gi (immutable after creation) | `50` | +| `vCPU Count` | Number of vCPUs to allocate (min: 2, max: 4) | `2` | +| `Memory` | Amount of memory in Gi to allocate (min: 2, max: 8) | `2` | +| `Storage` | Persistent volume size in Gi (immutable after creation, min: 10, max: 100) | `50` | | `Preview Port` | Port for web app preview (must be > 1023, max 65535) | `4200` | ## Infrastructure @@ -207,10 +256,10 @@ The agent displays real-time metrics: ## Files ``` -generic/ +universal-sandbox/ ├── main.tf # IDEs, apps, and git-clone configuration ├── workspace.tf # Kubernetes deployment, agent, and PVC setup ├── variables.tf # User-configurable parameters ├── providers.tf # Terraform provider configuration -└── tmp.auto.tfvars.json # Namespace variable (auto-loaded) +└── README.md # This file ``` \ No newline at end of file diff --git a/deployments/ai.coder.com/demo/generic/main.tf b/deployments/ai.coder.com/demo/universal-sandbox/main.tf similarity index 100% rename from deployments/ai.coder.com/demo/generic/main.tf rename to deployments/ai.coder.com/demo/universal-sandbox/main.tf diff --git a/deployments/ai.coder.com/demo/generic/providers.tf b/deployments/ai.coder.com/demo/universal-sandbox/providers.tf similarity index 100% rename from deployments/ai.coder.com/demo/generic/providers.tf rename to deployments/ai.coder.com/demo/universal-sandbox/providers.tf diff --git a/deployments/ai.coder.com/demo/generic/variables.tf b/deployments/ai.coder.com/demo/universal-sandbox/variables.tf similarity index 92% rename from deployments/ai.coder.com/demo/generic/variables.tf rename to deployments/ai.coder.com/demo/universal-sandbox/variables.tf index 841b958..d561f7d 100644 --- a/deployments/ai.coder.com/demo/generic/variables.tf +++ b/deployments/ai.coder.com/demo/universal-sandbox/variables.tf @@ -22,6 +22,11 @@ data "coder_parameter" "cpus" { default = 2 type = "number" order = 4 + + validation { + min = 2 + max = 4 + } } data "coder_parameter" "memory" { @@ -32,6 +37,11 @@ data "coder_parameter" "memory" { default = 2 type = "number" order = 4 + + validation { + min = 2 + max = 8 + } } data "coder_parameter" "storage" { @@ -42,6 +52,11 @@ data "coder_parameter" "storage" { default = 50 type = "number" order = 4 + + validation { + min = 10 + max = 100 + } } data "coder_parameter" "container_image" { diff --git a/deployments/ai.coder.com/demo/generic/workspace.tf b/deployments/ai.coder.com/demo/universal-sandbox/workspace.tf similarity index 77% rename from deployments/ai.coder.com/demo/generic/workspace.tf rename to deployments/ai.coder.com/demo/universal-sandbox/workspace.tf index e78f181..8110657 100644 --- a/deployments/ai.coder.com/demo/generic/workspace.tf +++ b/deployments/ai.coder.com/demo/universal-sandbox/workspace.tf @@ -9,6 +9,11 @@ locals { "com.coder.user.id" = data.coder_workspace_owner.me.id "com.coder.user.username" = data.coder_workspace_owner.me.name } + coder_org_map = tomap({ + "coder-ws-experiment" = "experiment" + "coder-ws" = "coder" + "coder-ws-demo" = "demo" + }) } resource "coder_metadata" "pod_info" { @@ -139,15 +144,25 @@ resource "kubernetes_deployment_v1" "this" { } resources { - limits = { - cpu = "${data.coder_parameter.cpus.value}" - memory = "${data.coder_parameter.memory.value}Gi" - } - - requests = { - cpu = "500m" - memory = "1Gi" - } + limits = merge( + { + cpu = "${data.coder_parameter.cpus.value}" + memory = "${data.coder_parameter.memory.value}Gi" + }, + local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? { + ephemeral-storage = "${data.coder_parameter.storage.value}Gi" + } : {} + ) + + requests = merge( + { + cpu = "500m" + memory = "1Gi" + }, + local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? { + ephemeral-storage = "25Gi" + } : {} + ) } volume_mount { @@ -168,9 +183,16 @@ resource "kubernetes_deployment_v1" "this" { volume { name = "home" - persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim_v1.home.metadata.0.name - read_only = false + dynamic "persistent_volume_claim" { + for_each = local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? [1] : [] + content { + claim_name = kubernetes_persistent_volume_claim_v1.home[0].metadata.0.name + read_only = false + } + } + dynamic "empty_dir" { + for_each = local.coder_org_map[nonsensitive(var.namespace)] == "coder" ? [1] : [] + content {} } } @@ -180,6 +202,7 @@ resource "kubernetes_deployment_v1" "this" { } resource "kubernetes_persistent_volume_claim_v1" "home" { + count = local.coder_org_map[nonsensitive(var.namespace)] != "coder" ? 1 : 0 metadata { name = data.coder_workspace.me.id namespace = var.namespace