Repository: grafana/tanka
Pull request #321 (2020-07-17 01:53:09)

Tanka can't handle top level arrays 
Hi @sh0rez.
I'm glad to help with this issue https://github.com/grafana/tanka/issues/310. Please, let me know if I forgot something or we need to add anything else.


Patch:
diff --git a/.gitignore b/.gitignore
index 1521c8b7..16c5327c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,1 +1,2 @@
 dist
+
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b58958a..edad824a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
 # Changelog
 
+## 0.11.1 (2020-07-17)
+
+This is a minor release with one bugfix and one minor feature.
+
+### Features
+
+* **process**: With 0.11.0, tanka started automatically adding namespaces to *all* manifests it processed. We updated this to *not*
+    add a namespace to cluster-wide object types in order to make handling of these resources more consistent in different workflows. **([#320](https://github.com/grafana/tanka/pull/320))**
+
+### Bug Fixes
+
+- **export**: Fix inverted logic while checking if a file already exists. This broke `tk export` entirely.
+  **([#317](https://github.com/grafana/tanka/pull/317))**
+
+
 ## 0.11.0 (2020-07-07)
 
 2 months later and here we are with another release! Packed with many
diff --git a/pkg/process/process.go b/pkg/process/process.go
index 9c6e68ad..3af81ac5 100644
--- a/pkg/process/process.go
+++ b/pkg/process/process.go
@@ -18,7 +18,7 @@ const (
 // - tanka.dev/** labels
 // - filtering
 // - best-effort sorting
-func Process(raw map[string]interface{}, cfg v1alpha1.Config, exprs Matchers) (manifest.List, error) {
+func Process(raw interface{}, cfg v1alpha1.Config, exprs Matchers) (manifest.List, error) {
 	// Scan for everything that looks like a Kubernetes object
 	extracted, err := Extract(raw)
 	if err != nil {
diff --git a/pkg/tanka/parse.go b/pkg/tanka/parse.go
index b89adbcb..9340b84a 100644
--- a/pkg/tanka/parse.go
+++ b/pkg/tanka/parse.go
@@ -74,7 +74,7 @@ func load(dir string, opts *options) (*loaded, error) {
 
 // eval runs all processing stages describe at the Processed type apart from
 // post-processing, thus returning the raw Jsonnet result.
-func eval(dir string, extCode map[string]string) (raw map[string]interface{}, env *v1alpha1.Config, err error) {
+func eval(dir string, extCode map[string]string) (raw interface{}, env *v1alpha1.Config, err error) {
 	_, baseDir, rootDir, err := jpath.Resolve(dir)
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "resolving jpath")
@@ -119,7 +119,7 @@ func parseSpec(baseDir, rootDir string) (*v1alpha1.Config, error) {
 
 // evalJsonnet evaluates the jsonnet environment at the given directory starting with
 // `main.jsonnet`
-func evalJsonnet(baseDir string, env *v1alpha1.Config, extCode map[string]string) (map[string]interface{}, error) {
+func evalJsonnet(baseDir string, env *v1alpha1.Config, extCode map[string]string) (interface{}, error) {
 	jsonEnv, err := json.Marshal(env)
 	if err != nil {
 		return nil, errors.Wrap(err, "marshalling environment config")
@@ -140,9 +140,9 @@ func evalJsonnet(baseDir string, env *v1alpha1.Config, extCode map[string]string
 		return nil, err
 	}
 
-	var dict map[string]interface{}
-	if err := json.Unmarshal([]byte(raw), &dict); err != nil {
+	var data interface{}
+	if err := json.Unmarshal([]byte(raw), &data); err != nil {
 		return nil, err
 	}
-	return dict, nil
+	return data, nil
 }
diff --git a/pkg/tanka/workflow.go b/pkg/tanka/workflow.go
index b3c7f510..b0e95ce2 100644
--- a/pkg/tanka/workflow.go
+++ b/pkg/tanka/workflow.go
@@ -144,7 +144,7 @@ func Show(baseDir string, mods ...Modifier) (manifest.List, error) {
 }
 
 // Eval returns the raw evaluated Jsonnet output (without any transformations)
-func Eval(dir string, mods ...Modifier) (raw map[string]interface{}, err error) {
+func Eval(dir string, mods ...Modifier) (raw interface{}, err error) {
 	opts := parseModifiers(mods)
 
 	r, _, err := eval(dir, opts.extCode)


Test patch:
diff --git a/pkg/tanka/parse_test.go b/pkg/tanka/parse_test.go
new file mode 100644
index 00000000..fe6014d1
--- /dev/null
+++ b/pkg/tanka/parse_test.go
@@ -0,0 +1,41 @@
+package tanka
+
+import (
+	"github.com/grafana/tanka/pkg/spec/v1alpha1"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestEvalJsonnet(t *testing.T) {
+	cases := []struct {
+		baseDir  string
+		expected interface{}
+	}{
+		{
+			baseDir: "./testdata/cases/array/",
+			expected: []interface{}{
+				[]interface{}{
+					map[string]interface{}{"testCase": "nestedArray[0][0]"},
+					map[string]interface{}{"testCase": "nestedArray[0][1]"},
+				},
+				[]interface{}{
+					map[string]interface{}{"testCase": "nestedArray[1][0]"},
+					map[string]interface{}{"testCase": "nestedArray[1][1]"},
+				},
+			},
+		},
+		{
+			baseDir: "./testdata/cases/object/",
+			expected: map[string]interface{}{
+				"testCase": "object",
+			},
+		},
+	}
+
+	for _, test := range cases {
+		m := make(map[string]string)
+		data, e := evalJsonnet(test.baseDir, v1alpha1.New(), m)
+		assert.NoError(t, e)
+		assert.Equal(t, test.expected, data)
+	}
+}
diff --git a/pkg/tanka/testdata/cases/array/main.jsonnet b/pkg/tanka/testdata/cases/array/main.jsonnet
new file mode 100644
index 00000000..62b0cd2f
--- /dev/null
+++ b/pkg/tanka/testdata/cases/array/main.jsonnet
@@ -0,0 +1,18 @@
+[
+  [
+    {
+      testCase: 'nestedArray[0][0]',
+    },
+    {
+      testCase: 'nestedArray[0][1]',
+    },
+  ],
+  [
+    {
+      testCase: 'nestedArray[1][0]',
+    },
+    {
+      testCase: 'nestedArray[1][1]',
+    },
+  ],
+]
diff --git a/pkg/tanka/testdata/cases/object/main.jsonnet b/pkg/tanka/testdata/cases/object/main.jsonnet
new file mode 100644
index 00000000..157b04a4
--- /dev/null
+++ b/pkg/tanka/testdata/cases/object/main.jsonnet
@@ -0,0 +1,3 @@
+{
+  testCase: 'object',
+}
diff --git a/pkg/tanka/testdata/jsonnetfile.json b/pkg/tanka/testdata/jsonnetfile.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/pkg/tanka/testdata/jsonnetfile.json
@@ -0,0 +1,1 @@
+{}