AppManager: Add API endpoint to install dodo app

Refactors cue definitions.

Next steps:
* Needs some cleanup, namespace is hard coded ...
* Maybe merge with regular install API
* Support exposing ports across clusters

Change-Id: Ibfc3c3f742b61f2c5874012fe6c77b958eae81d9
diff --git a/core/installer/dodo_app_test.go b/core/installer/dodo_app_test.go
index e9d7737..5b0f3b1 100644
--- a/core/installer/dodo_app_test.go
+++ b/core/installer/dodo_app_test.go
@@ -6,8 +6,9 @@
 	"cuelang.org/go/cue/errors"
 )
 
-var exposedPostgreSQL = `
-app: {
+var exposed = `
+service: [{
+    name: "app"
 	type: "golang:1.20.0"
 	run: "main.go"
 	ingress: {
@@ -15,25 +16,93 @@
 		subdomain: "testapp"
 		auth: enabled: false
 	}
-}
+    source: repository: "ssh://foo.bar"
+    ports: [{
+        name: "a"
+        value: 100
+    }, {
+		name: "web"
+		value: 8080
+    }, {
+		name: "b"
+		value: 101
+    }]
+    expose: [{
+		network: "private"
+		subdomain: "1"
+        port: value: 100
+	}, {
+		network: "public"
+		subdomain:"2"
+        port: name: "web"
+	}, {
+		network: "private"
+		subdomain: "3"
+        port: value: 101
+    }]
+}]
 
 postgresql: [{
 	name: "db_1"
-	expose: ["private", "public", "private"]
+	expose: [{
+		network: "private"
+		subdomain: "1"
+	}, {
+		network: "public"
+		subdomain:"2"
+	}, {
+		network: "private"
+		subdomain: "3"
+	}]
 }, {
 	name: "db_2"
-	expose: ["public", "private", "public"]
-}]`
+	expose: [{
+		network: "public"
+		subdomain: "1"
+	}, {
+		network: "private"
+		subdomain:"2"
+	}, {
+		network: "public"
+		subdomain: "3"
+	}]
+}]
 
-func TestExposedPostgreSQL(t *testing.T) {
-	app, err := NewDodoApp([]byte(exposedPostgreSQL))
+mongodb: [{
+	name: "mdb_1"
+	expose: [{
+		network: "public"
+		subdomain: "1"
+	}, {
+		network: "private"
+		subdomain:"2"
+	}, {
+		network: "public"
+		subdomain: "3"
+	}]
+}, {
+	name: "mdb_2"
+	expose: [{
+		network: "private"
+		subdomain: "1"
+	}, {
+		network: "public"
+		subdomain:"2"
+	}, {
+		network: "private"
+		subdomain: "3"
+	}]
+}]
+`
+
+func TestExposedPorts(t *testing.T) {
+	app, err := NewDodoApp([]byte(exposed))
 	if err != nil {
 		for _, e := range errors.Errors(err) {
 			t.Log(e)
 		}
 		t.Fatal(err)
 	}
-
 	release := Release{
 		Namespace:     "foo",
 		AppInstanceId: "foo-bar",
@@ -42,28 +111,102 @@
 	}
 	keyGen := testKeyGen{}
 	r, err := app.Render(release, env, networks, nil, map[string]any{
-		"repoAddr":       "",
-		"repoPublicAddr": "",
-		"managerAddr":    "",
-		"appId":          "",
-		"branch":         "",
-		"sshPrivateKey":  "",
-		"port_db_1_0":    1,
-		"port_db_1_1":    2,
-		"port_db_1_2":    3,
-		"port_db_2_0":    4,
-		"port_db_2_1":    5,
-		"port_db_2_2":    6,
+		"managerAddr":            "",
+		"appId":                  "",
+		"sshPrivateKey":          "",
+		"port_postgresql_db_1_0": 1,
+		"port_postgresql_db_1_1": 2,
+		"port_postgresql_db_1_2": 3,
+		"port_postgresql_db_2_0": 4,
+		"port_postgresql_db_2_1": 5,
+		"port_postgresql_db_2_2": 6,
+		"port_mongodb_mdb_1_0":   1,
+		"port_mongodb_mdb_1_1":   2,
+		"port_mongodb_mdb_1_2":   3,
+		"port_mongodb_mdb_2_0":   4,
+		"port_mongodb_mdb_2_1":   5,
+		"port_mongodb_mdb_2_2":   6,
+		"port_service_app_0":     7,
+		"port_service_app_1":     8,
+		"port_service_app_2":     9,
 	}, nil, keyGen)
 	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log(string(r.Raw))
+}
+
+const canvas = `
+{
+    "service": [
+        {
+            "type": "nextjs:deno-2.0.0",
+            "name": "app",
+            "source": {
+                "repository": "ssh://d.p.v1.dodo.cloud:62533/myblog",
+                "branch": "master",
+                "rootDir": "/"
+            },
+            "ports": [
+                {
+                    "name": "web",
+                    "value": 3000,
+                    "protocol": "TCP"
+                }
+            ],
+            "env": [
+                {
+                    "name": "DODO_POSTGRESQL_DB_CONNECTION_URL"
+                }
+            ],
+            "ingress": {
+                "network": "Private",
+                "subdomain": "foo",
+                "port": {
+                    "name": "web"
+                },
+                "auth": {
+                    "enabled": false
+                }
+            },
+            "expose": [],
+            "dev": { "enabled": true, "username": "gio" }
+        }
+    ],
+    "volume": [],
+    "postgresql": [
+        {
+            "name": "db",
+            "size": "1Gi",
+            "expose": []
+        }
+    ],
+    "mongodb": []
+}
+`
+
+func TestCanvas(t *testing.T) {
+	app, err := NewDodoApp([]byte(canvas))
+	if err != nil {
 		for _, e := range errors.Errors(err) {
-			for _, f := range errors.Errors(e) {
-				for _, g := range errors.Errors(f) {
-					t.Log(g)
-				}
-			}
+			t.Log(e)
 		}
 		t.Fatal(err)
 	}
+	release := Release{
+		Namespace:     "foo",
+		AppInstanceId: "foo-bar",
+		RepoAddr:      "ssh://192.168.100.210:22/config",
+		AppDir:        "/foo/bar",
+	}
+	keyGen := testKeyGen{}
+	r, err := app.Render(release, env, networks, nil, map[string]any{
+		"managerAddr":   "",
+		"appId":         "",
+		"sshPrivateKey": "",
+	}, nil, keyGen)
+	if err != nil {
+		t.Fatal(err)
+	}
 	t.Log(string(r.Raw))
 }