Unverified Commit 08f612ca authored by bryanl's avatar bryanl
Browse files

update actions to use action args



* updates actions to use actions args
* updates commands to use actions args
* adds tests for commands
Signed-off-by: default avatarbryanl <bryanliles@gmail.com>
parent a767df24
...@@ -669,6 +669,6 @@ ...@@ -669,6 +669,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "59b2dca47d9322c572df60faae156de3dd3a26f748d3f87323a7c2613f012ebc" inputs-digest = "fc110254cc8bc87036896f78a76c42360abb0156200a7a5931c79c78a7c781c8"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1
...@@ -20,19 +20,76 @@ import ( ...@@ -20,19 +20,76 @@ import (
"github.com/ksonnet/ksonnet/client" "github.com/ksonnet/ksonnet/client"
"github.com/ksonnet/ksonnet/metadata/app" "github.com/ksonnet/ksonnet/metadata/app"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "github.com/pkg/errors"
"github.com/spf13/afero"
) )
const ( const (
OptionAPIObjects = "api-objects" // OptionApp is app option.
OptionApp = "app" OptionApp = "app"
OptionClientConfig = "client-config" // OptionArguments is arguments option. Used for passing arguments to prototypes.
OptionArguments = "arguments"
// OptionClientConfig is clientConfig option.
OptionClientConfig = "client-config"
// OptionComponentName is a componentName option.
OptionComponentName = "component-name"
// OptionComponentNames is componentNames option.
OptionComponentNames = "component-names" OptionComponentNames = "component-names"
OptionCreate = "create" // OptionCreate is create option.
OptionDryRun = "dry-run" OptionCreate = "create"
OptionEnvName = "env-name" // OptionDryRun is dryRun option.
OptionGcTag = "gc-tag" OptionDryRun = "dry-run"
OptionSkipGc = "skip-gc" // OptionEnvName is envName option.
OptionEnvName = "env-name"
// OptionFs is fs option.
OptionFs = "fs"
// OptionGcTag is gcTag option.
OptionGcTag = "gc-tag"
// OptionGlobal is global option.
OptionGlobal = "global"
// OptionIndex is index option. Is used to target individual items in multi object
// components.
OptionIndex = "index"
// OptionLibName is libName.
OptionLibName = "lib-name"
// OptionName is name option.
OptionName = "name"
// OptionNamespaceName is namespaceName option.
OptionNamespaceName = "namespace-name"
// OptionNewEnvName is newEnvName option. Used for renaming environments.
OptionNewEnvName = "new-env-name"
// OptionOutput is output option.
OptionOutput = "output"
// OptionOverride is override option.
OptionOverride = "override"
// OptionPackageName is packageName option.
OptionPackageName = "package-name"
// OptionPath is path option.
OptionPath = "path"
// OptionQuery is query option.
OptionQuery = "query"
// OptionRootPath is path option.
OptionRootPath = "root-path"
// OptionServer is server option.
OptionServer = "server"
// OptionServerURI is serverURI option.
OptionServerURI = "server-uri"
// OptionSkipGc is skipGc option.
OptionSkipGc = "skip-gc"
// OptionSpecFlag is specFlag option. Used for setting k8s spec.
OptionSpecFlag = "spec-flag"
// OptionURI is uri option. Used for setting registry URI.
OptionURI = "URI"
// OptionValue is value option.
OptionValue = "value"
// OptionVersion is version option.
OptionVersion = "version"
)
var (
// ErrNotInApp is an error stating the user is not in a ksonnet application directory
// hierarchy.
ErrNotInApp = errors.Errorf("could not find ksonnet app")
) )
type missingOptionError struct { type missingOptionError struct {
...@@ -74,6 +131,21 @@ func newOptionLoader(m map[string]interface{}) *optionLoader { ...@@ -74,6 +131,21 @@ func newOptionLoader(m map[string]interface{}) *optionLoader {
} }
} }
func (o *optionLoader) loadFs(name string) afero.Fs {
i := o.load(name)
if i == nil {
return nil
}
a, ok := i.(afero.Fs)
if !ok {
o.err = newInvalidOptionError(name)
return nil
}
return a
}
func (o *optionLoader) loadBool(name string) bool { func (o *optionLoader) loadBool(name string) bool {
i := o.load(name) i := o.load(name)
if i == nil { if i == nil {
...@@ -89,6 +161,49 @@ func (o *optionLoader) loadBool(name string) bool { ...@@ -89,6 +161,49 @@ func (o *optionLoader) loadBool(name string) bool {
return a return a
} }
func (o *optionLoader) loadOptionalBool(name string) bool {
i := o.loadOptional(name)
if i == nil {
return false
}
a, ok := i.(bool)
if !ok {
return false
}
return a
}
func (o *optionLoader) loadInt(name string) int {
i := o.load(name)
if i == nil {
return 0
}
a, ok := i.(int)
if !ok {
o.err = newInvalidOptionError(name)
return 0
}
return a
}
func (o *optionLoader) loadOptionalInt(name string) int {
i := o.loadOptional(name)
if i == nil {
return 0
}
a, ok := i.(int)
if !ok {
return 0
}
return a
}
func (o *optionLoader) loadString(name string) string { func (o *optionLoader) loadString(name string) string {
i := o.load(name) i := o.load(name)
if i == nil { if i == nil {
...@@ -104,30 +219,29 @@ func (o *optionLoader) loadString(name string) string { ...@@ -104,30 +219,29 @@ func (o *optionLoader) loadString(name string) string {
return a return a
} }
func (o *optionLoader) loadStringSlice(name string) []string { func (o *optionLoader) loadOptionalString(name string) string {
i := o.load(name) i := o.loadOptional(name)
if i == nil { if i == nil {
return nil return ""
} }
a, ok := i.([]string) a, ok := i.(string)
if !ok { if !ok {
o.err = newInvalidOptionError(name) return ""
return nil
} }
return a return a
} }
func (o *optionLoader) loadAPIObjects() []*unstructured.Unstructured { func (o *optionLoader) loadStringSlice(name string) []string {
i := o.load(OptionAPIObjects) i := o.load(name)
if i == nil { if i == nil {
return nil return nil
} }
a, ok := i.([]*unstructured.Unstructured) a, ok := i.([]string)
if !ok { if !ok {
o.err = newInvalidOptionError(OptionAPIObjects) o.err = newInvalidOptionError(name)
return nil return nil
} }
...@@ -152,6 +266,7 @@ func (o *optionLoader) loadClientConfig() *client.Config { ...@@ -152,6 +266,7 @@ func (o *optionLoader) loadClientConfig() *client.Config {
func (o *optionLoader) loadApp() app.App { func (o *optionLoader) loadApp() app.App {
i := o.load(OptionApp) i := o.load(OptionApp)
if i == nil { if i == nil {
o.err = ErrNotInApp
return nil return nil
} }
...@@ -164,14 +279,27 @@ func (o *optionLoader) loadApp() app.App { ...@@ -164,14 +279,27 @@ func (o *optionLoader) loadApp() app.App {
return a return a
} }
func (ol *optionLoader) load(key string) interface{} { func (o *optionLoader) load(key string) interface{} {
if ol.err != nil { if o.err != nil {
return nil return nil
} }
i, ok := ol.m[key] i, ok := o.m[key]
if !ok { if !ok {
ol.err = newMissingOptionError(key) o.err = newMissingOptionError(key)
}
return i
}
func (o *optionLoader) loadOptional(key string) interface{} {
if o.err != nil {
return nil
}
i, ok := o.m[key]
if !ok {
return nil
} }
return i return i
......
...@@ -25,9 +25,50 @@ import ( ...@@ -25,9 +25,50 @@ import (
"github.com/ksonnet/ksonnet/pkg/registry" "github.com/ksonnet/ksonnet/pkg/registry"
rmocks "github.com/ksonnet/ksonnet/pkg/registry/mocks" rmocks "github.com/ksonnet/ksonnet/pkg/registry/mocks"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func Test_optionsLoader_loadApp(t *testing.T) {
withApp(t, func(a *mocks.App) {
cases := []struct {
name string
m map[string]interface{}
isErr bool
}{
{
name: "with app",
m: map[string]interface{}{
OptionApp: a,
},
},
{
name: "with invalid app",
m: map[string]interface{}{
OptionApp: "invalid",
},
isErr: true,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
ol := newOptionLoader(tc.m)
got := ol.loadApp()
if tc.isErr {
require.Error(t, ol.err)
return
}
require.NoError(t, ol.err)
assert.Equal(t, a, got)
})
}
})
}
func withApp(t *testing.T, fn func(*mocks.App)) { func withApp(t *testing.T, fn func(*mocks.App)) {
fs := afero.NewMemMapFs() fs := afero.NewMemMapFs()
......
...@@ -27,8 +27,8 @@ import ( ...@@ -27,8 +27,8 @@ import (
) )
// RunComponentList runs `component list` // RunComponentList runs `component list`
func RunComponentList(ksApp app.App, namespace, output string) error { func RunComponentList(m map[string]interface{}) error {
cl, err := NewComponentList(ksApp, namespace, output) cl, err := NewComponentList(m)
if err != nil { if err != nil {
return err return err
} }
...@@ -46,13 +46,20 @@ type ComponentList struct { ...@@ -46,13 +46,20 @@ type ComponentList struct {
} }
// NewComponentList creates an instance of ComponentList. // NewComponentList creates an instance of ComponentList.
func NewComponentList(ksApp app.App, namespace, output string) (*ComponentList, error) { func NewComponentList(m map[string]interface{}) (*ComponentList, error) {
ol := newOptionLoader(m)
cl := &ComponentList{ cl := &ComponentList{
nsName: namespace, app: ol.loadApp(),
output: output, nsName: ol.loadString(OptionNamespaceName),
app: ksApp, output: ol.loadString(OptionOutput),
cm: component.DefaultManager,
out: os.Stdout, cm: component.DefaultManager,
out: os.Stdout,
}
if ol.err != nil {
return nil, ol.err
} }
return cl, nil return cl, nil
......
...@@ -42,7 +42,13 @@ func TestComponentList(t *testing.T) { ...@@ -42,7 +42,13 @@ func TestComponentList(t *testing.T) {
cm := &cmocks.Manager{} cm := &cmocks.Manager{}
cm.On("Namespace", mock.Anything, "").Return(ns, nil) cm.On("Namespace", mock.Anything, "").Return(ns, nil)
a, err := NewComponentList(appMock, nsName, output) in := map[string]interface{}{
OptionApp: appMock,
OptionNamespaceName: nsName,
OptionOutput: output,
}
a, err := NewComponentList(in)
require.NoError(t, err) require.NoError(t, err)
a.cm = cm a.cm = cm
...@@ -76,7 +82,13 @@ func TestComponentList_wide(t *testing.T) { ...@@ -76,7 +82,13 @@ func TestComponentList_wide(t *testing.T) {
cm := &cmocks.Manager{} cm := &cmocks.Manager{}
cm.On("Namespace", mock.Anything, "").Return(ns, nil) cm.On("Namespace", mock.Anything, "").Return(ns, nil)
a, err := NewComponentList(appMock, nsName, output) in := map[string]interface{}{
OptionApp: appMock,
OptionNamespaceName: nsName,
OptionOutput: output,
}
a, err := NewComponentList(in)
require.NoError(t, err) require.NoError(t, err)
a.cm = cm a.cm = cm
......
...@@ -27,8 +27,8 @@ const ( ...@@ -27,8 +27,8 @@ const (
) )
// RunEnvAdd runs `env add` // RunEnvAdd runs `env add`
func RunEnvAdd(ksApp app.App, envName, server, namespace, k8sSpecFlag string, isOverride bool) error { func RunEnvAdd(m map[string]interface{}) error {
ea, err := NewEnvAdd(ksApp, envName, server, namespace, k8sSpecFlag, isOverride) ea, err := NewEnvAdd(m)
if err != nil { if err != nil {
return err return err
} }
...@@ -49,18 +49,24 @@ type EnvAdd struct { ...@@ -49,18 +49,24 @@ type EnvAdd struct {
} }
// NewEnvAdd creates an instance of EnvAdd. // NewEnvAdd creates an instance of EnvAdd.
func NewEnvAdd(ksApp app.App, envName, server, namespace, k8sSpecFlag string, isOverride bool) (*EnvAdd, error) { func NewEnvAdd(m map[string]interface{}) (*EnvAdd, error) {
ol := newOptionLoader(m)
ea := &EnvAdd{ ea := &EnvAdd{
app: ksApp, app: ol.loadApp(),
envName: envName, envName: ol.loadString(OptionEnvName),
server: server, server: ol.loadString(OptionServer),
namespace: namespace, namespace: ol.loadString(OptionNamespaceName),
k8sSpecFlag: k8sSpecFlag, k8sSpecFlag: ol.loadString(OptionSpecFlag),
isOverride: isOverride, isOverride: ol.loadBool(OptionOverride),
envCreateFn: env.Create, envCreateFn: env.Create,
} }
if ol.err != nil {
return nil, ol.err
}
return ea, nil return ea, nil
} }
......
...@@ -33,7 +33,16 @@ func TestEnvAdd(t *testing.T) { ...@@ -33,7 +33,16 @@ func TestEnvAdd(t *testing.T) {
aK8sSpecFlag := "flag" aK8sSpecFlag := "flag"
aIsOverride := false aIsOverride := false
a, err := NewEnvAdd(appMock, aName, aServer, aNamespace, aK8sSpecFlag, aIsOverride) in := map[string]interface{}{
OptionApp: appMock,
OptionEnvName: aName,
OptionServer: aServer,
OptionNamespaceName: aNamespace,
OptionSpecFlag: aK8sSpecFlag,
OptionOverride: aIsOverride,
}
a, err := NewEnvAdd(in)
require.NoError(t, err) require.NoError(t, err)
a.envCreateFn = func(a app.App, d env.Destination, name, specFlag string, od, pd []byte, override bool) error { a.envCreateFn = func(a app.App, d env.Destination, name, specFlag string, od, pd []byte, override bool) error {
......
...@@ -24,8 +24,9 @@ import ( ...@@ -24,8 +24,9 @@ import (
) )
// RunEnvDescribe runs `env describe` // RunEnvDescribe runs `env describe`
func RunEnvDescribe(ksApp app.App, envName string) error { // func RunEnvDescribe(ksApp app.App, envName string) error {
ed, err := NewEnvDescribe(ksApp, envName) func RunEnvDescribe(m map[string]interface{}) error {
ed, err := NewEnvDescribe(m)
if err != nil { if err != nil {
return err return err
} }
...@@ -41,11 +42,18 @@ type EnvDescribe struct { ...@@ -41,11 +42,18 @@ type EnvDescribe struct {
} }
// NewEnvDescribe creates an instance of EnvDescribe. // NewEnvDescribe creates an instance of EnvDescribe.
func NewEnvDescribe(ksApp app.App, envName string) (*EnvDescribe, error) { func NewEnvDescribe(m map[string]interface{}) (*EnvDescribe, error) {
ol := newOptionLoader(m)
ed := &EnvDescribe{ ed := &EnvDescribe{
app: ksApp, app: ol.loadApp(),
envName: envName, envName: ol.loadString(OptionEnvName),
out: os.Stdout,
out: os.Stdout,
}
if ol.err != nil {
return nil, ol.err
} }
return ed, nil return ed, nil
......
...@@ -34,7 +34,12 @@ func TestEnvDescribe(t *testing.T) { ...@@ -34,7 +34,12 @@ func TestEnvDescribe(t *testing.T) {
appMock.On("Environment", envName).Return(env, nil) appMock.On("Environment", envName).Return(env, nil)
a, err := NewEnvDescribe(appMock, envName) in := map[string]interface{}{
OptionApp: appMock,
OptionEnvName: envName,
}
a, err := NewEnvDescribe(in)
require.NoError(t, err) require.NoError(t, err)
var buf bytes.Buffer var buf bytes.Buffer
......
...@@ -25,8 +25,8 @@ import ( ...@@ -25,8 +25,8 @@ import (
) )
// RunEnvList runs `env list` // RunEnvList runs `env list`
func RunEnvList(ksApp app.App) error { func RunEnvList(m map[string]interface{}) error {
nl, err := NewEnvList(ksApp) nl, err := NewEnvList(m)
if err != nil { if err != nil {
return err return err
} }
...@@ -41,12 +41,19 @@ type EnvList struct { ...@@ -41,12 +41,19 @@ type EnvList struct {
} }
// NewEnvList creates an instance of EnvList // NewEnvList creates an instance of EnvList
func NewEnvList(ksApp app.App) (*EnvList, error) { func NewEnvList(m map[string]interface{}) (*EnvList, error) {
ol := newOptionLoader(m)
nl := &EnvList{ nl := &EnvList{
app: ksApp, app: ol.loadApp(),
out: os.Stdout, out: os.Stdout,
} }
if ol.err != nil {
return nil, ol.err
}
return nl, nil return nl, nil