AppManager: monitor installed HelmRelease resources

Change-Id: Ia036e7dda8136ad696d8222e799c4d1b6a9018a9
diff --git a/core/installer/tasks/dns.go b/core/installer/tasks/dns.go
index 1316dc0..0424cfe 100644
--- a/core/installer/tasks/dns.go
+++ b/core/installer/tasks/dns.go
@@ -49,7 +49,7 @@
 			instanceId := app.Slug()
 			appDir := fmt.Sprintf("/apps/%s", instanceId)
 			namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-			if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+			if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 				"addressPool":  addressPool,
 				"inClusterIP":  env.Network.DNSInClusterIP.String(),
 				"publicIP":     join(env.PublicIP, ","),
@@ -84,7 +84,7 @@
 				env.Domain,
 				env.Network.DNSInClusterIP.String(),
 			})
-			if err := st.infraAppManager.Update(app, "dns-gateway", map[string]any{
+			if _, err := st.infraAppManager.Update(app, "dns-gateway", map[string]any{
 				"servers": servers,
 			}); err != nil {
 				return err
diff --git a/core/installer/tasks/infra.go b/core/installer/tasks/infra.go
index 746b9cf..91d0fd9 100644
--- a/core/installer/tasks/infra.go
+++ b/core/installer/tasks/infra.go
@@ -125,7 +125,7 @@
 				instanceId := fmt.Sprintf("%s-ingress-private", app.Slug())
 				appDir := fmt.Sprintf("/apps/%s", instanceId)
 				namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
-				if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+				if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 					"name":       fmt.Sprintf("%s-ingress-private", env.Id),
 					"from":       env.Network.Ingress.String(),
 					"to":         env.Network.Ingress.String(),
@@ -139,7 +139,7 @@
 				instanceId := fmt.Sprintf("%s-headscale", app.Slug())
 				appDir := fmt.Sprintf("/apps/%s", instanceId)
 				namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
-				if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+				if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 					"name":       fmt.Sprintf("%s-headscale", env.Id),
 					"from":       env.Network.Headscale.String(),
 					"to":         env.Network.Headscale.String(),
@@ -153,7 +153,7 @@
 				instanceId := app.Slug()
 				appDir := fmt.Sprintf("/apps/%s", instanceId)
 				namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-				if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+				if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 					"name":       env.Id,
 					"from":       env.Network.ServicesFrom.String(),
 					"to":         env.Network.ServicesTo.String(),
@@ -183,7 +183,7 @@
 			instanceId := app.Slug()
 			appDir := fmt.Sprintf("/apps/%s", instanceId)
 			namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-			if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+			if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 				"privateNetwork": map[string]any{
 					"hostname": "private-network-proxy",
 					"username": "private-network-proxy",
@@ -208,7 +208,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
 			return err
 		}
 		return nil
@@ -221,7 +221,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
 			return err
 		}
 		return nil
@@ -238,7 +238,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"subdomain": "test", // TODO(giolekva): make core-auth chart actually use this
 		}); err != nil {
 			return err
@@ -262,7 +262,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"authGroups": strings.Join(initGroups, ","),
 		}); err != nil {
 			return err
@@ -286,7 +286,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"subdomain": "headscale",
 			"ipSubnet":  fmt.Sprintf("%s/24", env.Network.DNS.String()),
 		}); err != nil {
@@ -322,7 +322,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"repoAddr":      st.ssClient.GetRepoAddress("config"),
 			"sshPrivateKey": string(keys.RawPrivateKey()),
 		}); err != nil {
@@ -358,7 +358,7 @@
 		instanceId := app.Slug()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"repoAddr":      st.ssClient.GetRepoAddress("config"),
 			"sshPrivateKey": string(keys.RawPrivateKey()),
 			"authGroups":    strings.Join(initGroups, ","),
@@ -390,7 +390,7 @@
 		instanceId := app.Name()
 		appDir := fmt.Sprintf("/apps/%s", instanceId)
 		namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
-		if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
+		if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
 			"repoAddr":      st.ssClient.GetRepoAddress("config"),
 			"sshPrivateKey": string(keys.RawPrivateKey()),
 		}); err != nil {
diff --git a/core/installer/tasks/init.go b/core/installer/tasks/init.go
index 20e428d..f55344d 100644
--- a/core/installer/tasks/init.go
+++ b/core/installer/tasks/init.go
@@ -53,11 +53,12 @@
 			return err
 		}
 		appDir := filepath.Join("/environments", env.Id, "config-repo")
-		return st.infraAppManager.Install(app, appDir, env.Id, map[string]any{
+		_, err = st.infraAppManager.Install(app, appDir, env.Id, map[string]any{
 			"privateKey": string(keys.RawPrivateKey()),
 			"publicKey":  string(keys.RawAuthorizedKey()),
 			"adminKey":   string(adminKeys.RawAuthorizedKey()),
 		})
+		return err
 	})
 	return &t
 }
diff --git a/core/installer/tasks/reconciler.go b/core/installer/tasks/reconciler.go
index 461ffc8..0e8133e 100644
--- a/core/installer/tasks/reconciler.go
+++ b/core/installer/tasks/reconciler.go
@@ -27,7 +27,7 @@
 func (r fluxcdReconciler) Reconcile(ctx context.Context) {
 	for {
 		select {
-		case <-time.After(30 * time.Second):
+		case <-time.After(3 * time.Second):
 			for _, res := range r.resources {
 				http.Get(res)
 			}
diff --git a/core/installer/tasks/release.go b/core/installer/tasks/release.go
new file mode 100644
index 0000000..53e5e74
--- /dev/null
+++ b/core/installer/tasks/release.go
@@ -0,0 +1,29 @@
+package tasks
+
+import (
+	"fmt"
+	"time"
+
+	"github.com/giolekva/pcloud/core/installer"
+)
+
+func NewMonitorRelease(mon installer.HelmReleaseMonitor, rr installer.ReleaseResources) Task {
+	var t []Task
+	for _, h := range rr.Helm {
+		t = append(t, newMonitorHelm(mon, h))
+	}
+	return newConcurrentParentTask("Monitor", true, t...)
+}
+
+func newMonitorHelm(mon installer.HelmReleaseMonitor, h installer.Resource) Task {
+	t := newLeafTask(fmt.Sprintf("%s/%s", h.Namespace, h.Name), func() error {
+		for {
+			if ok, err := mon.IsReleased(h.Namespace, h.Name); err == nil && ok {
+				break
+			}
+			time.Sleep(5 * time.Second)
+		}
+		return nil
+	})
+	return &t
+}