Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type BaseConfig struct {
ClearLocalPackages bool `yaml:"clearLocalPackages,omitempty"`
ClearVSCodeCache bool `yaml:"clearVSCodeCache,omitempty"`
PythonBinPath string `yaml:"pythonBinPath,omitempty" validate:"omitempty,min=1,filepath"`
HostName string `yaml:"hostName,omitempty" validate:"omitempty,min=1,hostname"`
EnableAuth bool `yaml:"enableAuth,omitempty"`
AuthURL string `yaml:"authURL,omitempty" validate:"omitempty,min=1,url"`
AuthSignIn string `yaml:"authSignIn,omitempty" validate:"omitempty,min=1,url"`
}

// DevEnvConfig represents the complete configuration for a developer environment.
Expand Down
1 change: 1 addition & 0 deletions internal/templates/files/env-vars.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ metadata:
data:
USER: "{{.Name}}"
UID: "{{.GetUserID}}"
IS_ADMIN: "{{.IsAdmin}}"
GIT_NAME: "{{.Git.Name}}"
GIT_EMAIL: "{{.Git.Email}}"
31 changes: 31 additions & 0 deletions internal/templates/files/ingress.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: devenv-ingress-{{.Name}}
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt"

{{- if and .EnableAuth }}
nginx.ingress.kubernetes.io/auth-url: "{{.AuthURL}}"
nginx.ingress.kubernetes.io/auth-signin: "{{.AuthSignIn}}?rd=$scheme://$host$escaped_request_uri"
nginx.ingress.kubernetes.io/auth-response-headers: "Authorization,X-Auth-Request-User,X-Auth-Request-Email,X-Auth-Request-Access-Token"
{{- end}}

spec:
ingressClassName: nginx
rules:
- host: {{.Name}}.{{.HostName}}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: devenv-http-{{.Name}}
port:
name: http
tls:
- hosts:
- "*.{{.HostName}}"
secretName: http-{{.Name}}-tls
8 changes: 4 additions & 4 deletions internal/templates/files/startup-scripts.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ metadata:
data:
# Templated script - processed with config values
startup.sh: |
{{getTemplatedScript "startup.sh" . | indent 4}}
{{getTemplatedScript "startup.sh" . | indent 4}}

# Static utility scripts - included as-is
run_with_git.sh: |
{{getStaticScript "run_with_git.sh" | indent 4}}
{{getStaticScript "run_with_git.sh" | indent 4}}

# Static requirements file
requirements.txt: |
{{getStaticScript "requirements.txt" | indent 4}}
{{getStaticScript "requirements.txt" | indent 4}}

# User setup script
setup.sh: |
{{getTemplatedScript "user-setup.sh" . | indent 4}}
{{getTemplatedScript "user-setup.sh" . | indent 4}}
50 changes: 26 additions & 24 deletions internal/templates/files/statefulset.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,38 @@ spec:
containers:
- name: {{.Name}}
image: {{.Image}}
workingDir: "/src"
securityContext:
# Root required to configure new user and setup sshd
runAsUser: 0
command: ["/bin/bash", "/scripts/startup.sh"]
ports:
- containerPort: 22
name: ssh
protocol: TCP
{{- if ne .HTTPPort 0}}
- containerPort: {{.HTTPPort}}
name: http
protocol: TCP
{{- end}}

readinessProbe:
tcpSocket:
port: 22
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 6

env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: github-token
key: token
optional: true
envFrom:
- configMapRef:
name: env-vars-{{.Name}}

resources:
limits:
{{- if gt (.GPU) 0}}
Expand All @@ -72,20 +95,6 @@ spec:
{{- if ne (.MemoryRequest) "unlimited"}}
memory: "{{.MemoryRequest}}"
{{- end}}
env:
- name: USERNAME
value: {{.Name}}
- name: USER_ID
value: "{{if .UID}}{{.UID}}{{else}}1000{{end}}"
- name: IS_ADMIN
value: "{{.IsAdmin}}"
envFrom:
- configMapRef:
name: env-vars-{{.Name}}

securityContext:
runAsUser: {{if .UID}}{{.UID}}{{else}}1000{{end}}
runAsGroup: {{if .UID}}{{.UID}}{{else}}1000{{end}}

volumeMounts:
- name: dev-storage
Expand All @@ -95,9 +104,6 @@ spec:
- name: startup-scripts
mountPath: /scripts
readOnly: true
- name: ssh-keys
mountPath: /home/{{.Name}}/.ssh
readOnly: true
{{- range .Volumes}}
- name: {{.Name}}
mountPath: {{.ContainerPath}}
Expand All @@ -116,13 +122,9 @@ spec:
configMap:
name: startup-scripts-{{.Name}}
defaultMode: 0755
- name: ssh-keys
secret:
secretName: ssh-keys-{{.Name}}
defaultMode: 0600
{{- range .Volumes}}
- name: {{.Name}}
hostPath:
path: {{.LocalPath}}
type: Directory
type: DirectoryOrCreate
{{- end}}
4 changes: 3 additions & 1 deletion internal/templates/renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
"github.com/nauticalab/devenv-engine/internal/config"
)

var templatesToRender = []string{"statefulset", "service", "env-vars",
"secret", "startup-scripts", "ingress"}

// Embed all templates and scripts at compile time
//
//go:embed files/*.tmpl
Expand Down Expand Up @@ -113,7 +116,6 @@ func (r *Renderer) RenderTemplate(templateName string, config *config.DevEnvConf
}

func (r *Renderer) RenderAll(config *config.DevEnvConfig) error {
templatesToRender := []string{"statefulset", "service", "env-vars", "secret", "startup-scripts"}
for _, templateName := range templatesToRender {
if err := r.RenderTemplate(templateName, config); err != nil {
return fmt.Errorf("failed to render template %s: %w", templateName, err)
Expand Down
1 change: 1 addition & 0 deletions internal/templates/testdata/golden/env-vars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ metadata:
data:
USER: "testuser"
UID: "2000"
IS_ADMIN: "true"
GIT_NAME: "Test User"
GIT_EMAIL: "testuser@example.com"
8 changes: 4 additions & 4 deletions internal/templates/testdata/golden/startup-scripts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ metadata:
data:
# Templated script - processed with config values
startup.sh: |
#!/bin/bash
#!/bin/bash
# Container startup script for developer environment: testuser
set -e

Expand Down Expand Up @@ -157,7 +157,7 @@ data:

# Static utility scripts - included as-is
run_with_git.sh: |
#!/bin/bash
#!/bin/bash
#
# run_with_git - Run commands as another user with temporary Git credentials
#
Expand Down Expand Up @@ -217,7 +217,7 @@ data:

# Static requirements file
requirements.txt: |
# Common Python packages for scientific computing
# Common Python packages for scientific computing
# This file contains baseline packages that are installed in all environments

# Core scientific stack
Expand Down Expand Up @@ -246,7 +246,7 @@ data:

# User setup script
setup.sh: |
#!/bin/bash
#!/bin/bash
# User environment setup script for: testuser
# This script runs as the developer user to configure their personal environment
set -e
Expand Down
52 changes: 27 additions & 25 deletions internal/templates/testdata/golden/statefulset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,36 @@ spec:
containers:
- name: testuser
image: ubuntu:22.04
workingDir: "/src"
securityContext:
# Root required to configure new user and setup sshd
runAsUser: 0
command: ["/bin/bash", "/scripts/startup.sh"]
ports:
- containerPort: 22
name: ssh
protocol: TCP
- containerPort: 8080
name: http
protocol: TCP

readinessProbe:
tcpSocket:
port: 22
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 6

env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: github-token
key: token
optional: true
envFrom:
- configMapRef:
name: env-vars-testuser

resources:
limits:
nvidia.com/gpu: 2
Expand All @@ -49,20 +72,6 @@ spec:
nvidia.com/gpu: 2
cpu: "4"
memory: "16Gi"
env:
- name: USERNAME
value: testuser
- name: USER_ID
value: "2000"
- name: IS_ADMIN
value: "true"
envFrom:
- configMapRef:
name: env-vars-testuser

securityContext:
runAsUser: 2000
runAsGroup: 2000

volumeMounts:
- name: dev-storage
Expand All @@ -72,9 +81,6 @@ spec:
- name: startup-scripts
mountPath: /scripts
readOnly: true
- name: ssh-keys
mountPath: /home/testuser/.ssh
readOnly: true
- name: data-volume
mountPath: /data
- name: config-volume
Expand All @@ -93,15 +99,11 @@ spec:
configMap:
name: startup-scripts-testuser
defaultMode: 0755
- name: ssh-keys
secret:
secretName: ssh-keys-testuser
defaultMode: 0600
- name: data-volume
hostPath:
path: /mnt/data
type: Directory
type: DirectoryOrCreate
- name: config-volume
hostPath:
path: /mnt/config
type: Directory
type: DirectoryOrCreate