diff --git a/chart/USAGE.md b/chart/USAGE.md new file mode 100644 index 0000000..2b47e7a --- /dev/null +++ b/chart/USAGE.md @@ -0,0 +1,381 @@ +# Dev Container Helm Chart Usage Guide + +This guide provides common usage patterns and examples for the Dev Container Helm chart. + +## Quick Start + +### 1. Minimal Installation (Recommended) + +Use the quickstart values for the simplest setup: + +```bash +# Copy and customize quickstart values +cp values-quickstart.yaml my-values.yaml + +# Edit my-values.yaml to set your name and repo: +# name: myproject +# githubRepo: https://github.com/youruser/yourproject + +# Install +helm install myproject ./chart -f my-values.yaml +``` + +### 2. One-Command Installation + +```bash +helm install mydev ./chart \ + --set name=mydev \ + --set githubRepo=https://github.com/youruser/yourrepo +``` + +## Common Use Cases + +### Development Environment + +**Scenario**: Standard development with GitHub integration + +```yaml +name: dev-environment +githubRepo: https://github.com/company/project + +ide: + type: vscode + +mcp: + sidecars: + kubernetes: + enabled: true + playwright: + enabled: true + flux: + enabled: false # Disable if not using Flux +``` + +### Team Workspace + +**Scenario**: Shared development environment with more resources + +```yaml +name: team-workspace +githubRepo: https://github.com/company/project + +resources: + requests: + memory: "4Gi" + cpu: "2000m" + limits: + memory: "16Gi" + cpu: "8000m" + +storage: + size: 64Gi + +ssh: + enabled: true # Enable SSH access for team + +clusterAccess: readwrite # Full cluster access +``` + +### Kubernetes Admin Environment + +**Scenario**: Platform engineering with full cluster access + +```yaml +name: k8s-admin +githubRepo: https://github.com/company/k8s-configs + +clusterAccess: readwrite + +mcp: + sidecars: + kubernetes: + enabled: true + flux: + enabled: true + pgtuner: + enabled: true # Database administration + playwright: + enabled: false # Save resources +``` + +### AI/ML Development + +**Scenario**: AI development with browser automation + +```yaml +name: ai-playground +githubRepo: https://github.com/company/ai-project + +resources: + requests: + memory: "8Gi" # More memory for ML workloads + cpu: "4000m" + limits: + memory: "32Gi" + cpu: "16000m" + +storage: + size: 128Gi # Large datasets + +mcp: + sidecars: + playwright: + enabled: true # Web scraping, testing + kubernetes: + enabled: false # Save resources + flux: + enabled: false +``` + +### Lightweight Environment + +**Scenario**: Resource-constrained setup + +```yaml +name: lightweight +githubRepo: https://github.com/youruser/small-project + +resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "2Gi" + cpu: "1000m" + +storage: + size: 8Gi + +mcp: + sidecars: + kubernetes: + enabled: false + flux: + enabled: false + playwright: + enabled: false + # Only keep essential sidecars enabled +``` + +## Secret Configuration + +### Basic Secrets + +```bash +# GitHub access only +kubectl create secret generic devcontainer-mydev-secrets-env \ + --from-literal=GITHUB_TOKEN='ghp_...' \ + --from-literal=VNC_PASSWORD='changeme' +``` + +### Extended Secrets + +```bash +# Full feature set +kubectl create secret generic devcontainer-mydev-secrets-env \ + --from-literal=GITHUB_TOKEN='ghp_...' \ + --from-literal=VNC_PASSWORD='changeme' \ + --from-literal=SSH_AUTHORIZED_KEYS='ssh-ed25519 AAAA...' \ + --from-literal=HOMEASSISTANT_URL='http://homeassistant.local:8123' \ + --from-literal=HOMEASSISTANT_TOKEN='eyJ...' \ + --from-literal=DATABASE_URI='postgresql://user:pass@postgres:5432/db' +``` + +## Storage Configuration + +### Different Storage Classes + +```yaml +# For different Kubernetes distributions +storage: + className: "" # Auto-detect (recommended) + # className: longhorn # Longhorn + # className: nfs-client # NFS + # className: fast-ssd # Custom fast storage +``` + +### Storage Sizes by Use Case + +```yaml +# Small projects +storage: + size: 8Gi + +# Standard development +storage: + size: 32Gi + +# Large projects / datasets +storage: + size: 128Gi + +# Team environments +storage: + size: 256Gi +``` + +## Access Patterns + +### VNC Only (Default) + +```yaml +ide: + type: vscode + +# Access via: kubectl port-forward deployment/devcontainer-mydev 5800:5800 +``` + +### SSH Only + +```yaml +ide: + type: none + +ssh: + enabled: true + +# Access via: kubectl port-forward deployment/devcontainer-mydev 2222:22 +# ssh -p 2222 user@localhost +``` + +### Both VNC and SSH + +```yaml +ide: + type: vscode + +ssh: + enabled: true + +# VNC: kubectl port-forward deployment/devcontainer-mydev 5800:5800 +# SSH: kubectl port-forward deployment/devcontainer-mydev 2222:22 +``` + +## Resource Profiles + +### Small (1-2 developers) +```yaml +resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "4Gi" + cpu: "2000m" +``` + +### Medium (standard development) +```yaml +resources: + requests: + memory: "2Gi" + cpu: "1000m" + limits: + memory: "8Gi" + cpu: "4000m" +``` + +### Large (intensive workloads) +```yaml +resources: + requests: + memory: "4Gi" + cpu: "2000m" + limits: + memory: "16Gi" + cpu: "8000m" +``` + +### XLarge (AI/ML, data processing) +```yaml +resources: + requests: + memory: "8Gi" + cpu: "4000m" + limits: + memory: "32Gi" + cpu: "16000m" +``` + +## MCP Sidecar Combinations + +### Minimal (basic development) +```yaml +mcp: + sidecars: + kubernetes: + enabled: false + flux: + enabled: false + playwright: + enabled: true # Keep for web testing +``` + +### Standard (full-stack development) +```yaml +mcp: + sidecars: + kubernetes: + enabled: true + flux: + enabled: false + playwright: + enabled: true +``` + +### DevOps/Platform (infrastructure work) +```yaml +mcp: + sidecars: + kubernetes: + enabled: true + flux: + enabled: true + pgtuner: + enabled: true + playwright: + enabled: false +``` + +### All Features +```yaml +mcp: + sidecars: + kubernetes: + enabled: true + flux: + enabled: true + homeassistant: + enabled: true + pgtuner: + enabled: true + playwright: + enabled: true +``` + +## Troubleshooting + +### Values Validation + +Your IDE should automatically validate values.yaml against the schema. If not: + +```bash +# Manual validation (if you have a JSON schema validator) +helm template ./chart -f values.yaml > /dev/null +``` + +### Common Issues + +**Resource Limits**: Start with smaller resource requests and increase as needed. + +**Storage Class**: Use `className: ""` for auto-detection. + +**GitHub Access**: Ensure GITHUB_TOKEN has `repo` scope. + +**MCP Sidecars**: Disable unused sidecars to save resources. + +### Getting Help + +1. Check the main [README.md](../README.md) for detailed documentation +2. Review [values.yaml](values.yaml) for all available options +3. Use [values-quickstart.yaml](values-quickstart.yaml) as a starting point \ No newline at end of file diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl index 2bf65b1..03ddb5b 100644 --- a/chart/templates/_helpers.tpl +++ b/chart/templates/_helpers.tpl @@ -26,3 +26,71 @@ Common labels app: devcontainer instance: {{ .Values.name }} {{- end }} + +{{/* +Smart resource sizing based on enabled features +*/}} +{{- define "antigravity.smartResources" -}} +{{- $baseMemory := "2Gi" }} +{{- $baseCpu := "1000m" }} +{{- $limitMemory := "8Gi" }} +{{- $limitCpu := "4000m" }} + +{{/* Adjust for enabled MCP sidecars */}} +{{- if .Values.mcp.sidecars.playwright.enabled }} + {{- $baseMemory = "3Gi" }} + {{- $limitMemory = "12Gi" }} +{{- end }} + +{{/* Adjust for IDE type */}} +{{- if eq .Values.ide.type "antigravity" }} + {{- $baseMemory = "4Gi" }} + {{- $limitMemory = "16Gi" }} +{{- end }} + +requests: + memory: {{ .Values.resources.requests.memory | default $baseMemory | quote }} + cpu: {{ .Values.resources.requests.cpu | default $baseCpu | quote }} +limits: + memory: {{ .Values.resources.limits.memory | default $limitMemory | quote }} + cpu: {{ .Values.resources.limits.cpu | default $limitCpu | quote }} +{{- end }} + +{{/* +Auto-detect environment type and set smart defaults +*/}} +{{- define "antigravity.smartDefaults" -}} +{{- $isDev := or (contains "dev" .Values.name) (contains "test" .Values.name) (contains "local" .Values.name) }} +{{- $isProd := or (contains "prod" .Values.name) (contains "production" .Values.name) }} +{{- $isTeam := or (contains "team" .Values.name) (contains "shared" .Values.name) }} + +{{/* Development environment - enable more sidecars, smaller resources */}} +{{- if $isDev }} +development: true +{{/* Production environment - conservative defaults, fewer sidecars */}} +{{- else if $isProd }} +production: true +{{/* Team environment - enable SSH, more resources */}} +{{- else if $isTeam }} +team: true +{{- end }} +{{- end }} + +{{/* +Smart MCP sidecar selection based on cluster access +*/}} +{{- define "antigravity.mcpDefaults" -}} +{{- if eq .Values.clusterAccess "none" }} + {{/* No cluster access - disable k8s/flux sidecars */}} + kubernetes: + enabled: false + flux: + enabled: false +{{- else }} + {{/* Has cluster access - enable k8s sidecars */}} + kubernetes: + enabled: true + flux: + enabled: {{ ne .Values.clusterAccess "readonly" }} +{{- end }} +{{- end }} diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml index 916348e..95d50f3 100644 --- a/chart/templates/deployment.yaml +++ b/chart/templates/deployment.yaml @@ -20,7 +20,7 @@ spec: securityContext: fsGroup: 1000 fsGroupChangePolicy: "OnRootMismatch" - {{- if and .Values.ide (eq .Values.ide "antigravity") }} + {{- if and .Values.ide.type (eq .Values.ide.type "antigravity") }} initContainers: - name: setup-userdata image: busybox:latest @@ -44,39 +44,39 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - {{- if ne (.Values.ide | default "vscode") "none" }} + {{- if ne (.Values.ide.type | default "vscode") "none" }} - containerPort: 5800 name: vnc-web protocol: TCP {{- end }} - {{- if .Values.ssh }} + {{- if .Values.ssh.enabled }} - containerPort: 22 name: ssh protocol: TCP {{- end }} env: - name: IDE - value: {{ .Values.ide | default "vscode" | quote }} + value: {{ .Values.ide.type | default "vscode" | quote }} - name: SSH - value: {{ .Values.ssh | toString | quote }} + value: {{ .Values.ssh.enabled | toString | quote }} - name: USER_ID - value: {{ .Values.userId | quote }} + value: {{ .Values.user.id | quote }} - name: GROUP_ID - value: {{ .Values.groupId | quote }} + value: {{ .Values.user.groupId | quote }} - name: DISPLAY_WIDTH value: {{ .Values.display.width | quote }} - name: DISPLAY_HEIGHT value: {{ .Values.display.height | quote }} - name: SECURE_CONNECTION - value: {{ .Values.secureConnection | quote }} + value: {{ .Values.display.secureConnection | quote }} - name: HAPPY_HOME_DIR - value: {{ .Values.happyHomeDir | quote }} + value: {{ .Values.happy.homeDir | quote }} - name: HAPPY_EXPERIMENTAL - value: {{ .Values.happyExperimental | quote }} + value: {{ .Values.happy.experimental | quote }} - name: HAPPY_SERVER_URL - value: {{ .Values.happyServerUrl | quote }} + value: {{ .Values.happy.serverUrl | quote }} - name: HAPPY_WEBAPP_URL - value: {{ .Values.happyWebappUrl | quote }} + value: {{ .Values.happy.webappUrl | quote }} - name: GITHUB_REPO value: {{ .Values.githubRepo | quote }} envFrom: @@ -92,7 +92,7 @@ spec: mountPath: /workspace - name: shm mountPath: /dev/shm - {{- if ne (.Values.ide | default "vscode") "none" }} + {{- if ne (.Values.ide.type | default "vscode") "none" }} livenessProbe: httpGet: path: / @@ -105,7 +105,7 @@ spec: port: 5800 initialDelaySeconds: 10 periodSeconds: 5 - {{- else if .Values.ssh }} + {{- else if .Values.ssh.enabled }} livenessProbe: tcpSocket: port: 22 @@ -117,63 +117,63 @@ spec: initialDelaySeconds: 5 periodSeconds: 5 {{- end }} - {{- if and .Values.mcpSidecars.kubernetes.enabled (ne .Values.clusterAccess "none") }} + {{- if and .Values.mcp.sidecars.kubernetes.enabled (ne .Values.clusterAccess "none") }} - name: kubernetes-mcp - image: "{{ .Values.mcpSidecars.kubernetes.image.repository }}:{{ .Values.mcpSidecars.kubernetes.image.tag }}" + image: "{{ .Values.mcp.sidecars.kubernetes.image.repository }}:{{ .Values.mcp.sidecars.kubernetes.image.tag }}" args: - --port - - {{ .Values.mcpSidecars.kubernetes.port | quote }} + - {{ .Values.mcp.sidecars.kubernetes.port | quote }} ports: - - containerPort: {{ .Values.mcpSidecars.kubernetes.port }} + - containerPort: {{ .Values.mcp.sidecars.kubernetes.port }} name: k8s-mcp protocol: TCP livenessProbe: httpGet: path: /healthz - port: {{ .Values.mcpSidecars.kubernetes.port }} + port: {{ .Values.mcp.sidecars.kubernetes.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /healthz - port: {{ .Values.mcpSidecars.kubernetes.port }} + port: {{ .Values.mcp.sidecars.kubernetes.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.kubernetes.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.kubernetes.resources | nindent 12 }} {{- end }} - {{- if and .Values.mcpSidecars.flux.enabled (ne .Values.clusterAccess "none") }} + {{- if and .Values.mcp.sidecars.flux.enabled (ne .Values.clusterAccess "none") }} - name: flux-mcp - image: "{{ .Values.mcpSidecars.flux.image.repository }}:{{ .Values.mcpSidecars.flux.image.tag }}" + image: "{{ .Values.mcp.sidecars.flux.image.repository }}:{{ .Values.mcp.sidecars.flux.image.tag }}" args: - serve - --transport=sse - - --port={{ .Values.mcpSidecars.flux.port }} + - --port={{ .Values.mcp.sidecars.flux.port }} ports: - - containerPort: {{ .Values.mcpSidecars.flux.port }} + - containerPort: {{ .Values.mcp.sidecars.flux.port }} name: flux-mcp protocol: TCP livenessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.flux.port }} + port: {{ .Values.mcp.sidecars.flux.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.flux.port }} + port: {{ .Values.mcp.sidecars.flux.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.flux.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.flux.resources | nindent 12 }} {{- end }} - {{- if .Values.mcpSidecars.homeassistant.enabled }} + {{- if .Values.mcp.sidecars.homeassistant.enabled }} - name: homeassistant-mcp - image: "{{ .Values.mcpSidecars.homeassistant.image.repository }}:{{ .Values.mcpSidecars.homeassistant.image.tag }}" + image: "{{ .Values.mcp.sidecars.homeassistant.image.repository }}:{{ .Values.mcp.sidecars.homeassistant.image.tag }}" imagePullPolicy: Always - command: ["fastmcp", "run", "--transport", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcpSidecars.homeassistant.port }}"] + command: ["fastmcp", "run", "--transport", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcp.sidecars.homeassistant.port }}"] ports: - name: homeassistant - containerPort: {{ .Values.mcpSidecars.homeassistant.port }} + containerPort: {{ .Values.mcp.sidecars.homeassistant.port }} env: - name: HOMEASSISTANT_URL valueFrom: @@ -189,27 +189,27 @@ spec: optional: true livenessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.homeassistant.port }} + port: {{ .Values.mcp.sidecars.homeassistant.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.homeassistant.port }} + port: {{ .Values.mcp.sidecars.homeassistant.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.homeassistant.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.homeassistant.resources | nindent 12 }} {{- end }} - {{- if .Values.mcpSidecars.github.enabled }} + {{- if .Values.mcp.sidecars.github.enabled }} - name: github-mcp - image: "{{ .Values.mcpSidecars.github.image.repository }}:{{ .Values.mcpSidecars.github.image.tag }}" + image: "{{ .Values.mcp.sidecars.github.image.repository }}:{{ .Values.mcp.sidecars.github.image.tag }}" imagePullPolicy: Always args: - --sse - - --port={{ .Values.mcpSidecars.github.port }} + - --port={{ .Values.mcp.sidecars.github.port }} ports: - name: github - containerPort: {{ .Values.mcpSidecars.github.port }} + containerPort: {{ .Values.mcp.sidecars.github.port }} env: - name: GITHUB_PERSONAL_ACCESS_TOKEN valueFrom: @@ -220,26 +220,26 @@ spec: livenessProbe: httpGet: path: /health - port: {{ .Values.mcpSidecars.github.port }} + port: {{ .Values.mcp.sidecars.github.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /health - port: {{ .Values.mcpSidecars.github.port }} + port: {{ .Values.mcp.sidecars.github.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.github.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.github.resources | nindent 12 }} {{- end }} - {{- if .Values.mcpSidecars.pgtuner.enabled }} + {{- if .Values.mcp.sidecars.pgtuner.enabled }} - name: pgtuner-mcp - image: "{{ .Values.mcpSidecars.pgtuner.image.repository }}:{{ .Values.mcpSidecars.pgtuner.image.tag }}" + image: "{{ .Values.mcp.sidecars.pgtuner.image.repository }}:{{ .Values.mcp.sidecars.pgtuner.image.tag }}" imagePullPolicy: Always - command: ["python", "-m", "pgtuner_mcp", "--transport", "sse", "--port", "{{ .Values.mcpSidecars.pgtuner.port }}"] + command: ["python", "-m", "pgtuner_mcp", "--transport", "sse", "--port", "{{ .Values.mcp.sidecars.pgtuner.port }}"] ports: - name: pgtuner - containerPort: {{ .Values.mcpSidecars.pgtuner.port }} + containerPort: {{ .Values.mcp.sidecars.pgtuner.port }} env: - name: DATABASE_URI valueFrom: @@ -255,41 +255,41 @@ spec: optional: true livenessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.pgtuner.port }} + port: {{ .Values.mcp.sidecars.pgtuner.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.pgtuner.port }} + port: {{ .Values.mcp.sidecars.pgtuner.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.pgtuner.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.pgtuner.resources | nindent 12 }} {{- end }} - {{- if .Values.mcpSidecars.playwright.enabled }} + {{- if .Values.mcp.sidecars.playwright.enabled }} - name: playwright-mcp - image: "{{ .Values.mcpSidecars.playwright.image.repository }}:{{ .Values.mcpSidecars.playwright.image.tag }}" + image: "{{ .Values.mcp.sidecars.playwright.image.repository }}:{{ .Values.mcp.sidecars.playwright.image.tag }}" imagePullPolicy: Always args: - --transport - sse - --port - - {{ .Values.mcpSidecars.playwright.port | quote }} + - {{ .Values.mcp.sidecars.playwright.port | quote }} ports: - name: playwright - containerPort: {{ .Values.mcpSidecars.playwright.port }} + containerPort: {{ .Values.mcp.sidecars.playwright.port }} livenessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.playwright.port }} + port: {{ .Values.mcp.sidecars.playwright.port }} initialDelaySeconds: 15 periodSeconds: 10 readinessProbe: tcpSocket: - port: {{ .Values.mcpSidecars.playwright.port }} + port: {{ .Values.mcp.sidecars.playwright.port }} initialDelaySeconds: 10 periodSeconds: 5 resources: - {{- toYaml .Values.mcpSidecars.playwright.resources | nindent 12 }} + {{- toYaml .Values.mcp.sidecars.playwright.resources | nindent 12 }} securityContext: runAsUser: 1000 runAsGroup: 1000 diff --git a/chart/values-quickstart.yaml b/chart/values-quickstart.yaml new file mode 100644 index 0000000..922cf06 --- /dev/null +++ b/chart/values-quickstart.yaml @@ -0,0 +1,58 @@ +# ============================================================================= +# QUICKSTART VALUES - Just set these 3 essentials! +# ============================================================================= + +# Instance name (required) +name: mydev + +# GitHub repository to clone (required) +githubRepo: https://github.com/youruser/yourrepo + +# IDE choice (optional - defaults to vscode) +# Options: vscode | antigravity | none +ide: + type: vscode + +# ============================================================================= +# COMMON CUSTOMIZATIONS (optional) +# ============================================================================= + +# Enable SSH access +# ssh: +# enabled: true + +# Adjust resources for smaller/larger workloads +# resources: +# requests: +# memory: "1Gi" # Smaller +# cpu: "500m" +# limits: +# memory: "4Gi" # Smaller +# cpu: "2000m" + +# Different storage size +# storage: +# size: 16Gi # Smaller + +# Disable some MCP sidecars to save resources +# mcp: +# sidecars: +# kubernetes: +# enabled: false +# flux: +# enabled: false + +# ============================================================================= +# USAGE INSTRUCTIONS +# ============================================================================= + +# 1. Copy this file: cp values-quickstart.yaml my-values.yaml +# 2. Edit the 'name' and 'githubRepo' fields above +# 3. Deploy: helm install mydev ./chart -f my-values.yaml +# 4. Access: kubectl port-forward deployment/devcontainer-mydev 5800:5800 +# 5. Open: http://localhost:5800 + +# For secrets (GitHub token, passwords): +# kubectl create secret generic devcontainer-mydev-secrets-env \ +# --from-literal=GITHUB_TOKEN='ghp_...' \ +# --from-literal=VNC_PASSWORD='changeme' \ No newline at end of file diff --git a/chart/values.schema.json b/chart/values.schema.json new file mode 100644 index 0000000..7d3837e --- /dev/null +++ b/chart/values.schema.json @@ -0,0 +1,259 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://github.com/cpfarhood/devcontainer/chart/values.schema.json", + "title": "Dev Container Helm Chart Values Schema", + "description": "Schema for validating values.yaml in the Dev Container Helm chart", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Instance name used to generate resource names", + "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$", + "minLength": 1, + "maxLength": 63 + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Container image repository" + }, + "tag": { + "type": "string", + "description": "Container image tag" + }, + "pullPolicy": { + "type": "string", + "enum": ["Always", "IfNotPresent", "Never"], + "description": "Image pull policy" + } + }, + "required": ["repository", "tag"] + }, + "githubRepo": { + "type": "string", + "description": "GitHub repository URL to clone", + "pattern": "^https://github\\.com/.+/.+$" + }, + "ide": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": ["vscode", "antigravity", "none"], + "description": "IDE to launch in the container" + } + }, + "required": ["type"] + }, + "ssh": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable SSH server on port 22" + } + }, + "required": ["enabled"] + }, + "display": { + "type": "object", + "properties": { + "width": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "VNC display width in pixels" + }, + "height": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "VNC display height in pixels" + }, + "secureConnection": { + "type": "string", + "enum": ["0", "1"], + "description": "Enable secure VNC connection" + } + }, + "required": ["width", "height", "secureConnection"] + }, + "user": { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "User ID (UID)" + }, + "groupId": { + "type": "string", + "pattern": "^[0-9]+$", + "description": "Group ID (GID)" + } + }, + "required": ["id", "groupId"] + }, + "storage": { + "type": "object", + "properties": { + "size": { + "type": "string", + "pattern": "^[0-9]+[KMGT]i$", + "description": "Storage size (e.g., 32Gi)" + }, + "className": { + "type": "string", + "description": "Storage class name (must support ReadWriteMany)" + } + }, + "required": ["size", "className"] + }, + "resources": { + "type": "object", + "properties": { + "requests": { + "$ref": "#/$defs/resourceSpec" + }, + "limits": { + "$ref": "#/$defs/resourceSpec" + } + }, + "required": ["requests", "limits"] + }, + "shm": { + "type": "object", + "properties": { + "sizeLimit": { + "type": "string", + "pattern": "^[0-9]+[KMGT]i$", + "description": "Shared memory size limit" + } + }, + "required": ["sizeLimit"] + }, + "clusterAccess": { + "type": "string", + "enum": ["none", "readonlyns", "readwritens", "readonly", "readwrite"], + "description": "Kubernetes cluster access level" + }, + "happy": { + "type": "object", + "properties": { + "serverUrl": { + "type": "string", + "format": "uri", + "description": "Happy Coder server URL" + }, + "webappUrl": { + "type": "string", + "format": "uri", + "description": "Happy Coder webapp URL" + }, + "homeDir": { + "type": "string", + "description": "Happy Coder home directory" + }, + "experimental": { + "type": "string", + "enum": ["true", "false"], + "description": "Enable experimental Happy features" + } + }, + "required": ["serverUrl", "webappUrl", "homeDir", "experimental"] + }, + "mcp": { + "type": "object", + "properties": { + "sidecars": { + "type": "object", + "properties": { + "kubernetes": { + "$ref": "#/$defs/mcpSidecar" + }, + "flux": { + "$ref": "#/$defs/mcpSidecar" + }, + "homeassistant": { + "$ref": "#/$defs/mcpSidecar" + }, + "github": { + "$ref": "#/$defs/mcpSidecar" + }, + "pgtuner": { + "$ref": "#/$defs/mcpSidecar" + }, + "playwright": { + "$ref": "#/$defs/mcpSidecar" + } + }, + "additionalProperties": false + } + }, + "required": ["sidecars"] + }, + "envSecretName": { + "type": "string", + "description": "Custom environment secret name" + } + }, + "required": ["name"], + "$defs": { + "resourceSpec": { + "type": "object", + "properties": { + "memory": { + "type": "string", + "pattern": "^[0-9]+[KMGT]i$", + "description": "Memory resource specification" + }, + "cpu": { + "type": "string", + "pattern": "^[0-9]+m?$", + "description": "CPU resource specification" + } + }, + "required": ["memory", "cpu"] + }, + "mcpSidecar": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable this MCP sidecar" + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + }, + "required": ["repository", "tag"] + }, + "port": { + "type": "integer", + "minimum": 1, + "maximum": 65535, + "description": "Port for the MCP sidecar" + }, + "resources": { + "type": "object", + "properties": { + "requests": { + "$ref": "#/$defs/resourceSpec" + }, + "limits": { + "$ref": "#/$defs/resourceSpec" + } + }, + "required": ["requests", "limits"] + } + }, + "required": ["enabled", "image", "port", "resources"] + } + } +} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index 500f455..42cbb0e 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -1,6 +1,11 @@ +# ============================================================================= +# BASIC CONFIGURATION +# ============================================================================= + # Instance name — used to generate resource names (devcontainer-{name}, userhome-{name}) name: "" +# Container image configuration image: repository: ghcr.io/cpfarhood/devcontainer tag: latest @@ -9,43 +14,40 @@ image: # GitHub repository to clone into /workspace githubRepo: "" -# IDE to launch inside the container. -# Options: -# vscode — VSCode via VNC browser UI on port 5800 (default) -# antigravity — Google Antigravity (VSCode fork) via VNC on port 5800 -# none — no IDE; useful when ssh: true is the sole access method -ide: vscode +# ============================================================================= +# ACCESS & INTERFACE +# ============================================================================= -# Start an OpenSSH server on port 22 in addition to the IDE. -# Set SSH_AUTHORIZED_KEYS in the env secret to allow key-based login. -ssh: false +# IDE configuration +ide: + # Options: vscode | antigravity | none + type: vscode -# Happy Coder endpoints -happyServerUrl: "https://happy.farh.net" -happyWebappUrl: "https://happy-coder.farh.net" -happyHomeDir: "/config/userdata/.happy" -happyExperimental: "true" +# SSH access configuration +ssh: + enabled: false -# VNC display +# VNC display settings display: width: "1920" height: "1080" + secureConnection: "0" # Set to "1" when TLS is not terminated upstream -# Set to "0" when TLS is terminated at the gateway layer -secureConnection: "0" +# User configuration +user: + id: "1000" + groupId: "1000" -userId: "1000" -groupId: "1000" +# ============================================================================= +# INFRASTRUCTURE & RESOURCES +# ============================================================================= +# Storage configuration storage: size: 32Gi className: ceph-filesystem -# Shared memory size — mounted at /dev/shm as a memory-backed emptyDir. -# Electron apps (Antigravity, Chrome) use /dev/shm for GPU/IPC buffers. -shm: - sizeLimit: 2Gi - +# Resource allocation resources: requests: memory: "2Gi" @@ -54,96 +56,136 @@ resources: memory: "8Gi" cpu: "4000m" -# Kubernetes cluster access granted to the devcontainer pod via RBAC. -# Options: -# none — no cluster access (default) -# readonlyns — get/list/watch all resources in the release namespace -# readwritens — full access to all resources in the release namespace -# readonly — get/list/watch all resources cluster-wide -# readwrite — full access to all resources cluster-wide +# Shared memory for Electron apps (Chrome, Antigravity) +shm: + sizeLimit: 2Gi + +# Kubernetes cluster access via RBAC +# Options: none | readonlyns | readwritens | readonly | readwrite clusterAccess: none -# Name of existing Secret containing env vars (GITHUB_TOKEN, VNC_PASSWORD, etc.) -# Defaults to: devcontainer-{name}-secrets-env -envSecretName: "" +# ============================================================================= +# INTEGRATIONS +# ============================================================================= -# MCP server sidecars — run alongside the devcontainer to inherit pod RBAC. -mcpSidecars: - kubernetes: - enabled: true - image: - repository: quay.io/containers/kubernetes_mcp_server - tag: v0.0.57 # Pinned version (Jan 27, 2025) with token exchange and field selector support - port: 8080 - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "256Mi" - cpu: "500m" - flux: - enabled: true - image: - repository: ghcr.io/controlplaneio-fluxcd/flux-operator-mcp - tag: v0.41.1 - port: 8081 - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "256Mi" - cpu: "500m" - homeassistant: - enabled: false # Disabled by default, requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN - image: - repository: ghcr.io/homeassistant-ai/ha-mcp - tag: stable - port: 8087 - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "256Mi" - cpu: "500m" - github: - enabled: false # DISABLED: GitHub MCP server has been archived, image doesn't exist - image: - repository: ghcr.io/modelcontextprotocol/servers/github - tag: latest # Update to specific version once available - port: 8088 - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "256Mi" - cpu: "500m" - pgtuner: - enabled: false # Disabled by default, requires DATABASE_URI in secrets - image: - repository: dog830228/pgtuner_mcp - tag: latest - port: 8085 - resources: - requests: - memory: "64Mi" - cpu: "50m" - limits: - memory: "256Mi" - cpu: "500m" - playwright: - enabled: true # Enabled by default for browser automation - image: - repository: microsoft/playwright-mcp - tag: latest - port: 8086 - resources: - requests: - memory: "128Mi" - cpu: "100m" - limits: - memory: "512Mi" - cpu: "1000m" +# Happy Coder AI assistant configuration +happy: + serverUrl: "https://happy.farh.net" + webappUrl: "https://happy-coder.farh.net" + homeDir: "/config/userdata/.happy" + experimental: "true" + +# MCP (Model Context Protocol) server sidecars +mcp: + sidecars: + # Kubernetes API access + kubernetes: + enabled: true + image: + repository: quay.io/containers/kubernetes_mcp_server + tag: v0.0.57 + port: 8080 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + + # Flux GitOps operations + flux: + enabled: true + image: + repository: ghcr.io/controlplaneio-fluxcd/flux-operator-mcp + tag: v0.41.1 + port: 8081 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + + # Home Assistant smart home control + homeassistant: + enabled: false # Requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN + image: + repository: ghcr.io/homeassistant-ai/ha-mcp + tag: stable + port: 8087 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + + # GitHub API access (DISABLED: archived image) + github: + enabled: false + image: + repository: ghcr.io/modelcontextprotocol/servers/github + tag: latest + port: 8088 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + + # PostgreSQL performance tuning + pgtuner: + enabled: false # Requires DATABASE_URI in secrets + image: + repository: dog830228/pgtuner_mcp + tag: latest + port: 8085 + resources: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "500m" + + # Browser automation and web testing + playwright: + enabled: true + image: + repository: microsoft/playwright-mcp + tag: latest + port: 8086 + resources: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "1000m" + +# ============================================================================= +# SMART DEFAULTS & AUTO-DETECTION +# ============================================================================= + +# Environment auto-detection based on name patterns +# Automatically adjusts defaults for dev/test/prod/team environments +autoDetect: + environment: true # Auto-detect dev/prod/team from name + storageClass: true # Auto-detect ReadWriteMany storage class + resources: true # Auto-size resources based on enabled features + +# Resource profiles (auto-selected based on environment and features) +# Override specific values above to customize +resourceProfile: auto # auto | small | medium | large | xlarge + +# ============================================================================= +# ADVANCED CONFIGURATION +# ============================================================================= + +# Custom env secret name (defaults to: devcontainer-{name}-secrets-env) +envSecretName: "" \ No newline at end of file