From 43896a67b3ccdd9da3f49fa81c58d24c6b66d8f7 Mon Sep 17 00:00:00 2001
From: Jessica Yuen <im.jessicayuen@gmail.com>
Date: Mon, 2 Oct 2017 10:45:01 -0700
Subject: [PATCH] Generate per-environment override file
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This commit will generate an "<env-name>.jsonnet" file when an
environment is created.

For example, the default environment would have the following tree
structure:
├── environments
│   ├── base.libsonnet
│   └── default
│       ├── .metadata
│       │   ├── k.libsonnet
│       │   ├── k8s.libsonnet
│       │   └── swagger.json
│       ├── default.jsonnet
│       └── spec.json

The goal of this file is to allow users to extend on base.libsonnet on a
per-environment basis to allow for custom overrides, such as replica
count.
---
 metadata/environment.go      | 23 +++++++++++++++++++++++
 metadata/environment_test.go | 17 +++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/metadata/environment.go b/metadata/environment.go
index d4e3a534..8d1e8ef7 100644
--- a/metadata/environment.go
+++ b/metadata/environment.go
@@ -16,9 +16,11 @@
 package metadata
 
 import (
+	"bytes"
 	"encoding/json"
 	"fmt"
 	"os"
+	"path"
 	"path/filepath"
 	"strings"
 
@@ -121,6 +123,17 @@ func (m *manager) createEnvironment(name, uri string, extensionsLibData, k8sLibD
 		return err
 	}
 
+	// Generate the base.libsonnet override file
+	overrideFileName := path.Base(name) + ".jsonnet"
+	overrideData := m.generateOverrideData()
+	log.Debugf("Generating '%s', length: %d", overrideFileName, len(overrideData))
+	overrideLibPath := appendToAbsPath(envPath, overrideFileName)
+	err = afero.WriteFile(m.appFS, string(overrideLibPath), overrideData, defaultFilePermissions)
+	if err != nil {
+		log.Debugf("Failed to write '%s'", overrideFileName)
+		return err
+	}
+
 	// Generate the environment spec file.
 	envSpecData, err := generateSpecData(uri)
 	if err != nil {
@@ -334,6 +347,16 @@ func (m *manager) generateKsonnetLibData(spec ClusterSpec) ([]byte, []byte, []by
 	return extensionsLibData, k8sLibData, text, err
 }
 
+func (m *manager) generateOverrideData() []byte {
+	var buf bytes.Buffer
+	buf.WriteString(fmt.Sprintf("local base = import \"%s\";\n", m.baseLibsonnetPath))
+	buf.WriteString(fmt.Sprintf("local k = import \"%s\";\n\n", path.Join(metadataDirName, extensionsLibFilename)))
+	buf.WriteString("base + {\n")
+	buf.WriteString("  // Insert user-specified overrides here.\n")
+	buf.WriteString("}\n")
+	return buf.Bytes()
+}
+
 func generateSpecData(uri string) ([]byte, error) {
 	// Format the spec json and return; preface keys with 2 space idents.
 	return json.MarshalIndent(EnvironmentSpec{URI: uri}, "", "  ")
diff --git a/metadata/environment_test.go b/metadata/environment_test.go
index 2d9d2d73..d922b6fc 100644
--- a/metadata/environment_test.go
+++ b/metadata/environment_test.go
@@ -180,3 +180,20 @@ func TestSetEnvironment(t *testing.T) {
 		t.Fatalf("Expected set URI to be \"%s\", got:\n  %s", set.URI, envSpec.URI)
 	}
 }
+
+func TestGenerateOverrideData(t *testing.T) {
+	m := mockEnvironments(t, "test-gen-override-data")
+
+	expected := `local base = import "test-gen-override-data/environments/base.libsonnet";
+local k = import ".metadata/k.libsonnet";
+
+base + {
+  // Insert user-specified overrides here.
+}
+`
+	result := m.generateOverrideData()
+
+	if string(result) != expected {
+		t.Fatalf("Expected to generate override file with data:\n%s\n,got:\n%s", expected, result)
+	}
+}
-- 
GitLab