-
Notifications
You must be signed in to change notification settings - Fork 167
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactors the parsing of an environments `spec.json` into a separate package `pkg/spec` to allow working with Tanka environments from outside of our codebase. A separate package was required because spec parsing also involves dealing with deprecated ksonnet attributes and correctly setting constants and the environments name, which would be too much logic to re-implement in every project needing to parse our `spec.json`.
- Loading branch information
Showing
9 changed files
with
159 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package spec | ||
|
||
import "fmt" | ||
|
||
type depreciation struct { | ||
old, new string | ||
} | ||
|
||
// ErrDeprecated is a non-fatal error that occurs when deprecated fields are | ||
// used in the spec.json | ||
type ErrDeprecated []depreciation | ||
|
||
func (e ErrDeprecated) Error() string { | ||
buf := "" | ||
for _, d := range e { | ||
buf += fmt.Sprintf("Warning: `%s` is deprecated, use `%s` instead.\n", d.old, d.new) | ||
} | ||
return buf | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package spec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/grafana/tanka/pkg/spec/v1alpha1" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// TestDeprecated checks that deprecated fields are still respected, but can be | ||
// overwritten by the newer format. | ||
func TestDeprecated(t *testing.T) { | ||
data := []byte(` | ||
{ | ||
"spec": { | ||
"namespace": "new" | ||
}, | ||
"server": "https://127.0.0.1", | ||
"team": "cool", | ||
"namespace": "old" | ||
}`) | ||
|
||
got, err := Parse(data, "test") | ||
require.Equal(t, ErrDeprecated{ | ||
{old: "server", new: "spec.apiServer"}, | ||
{old: "team", new: "metadata.labels.team"}, | ||
}, err) | ||
|
||
want := v1alpha1.New() | ||
want.Spec.APIServer = "https://127.0.0.1" | ||
want.Spec.Namespace = "new" | ||
want.Metadata.Labels["team"] = "cool" | ||
want.Metadata.Name = "test" | ||
|
||
assert.Equal(t, want, got) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package spec | ||
|
||
import ( | ||
"bytes" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/grafana/tanka/pkg/spec/v1alpha1" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
// list of deprecated config keys and their alternatives | ||
// however, they still work and are aliased internally | ||
var deprecated = []depreciation{ | ||
{old: "namespace", new: "spec.namespace"}, | ||
{old: "server", new: "spec.apiServer"}, | ||
{old: "team", new: "metadata.labels.team"}, | ||
} | ||
|
||
// Parse parses the json `data` into a `v1alpha1.Config` object. | ||
// `name` is the name of the environment | ||
func Parse(data []byte, name string) (*v1alpha1.Config, error) { | ||
v := viper.New() | ||
v.SetConfigType("json") | ||
if err := v.ReadConfig(bytes.NewReader(data)); err != nil { | ||
return nil, err | ||
} | ||
return parse(v, name) | ||
} | ||
|
||
// 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) { | ||
fi, err := os.Stat(baseDir) | ||
if err != nil { | ||
return nil, err | ||
} | ||
if !fi.IsDir() { | ||
return nil, errors.New("baseDir is not an directory") | ||
} | ||
|
||
v := viper.New() | ||
v.SetConfigName("spec") | ||
v.AddConfigPath(baseDir) | ||
|
||
if err := v.ReadInConfig(); err != nil { | ||
return nil, err | ||
} | ||
|
||
return parse(v, filepath.Base(baseDir)) | ||
} | ||
|
||
// parse accepts a viper.Viper already loaded with the actual config and | ||
// unmarshals it onto a v1alpha1.Config | ||
func parse(v *viper.Viper, name string) (*v1alpha1.Config, error) { | ||
var errDepr ErrDeprecated | ||
|
||
// 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) | ||
} | ||
v.Set(d.new, v.Get(d.old)) | ||
} | ||
} | ||
|
||
config := v1alpha1.New() | ||
if err := v.Unmarshal(config); err != nil { | ||
return nil, errors.Wrap(err, "parsing spec.json") | ||
} | ||
|
||
// set the name field | ||
config.Metadata.Name = name | ||
|
||
// return depreciation notes in case any exist as well | ||
return config, errDepr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters