diff --git a/tf/scripts/workspace-metrics.sh b/tf/scripts/workspace-metrics.sh new file mode 100755 index 0000000..6de7755 --- /dev/null +++ b/tf/scripts/workspace-metrics.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# Workspace Metrics Display Script +# Formats CPU, Memory, and Disk usage with proper units and precision + +set -e + +echo "=== Workspace Metrics ===" + +# CPU Usage - convert cores to percentage (assuming 4 cores total, adjust as needed) +if command -v coder >/dev/null 2>&1; then + # Use coder stat if available (more accurate for container metrics) + cpu_usage=$(coder stat cpu 2>/dev/null || echo "N/A") + if [[ "$cpu_usage" != "N/A" ]]; then + echo "CPU Usage: $cpu_usage" + else + # Fallback to top-based calculation + cpu_percent=$(top -bn1 | awk 'FNR==3 {printf "%.2f%%", $2+$4}' 2>/dev/null || echo "N/A") + echo "CPU Usage: $cpu_percent" + fi +else + # Calculate CPU percentage using top + cpu_percent=$(top -bn1 | awk 'FNR==3 {printf "%.2f%%", $2+$4}' 2>/dev/null || echo "N/A") + echo "CPU Usage: $cpu_percent" +fi + +# Memory Usage - show both absolute values in GB and percentage +if command -v coder >/dev/null 2>&1; then + # Try coder stat first + mem_usage=$(coder stat mem --prefix Gi 2>/dev/null || echo "") + if [[ -n "$mem_usage" ]]; then + echo "Memory Usage: $mem_usage" + else + # Fallback to manual calculation + mem_info=$(free -g | awk 'NR==2{ + used=$3; + total=$2; + percent=(used/total)*100; + printf "%.2f/%.2f GB (%.1f%%)", used, total, percent + }' 2>/dev/null || echo "N/A") + echo "Memory Usage: $mem_info" + fi +else + # Manual memory calculation in GB + mem_info=$(free -g | awk 'NR==2{ + used=$3; + total=$2; + percent=(used/total)*100; + printf "%.2f/%.2f GB (%.1f%%)", used, total, percent + }' 2>/dev/null || echo "N/A") + echo "Memory Usage: $mem_info" +fi + +# Disk Usage - focus on /home or workspace directory instead of root +# First try to find the actual workspace mount point +workspace_path="/home" +if [[ -d "/workspaces" ]]; then + workspace_path="/workspaces" +elif [[ -d "/home/coder" ]]; then + workspace_path="/home/coder" +fi + +# Get disk usage for the workspace path +disk_usage=$(df -h "$workspace_path" 2>/dev/null | awk 'NR==2 { + used=$3; + total=$2; + percent=$5; + printf "%s/%s (%s)", used, total, percent +}' || echo "N/A") + +echo "Disk Usage: $disk_usage" + +# Load Average (optional additional metric) +if [[ -f /proc/loadavg ]]; then + load_avg=$(awk '{printf "%.2f %.2f %.2f", $1, $2, $3}' /proc/loadavg 2>/dev/null || echo "N/A") + echo "Load Average: $load_avg" +fi + +echo "=========================" diff --git a/tf/workspace.tf b/tf/workspace.tf index e52a9b3..b098ef3 100644 --- a/tf/workspace.tf +++ b/tf/workspace.tf @@ -163,63 +163,70 @@ module "windsurf_desktop" { } module "pycharm_desktop" { - count = data.coder_workspace.me.start_count > 0 && data.coder_parameter.enable_jetbrains.value ? 1 : 0 - source = "registry.coder.com/coder/jetbrains-gateway/coder" - agent_id = coder_agent.main.id - folder = "/workspaces" - jetbrains_ides = ["PY"] - default = "PY" - group = "Desktop IDEs" - order = 60 - coder_parameter_order = 6 - slug = "pycharm-gateway" + count = data.coder_workspace.me.start_count > 0 && data.coder_parameter.enable_jetbrains.value ? 1 : 0 + source = "registry.coder.com/coder/jetbrains-gateway/coder" + agent_id = coder_agent.main.id + folder = "/workspaces" + jetbrains_ides = ["PY"] + default = "PY" + group = "Desktop IDEs" + order = 60 + coder_parameter_order = 6 + slug = "pycharm-gateway" } module "claude_code" { - count = data.coder_workspace.me.start_count > 0 && data.coder_parameter.enable_ai_tools.value ? 1 : 0 - source = "registry.coder.com/coder/claude-code/coder" - agent_id = coder_agent.main.id - workdir = "/workspaces" - group = "AI Tools" - order = 30 + count = data.coder_workspace.me.start_count > 0 && data.coder_parameter.enable_ai_tools.value ? 1 : 0 + source = "registry.coder.com/coder/claude-code/coder" + agent_id = coder_agent.main.id + workdir = "/workspaces" + group = "AI Tools" + order = 30 pre_install_script = <<-EOT #!/bin/bash set -euo pipefail - if curl --help 2>&1 | grep -q -- "--retry-all-errors"; then + if command -v curl >/dev/null 2>&1 && curl --help 2>&1 | grep -q -- "--retry-all-errors"; then exit 0 fi - if ! command -v apt-get >/dev/null 2>&1; then + real_curl="$(command -v curl || true)" + if [[ -z "$real_curl" ]]; then exit 0 fi - wait_for_apt() { - if command -v fuser >/dev/null 2>&1; then - while \ - fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || - fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || - fuser /var/lib/dpkg/lock >/dev/null 2>&1; do - echo "Waiting for apt locks to clear..." >&2 - sleep 2 - done - else - sleep 2 - fi - } + wrapper=/usr/local/bin/curl + if [[ "$real_curl" == "$wrapper" ]]; then + exit 0 + fi - apt_exec() { - if command -v sudo >/dev/null 2>&1; then - sudo "$@" - else - "$@" - fi - } + real_curl="$(readlink -f "$real_curl")" - export DEBIAN_FRONTEND=noninteractive - wait_for_apt - apt_exec apt-get update -qq - wait_for_apt - apt_exec apt-get install -y curl >/dev/null + python3 - <<'PY' "$real_curl" "$wrapper" +import os +import stat +import sys + +real = sys.argv[1] +wrapper = sys.argv[2] +script = """#!/usr/bin/env python3 +import os +import sys + +real_curl = {real!r} +args = [arg for arg in sys.argv[1:] if arg != "--retry-all-errors"] +os.execv(real_curl, [real_curl] + args) +""".format(real=real) + +with open(wrapper, "w", encoding="utf-8") as fh: + fh.write(script) + +os.chmod( + wrapper, + stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | + stat.S_IRGRP | stat.S_IXGRP | + stat.S_IROTH | stat.S_IXOTH, +) +PY EOT }