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

fix: Stable environment name #182

Merged
merged 4 commits into from
Jan 27, 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
12 changes: 11 additions & 1 deletion cmd/tk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import (
"fmt"
"log"
"os"
"path/filepath"

"github.com/posener/complete"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/crypto/ssh/terminal"

"github.com/grafana/tanka/pkg/cli/cmp"
"github.com/grafana/tanka/pkg/jsonnet/jpath"
"github.com/grafana/tanka/pkg/spec"
"github.com/grafana/tanka/pkg/spec/v1alpha1"
)
Expand Down Expand Up @@ -86,7 +88,15 @@ func main() {
}

func setupConfiguration(baseDir string) *v1alpha1.Config {
config, err := spec.ParseDir(baseDir)
_, baseDir, rootDir, err := jpath.Resolve(baseDir)
if err != nil {
log.Fatalln("Resolving jpath:", err)
}

// name of the environment: relative path from rootDir
name, _ := filepath.Rel(rootDir, baseDir)

config, err := spec.ParseDir(baseDir, name)
if err != nil {
switch err.(type) {
// just run fine without config. Provider features won't work (apply, show, diff)
Expand Down
27 changes: 18 additions & 9 deletions cmd/tk/tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ func jpathCmd() *cobra.Command {

func importsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "imports <file>",
Short: "list all transitive imports of a file",
Use: "imports <directory>",
Short: "list all transitive imports of an environment",
Args: cobra.ExactArgs(1),
Annotations: map[string]string{
"args": "baseDir",
},
Run: func(cmd *cobra.Command, args []string) {
var modFiles []string
if cmd.Flag("check").Changed {
Expand All @@ -64,22 +67,28 @@ func importsCmd() *cobra.Command {
}
}

f, err := filepath.Abs(args[0])
dir, err := filepath.Abs(args[0])
if err != nil {
log.Fatalln("Opening file:", err)
log.Fatalln("Loading environment:", err)
}

deps, err := jsonnet.TransitiveImports(f)
fi, err := os.Stat(dir)
if err != nil {
log.Fatalln("resolving imports:", err)
log.Fatalln("Loading environment:", err)
}

if !fi.IsDir() {
log.Fatalln("The argument must be an environment's directory, but this does not seem to be the case.")
}

// include main.jsonnet as well
deps = append(deps, f)
deps, err := jsonnet.TransitiveImports(dir)
if err != nil {
log.Fatalln("Resolving imports:", err)
}

root, err := gitRoot()
if err != nil {
log.Fatalln("invoking git:", err)
log.Fatalln("Invoking git:", err)
}
if modFiles != nil {
for _, m := range modFiles {
Expand Down
34 changes: 26 additions & 8 deletions pkg/jsonnet/imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jsonnet
import (
"io/ioutil"
"path/filepath"
"sort"

jsonnet "github.com/google/go-jsonnet"
"github.com/google/go-jsonnet/ast"
Expand All @@ -13,14 +14,21 @@ import (
"github.com/grafana/tanka/pkg/jsonnet/native"
)

// TransitiveImports returns all recursive imports of a file
func TransitiveImports(filename string) ([]string, error) {
sonnet, err := ioutil.ReadFile(filename)
// TransitiveImports returns all recursive imports of an environment
func TransitiveImports(dir string) ([]string, error) {
dir, err := filepath.Abs(dir)
if err != nil {
return nil, err
}

mainFile := filepath.Join(dir, "main.jsonnet")

sonnet, err := ioutil.ReadFile(mainFile)
if err != nil {
return nil, errors.Wrap(err, "opening file")
}

jpath, _, _, err := jpath.Resolve(filepath.Dir(filename))
jpath, _, rootDir, err := jpath.Resolve(dir)
if err != nil {
return nil, errors.Wrap(err, "resolving JPATH")
}
Expand All @@ -37,9 +45,17 @@ func TransitiveImports(filename string) ([]string, error) {
}

imports := make([]string, 0)
err = importRecursive(&imports, vm, node, "main.jsonnet")
if err = importRecursive(&imports, vm, node, "main.jsonnet"); err != nil {
return nil, err
}

uniq := append(uniqueStringSlice(imports), mainFile)
for i := range uniq {
uniq[i], _ = filepath.Rel(rootDir, uniq[i])
}
sort.Strings(uniq)

return uniqueStringSlice(imports), err
return uniq, nil
}

// importRecursive takes a Jsonnet VM and recursively imports the AST. Every
Expand All @@ -56,7 +72,8 @@ func importRecursive(list *[]string, vm *jsonnet.VM, node ast.Node, currentPath
return errors.Wrap(err, "importing jsonnet")
}

*list = append(*list, foundAt)
abs, _ := filepath.Abs(foundAt)
*list = append(*list, abs)

if err := importRecursive(list, vm, contents, foundAt); err != nil {
return err
Expand All @@ -71,7 +88,8 @@ func importRecursive(list *[]string, vm *jsonnet.VM, node ast.Node, currentPath
return errors.Wrap(err, "importing string")
}

*list = append(*list, foundAt)
abs, _ := filepath.Abs(foundAt)
*list = append(*list, abs)

// neither `import` nor `importstr`, probably object or similar: try children
default:
Expand Down
19 changes: 10 additions & 9 deletions pkg/jsonnet/imports_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jsonnet

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -10,15 +11,15 @@ import (
// TestTransitiveImports checks that TransitiveImports is able to report all
// recursive imports of a file
func TestTransitiveImports(t *testing.T) {
imports, err := TransitiveImports("testdata/main.jsonnet")
imports, err := TransitiveImports("testdata")
fmt.Println(imports)
require.NoError(t, err)
assert.ElementsMatch(t, []string{
"testdata/trees.jsonnet",

"testdata/trees/apple.jsonnet",
"testdata/trees/cherry.jsonnet",
"testdata/trees/peach.jsonnet",

"testdata/trees/generic.libsonnet",
assert.Equal(t, []string{
"main.jsonnet",
"trees.jsonnet",
"trees/apple.jsonnet",
"trees/cherry.jsonnet",
"trees/generic.libsonnet",
"trees/peach.jsonnet",
}, imports)
}
5 changes: 5 additions & 0 deletions pkg/jsonnet/jpath/jpath.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func (e ErrorFileNotFound) Error() string {
// This results in predictable imports, as it doesn't matter whether the user called
// called the command further down tree or not. A little bit like git.
func Resolve(workdir string) (path []string, base, root string, err error) {
workdir, err = filepath.Abs(workdir)
if err != nil {
return nil, "", "", err
}

root, err = FindParentFile("jsonnetfile.json", workdir, "/")
if err != nil {
if _, ok := err.(ErrorFileNotFound); ok {
Expand Down
6 changes: 4 additions & 2 deletions pkg/kubernetes/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ func TestReconcile(t *testing.T) {

for _, c := range tests {
t.Run(c.name, func(t *testing.T) {
got, err := Reconcile(c.deep.(map[string]interface{}), c.spec, c.targets)
config := v1alpha1.New()
config.Spec = c.spec
got, err := Reconcile(c.deep.(map[string]interface{}), config.Spec, c.targets)

require.Equal(t, c.err, err)
assert.ElementsMatch(t, c.flat, got)
Expand All @@ -99,7 +101,7 @@ func TestReconcile(t *testing.T) {
func TestReconcileOrder(t *testing.T) {
got := make([]manifest.List, 10)
for i := 0; i < 10; i++ {
r, err := Reconcile(testDataDeep().deep.(map[string]interface{}), v1alpha1.Spec{}, nil)
r, err := Reconcile(testDataDeep().deep.(map[string]interface{}), v1alpha1.New().Spec, nil)
require.NoError(t, err)
got[i] = r
}
Expand Down
15 changes: 7 additions & 8 deletions pkg/spec/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package spec
import (
"bytes"
"os"
"path/filepath"

"github.com/pkg/errors"
"github.com/spf13/viper"
Expand Down Expand Up @@ -34,7 +33,7 @@ func Parse(data []byte, name string) (*v1alpha1.Config, error) {

// ParseDir parses the given environments `spec.json` into a `v1alpha1.Config`
// object with the name set to the directories name
func ParseDir(baseDir string) (*v1alpha1.Config, error) {
func ParseDir(baseDir, name string) (*v1alpha1.Config, error) {
fi, err := os.Stat(baseDir)
if err != nil {
return nil, err
Expand All @@ -51,7 +50,7 @@ func ParseDir(baseDir string) (*v1alpha1.Config, error) {
return nil, err
}

return parse(v, filepath.Base(baseDir))
return parse(v, name)
}

// parse accepts a viper.Viper already loaded with the actual config and
Expand All @@ -62,11 +61,7 @@ func parse(v *viper.Viper, name string) (*v1alpha1.Config, error) {
// handle deprecated ksonnet spec
for _, d := range deprecated {
if v.IsSet(d.old) && !v.IsSet(d.new) {
if errDepr == nil {
errDepr = ErrDeprecated{d}
} else {
errDepr = append(errDepr, d)
}
errDepr = append(errDepr, d)
v.Set(d.new, v.Get(d.old))
}
}
Expand All @@ -79,6 +74,10 @@ func parse(v *viper.Viper, name string) (*v1alpha1.Config, error) {
// set the name field
config.Metadata.Name = name

if len(errDepr) == 0 {
return config, nil
}

// return depreciation notes in case any exist as well
return config, errDepr
}
Loading