VirtualMachines: Support auto creation of the config files

Mount using virtiofs

Change-Id: I77c5282b7bb1ad55df6ddfe0e4e53757b94f11e8
diff --git a/charts/virtual-machine/templates/configs.yaml b/charts/virtual-machine/templates/configs.yaml
new file mode 100644
index 0000000..e3daf7f
--- /dev/null
+++ b/charts/virtual-machine/templates/configs.yaml
@@ -0,0 +1,8 @@
+{{- if .Values.configFiles }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: configs-{{ .Values.name }}
+data:
+    {{ toYaml .Values.configFiles | nindent 2 }}
+{{- end }}
diff --git a/charts/virtual-machine/templates/secret-network-data.yaml b/charts/virtual-machine/templates/secret-network-data.yaml
index 02c002c..8d7a94c 100644
--- a/charts/virtual-machine/templates/secret-network-data.yaml
+++ b/charts/virtual-machine/templates/secret-network-data.yaml
@@ -4,4 +4,4 @@
   name: {{ .Values.name }}-network-data
 type: Opaque
 data:
-  networkdata: {{ .Values.cloudInit.networkData}}
+  networkdata: {{ .Values.cloudInit.networkData | toYaml | b64enc}}
diff --git a/charts/virtual-machine/templates/secret-user-data.yaml b/charts/virtual-machine/templates/secret-user-data.yaml
index 228ab91..057fda5 100644
--- a/charts/virtual-machine/templates/secret-user-data.yaml
+++ b/charts/virtual-machine/templates/secret-user-data.yaml
@@ -1,7 +1,17 @@
+{{- $userData := .Values.cloudInit.userData }}
+{{- if .Values.configFiles }}
+{{- $runcmd := get $userData "runcmd" | default list }}
+{{- $mkdir := print "sudo mkdir -p /home/" .Values.username "/.dodo" }}
+# TODO(gio): use this when switching to filesystems
+# {{- $mount := print "sudo mount -t virtiofs configs /home/" .Values.username "/.dodo" }}
+{{- $mount := print "sudo mount /dev/$(lsblk --nodeps -no name,serial | grep DODOCONFIGFILES | cut -f1 -d' ') /home/" .Values.username "/.dodo" }}
+{{- $_ := set $userData "runcmd" (concat $runcmd (list $mkdir $mount)) }}
+{{- end }}
+{{- $userDataYaml := print "#cloud-config\n" (toYaml $userData) }}
 apiVersion: v1
 kind: Secret
 metadata:
   name: {{ .Values.name }}-user-data
 type: Opaque
 data:
-  userdata: {{ .Values.cloudInit.userData}}
+  userdata: {{ $userDataYaml | b64enc}}
diff --git a/charts/virtual-machine/templates/vm.yaml b/charts/virtual-machine/templates/vm.yaml
index 3a0a446..a0d19e5 100644
--- a/charts/virtual-machine/templates/vm.yaml
+++ b/charts/virtual-machine/templates/vm.yaml
@@ -38,6 +38,14 @@
               disk:
                 bus: virtio
                 readonly: true
+            {{- if .Values.configFiles }}
+            # TODO(gio): switch to filesystems for real-time updates
+            - name: configs
+              disk:
+                bus: virtio
+                readonly: true
+              serial: DODOCONFIGFILES
+            {{- end }}
       networks:
         - name: default
           pod: {}
@@ -51,3 +59,8 @@
               name: {{ .Values.name }}-user-data
             networkDataSecretRef:
               name: {{ .Values.name }}-network-data
+        {{- if .Values.configFiles }}
+        - name: configs
+          configMap:
+            name: configs-{{ .Values.name }}
+        {{- end }}
diff --git a/charts/virtual-machine/values.yaml b/charts/virtual-machine/values.yaml
index 0199d6f..cf2f6ed 100644
--- a/charts/virtual-machine/values.yaml
+++ b/charts/virtual-machine/values.yaml
@@ -1,4 +1,5 @@
-name: ""
+name: "dodo"
+username: "dodo"
 cpuCores: 1
 memory: "1Gi"
 disk:
@@ -6,5 +7,6 @@
   size: 64Gi
 ports: []
 cloudInit:
-  userData: "" # base64 encoded
-  networkData: "" # base64 encoded
+  userData: {}
+  networkData: {}
+configFiles: {}
diff --git a/core/installer/app_configs/app_base.cue b/core/installer/app_configs/app_base.cue
index 8a85417..0724f73 100644
--- a/core/installer/app_configs/app_base.cue
+++ b/core/installer/app_configs/app_base.cue
@@ -1,6 +1,5 @@
 import (
 	"encoding/base64"
-	"encoding/yaml"
 	"list"
 	"net"
 	"strings"
@@ -168,6 +167,7 @@
 #VPN: #VPNEnabled | #VPNDisabled
 
 #VirtualMachine: #WithOut & {
+	cluster?: #Cluster
 	name: string
 	username: string
 	domain: string
@@ -178,12 +178,16 @@
 	sshKnownHosts: [...string] | *[]
 	sshAuthorizedKeys: [...string] | *[]
 	cloudInit: #CloudInit
+	// They will end up under ~/.dodo dir
+	configFiles: {...} | *{}
 	ports: [...#Port]
-	_ports: ports
 
 	_name: name
+	_username: username
 	_cpuCores: cpuCores
 	_memory: memory
+	_ports: ports
+	_configFiles: configFiles
 
 	_codeServerPort: 9090
 	_codeServerCmd: [...[...string]] | *[]
@@ -231,12 +235,13 @@
 			annotations: {
 				"dodo.cloud/resource-type": "virtual-machine"
 				"dodo.cloud/resource.virtual-machine.name": _name
-				"dodo.cloud/resource.virtual-machine.user": username
+				"dodo.cloud/resource.virtual-machine.user": _username
 				"dodo.cloud/resource.virtual-machine.cpu-cores": "\(_cpuCores)"
 				"dodo.cloud/resource.virtual-machine.memory": _memory
 			}
 			values: {
 				name: _name
+				username: _username
 				cpuCores: _cpuCores
 				memory: _memory
 				disk: {
@@ -259,22 +264,25 @@
 					protocol: p.protocol
 				}]
 				cloudInit: {
-					userData: base64.Encode(null, "#cloud-config\n\(yaml.Marshal(_cloudInitUserData))")
-					networkData: base64.Encode(null, yaml.Marshal({
+					userData: _cloudInitUserData
+					networkData: {
 						version: 2
 						ethernets: {
 							enp1s0: {
 								dhcp4: true
 							}
 						}
-					}))
+					}
 				}
+				configFiles: _configFiles
 			}
 			_cloudInitUserData: {
 				system_info: {
 					default_user: {
 						name: username
-						home: "/home/\(username)"
+						homedir: "/home/\(username)"
+						sudo: "ALL=(ALL) NOPASSWD:ALL"
+						groups: "users, admin"
 					}
 				}
 				password: "dodo" // TODO(gio): remove if possible
@@ -978,31 +986,35 @@
 }
 
 #WithOut: {
+	cluster?: #Cluster
+	_cluster: cluster
 	vm: {...}
-	_vm: {...}
-	_vm: {
-		for k, v in vm if len(v) > 0 {
+	vm: {
+		for k, v in vm {
 			"\(k)": #VirtualMachine & v & {
 				name: k
+				if _cluster != _|_ {
+					cluster: _cluster
+				}
 			}
 		}
 	}
 	images: {
-		for k, v in _vm {
+		for k, v in vm {
 			for x, y in v.images {
 				"\(x)": y
 			}
 		}
 	}
 	charts: {
-		for k, v in _vm {
+		for k, v in vm {
 			for x, y in v.charts {
 				"\(x)": y
 			}
 		}
 	}
 	helmR: {
-		for k, v in _vm {
+		for k, v in vm {
 			for x, y in v.helmR {
 				"\(x)": y
 			}
diff --git a/core/installer/app_configs/dodo_app.cue b/core/installer/app_configs/dodo_app.cue
index ff1a8ed..6e18feb 100644
--- a/core/installer/app_configs/dodo_app.cue
+++ b/core/installer/app_configs/dodo_app.cue
@@ -574,21 +574,16 @@
 								cpuCores: 2
 								memory: "3Gi"
 								ports: svc.ports
+								configFiles: {
+									"env.sh": _envProfile
+								}
 								cloudInit: {
-									_loadEnvFile: "/home/\(username)/.dodo_env.sh"
 									writeFiles: [{
-										// TODO(gio): create configmap instead
-										path: _loadEnvFile
-										content: _envProfile // "source <(curl -fsSL \(input.managerAddr)/api/apps/\(input.appId)/branch/\(svc.source.branch)/env-profile)"
+										path: "/home/\(username)/.bash_profile"
+										content: "source /home/\(username)/.dodo/env.sh"
 										owner: "\(username):\(username)"
 										permissions: "0700"
-									},
-										{
-											path: "/home/\(username)/.bash_profile"
-											content: "source \(_loadEnvFile)"
-											owner: "\(username):\(username)"
-											permissions: "0700"
-										}]
+									}]
 									runCmd: list.Concat([[
 																["sh", "-c", "chown \(username):\(username) /home/\(username)/.cache"],
 										["sh", "-c", "GIT_SSH_COMMAND='ssh -i /home/\(username)/.ssh/id_ed25519 -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new' git clone --branch \(svc.source.branch) \(svc.source.repository) /home/\(username)/code"],
diff --git a/core/installer/canvas-app.cue b/core/installer/canvas-app.cue
index 3f41047..eda5de2 100644
--- a/core/installer/canvas-app.cue
+++ b/core/installer/canvas-app.cue
@@ -1,4 +1,4 @@
-POST http://localhost:8080/api/dodo-app
+POST http://appmanager.hgrz-appmanager.svc.cluster.local/api/dodo-app
 Content-Type: application/json
 
 {
@@ -6,7 +6,7 @@
   "sshPrivateKey": "",
   "config": {
 	"service": [{
-		"name": "c1",
+		"name": "c36",
 		"type": "golang:1.24.0",
 		"source": {
 			"repository": "https://code.v1.dodo.cloud/pcloud",
@@ -19,28 +19,7 @@
 		}],
 		"ingress": [{
 			"network": "private",
-			"subdomain": "c1",
-			"port": { "name": "web" }
-		}],
-		"dev": {
-			"enabled": true,
-			"username": "gio"
-		}
-	}, {
-		"name": "c2",
-		"type": "golang:1.24.0",
-		"source": {
-			"repository": "https://code.v1.dodo.cloud/pcloud",
-			"branch": "main",
-			"rootDir": "apps/canvas/server"
-		},
-		"ports": [{
-				 "name": "web",
-				 "value": 8080
-		}],
-		"ingress": [{
-			"network": "private",
-			"subdomain": "c2",
+			"subdomain": "c36",
 			"port": { "name": "web" }
 		}],
 		"dev": {