appmanager: support init::postInstall
diff --git a/appmanager/actions.go b/appmanager/actions.go
index 88d2551..65fb061 100644
--- a/appmanager/actions.go
+++ b/appmanager/actions.go
@@ -16,6 +16,20 @@
 	Actions []Action `yaml:"actions"`
 }
 
+type CallAction struct {
+	App    string                 `yaml:"app"`
+	Action string                 `yaml:"action"`
+	Args   map[string]interface{} `yaml:"args"`
+}
+
+type PostInstall struct {
+	CallAction []CallAction `yaml:"callAction"`
+}
+
+type Init struct {
+	PostInstall PostInstall `yaml:"postInstall"`
+}
+
 func FromYaml(str string, out interface{}) error {
 	return yaml.Unmarshal([]byte(str), out)
 }
diff --git a/appmanager/cmd/main.go b/appmanager/cmd/main.go
index 4905a04..b4ef21a 100644
--- a/appmanager/cmd/main.go
+++ b/appmanager/cmd/main.go
@@ -149,25 +149,24 @@
 		http.Error(w, err.Error(), http.StatusBadRequest)
 		return
 	}
+	if err := hn.launchAction(req); err != nil {
+		http.Error(w, err.Error(), http.StatusBadRequest)
+		return
+	}
+}
+
+func (hn *handler) launchAction(req actionReq) error {
 	for _, a := range hn.manager.Apps {
 		if a.Name != req.App {
 			continue
 		}
 		for _, action := range a.Actions.Actions {
-			if action.Name != req.Action {
-				continue
+			if action.Name == req.Action {
+				return hn.launcher.Launch(a.Namespace, action.Template, req.Args)
 			}
-			err := hn.launcher.Launch(a.Namespace, action.Template, req.Args)
-			if err != nil {
-				http.Error(w, err.Error(), http.StatusInternalServerError)
-			}
-			return
 		}
 	}
-	http.Error(
-		w,
-		fmt.Sprintf("Application action not found: %s %s", req.App, req.Action),
-		http.StatusBadRequest)
+	return fmt.Errorf("Action not found: %s %s", req.App, req.Action)
 }
 
 func (hn *handler) installHelmChart(path string) error {
@@ -197,6 +196,11 @@
 	}
 	hn.manager.Apps[h.Name] = app.App{h.Name, namespace, h.Triggers, h.Actions}
 	app.StoreManagerStateToFile(hn.manager, *managerStoreFile)
+	for _, a := range h.Init.PostInstall.CallAction {
+		if err := hn.launchAction(actionReq{a.App, a.Action, a.Args}); err != nil {
+			return err
+		}
+	}
 	glog.Info("Installed")
 	return nil
 }
diff --git a/appmanager/helm.go b/appmanager/helm.go
index ede5faf..c8c2730 100644
--- a/appmanager/helm.go
+++ b/appmanager/helm.go
@@ -26,6 +26,7 @@
 	Schema   Schema
 	Triggers Triggers
 	Actions  Actions
+	Init     Init
 	Yamls    []string
 }
 
@@ -48,6 +49,10 @@
 	if err != nil && !os.IsNotExist(err) {
 		return nil, err
 	}
+	err = FromYamlFile(path.Join(chartDir, "Init.yaml"), &chart.Init)
+	if err != nil && !os.IsNotExist(err) {
+		return nil, err
+	}
 	return &chart, nil
 }
 
diff --git a/appmanager/install.yaml b/appmanager/install.yaml
index a4c9d69..b6ea5f6 100644
--- a/appmanager/install.yaml
+++ b/appmanager/install.yaml
@@ -17,14 +17,17 @@
   name: deploy-apps
 rules:
   - apiGroups: [""]
-    resources: ["namespaces", "services", "pods", "secrets"]
+    resources: ["namespaces", "services", "pods", "secrets", "serviceaccounts", "configmaps", "persistentvolumeclaims"]
     verbs: ["*"]
   - apiGroups: ["apps"]
     resources: ["deployments", "statefulsets"]
     verbs: ["*"]
   - apiGroups: ["traefik.containo.us"]
     resources: ["ingressroutes"]
-    verbs: ["*"] 
+    verbs: ["*"]
+  - apiGroups: ["rbac.authorization.k8s.io"]
+    resources: ["roles", "rolebindings"]
+    verbs: ["*"]
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: ClusterRoleBinding
diff --git a/appmanager/main b/appmanager/main
new file mode 100755
index 0000000..9ad7e7c
--- /dev/null
+++ b/appmanager/main
Binary files differ