AppManager: Support exposing cross-cluster ports

Change-Id: I4bdb3573209935f6777656ec2f3481e79d84a9c9
diff --git a/core/installer/app_manager.go b/core/installer/app_manager.go
index c5b849f..3285c19 100644
--- a/core/installer/app_manager.go
+++ b/core/installer/app_manager.go
@@ -182,10 +182,19 @@
 	Secret string `json:"secret"`
 }
 
-func reservePorts(ports map[string]string) (map[string]reservePortResp, error) {
+type reservePortInfo struct {
+	reserveAddr string
+	RemoteProxy bool `json:"remoteProxy"`
+}
+
+func reservePorts(ports map[string]reservePortInfo) (map[string]reservePortResp, error) {
 	ret := map[string]reservePortResp{}
-	for p, reserveAddr := range ports {
-		resp, err := http.Post(reserveAddr, "application/json", nil) // TODO(gio): address
+	for p, cfg := range ports {
+		var buf bytes.Buffer
+		if err := json.NewEncoder(&buf).Encode(cfg); err != nil {
+			return nil, err
+		}
+		resp, err := http.Post(cfg.reserveAddr, "application/json", &buf)
 		if err != nil {
 			return nil, err
 		}
@@ -205,11 +214,17 @@
 
 func openPorts(ports []PortForward, reservations map[string]reservePortResp, allocators map[string]string, ns string) error {
 	for _, p := range ports {
+		var target string
+		if p.Cluster == "" {
+			target = fmt.Sprintf("%s/%s", ns, p.Service.Name)
+		} else {
+			target = p.Service.Name
+		}
 		var buf bytes.Buffer
 		req := allocatePortReq{
 			Protocol:      p.Protocol,
 			SourcePort:    p.Port,
-			TargetService: fmt.Sprintf("%s/%s", ns, p.Service.Name),
+			TargetService: target,
 			TargetPort:    p.Service.Port,
 		}
 		allocator := ""
@@ -475,10 +490,13 @@
 	if err != nil {
 		return ReleaseResources{}, err
 	}
-	reservators := map[string]string{}
+	reservators := map[string]reservePortInfo{}
 	allocators := map[string]string{}
 	for _, pf := range rendered.Ports {
-		reservators[portFields[pf.Port]] = pf.ReserveAddr
+		reservators[portFields[pf.Port]] = reservePortInfo{
+			reserveAddr: pf.ReserveAddr,
+			RemoteProxy: pf.Cluster != "",
+		}
 		allocators[portFields[pf.Port]] = pf.Allocator
 	}
 	portReservations, err := reservePorts(reservators)
@@ -530,7 +548,7 @@
 		return ReleaseResources{}, err
 	}
 	for _, p := range rendered.ClusterProxies {
-		if err := m.cnc.AddProxy(p.From, p.To); err != nil {
+		if err := m.cnc.AddIngressProxy(p.From, p.To); err != nil {
 			return ReleaseResources{}, err
 		}
 	}
@@ -651,7 +669,7 @@
 			}
 		}
 		if !found {
-			if err := m.cnc.RemoveProxy(ocp.From, ocp.To); err != nil {
+			if err := m.cnc.RemoveIngressProxy(ocp.From, ocp.To); err != nil {
 				return ReleaseResources{}, err
 			}
 		}
@@ -665,7 +683,7 @@
 			}
 		}
 		if !found {
-			if err := m.cnc.AddProxy(ncp.From, ncp.To); err != nil {
+			if err := m.cnc.AddIngressProxy(ncp.From, ncp.To); err != nil {
 				return ReleaseResources{}, err
 			}
 		}
@@ -723,7 +741,7 @@
 		return err
 	}
 	for _, cp := range cfg.Out.ClusterProxy {
-		if err := m.cnc.RemoveProxy(cp.From, cp.To); err != nil {
+		if err := m.cnc.RemoveIngressProxy(cp.From, cp.To); err != nil {
 			return err
 		}
 	}