go/mirko: move kubernetes clientset state to singleton

We want to access the clientset (or at least check the fact that we're
in a cluster) outside of the Mirko object lifecycle.

In reality, this should _probably_ be moved outside of the Mirko library
and get a better API than this (ie. one that returns complete
information about the state of being in production/dev/...).

Change-Id: I86444477e0306a39a1611207855127a7b963603e
diff --git a/go/mirko/kubernetes.go b/go/mirko/kubernetes.go
index c3a0bb3..a05d4c1 100644
--- a/go/mirko/kubernetes.go
+++ b/go/mirko/kubernetes.go
@@ -1,23 +1,54 @@
 package mirko
 
 import (
+	"sync"
+
 	"github.com/golang/glog"
 	"k8s.io/client-go/kubernetes"
 	"k8s.io/client-go/rest"
 )
 
-func (m *Mirko) kubernetesConnect() {
+var (
+	// kubernetesCS is a kubernetes clientset that can connect to the cluster
+	// that this program is running in, or nil if uninitialized (or not in a
+	// cluster.
+	kubernetesCS *kubernetes.Clientset
+	// kubernetesCSValid is true when kubernetesCS is 'valid', ie. when the
+	// clientset is either an actual clientset object, or nil if the program is
+	// not running in production.
+	kubernetesCSValid bool
+	// kubernetesCSMu guards kubernetesCS and kubernetesCSValid.
+	kubernetesCSMu sync.Mutex
+)
+
+// KubernetesClient attempts to connect to Kubernetes using in-cluster
+// configuration and returns the resulting clientset. If connecting fails, nil
+// is returned. Connection will fail if the program is not running in
+// production.
+// The connection result is cached for the rest of the program lifetime, so
+// this function is cheap to call.
+func KubernetesClient() *kubernetes.Clientset {
+	kubernetesCSMu.Lock()
+	defer kubernetesCSMu.Unlock()
+
+	if kubernetesCSValid {
+		return kubernetesCS
+	}
+
+	kubernetesCSValid = true
 	config, err := rest.InClusterConfig()
 	if err != nil {
-		glog.Errorf("mirko.KubernetesClientSet: %v", err)
-		return
+		glog.Errorf("Kubernetes InClusterConfig: %v", err)
+		glog.Infof("Mirko: no kubernetes config available...")
+		return nil
 	}
-
 	clientset, err := kubernetes.NewForConfig(config)
 	if err != nil {
-		glog.Errorf("kubernetes.NewForConfig: %v", err)
-		return
+		glog.Errorf("Kubernetes NewForConfig: %v", err)
+		glog.Infof("Mirko: no kubernetes client available...")
+		return nil
 	}
 
-	m.kubernetesCS = clientset
+	kubernetesCS = clientset
+	return clientset
 }