Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tanka can't handle top level arrays #321

Merged
merged 7 commits into from
Aug 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist

2 changes: 1 addition & 1 deletion pkg/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions pkg/tanka/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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")
Expand All @@ -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
}
41 changes: 41 additions & 0 deletions pkg/tanka/parse_test.go
Original file line number Diff line number Diff line change
@@ -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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love to see this also check objects, and evaluation results.

You could for example create multiple pseudo "environments" in testdata, like so:

- /
- /jsonnetfile.json
- /cases/
- /cases/array/main.jsonnet
- /cases/object/main.jsonnet

Then evaluate these as a table test, checking the error is nil and the result is what we expect.
Good work!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! I'll add it. Thank you for your feedback.

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)
}
}
18 changes: 18 additions & 0 deletions pkg/tanka/testdata/cases/array/main.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
[
{
testCase: 'nestedArray[0][0]',
},
{
testCase: 'nestedArray[0][1]',
},
],
[
{
testCase: 'nestedArray[1][0]',
},
{
testCase: 'nestedArray[1][1]',
},
],
]
3 changes: 3 additions & 0 deletions pkg/tanka/testdata/cases/object/main.jsonnet
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
testCase: 'object',
}
1 change: 1 addition & 0 deletions pkg/tanka/testdata/jsonnetfile.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
2 changes: 1 addition & 1 deletion pkg/tanka/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down