From e8d1df72984cf68cafe0922ab5bf7b5bbdcceb14 Mon Sep 17 00:00:00 2001
From: Alex Clemmer <clemmer.alexander@gmail.com>
Date: Mon, 6 Nov 2017 11:54:51 -0800
Subject: [PATCH] Initialize `incubator` registry during `ks init`

The ksonnet project exposes a "default" registry, `incubator`, in the
ksonnet/parts repository.

This commit will cause ever `ks init` command to automatically add this
registry to the ksonnet application.
---
 metadata/environment_test.go |  3 ++-
 metadata/interface.go        | 22 +++++++++++++++++++++-
 metadata/manager.go          | 26 +++++++++++++++++++++++---
 metadata/manager_test.go     | 23 +++++++++++++++++------
 4 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/metadata/environment_test.go b/metadata/environment_test.go
index 35349e98..c2cb99f1 100644
--- a/metadata/environment_test.go
+++ b/metadata/environment_test.go
@@ -46,7 +46,8 @@ func mockEnvironments(t *testing.T, appName string) *manager {
 	}
 
 	appPath := AbsPath(appName)
-	m, err := initManager(appName, appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	reg := newMockRegistryManager("incubator")
+	m, err := initManager(appName, appPath, spec, &mockAPIServer, &mockNamespace, reg, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
diff --git a/metadata/interface.go b/metadata/interface.go
index 3e65f0f8..2d31df77 100644
--- a/metadata/interface.go
+++ b/metadata/interface.go
@@ -86,7 +86,27 @@ func Find(path AbsPath) (Manager, error) {
 // capabilities-compliant version of ksonnet-lib, and then generate the
 // directory tree for an application.
 func Init(name string, rootPath AbsPath, spec ClusterSpec, serverURI, namespace *string) (Manager, error) {
-	return initManager(name, rootPath, spec, serverURI, namespace, appFS)
+	// Generate `incubator` registry. We do this before before creating
+	// directory tree, in case the network call fails.
+	const (
+		defaultIncubatorRegName = "incubator"
+		defaultIncubatorURI     = "github.com/ksonnet/parts/tree/test-reg/" + defaultIncubatorRegName
+		defaultIncubatorRefSpec = "test-reg"
+	)
+
+	gh, err := makeGitHubRegistryManager(&app.RegistryRefSpec{
+		Protocol: "github",
+		Spec: map[string]interface{}{
+			uriField:     defaultIncubatorURI,
+			refSpecField: defaultIncubatorRefSpec,
+		},
+		Name: "incubator",
+	})
+	if err != nil {
+		return nil, err
+	}
+
+	return initManager(name, rootPath, spec, serverURI, namespace, gh, appFS)
 }
 
 // ClusterSpec represents the API supported by some cluster. There are several
diff --git a/metadata/manager.go b/metadata/manager.go
index 7356085a..14e2d705 100644
--- a/metadata/manager.go
+++ b/metadata/manager.go
@@ -26,6 +26,7 @@ import (
 
 	"github.com/ksonnet/ksonnet/metadata/app"
 	param "github.com/ksonnet/ksonnet/metadata/params"
+	"github.com/ksonnet/ksonnet/metadata/registry"
 	"github.com/ksonnet/ksonnet/prototype"
 	log "github.com/sirupsen/logrus"
 	"github.com/spf13/afero"
@@ -44,6 +45,7 @@ const (
 	environmentsDir = "environments"
 	vendorDir       = "vendor"
 
+	// Files names.
 	componentParamsFile = "params.libsonnet"
 	baseLibsonnetFile   = "base.libsonnet"
 	appYAMLFile         = "app.yaml"
@@ -102,12 +104,13 @@ func findManager(abs AbsPath, appFS afero.Fs) (*manager, error) {
 	}
 }
 
-func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, namespace *string, appFS afero.Fs) (*manager, error) {
+func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, namespace *string, incubatorReg registry.Manager, appFS afero.Fs) (*manager, error) {
 	m, err := newManager(rootPath, appFS)
 	if err != nil {
 		return nil, err
 	}
 
+	//
 	// Generate the program text for ksonnet-lib.
 	//
 	// IMPLEMENTATION NOTE: We get the cluster specification and generate
@@ -120,8 +123,18 @@ func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, nam
 		return nil, err
 	}
 
+	regSpec, err := incubatorReg.FindSpec()
+	if err != nil {
+		return nil, err
+	}
+
+	registrySpecBytes, err := regSpec.Marshal()
+	if err != nil {
+		return nil, err
+	}
+
 	// Initialize directory structure.
-	if err := m.createAppDirTree(name); err != nil {
+	if err := m.createAppDirTree(name, incubatorReg); err != nil {
 		return nil, err
 	}
 
@@ -138,6 +151,12 @@ func initManager(name string, rootPath AbsPath, spec ClusterSpec, serverURI, nam
 		}
 	}
 
+	// Write out `incubator` registry spec.
+	err = afero.WriteFile(m.appFS, string(m.registryPath(incubatorReg)), registrySpecBytes, defaultFilePermissions)
+	if err != nil {
+		return nil, err
+	}
+
 	return m, nil
 }
 
@@ -296,7 +315,7 @@ func (m *manager) createUserDirTree() error {
 	return nil
 }
 
-func (m *manager) createAppDirTree(name string) error {
+func (m *manager) createAppDirTree(name string, gh registry.Manager) error {
 	exists, err := afero.DirExists(m.appFS, string(m.rootPath))
 	if err != nil {
 		return fmt.Errorf("Could not check existance of directory '%s':\n%v", m.rootPath, err)
@@ -312,6 +331,7 @@ func (m *manager) createAppDirTree(name string) error {
 		m.componentsPath,
 		m.environmentsPath,
 		m.vendorPath,
+		m.registryDir(gh),
 	}
 
 	for _, p := range dirPaths {
diff --git a/metadata/manager_test.go b/metadata/manager_test.go
index 178106e6..673ff45d 100644
--- a/metadata/manager_test.go
+++ b/metadata/manager_test.go
@@ -61,7 +61,8 @@ func TestInitSuccess(t *testing.T) {
 	}
 
 	appPath := AbsPath("/fromEmptySwagger")
-	_, err = initManager("fromEmptySwagger", appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	reg := newMockRegistryManager("incubator")
+	_, err = initManager("fromEmptySwagger", appPath, spec, &mockAPIServer, &mockNamespace, reg, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -158,6 +159,14 @@ func TestInitSuccess(t *testing.T) {
 	} else if len(appYAMLBytes) == 0 {
 		t.Fatalf("Expected app.yaml at '%s' to be non-empty", appYAMLPath)
 	}
+
+	registryYAMLPath := appendToAbsPath(appPath, registriesDir, "incubator", "master.yaml")
+	registryYAMLBytes, err := afero.ReadFile(testFS, string(registryYAMLPath))
+	if err != nil {
+		t.Fatalf("Failed to read registry.yaml file at '%s':\n%v", registryYAMLPath, err)
+	} else if len(registryYAMLBytes) == 0 {
+		t.Fatalf("Expected registry.yaml at '%s' to be non-empty", registryYAMLPath)
+	}
 }
 
 func TestFindSuccess(t *testing.T) {
@@ -176,7 +185,8 @@ func TestFindSuccess(t *testing.T) {
 	}
 
 	appPath := AbsPath("/findSuccess")
-	_, err = initManager("findSuccess", appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	reg := newMockRegistryManager("incubator")
+	_, err = initManager("findSuccess", appPath, spec, &mockAPIServer, &mockNamespace, reg, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -204,7 +214,8 @@ func TestComponentPaths(t *testing.T) {
 	}
 
 	appPath := AbsPath("/componentPaths")
-	m, err := initManager("componentPaths", appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	reg := newMockRegistryManager("incubator")
+	m, err := initManager("componentPaths", appPath, spec, &mockAPIServer, &mockNamespace, reg, testFS)
 	if err != nil {
 		t.Fatalf("Failed to init cluster spec: %v", err)
 	}
@@ -293,14 +304,14 @@ func TestDoubleNewFailure(t *testing.T) {
 	}
 
 	appPath := AbsPath("/doubleNew")
-
-	_, err = initManager("doubleNew", appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	reg := newMockRegistryManager("incubator")
+	_, err = initManager("doubleNew", appPath, spec, &mockAPIServer, &mockNamespace, reg, 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("doubleNew", appPath, spec, &mockAPIServer, &mockNamespace, testFS)
+	_, err = initManager("doubleNew", appPath, spec, &mockAPIServer, &mockNamespace, reg, testFS)
 	if err == nil || err.Error() != targetErr {
 		t.Fatalf("Expected to fail to create app with message '%s', got '%s'", targetErr, err.Error())
 	}
-- 
GitLab