Skip to content

Commit

Permalink
feat(api): Loader.List
Browse files Browse the repository at this point in the history
Introduces `Loader.List(path, opts)` which returns all environments that could
possibly be found at path.

This can be used to prompt the user for the correct inline environment,
while the actual Load does not need to be concerned with this
  • Loading branch information
sh0rez committed Jan 7, 2021
1 parent ebe89fd commit 91651e9
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 22 deletions.
83 changes: 63 additions & 20 deletions pkg/tanka/inline.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,7 @@ import (
type InlineLoader struct{}

func (i *InlineLoader) Load(path string, opts JsonnetOpts) (*v1alpha1.Environment, error) {
raw, err := EvalJsonnet(path, opts)
if err != nil {
return nil, err
}

var data interface{}
if err := json.Unmarshal([]byte(raw), &data); err != nil {
return nil, err
}

envs, err := extractEnvs(data)
envs, err := inlineEval(path, opts)
if err != nil {
return nil, err
}
Expand All @@ -45,33 +35,86 @@ func (i *InlineLoader) Load(path string, opts JsonnetOpts) (*v1alpha1.Environmen
return nil, fmt.Errorf("Found no environments in '%s'", path)
}

root, base, err := jpath.Dirs(path)
// TODO: Re-serializing the entire env here. This is horribly inefficient
envData, err := json.Marshal(envs[0])
if err != nil {
return nil, err
}

name, err := filepath.Rel(root, base)
env, err := inlineParse(path, envData)
if err != nil {
return nil, err
}

// TODO: Re-serializing the entire env here. This is horribly inefficient
envData, err := json.Marshal(envs[0])
return env, nil
}

func (i *InlineLoader) Peek(path string, opts JsonnetOpts) (*v1alpha1.Environment, error) {
opts.EvalScript = EnvsOnlyEvalScript
return i.Load(path, opts)
}

func (i *InlineLoader) List(path string, opts JsonnetOpts) ([]*v1alpha1.Environment, error) {
opts.EvalScript = EnvsOnlyEvalScript
list, err := inlineEval(path, opts)
if err != nil {
return nil, err
}

envs := make([]*v1alpha1.Environment, 0, len(list))
for _, raw := range list {
data, err := json.Marshal(raw)
if err != nil {
return nil, err
}

env, err := inlineParse(path, data)
if err != nil {
return nil, err
}

envs = append(envs, env)
}

return envs, nil
}

func inlineEval(path string, opts JsonnetOpts) (manifest.List, error) {
raw, err := EvalJsonnet(path, opts)
if err != nil {
return nil, err
}

env, err := spec.Parse(envData, name)
var data interface{}
if err := json.Unmarshal([]byte(raw), &data); err != nil {
return nil, err
}

envs, err := extractEnvs(data)
if err != nil {
return nil, err
}

return env, nil
return envs, nil
}

func (i *InlineLoader) Peek(path string, opts JsonnetOpts) (*v1alpha1.Environment, error) {
opts.EvalScript = EnvsOnlyEvalScript
return i.Load(path, opts)
func inlineParse(path string, data []byte) (*v1alpha1.Environment, error) {
root, base, err := jpath.Dirs(path)
if err != nil {
return nil, err
}

namespace, err := filepath.Rel(root, base)
if err != nil {
return nil, err
}

env, err := spec.Parse(data, namespace)
if err != nil {
return nil, err
}

return env, nil
}

// extractEnvs filters out any Environment manifests
Expand Down
18 changes: 17 additions & 1 deletion pkg/tanka/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ func Peek(path string, opts JsonnetOpts) (*v1alpha1.Environment, error) {
return loader.Peek(path, opts)
}

// List finds metadata of all environments at path that could possibly be
// loaded. List can be used to deal with multiple inline environments, by first
// listing them, choosing the right one and then only loading that one
func List(path string, opts JsonnetOpts) ([]*v1alpha1.Environment, error) {
loader, err := DetectLoader(path)
if err != nil {
return nil, err
}

return loader.List(path, opts)
}

// DetectLoader detects whether the environment is inline or static and picks
// the approriate loader
func DetectLoader(path string) (Loader, error) {
Expand All @@ -71,11 +83,15 @@ func DetectLoader(path string) (Loader, error) {

// Loader is an abstraction over the process of loading Environments
type Loader interface {
// Load the environment with path
// Load a single environment at path
Load(path string, opts JsonnetOpts) (*v1alpha1.Environment, error)

// Peek only loads metadata and omits the actual resources
Peek(path string, opts JsonnetOpts) (*v1alpha1.Environment, error)

// List returns metadata of all possible environments at path that can be
// loaded
List(path string, opts JsonnetOpts) ([]*v1alpha1.Environment, error)
}

type LoadResult struct {
Expand Down
11 changes: 10 additions & 1 deletion pkg/tanka/static.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
type StaticLoader struct{}

func (s StaticLoader) Load(path string, opts JsonnetOpts) (*v1alpha1.Environment, error) {
config, err := Peek(path, opts)
config, err := s.Peek(path, opts)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -46,6 +46,15 @@ func (s StaticLoader) Peek(path string, opts JsonnetOpts) (*v1alpha1.Environment
return config, nil
}

func (s StaticLoader) List(path string, opts JsonnetOpts) ([]*v1alpha1.Environment, error) {
env, err := s.Peek(path, opts)
if err != nil {
return nil, err
}

return []*v1alpha1.Environment{env}, nil
}

// parseStaticSpec parses the `spec.json` of the environment and returns a
// *kubernetes.Kubernetes from it
func parseStaticSpec(root, base string) (*v1alpha1.Environment, error) {
Expand Down

0 comments on commit 91651e9

Please sign in to comment.