{{- if eq .Values.deploymentMode "persistent" }} apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "devcontainer.fullname" . }} labels: {{- include "devcontainer.labels" . | nindent 4 }} spec: replicas: 1 selector: matchLabels: {{- include "devcontainer.selectorLabels" . | nindent 6 }} template: metadata: labels: {{- include "devcontainer.labels" . | nindent 8 }} spec: {{- if ne (.Values.clusterAccess | default "none") "none" }} serviceAccountName: {{ include "devcontainer.fullname" . }} {{- end }} securityContext: fsGroup: 1000 fsGroupChangePolicy: "OnRootMismatch" {{- if and .Values.ide.type (eq .Values.ide.type "antigravity") }} initContainers: - name: setup-userdata image: busybox:1.37 command: ['sh', '-c'] args: - | echo "Setting up userdata directory..." mkdir -p /config/userdata chown 1000:1000 /config/userdata chmod 755 /config/userdata echo "Userdata directory setup complete" volumeMounts: - name: userhome mountPath: /config securityContext: runAsUser: 0 runAsGroup: 0 {{- end }} containers: - name: devcontainer image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: {{- if ne (.Values.ide.type | default "vscode") "none" }} - containerPort: 5800 name: vnc-web protocol: TCP {{- end }} {{- if .Values.ssh.enabled }} - containerPort: 22 name: ssh protocol: TCP {{- end }} env: - name: IDE value: {{ .Values.ide.type | default "vscode" | quote }} - name: SSH value: {{ .Values.ssh.enabled | toString | quote }} - name: USER_ID value: {{ .Values.user.id | quote }} - name: GROUP_ID 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.display.secureConnection | quote }} {{- if .Values.fileManager.enabled }} - name: WEB_FILE_MANAGER value: "1" - name: WEB_FILE_MANAGER_ALLOWED_PATHS value: {{ .Values.fileManager.allowedPaths | quote }} {{- if .Values.fileManager.deniedPaths }} - name: WEB_FILE_MANAGER_DENIED_PATHS value: {{ .Values.fileManager.deniedPaths | quote }} {{- end }} {{- end }} - name: HAPPY_HOME_DIR value: {{ .Values.happy.homeDir | quote }} - name: HAPPY_EXPERIMENTAL value: {{ .Values.happy.experimental | quote }} - name: HAPPY_SERVER_URL value: {{ .Values.happy.serverUrl | quote }} - name: HAPPY_WEBAPP_URL value: {{ .Values.happy.webappUrl | quote }} {{- if .Values.githubRepo }} - name: GITHUB_REPO value: {{ .Values.githubRepo | quote }} {{- end }} envFrom: - secretRef: name: {{ include "devcontainer.envSecretName" . }} optional: true resources: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: - name: userhome mountPath: /config - name: workspace mountPath: /workspace - name: shm mountPath: /dev/shm {{- if ne (.Values.ide.type | default "vscode") "none" }} livenessProbe: httpGet: path: / port: 5800 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: / port: 5800 initialDelaySeconds: 10 periodSeconds: 5 {{- else if .Values.ssh.enabled }} livenessProbe: tcpSocket: port: 22 initialDelaySeconds: 15 periodSeconds: 10 readinessProbe: tcpSocket: port: 22 initialDelaySeconds: 5 periodSeconds: 5 {{- end }} {{- if and .Values.mcp.sidecars.kubernetes.enabled (ne .Values.clusterAccess "none") }} - name: kubernetes-mcp image: "{{ .Values.mcp.sidecars.kubernetes.image.repository }}:{{ .Values.mcp.sidecars.kubernetes.image.tag }}" args: - --port - {{ .Values.mcp.sidecars.kubernetes.port | quote }} ports: - containerPort: {{ .Values.mcp.sidecars.kubernetes.port }} name: k8s-mcp protocol: TCP livenessProbe: httpGet: path: /healthz port: {{ .Values.mcp.sidecars.kubernetes.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /healthz port: {{ .Values.mcp.sidecars.kubernetes.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.kubernetes.resources | nindent 12 }} {{- end }} {{- if and .Values.mcp.sidecars.flux.enabled (ne .Values.clusterAccess "none") }} - name: flux-mcp image: "{{ .Values.mcp.sidecars.flux.image.repository }}:{{ .Values.mcp.sidecars.flux.image.tag }}" args: - serve - --transport=sse - --port={{ .Values.mcp.sidecars.flux.port }} ports: - containerPort: {{ .Values.mcp.sidecars.flux.port }} name: flux-mcp protocol: TCP livenessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.flux.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.flux.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.flux.resources | nindent 12 }} {{- end }} {{- if .Values.mcp.sidecars.helm.enabled }} - name: helm-mcp image: "{{ .Values.mcp.sidecars.helm.image.repository }}:{{ .Values.mcp.sidecars.helm.image.tag }}" args: - -mode=sse - -port={{ .Values.mcp.sidecars.helm.port }} ports: - containerPort: {{ .Values.mcp.sidecars.helm.port }} name: helm-mcp protocol: TCP livenessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.helm.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.helm.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.helm.resources | nindent 12 }} {{- end }} {{- if .Values.mcp.sidecars.homeassistant.enabled }} - name: homeassistant-mcp image: "{{ .Values.mcp.sidecars.homeassistant.image.repository }}:{{ .Values.mcp.sidecars.homeassistant.image.tag }}" imagePullPolicy: IfNotPresent command: ["fastmcp", "run", "--transport", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcp.sidecars.homeassistant.port }}"] ports: - name: homeassistant containerPort: {{ .Values.mcp.sidecars.homeassistant.port }} env: - name: HOMEASSISTANT_URL valueFrom: secretKeyRef: name: {{ include "devcontainer.envSecretName" . }} key: HOMEASSISTANT_URL optional: true - name: HOMEASSISTANT_TOKEN valueFrom: secretKeyRef: name: {{ include "devcontainer.envSecretName" . }} key: HOMEASSISTANT_TOKEN optional: true livenessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.homeassistant.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.homeassistant.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.homeassistant.resources | nindent 12 }} {{- end }} {{- if .Values.mcp.sidecars.pgtuner.enabled }} - name: pgtuner-mcp image: "{{ .Values.mcp.sidecars.pgtuner.image.repository }}:{{ .Values.mcp.sidecars.pgtuner.image.tag }}" imagePullPolicy: Always # pgtuner uses `latest` tag (no versioned releases available) command: ["python", "-m", "pgtuner_mcp", "--mode", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcp.sidecars.pgtuner.port }}"] ports: - name: pgtuner containerPort: {{ .Values.mcp.sidecars.pgtuner.port }} env: - name: DATABASE_URI valueFrom: secretKeyRef: name: {{ include "devcontainer.envSecretName" . }} key: DATABASE_URI optional: true - name: PGTUNER_EXCLUDE_USERIDS valueFrom: secretKeyRef: name: {{ include "devcontainer.envSecretName" . }} key: PGTUNER_EXCLUDE_USERIDS optional: true livenessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.pgtuner.port }} initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.pgtuner.port }} initialDelaySeconds: 5 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.pgtuner.resources | nindent 12 }} {{- end }} {{- if .Values.mcp.sidecars.playwright.enabled }} - name: playwright-mcp image: "{{ .Values.mcp.sidecars.playwright.image.repository }}:{{ .Values.mcp.sidecars.playwright.image.tag }}" imagePullPolicy: IfNotPresent command: ["node"] args: - cli.js - --headless - --browser - chromium - --no-sandbox - --host - 0.0.0.0 - --port - {{ .Values.mcp.sidecars.playwright.port | quote }} ports: - name: playwright containerPort: {{ .Values.mcp.sidecars.playwright.port }} livenessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.playwright.port }} initialDelaySeconds: 15 periodSeconds: 10 readinessProbe: tcpSocket: port: {{ .Values.mcp.sidecars.playwright.port }} initialDelaySeconds: 10 periodSeconds: 5 resources: {{- toYaml .Values.mcp.sidecars.playwright.resources | nindent 12 }} securityContext: runAsUser: 1000 runAsGroup: 1000 {{- end }} volumes: - name: workspace emptyDir: {} - name: shm emptyDir: medium: Memory sizeLimit: {{ .Values.shm.sizeLimit }} - name: userhome persistentVolumeClaim: claimName: {{ include "devcontainer.pvcName" . }} {{- end }}