ClusterManager: Implements support of remote clusters.

After this change users will be able to:
* Create cluster and add/remove servers to it
* Install apps on remote cluster
* Move already installed apps between clusters
* Apps running on server being removed will auto-migrate
  to another server from that same cluster

This is achieved by:
* Installing and running minimal version of dodo on remote cluster
* Ingress-nginx is installed automatically on new clusters
* Next to nginx we run VPN client in the same pod, so that
  default cluster can establish secure communication with it
* Multiple reverse proxies are configured to get to the
  remote cluster service from ingress installed on default cluster.

Next steps:
* Support remote clusters in dodo apps (prototype ready)
* Clean up old cluster when moving app to the new one. Currently
  old cluster keeps running app pods even though no ingress can
  reach it anymore.

Change-Id: Iffc908c93416d4126a8e1c2832eae7b659cb8044
diff --git a/core/installer/kube.go b/core/installer/kube.go
index c8251ff..7f861af 100644
--- a/core/installer/kube.go
+++ b/core/installer/kube.go
@@ -8,14 +8,14 @@
 	"io"
 	"net/http"
 
+	"github.com/giolekva/pcloud/core/installer/kube"
+
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/kubernetes"
-	"k8s.io/client-go/rest"
-	"k8s.io/client-go/tools/clientcmd"
 )
 
 type NamespaceCreator interface {
@@ -77,8 +77,8 @@
 	return buf.String(), nil
 }
 
-func NewNamespaceCreator(kubeconfig string) (NamespaceCreator, error) {
-	clientset, err := NewKubeConfig(kubeconfig)
+func NewNamespaceCreator(opts kube.KubeConfigOpts) (NamespaceCreator, error) {
+	clientset, err := kube.NewKubeClient(opts)
 	if err != nil {
 		return nil, err
 	}
@@ -120,27 +120,10 @@
 }
 
 func NewHelmReleaseMonitor(kubeconfig string) (HelmReleaseMonitor, error) {
-	c, err := NewKubeConfig(kubeconfig)
+	c, err := kube.NewKubeClient(kube.KubeConfigOpts{KubeConfigPath: kubeconfig})
 	if err != nil {
 		return nil, err
 	}
 	d := dynamic.New(c.RESTClient())
 	return &realHelmReleaseMonitor{d}, nil
 }
-
-func NewKubeConfig(kubeconfig string) (*kubernetes.Clientset, error) {
-	if kubeconfig == "" {
-		config, err := rest.InClusterConfig()
-		if err != nil {
-			return nil, err
-		}
-		return kubernetes.NewForConfig(config)
-
-	} else {
-		config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
-		if err != nil {
-			return nil, err
-		}
-		return kubernetes.NewForConfig(config)
-	}
-}