From 61e7d9d7b918d7d197b4d0b4b88b6339eb251b9d Mon Sep 17 00:00:00 2001
From: Shane Starcher <shanestarcher@gmail.com>
Date: Tue, 13 Nov 2018 09:46:35 -0800
Subject: [PATCH] add support for release stats

---
 .gitignore                                   |  1 +
 helm/helm-exporter/templates/deployment.yaml |  4 +-
 main.go                                      | 76 ++++++++++++++++----
 3 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore
index 9df240c..a994034 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
 helm_exporter
+helm/helm-exporter*.tgz
diff --git a/helm/helm-exporter/templates/deployment.yaml b/helm/helm-exporter/templates/deployment.yaml
index b66c653..bec26e9 100644
--- a/helm/helm-exporter/templates/deployment.yaml
+++ b/helm/helm-exporter/templates/deployment.yaml
@@ -29,11 +29,11 @@ spec:
               protocol: TCP
           livenessProbe:
             httpGet:
-              path: /
+              path: /metrics
               port: http
           readinessProbe:
             httpGet:
-              path: /
+              path: /metrics
               port: http
           resources:
 {{ toYaml .Values.resources | indent 12 }}
diff --git a/main.go b/main.go
index cecf973..f9f6e9f 100644
--- a/main.go
+++ b/main.go
@@ -1,12 +1,15 @@
 package main
 
 import (
+	"fmt"
 	"time"
 
 	"net/http"
 
 	"k8s.io/helm/pkg/helm"
 
+	"k8s.io/helm/pkg/proto/hapi/release"
+
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promauto"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
@@ -23,35 +26,82 @@ var (
 	})
 
 	client = NewClient()
-)
 
-func HelmStats() {
-	items, err := client.ListReleases()
-	if err == nil {
-		for _, item := range items.GetReleases() {
-			stats.WithLabelValues(item.GetChart().GetMetadata().GetName(), item.GetName(), item.GetChart().GetMetadata().GetVersion()).Set(1)
-		}
+	inClusterTiller = "tiller-deploy.kube-system:44134"
+	localTiller     = "127.0.0.1:44134"
+	statusCodes     = []release.Status_Code{
+		release.Status_UNKNOWN,
+		release.Status_DEPLOYED,
+		release.Status_DELETED,
+		release.Status_DELETING,
+		release.Status_FAILED,
+		release.Status_PENDING_INSTALL,
+		release.Status_PENDING_UPGRADE,
+		release.Status_PENDING_ROLLBACK,
 	}
-}
+)
 
 func NewClient() *helm.Client {
-	client := helm.NewClient(helm.Host("tiller-deploy.kube-system:44134"))
+	fmt.Printf("attempting to connect to %s\n", inClusterTiller)
+	client := helm.NewClient(helm.Host(inClusterTiller))
 	err := client.PingTiller()
 	if err != nil {
-		client = helm.NewClient(helm.Host("127.0.0.1:44134"))
+		fmt.Printf("attempting to connect to %s\n", localTiller)
+		client = helm.NewClient(helm.Host(localTiller))
 		err := client.PingTiller()
 		if err != nil {
-			panic("unable to connect to 127.0.0.1:44134 and tiller-deploy.kube-system:44134")
+			panic(fmt.Sprintf("unable to connect to %s and %s\n", inClusterTiller, localTiller))
 		}
+		fmt.Printf("connected to %s\n", localTiller)
+		return client
 	}
+	fmt.Printf("connected to %s\n", inClusterTiller)
 	return client
 }
 
+// Taken from https://github.com/helm/helm/blob/master/cmd/helm/list.go#L197
+// filterList returns a list scrubbed of old releases.
+func filterList(rels []*release.Release) []*release.Release {
+	idx := map[string]int32{}
+
+	for _, r := range rels {
+		name, version := r.GetName(), r.GetVersion()
+		if max, ok := idx[name]; ok {
+			// check if we have a greater version already
+			if max > version {
+				continue
+			}
+		}
+		idx[name] = version
+	}
+
+	uniq := make([]*release.Release, 0, len(idx))
+	for _, r := range rels {
+		if idx[r.GetName()] == r.GetVersion() {
+			uniq = append(uniq, r)
+		}
+	}
+	return uniq
+}
+
+func helmStats() {
+	items, err := client.ListReleases(helm.ReleaseListStatuses(statusCodes))
+	if err == nil {
+		for _, item := range filterList(items.GetReleases()) {
+			chart := item.GetChart().GetMetadata().GetName()
+			status := item.GetInfo().GetStatus().GetCode()
+			release := item.GetName()
+			version := item.GetChart().GetMetadata().GetVersion()
+			stats.WithLabelValues(chart, release, version).Set(float64(status))
+		}
+	}
+}
+
 func main() {
 	go func() {
 		for {
-			HelmStats()
-			time.Sleep(2 * time.Second)
+			helmStats()
+			time.Sleep(30 * time.Second)
 		}
 	}()