302 lines
9.1 KiB
HCL
302 lines
9.1 KiB
HCL
terraform {
|
|
required_version = ">= 1.0"
|
|
required_providers {
|
|
coder = {
|
|
source = "coder/coder"
|
|
version = "~> 2.0"
|
|
}
|
|
docker = {
|
|
source = "kreuzwerker/docker"
|
|
version = "~> 2.25"
|
|
}
|
|
envbuilder = {
|
|
source = "coder/envbuilder"
|
|
version = "~> 1.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
provider "coder" {}
|
|
provider "docker" {
|
|
host = var.docker_socket != "" ? var.docker_socket : null
|
|
}
|
|
provider "envbuilder" {}
|
|
|
|
# Data Sources
|
|
data "coder_provisioner" "me" {}
|
|
data "coder_workspace" "me" {}
|
|
data "coder_workspace_owner" "me" {}
|
|
|
|
# Parameters
|
|
data "coder_parameter" "repo" {
|
|
name = "repo"
|
|
display_name = "Repository"
|
|
description = "Select a repository to clone"
|
|
mutable = true
|
|
order = 1
|
|
|
|
option {
|
|
name = "Custom Development Environment"
|
|
description = "Full-stack development with all services"
|
|
value = "custom"
|
|
}
|
|
option {
|
|
name = "vercel/next.js"
|
|
description = "The React Framework"
|
|
value = "https://github.com/vercel/next.js"
|
|
}
|
|
option {
|
|
name = "Custom URL"
|
|
description = "Specify a custom repo URL below"
|
|
value = "custom-url"
|
|
}
|
|
}
|
|
|
|
data "coder_parameter" "custom_repo_url" {
|
|
name = "custom_repo_url"
|
|
display_name = "Custom Repository URL"
|
|
description = "Enter a custom repository URL"
|
|
default = ""
|
|
mutable = true
|
|
order = 2
|
|
}
|
|
|
|
data "coder_parameter" "enable_services" {
|
|
name = "enable_services"
|
|
display_name = "Enable Database Services"
|
|
description = "Enable PostgreSQL, Redis, Qdrant, and Docker Registry"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 3
|
|
}
|
|
|
|
data "coder_parameter" "enable_ai_tools" {
|
|
name = "enable_ai_tools"
|
|
display_name = "Enable AI Assistant Tools"
|
|
description = "Install Claude Code and AI development tools"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 4
|
|
}
|
|
|
|
data "coder_parameter" "enable_claude_code" {
|
|
name = "enable_claude_code"
|
|
display_name = "Enable Claude Code CLI"
|
|
description = "Install Claude Code command-line interface"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 5
|
|
}
|
|
|
|
data "coder_parameter" "enable_cursor_support" {
|
|
name = "enable_cursor_support"
|
|
display_name = "Enable Cursor IDE Support"
|
|
description = "Install Cursor IDE configuration and settings"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 6
|
|
}
|
|
|
|
data "coder_parameter" "enable_windsurf_support" {
|
|
name = "enable_windsurf_support"
|
|
display_name = "Enable Windsurf IDE Support"
|
|
description = "Install Windsurf IDE configuration and settings"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 7
|
|
}
|
|
|
|
data "coder_parameter" "enable_jetbrains" {
|
|
name = "enable_jetbrains"
|
|
display_name = "Enable JetBrains Gateway"
|
|
description = "Enable JetBrains Gateway integration for remote development"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 8
|
|
}
|
|
|
|
data "coder_parameter" "enable_jupyter" {
|
|
name = "enable_jupyter"
|
|
display_name = "Enable Jupyter Lab"
|
|
description = "Enable Jupyter Lab for data science and notebook development"
|
|
type = "bool"
|
|
default = "false"
|
|
mutable = true
|
|
order = 9
|
|
}
|
|
|
|
data "coder_parameter" "enable_pgadmin" {
|
|
name = "enable_pgadmin"
|
|
display_name = "Enable pgAdmin"
|
|
description = "Enable pgAdmin web interface for PostgreSQL management"
|
|
type = "bool"
|
|
default = "true"
|
|
mutable = true
|
|
order = 10
|
|
}
|
|
|
|
# Local Variables
|
|
locals {
|
|
# Container and workspace naming - use ID for immutability
|
|
container_name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
|
|
workspace_id = data.coder_workspace.me.id
|
|
# Use workspace ID for volume naming to prevent destruction on rename
|
|
volume_suffix = substr(data.coder_workspace.me.id, 0, 8)
|
|
|
|
# Git configuration
|
|
git_author_name = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
|
|
git_author_email = data.coder_workspace_owner.me.email
|
|
|
|
# Repository URL logic
|
|
repo_url = (
|
|
data.coder_parameter.repo.value == "custom" ? "https://github.com/coder/envbuilder" :
|
|
data.coder_parameter.repo.value == "custom-url" ? data.coder_parameter.custom_repo_url.value :
|
|
data.coder_parameter.repo.value
|
|
)
|
|
|
|
# Development container image is now built by envbuilder
|
|
# devcontainer_image = var.devcontainer_image # Deprecated
|
|
|
|
# Environment variables for the development container
|
|
dev_environment = {
|
|
# Git configuration
|
|
"GIT_AUTHOR_NAME" = local.git_author_name
|
|
"GIT_AUTHOR_EMAIL" = local.git_author_email
|
|
"GIT_COMMITTER_NAME" = local.git_author_name
|
|
"GIT_COMMITTER_EMAIL" = local.git_author_email
|
|
|
|
# Development tools
|
|
"NODE_VERSION" = var.node_version
|
|
"PYTHON_VERSION" = var.python_version
|
|
"RUST_VERSION" = "stable"
|
|
|
|
# Service URLs (when services are enabled)
|
|
"POSTGRES_URL" = data.coder_parameter.enable_services.value ? "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres" : ""
|
|
"REDIS_URL" = data.coder_parameter.enable_services.value ? "redis://:${var.redis_password}@redis-${local.workspace_id}:6379" : ""
|
|
"QDRANT_URL" = data.coder_parameter.enable_services.value ? "http://qdrant-${local.workspace_id}:6333" : ""
|
|
|
|
# Development configuration
|
|
"EDITOR" = "code"
|
|
"PYTHONPATH" = "/workspaces"
|
|
"CARGO_HOME" = "/home/coder/.cargo"
|
|
"RUSTUP_HOME" = "/home/coder/.rustup"
|
|
}
|
|
|
|
# Legacy service URLs for backward compatibility
|
|
postgres_url = "postgresql://postgres:${var.postgres_password}@postgres-${local.workspace_id}:5432/postgres"
|
|
redis_url = "redis://:${var.redis_password}@redis-${local.workspace_id}:6379"
|
|
qdrant_url = "http://qdrant-${local.workspace_id}:6333"
|
|
|
|
# Port forwarding script for services
|
|
port_forward_script = <<-SCRIPT
|
|
#!/bin/bash
|
|
export NVM_SYMLINK_CURRENT=false
|
|
export CODER_WORKSPACE_ID="${local.workspace_id}"
|
|
echo 'Starting workspace with services enabled...'
|
|
|
|
# Ensure tools are in PATH
|
|
export PATH=/usr/bin:/usr/local/bin:$$PATH
|
|
|
|
# Install essential tools in background if needed
|
|
(
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
# Always update package lists first
|
|
echo "Updating package lists..."
|
|
apt-get update -qq 2>/dev/null || true
|
|
|
|
# Install all needed tools
|
|
echo "Installing essential tools..."
|
|
apt-get install -y socat ranger postgresql-client redis-tools 2>/dev/null || {
|
|
# If group install fails, try individually
|
|
apt-get install -y socat 2>/dev/null || true
|
|
apt-get install -y ranger 2>/dev/null || true
|
|
apt-get install -y postgresql-client 2>/dev/null || true
|
|
apt-get install -y redis-tools 2>/dev/null || true
|
|
}
|
|
elif command -v apk >/dev/null 2>&1; then
|
|
# Alpine Linux
|
|
apk add --no-cache socat ranger postgresql-client redis 2>/dev/null || true
|
|
fi
|
|
) &
|
|
|
|
# Start port forwarding after a delay to ensure socat is installed
|
|
(sleep 10 && {
|
|
if command -v socat >/dev/null 2>&1; then
|
|
echo "Starting port forwarding..."
|
|
if [ "${data.coder_parameter.enable_pgadmin.value}" = "true" ]; then
|
|
echo 'Forwarding pgAdmin (localhost:5050 -> pgadmin-${local.workspace_id}:80)...'
|
|
nohup socat TCP-LISTEN:5050,reuseaddr,fork TCP:pgadmin-${local.workspace_id}:80 >/tmp/socat-pgadmin.log 2>&1 &
|
|
fi
|
|
echo 'Forwarding Qdrant (localhost:6333 -> qdrant-${local.workspace_id}:6333)...'
|
|
nohup socat TCP-LISTEN:6333,reuseaddr,fork TCP:qdrant-${local.workspace_id}:6333 >/tmp/socat-qdrant.log 2>&1 &
|
|
echo "Port forwarding started"
|
|
else
|
|
echo "Socat not available yet, port forwarding skipped"
|
|
fi
|
|
}) &
|
|
|
|
echo 'Workspace startup initiated.'
|
|
SCRIPT
|
|
}
|
|
|
|
# Docker Network
|
|
resource "docker_network" "workspace" {
|
|
name = "coder-${local.workspace_id}"
|
|
driver = "bridge"
|
|
|
|
labels {
|
|
label = "coder.workspace_id"
|
|
value = local.workspace_id
|
|
}
|
|
labels {
|
|
label = "coder.owner"
|
|
value = data.coder_workspace_owner.me.name
|
|
}
|
|
labels {
|
|
label = "coder.project"
|
|
value = var.project_name
|
|
}
|
|
}
|
|
|
|
# Workspace Volume
|
|
resource "docker_volume" "workspaces" {
|
|
name = "workspaces-${local.workspace_id}"
|
|
|
|
labels {
|
|
label = "coder.workspace_id"
|
|
value = local.workspace_id
|
|
}
|
|
labels {
|
|
label = "coder.owner"
|
|
value = data.coder_workspace_owner.me.name
|
|
}
|
|
labels {
|
|
label = "coder.type"
|
|
value = "workspace-data"
|
|
}
|
|
}
|
|
|
|
# Temporarily use the base image until we can push the devcontainer files
|
|
# TODO: Uncomment the envbuilder block after pushing to git
|
|
# resource "envbuilder_cached_image" "devcontainer" {
|
|
# builder_image = "ghcr.io/coder/envbuilder:latest"
|
|
# git_url = var.devcontainer_repo_url
|
|
#
|
|
# # Use the devcontainer.json from our repository
|
|
# devcontainer_dir = ".devcontainer"
|
|
#
|
|
# # Cache settings for faster builds
|
|
# cache_repo = var.envbuilder_cache_repo
|
|
# }
|
|
|
|
# Development Container Image - using base image for now
|
|
resource "docker_image" "devcontainer" {
|
|
name = var.devcontainer_image
|
|
keep_locally = true
|
|
} |