AppManager: Handle new port forwards during app update

Change-Id: I72a4c5b7ec4bd5ba6ddd32cd3f33dce023d7d9ea
diff --git a/core/installer/app_test.go b/core/installer/app_test.go
index 7a7bf7a..0838f14 100644
--- a/core/installer/app_test.go
+++ b/core/installer/app_test.go
@@ -6,6 +6,7 @@
 	"net"
 	"testing"
 
+	"cuelang.org/go/cue"
 	"cuelang.org/go/cue/errors"
 )
 
@@ -644,3 +645,63 @@
 		t.Log(string(r))
 	}
 }
+
+func TestUpdateUsesPreviousValues(t *testing.T) {
+	contents := `
+input: {
+  port: int | *5
+}
+
+out: {
+  openPort: [{
+    name: "api"
+    network: networks["private"]
+    port: input.port
+    service: {
+      name: "app"
+      port: 8080
+    }
+  }]
+}
+
+input: {
+  port: 10
+}
+`
+	app, err := NewCueEnvApp(CueAppData{
+		"base.cue":   []byte(cueBaseConfig),
+		"app.cue":    []byte(contents),
+		"global.cue": []byte(cueEnvAppGlobal),
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	a, ok := app.(cueEnvApp)
+	if !ok {
+		t.Fatal("expected cue app")
+	}
+	defaults, err := ExtractDefaultValues(a.cfg.LookupPath(cue.ParsePath("input")))
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Log(defaults)
+	if defaults.(map[string]any)["port"].(int64) != 10 {
+		t.Fatal("port")
+	}
+}
+
+func TestMerge(t *testing.T) {
+	x := map[string]any{
+		"key": map[string]any{
+			"pub":  1,
+			"priv": 2,
+		},
+	}
+	y := map[string]any{
+		"foo": 3,
+	}
+	z := merge(x, y)
+	if _, ok := z["foo"]; !ok {
+		t.Fatal(z)
+	}
+}