Unverified Commit d3c8cfd1 authored by bryanl's avatar bryanl
Browse files

bug: param list with env


Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent 03dbafb5
...@@ -80,6 +80,7 @@ func withApp(t *testing.T, fn func(*mocks.App)) { ...@@ -80,6 +80,7 @@ func withApp(t *testing.T, fn func(*mocks.App)) {
} }
func assertOutput(t *testing.T, filename, actual string) { func assertOutput(t *testing.T, filename, actual string) {
require.NotEmpty(t, filename, "filename can not be empty")
path := filepath.Join("testdata", filename) path := filepath.Join("testdata", filename)
b, err := ioutil.ReadFile(path) b, err := ioutil.ReadFile(path)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -25,6 +25,10 @@ import ( ...@@ -25,6 +25,10 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
type findModulesFn func(a app.App, envName string) ([]component.Module, error)
type findModuleFn func(a app.App, moduleName string) (component.Module, error)
type findComponentFn func(a app.App, moduleName, componentName string) (component.Component, error)
// RunParamList runs `param list`. // RunParamList runs `param list`.
func RunParamList(m map[string]interface{}) error { func RunParamList(m map[string]interface{}) error {
pl, err := NewParamList(m) pl, err := NewParamList(m)
...@@ -38,11 +42,14 @@ func RunParamList(m map[string]interface{}) error { ...@@ -38,11 +42,14 @@ func RunParamList(m map[string]interface{}) error {
// ParamList lists parameters for a component. // ParamList lists parameters for a component.
type ParamList struct { type ParamList struct {
app app.App app app.App
module string moduleName string
componentName string componentName string
envName string envName string
cm component.Manager
out io.Writer out io.Writer
findModulesFn findModulesFn
findModuleFn findModuleFn
findComponentFn findComponentFn
} }
// NewParamList creates an instances of ParamList. // NewParamList creates an instances of ParamList.
...@@ -51,12 +58,14 @@ func NewParamList(m map[string]interface{}) (*ParamList, error) { ...@@ -51,12 +58,14 @@ func NewParamList(m map[string]interface{}) (*ParamList, error) {
pl := &ParamList{ pl := &ParamList{
app: ol.loadApp(), app: ol.loadApp(),
module: ol.loadString(OptionModule), moduleName: ol.loadOptionalString(OptionModule),
componentName: ol.loadString(OptionComponentName), componentName: ol.loadOptionalString(OptionComponentName),
envName: ol.loadString(OptionEnvName), envName: ol.loadOptionalString(OptionEnvName),
cm: component.DefaultManager, out: os.Stdout,
out: os.Stdout, findModulesFn: component.ModulesFromEnv,
findModuleFn: component.GetModule,
findComponentFn: component.LocateComponent,
} }
if ol.err != nil { if ol.err != nil {
...@@ -68,9 +77,13 @@ func NewParamList(m map[string]interface{}) (*ParamList, error) { ...@@ -68,9 +77,13 @@ func NewParamList(m map[string]interface{}) (*ParamList, error) {
// Run runs the ParamList action. // Run runs the ParamList action.
func (pl *ParamList) Run() error { func (pl *ParamList) Run() error {
module, err := pl.cm.Module(pl.app, pl.module) if pl.envName != "" {
return pl.handleEnvParams()
}
module, err := pl.findModuleFn(pl.app, pl.moduleName)
if err != nil { if err != nil {
return errors.Wrap(err, "could not find namespace") return errors.Wrap(err, "could not find module")
} }
params, err := pl.collectParams(module) params, err := pl.collectParams(module)
...@@ -78,16 +91,31 @@ func (pl *ParamList) Run() error { ...@@ -78,16 +91,31 @@ func (pl *ParamList) Run() error {
return err return err
} }
table := table.New(pl.out) return pl.print(params)
}
table.SetHeader([]string{"COMPONENT", "INDEX", "PARAM", "VALUE"}) func (pl *ParamList) handleEnvParams() error {
for _, data := range params { modules, err := pl.findModulesFn(pl.app, pl.envName)
table.Append([]string{data.Component, data.Index, data.Key, data.Value}) if err != nil {
return err
} }
table.Render() var params []component.ModuleParameter
for _, module := range modules {
moduleParams, err := pl.collectParams(module)
if err != nil {
return err
}
if pl.moduleName != "" && module.Name() != pl.moduleName {
continue
}
params = append(params, moduleParams...)
}
return pl.print(params)
return nil
} }
func (pl *ParamList) collectParams(module component.Module) ([]component.ModuleParameter, error) { func (pl *ParamList) collectParams(module component.Module) ([]component.ModuleParameter, error) {
...@@ -95,10 +123,21 @@ func (pl *ParamList) collectParams(module component.Module) ([]component.ModuleP ...@@ -95,10 +123,21 @@ func (pl *ParamList) collectParams(module component.Module) ([]component.ModuleP
return module.Params(pl.envName) return module.Params(pl.envName)
} }
c, err := pl.cm.Component(pl.app, pl.module, pl.componentName) c, err := pl.findComponentFn(pl.app, pl.moduleName, pl.componentName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return c.Params(pl.envName) return c.Params(pl.envName)
} }
func (pl *ParamList) print(params []component.ModuleParameter) error {
table := table.New(pl.out)
table.SetHeader([]string{"COMPONENT", "INDEX", "PARAM", "VALUE"})
for _, data := range params {
table.Append([]string{data.Component, data.Index, data.Key, data.Value})
}
return table.Render()
}
...@@ -17,92 +17,123 @@ package actions ...@@ -17,92 +17,123 @@ package actions
import ( import (
"bytes" "bytes"
"path/filepath"
"testing" "testing"
"github.com/ksonnet/ksonnet/component" "github.com/ksonnet/ksonnet/component"
cmocks "github.com/ksonnet/ksonnet/component/mocks" cmocks "github.com/ksonnet/ksonnet/component/mocks"
"github.com/ksonnet/ksonnet/metadata/app"
amocks "github.com/ksonnet/ksonnet/metadata/app/mocks" amocks "github.com/ksonnet/ksonnet/metadata/app/mocks"
"github.com/stretchr/testify/mock" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestParamList_with_component_name(t *testing.T) { func TestParamList(t *testing.T) {
withApp(t, func(appMock *amocks.App) { moduleParams := []component.ModuleParameter{
componentName := "deployment" {Component: "deployment", Index: "0", Key: "key", Value: `"value"`},
module := "ns" }
envName := ""
ns := &cmocks.Module{}
c := &cmocks.Component{}
nsParams := []component.ModuleParameter{
{Component: "deployment", Index: "0", Key: "key", Value: `"value"`},
}
c.On("Params", "").Return(nsParams, nil)
cm := &cmocks.Manager{}
cm.On("Module", mock.Anything, "ns").Return(ns, nil)
cm.On("Component", mock.Anything, "ns", "deployment").Return(c, nil)
in := map[string]interface{}{
OptionApp: appMock,
OptionComponentName: componentName,
OptionModule: module,
OptionEnvName: envName,
}
a, err := NewParamList(in)
require.NoError(t, err)
a.cm = cm module := &cmocks.Module{}
module.On("Params", "envName").Return(moduleParams, nil)
module.On("Params", "").Return(moduleParams, nil)
var buf bytes.Buffer c := &cmocks.Component{}
a.out = &buf c.On("Params", "").Return(moduleParams, nil)
err = a.Run()
require.NoError(t, err)
assertOutput(t, "param_list/with_component.txt", buf.String())
})
}
func TestParamList_without_component_name(t *testing.T) {
withApp(t, func(appMock *amocks.App) { withApp(t, func(appMock *amocks.App) {
componentName := "" cases := []struct {
module := "ns" name string
envName := "" in map[string]interface{}
findModulesFn func(t *testing.T) findModulesFn
nsParams := []component.ModuleParameter{ findModuleFn func(t *testing.T) findModuleFn
{Component: "deployment", Index: "0", Key: "key1", Value: `"value"`}, findComponentFn func(t *testing.T) findComponentFn
{Component: "deployment", Index: "0", Key: "key2", Value: `"value"`}, outputFile string
}{
{
name: "component name",
in: map[string]interface{}{
OptionApp: appMock,
OptionComponentName: "deployment",
OptionModule: "module",
},
findModuleFn: func(t *testing.T) findModuleFn {
return func(a app.App, moduleName string) (component.Module, error) {
assert.Equal(t, "module", moduleName)
return module, nil
}
},
findComponentFn: func(t *testing.T) findComponentFn {
return func(a app.App, moduleName, componentName string) (component.Component, error) {
assert.Equal(t, "module", moduleName)
assert.Equal(t, "deployment", componentName)
return c, nil
}
},
outputFile: filepath.Join("param", "list", "with_component.txt"),
},
{
name: "no component name",
in: map[string]interface{}{
OptionApp: appMock,
OptionModule: "module",
},
findModuleFn: func(t *testing.T) findModuleFn {
return func(a app.App, moduleName string) (component.Module, error) {
assert.Equal(t, "module", moduleName)
return module, nil
}
},
findComponentFn: func(t *testing.T) findComponentFn {
return func(a app.App, moduleName, componentName string) (component.Component, error) {
assert.Equal(t, "module", moduleName)
assert.Equal(t, "deployment", componentName)
return c, nil
}
},
outputFile: filepath.Join("param", "list", "without_component.txt"),
},
{
name: "env",
in: map[string]interface{}{
OptionApp: appMock,
OptionEnvName: "envName",
},
findModulesFn: func(t *testing.T) findModulesFn {
return func(a app.App, envName string) ([]component.Module, error) {
assert.Equal(t, "envName", envName)
return []component.Module{module}, nil
}
},
outputFile: filepath.Join("param", "list", "env.txt"),
},
} }
ns := &cmocks.Module{} for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ns.On("Params", "").Return(nsParams, nil)
cm := &cmocks.Manager{} a, err := NewParamList(tc.in)
cm.On("Module", mock.Anything, "ns").Return(ns, nil) require.NoError(t, err)
in := map[string]interface{}{ if tc.findModulesFn != nil {
OptionApp: appMock, a.findModulesFn = tc.findModulesFn(t)
OptionComponentName: componentName, }
OptionModule: module,
OptionEnvName: envName,
}
a, err := NewParamList(in) if tc.findModuleFn != nil {
require.NoError(t, err) a.findModuleFn = tc.findModuleFn(t)
}
a.cm = cm if tc.findComponentFn != nil {
a.findComponentFn = tc.findComponentFn(t)
}
var buf bytes.Buffer var buf bytes.Buffer
a.out = &buf a.out = &buf
err = a.Run() err = a.Run()
require.NoError(t, err) require.NoError(t, err)
assertOutput(t, "param_list/without_component.txt", buf.String()) assertOutput(t, tc.outputFile, buf.String())
})
}
}) })
} }
COMPONENT INDEX PARAM VALUE
========= ===== ===== =====
deployment 0 key "value"
COMPONENT INDEX PARAM VALUE COMPONENT INDEX PARAM VALUE
========= ===== ===== ===== ========= ===== ===== =====
deployment 0 key1 "value" deployment 0 key "value"
deployment 0 key2 "value"
...@@ -68,6 +68,10 @@ var ( ...@@ -68,6 +68,10 @@ var (
// NOTE: It warns when it makes a change. This serves as a temporary fix until // NOTE: It warns when it makes a change. This serves as a temporary fix until
// ksonnet generates the correct file. // ksonnet generates the correct file.
func upgradeParams(envName, in string) string { func upgradeParams(envName, in string) string {
logrus.Warnf("rewriting %q environment params to not use relative paths", envName) if reParamSwap.MatchString(in) {
return reParamSwap.ReplaceAllLiteralString(in, `std.extVar("__ksonnet/params")`) logrus.Warnf("rewriting %q environment params to not use relative paths", envName)
return reParamSwap.ReplaceAllLiteralString(in, `std.extVar("__ksonnet/params")`)
}
return in
} }
...@@ -52,7 +52,7 @@ func (egs *EnvGlobalsSet) Set(snippet string, p params.Params) (string, error) { ...@@ -52,7 +52,7 @@ func (egs *EnvGlobalsSet) Set(snippet string, p params.Params) (string, error) {
} }
if err = egs.setParams(obj, p); err != nil { if err = egs.setParams(obj, p); err != nil {
return "", errors.Wrap(err, "delete entry") return "", errors.Wrap(err, "set global params")
} }
// root node should be a local if not, return an error // root node should be a local if not, return an error
......
...@@ -57,7 +57,7 @@ func (epa *EnvParamSet) Set(componentName, snippet string, p params.Params) (str ...@@ -57,7 +57,7 @@ func (epa *EnvParamSet) Set(componentName, snippet string, p params.Params) (str
} }
if err = epa.setParams(obj, componentName, p); err != nil { if err = epa.setParams(obj, componentName, p); err != nil {
return "", errors.Wrap(err, "delete entry") return "", errors.Wrap(err, "set params")
} }
// root node should be a local if not, return an error // root node should be a local if not, return an error
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment