app-manager: support triggers
diff --git a/appmanager/cmd/main.go b/appmanager/cmd/main.go
index 149a11d..4ad45cc 100644
--- a/appmanager/cmd/main.go
+++ b/appmanager/cmd/main.go
@@ -1,7 +1,9 @@
 package main
 
 import (
+	"bytes"
 	"context"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"io"
@@ -26,6 +28,7 @@
 var helmBin = flag.String("helm_bin", "/usr/local/bin/helm", "Path to the Helm binary.")
 var port = flag.Int("port", 1234, "Port to listen on.")
 var apiAddr = flag.String("api_addr", "", "PCloud API service address.")
+var managerStoreFile = flag.String("manager_store_file", "", "Persistent file containing installed application information.")
 
 var helmUploadPage = `
 <html>
@@ -42,10 +45,11 @@
 `
 
 type handler struct {
+	manager  *app.Manager
 	nsClient corev1.NamespaceInterface
 }
 
-func (hn *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+func (hn *handler) handleInstall(w http.ResponseWriter, r *http.Request) {
 	if r.Method == "GET" {
 		_, err := io.WriteString(w, helmUploadPage)
 		if err != nil {
@@ -82,7 +86,7 @@
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
 		}
-		if err = installHelmChart(p, hn.nsClient); err != nil {
+		if err = hn.installHelmChart(p); err != nil {
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 			return
 		}
@@ -90,7 +94,46 @@
 	}
 }
 
-func installHelmChart(path string, nsClient corev1.NamespaceInterface) error {
+type trigger struct {
+	Namespace string `json:"namespace"`
+	Template  string `json:"template"`
+}
+
+func (hn *handler) handleTriggers(w http.ResponseWriter, r *http.Request) {
+	if r.Method != "GET" {
+		http.Error(w, "Only GET method is supported on /triggers", http.StatusBadRequest)
+		return
+	}
+	if err := r.ParseForm(); err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+	// TODO(giolekva): check if exists
+	triggerOnType := r.Form["trigger_on_type"][0]
+	triggerOnEvent := r.Form["trigger_on_event"][0]
+	var triggers []trigger
+	for _, a := range hn.manager.Apps {
+		if a.Triggers == nil {
+			continue
+		}
+		for _, t := range a.Triggers.Triggers {
+			if t.TriggerOn.Type == triggerOnType && t.TriggerOn.Event == triggerOnEvent {
+				triggers = append(triggers, trigger{a.Namespace, t.Template})
+			}
+		}
+	}
+	respBody, err := json.Marshal(triggers)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+	if _, err := io.Copy(w, bytes.NewReader(respBody)); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+}
+
+func (hn *handler) installHelmChart(path string) error {
 	h, err := app.HelmChartFromTar(path)
 	if err != nil {
 		return err
@@ -100,7 +143,7 @@
 	}
 	glog.Infof("Installed schema: %s", h.Schema)
 	namespace := fmt.Sprintf("app-%s", h.Name)
-	if err = createNamespace(nsClient, namespace); err != nil {
+	if err = createNamespace(hn.nsClient, namespace); err != nil {
 		return err
 	}
 	glog.Infof("Created namespaces: %s", namespace)
@@ -109,6 +152,9 @@
 		map[string]string{}); err != nil {
 		return err
 	}
+	glog.Info("Deployed")
+	hn.manager.Apps[h.Name] = app.App{namespace, h.Triggers}
+	app.StoreManagerStateToFile(hn.manager, *managerStoreFile)
 	glog.Info("Installed")
 	return nil
 }
@@ -142,7 +188,13 @@
 		glog.Fatalf("Could not create Kubernetes API client: %v", err)
 	}
 	namespaces := clientset.CoreV1().Namespaces()
-	http.Handle("/", &handler{namespaces})
+	manager, err := app.LoadManagerStateFromFile(*managerStoreFile)
+	if err != nil {
+		glog.Fatalf("Could ot initialize manager: %v", err)
+	}
+	h := handler{manager, namespaces}
+	http.HandleFunc("/triggers", h.handleTriggers)
+	http.HandleFunc("/", h.handleInstall)
 	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), nil))
 
 }