From 361a62c03b3043902f4c749d88c8a26abc6b9947 Mon Sep 17 00:00:00 2001
From: Alex Clemmer <clemmer.alexander@gmail.com>
Date: Wed, 20 Sep 2017 22:39:06 -0700
Subject: [PATCH] Cause `init` to generate env using current-context

When we run `init`, currently we generate a simple environment called
'default' with no URI. A better idea is to generate the URI from the
current context of the active kubeconfig file, if it exists.
---
 cmd/init.go                  | 41 ++++++++++++++++++++++++++++++------
 metadata/environment_test.go |  4 +++-
 metadata/interface.go        |  4 ++--
 metadata/manager.go          |  9 +++++---
 metadata/manager_test.go     | 10 ++++-----
 pkg/kubecfg/init.go          | 11 +++++-----
 6 files changed, 56 insertions(+), 23 deletions(-)

diff --git a/cmd/init.go b/cmd/init.go
index 250ca7d6..fafe64df 100644
--- a/cmd/init.go
+++ b/cmd/init.go
@@ -20,6 +20,8 @@ import (
 	"os"
 	"path"
 
+	"k8s.io/client-go/tools/clientcmd/api"
+
 	"github.com/ksonnet/kubecfg/metadata"
 	"github.com/ksonnet/kubecfg/pkg/kubecfg"
 	"github.com/spf13/cobra"
@@ -53,7 +55,32 @@ var initCmd = &cobra.Command{
 			return err
 		}
 
-		c, err := kubecfg.NewInitCmd(appRoot, specFlag)
+		//
+		// Find the URI of the current cluster, if it exists.
+		//
+
+		rawConfig, err := clientConfig.RawConfig()
+		if err != nil {
+			return err
+		}
+
+		var currCtx *api.Context
+		for name, ctx := range rawConfig.Contexts {
+			if name == rawConfig.CurrentContext {
+				currCtx = ctx
+			}
+		}
+
+		var currClusterURI *string
+		if rawConfig.CurrentContext != "" && currCtx != nil {
+			for name, cluster := range rawConfig.Clusters {
+				if currCtx.Cluster == name {
+					currClusterURI = &cluster.Server
+				}
+			}
+		}
+
+		c, err := kubecfg.NewInitCmd(appRoot, specFlag, currClusterURI)
 		if err != nil {
 			return err
 		}
@@ -73,12 +100,12 @@ consists of two steps:
    app-name/
      .gitignore     Default .gitignore; can customize VCS
      .ksonnet/      Metadata for ksonnet
-     envs/          Env specs (defaults: dev, test, prod)
-       params.yaml  Specifies the schema of the environments
-       dev.yaml
-       test.yaml
-       prod.yaml
-       us-east.yaml [Example of user-generated env]
+     envs/
+       default/     Default generated environment]
+         k.libsonnet
+         k8s.libsonnet
+         swagger.json
+         spec.json
      components/    Top-level Kubernetes objects defining application
      lib/           user-written .libsonnet files
      vendor/        mixin libraries, prototypes
diff --git a/metadata/environment_test.go b/metadata/environment_test.go
index b94d9f16..2d9d2d73 100644
--- a/metadata/environment_test.go
+++ b/metadata/environment_test.go
@@ -34,6 +34,8 @@ const (
 	mockEnvName3 = "us-east/test"
 )
 
+var mockAPIServerURI = "http://google.com"
+
 func mockEnvironments(t *testing.T, appName string) *manager {
 	spec, err := parseClusterSpec(fmt.Sprintf("file:%s", blankSwagger), testFS)
 	if err != nil {
@@ -41,7 +43,7 @@ func mockEnvironments(t *testing.T, appName string) *manager {
 	}
 
 	appPath := AbsPath(appName)
-	m, err := initManager(appPath, spec, testFS)
+	m, err := initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
diff --git a/metadata/interface.go b/metadata/interface.go
index 3a1d780b..c59c9b77 100644
--- a/metadata/interface.go
+++ b/metadata/interface.go
@@ -64,8 +64,8 @@ func Find(path AbsPath) (Manager, error) {
 // Init will retrieve a cluster API specification, generate a
 // capabilities-compliant version of ksonnet-lib, and then generate the
 // directory tree for an application.
-func Init(rootPath AbsPath, spec ClusterSpec) (Manager, error) {
-	return initManager(rootPath, spec, appFS)
+func Init(rootPath AbsPath, spec ClusterSpec, serverURI *string) (Manager, error) {
+	return initManager(rootPath, spec, serverURI, appFS)
 }
 
 // ClusterSpec represents the API supported by some cluster. There are several
diff --git a/metadata/manager.go b/metadata/manager.go
index 21742567..2950905c 100644
--- a/metadata/manager.go
+++ b/metadata/manager.go
@@ -70,7 +70,7 @@ func findManager(abs AbsPath, appFS afero.Fs) (*manager, error) {
 	}
 }
 
-func initManager(rootPath AbsPath, spec ClusterSpec, appFS afero.Fs) (*manager, error) {
+func initManager(rootPath AbsPath, spec ClusterSpec, serverURI *string, appFS afero.Fs) (*manager, error) {
 	m := newManager(rootPath, appFS)
 
 	// Generate the program text for ksonnet-lib.
@@ -92,8 +92,11 @@ func initManager(rootPath AbsPath, spec ClusterSpec, appFS afero.Fs) (*manager,
 
 	// Initialize environment, and cache specification data.
 	// TODO the URI for the default environment needs to be generated from KUBECONFIG
-	if err := m.createEnvironment(defaultEnvName, "", extensionsLibData, k8sLibData, specData); err != nil {
-		return nil, err
+	if serverURI != nil {
+		err := m.createEnvironment(defaultEnvName, *serverURI, extensionsLibData, k8sLibData, specData)
+		if err != nil {
+			return nil, err
+		}
 	}
 
 	return m, nil
diff --git a/metadata/manager_test.go b/metadata/manager_test.go
index 783155b5..66c8f2d7 100644
--- a/metadata/manager_test.go
+++ b/metadata/manager_test.go
@@ -59,7 +59,7 @@ func TestInitSuccess(t *testing.T) {
 	}
 
 	appPath := AbsPath("/fromEmptySwagger")
-	_, err = initManager(appPath, spec, testFS)
+	_, err = initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -126,7 +126,7 @@ func TestFindSuccess(t *testing.T) {
 	}
 
 	appPath := AbsPath("/findSuccess")
-	_, err = initManager(appPath, spec, testFS)
+	_, err = initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -154,7 +154,7 @@ func TestComponentPaths(t *testing.T) {
 	}
 
 	appPath := AbsPath("/componentPaths")
-	m, err := initManager(appPath, spec, testFS)
+	m, err := initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -221,13 +221,13 @@ func TestDoubleNewFailure(t *testing.T) {
 
 	appPath := AbsPath("/doubleNew")
 
-	_, err = initManager(appPath, spec, testFS)
+	_, err = initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
 
 	targetErr := fmt.Sprintf("Could not create app; directory '%s' already exists", appPath)
-	_, err = initManager(appPath, spec, testFS)
+	_, err = initManager(appPath, spec, &mockAPIServerURI, testFS)
 	if err == nil || err.Error() != targetErr {
 		t.Fatalf("Expected to fail to create app with message '%s', got '%s'", targetErr, err.Error())
 	}
diff --git a/pkg/kubecfg/init.go b/pkg/kubecfg/init.go
index 454d7dc8..851a915a 100644
--- a/pkg/kubecfg/init.go
+++ b/pkg/kubecfg/init.go
@@ -3,11 +3,12 @@ package kubecfg
 import "github.com/ksonnet/kubecfg/metadata"
 
 type InitCmd struct {
-	rootPath metadata.AbsPath
-	spec     metadata.ClusterSpec
+	rootPath  metadata.AbsPath
+	spec      metadata.ClusterSpec
+	serverURI *string
 }
 
-func NewInitCmd(rootPath metadata.AbsPath, specFlag string) (*InitCmd, error) {
+func NewInitCmd(rootPath metadata.AbsPath, specFlag string, serverURI *string) (*InitCmd, error) {
 	// NOTE: We're taking `rootPath` here as an absolute path (rather than a partial path we expand to an absolute path)
 	// to make it more testable.
 
@@ -16,10 +17,10 @@ func NewInitCmd(rootPath metadata.AbsPath, specFlag string) (*InitCmd, error) {
 		return nil, err
 	}
 
-	return &InitCmd{rootPath: rootPath, spec: spec}, nil
+	return &InitCmd{rootPath: rootPath, spec: spec, serverURI: serverURI}, nil
 }
 
 func (c *InitCmd) Run() error {
-	_, err := metadata.Init(c.rootPath, c.spec)
+	_, err := metadata.Init(c.rootPath, c.spec, c.serverURI)
 	return err
 }
-- 
GitLab