Unverified Commit 3043f720 authored by Bryan Liles's avatar Bryan Liles Committed by GitHub
Browse files

Merge pull request #402 from bryanl/actions-take-map

update actions to use action args
parents a767df24 08f612ca
......@@ -669,6 +669,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "59b2dca47d9322c572df60faae156de3dd3a26f748d3f87323a7c2613f012ebc"
inputs-digest = "fc110254cc8bc87036896f78a76c42360abb0156200a7a5931c79c78a7c781c8"
solver-name = "gps-cdcl"
solver-version = 1
......@@ -20,19 +20,76 @@ import (
"github.com/ksonnet/ksonnet/client"
"github.com/ksonnet/ksonnet/metadata/app"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/pkg/errors"
"github.com/spf13/afero"
)
const (
OptionAPIObjects = "api-objects"
OptionApp = "app"
OptionClientConfig = "client-config"
// OptionApp is app option.
OptionApp = "app"
// 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"
OptionCreate = "create"
OptionDryRun = "dry-run"
OptionEnvName = "env-name"
OptionGcTag = "gc-tag"
OptionSkipGc = "skip-gc"
// OptionCreate is create option.
OptionCreate = "create"
// OptionDryRun is dryRun option.
OptionDryRun = "dry-run"
// 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 {
......@@ -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 {
i := o.load(name)
if i == nil {
......@@ -89,6 +161,49 @@ func (o *optionLoader) loadBool(name string) bool {
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 {
i := o.load(name)
if i == nil {
......@@ -104,30 +219,29 @@ func (o *optionLoader) loadString(name string) string {
return a
}
func (o *optionLoader) loadStringSlice(name string) []string {
i := o.load(name)
func (o *optionLoader) loadOptionalString(name string) string {
i := o.loadOptional(name)
if i == nil {
return nil
return ""
}
a, ok := i.([]string)
a, ok := i.(string)
if !ok {
o.err = newInvalidOptionError(name)
return nil
return ""
}
return a
}
func (o *optionLoader) loadAPIObjects() []*unstructured.Unstructured {
i := o.load(OptionAPIObjects)
func (o *optionLoader) loadStringSlice(name string) []string {
i := o.load(name)
if i == nil {
return nil
}
a, ok := i.([]*unstructured.Unstructured)
a, ok := i.([]string)
if !ok {
o.err = newInvalidOptionError(OptionAPIObjects)
o.err = newInvalidOptionError(name)
return nil
}
......@@ -152,6 +266,7 @@ func (o *optionLoader) loadClientConfig() *client.Config {
func (o *optionLoader) loadApp() app.App {
i := o.load(OptionApp)
if i == nil {
o.err = ErrNotInApp
return nil
}
......@@ -164,14 +279,27 @@ func (o *optionLoader) loadApp() app.App {
return a
}
func (ol *optionLoader) load(key string) interface{} {
if ol.err != nil {
func (o *optionLoader) load(key string) interface{} {
if o.err != nil {
return nil
}
i, ok := ol.m[key]
i, ok := o.m[key]
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
......
......@@ -25,9 +25,50 @@ import (
"github.com/ksonnet/ksonnet/pkg/registry"
rmocks "github.com/ksonnet/ksonnet/pkg/registry/mocks"
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"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)) {
fs := afero.NewMemMapFs()
......
......@@ -27,8 +27,8 @@ import (
)
// RunComponentList runs `component list`
func RunComponentList(ksApp app.App, namespace, output string) error {
cl, err := NewComponentList(ksApp, namespace, output)
func RunComponentList(m map[string]interface{}) error {
cl, err := NewComponentList(m)
if err != nil {
return err
}
......@@ -46,13 +46,20 @@ type ComponentList struct {
}
// 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{
nsName: namespace,
output: output,
app: ksApp,
cm: component.DefaultManager,
out: os.Stdout,
app: ol.loadApp(),
nsName: ol.loadString(OptionNamespaceName),
output: ol.loadString(OptionOutput),
cm: component.DefaultManager,
out: os.Stdout,
}
if ol.err != nil {
return nil, ol.err
}
return cl, nil
......
......@@ -42,7 +42,13 @@ func TestComponentList(t *testing.T) {
cm := &cmocks.Manager{}
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)
a.cm = cm
......@@ -76,7 +82,13 @@ func TestComponentList_wide(t *testing.T) {
cm := &cmocks.Manager{}
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)
a.cm = cm
......
......@@ -27,8 +27,8 @@ const (
)
// RunEnvAdd runs `env add`
func RunEnvAdd(ksApp app.App, envName, server, namespace, k8sSpecFlag string, isOverride bool) error {
ea, err := NewEnvAdd(ksApp, envName, server, namespace, k8sSpecFlag, isOverride)
func RunEnvAdd(m map[string]interface{}) error {
ea, err := NewEnvAdd(m)
if err != nil {
return err
}
......@@ -49,18 +49,24 @@ type EnvAdd struct {
}
// 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{
app: ksApp,
envName: envName,
server: server,
namespace: namespace,
k8sSpecFlag: k8sSpecFlag,
isOverride: isOverride,
app: ol.loadApp(),
envName: ol.loadString(OptionEnvName),
server: ol.loadString(OptionServer),
namespace: ol.loadString(OptionNamespaceName),
k8sSpecFlag: ol.loadString(OptionSpecFlag),
isOverride: ol.loadBool(OptionOverride),
envCreateFn: env.Create,
}
if ol.err != nil {
return nil, ol.err
}
return ea, nil
}
......
......@@ -33,7 +33,16 @@ func TestEnvAdd(t *testing.T) {
aK8sSpecFlag := "flag"
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)
a.envCreateFn = func(a app.App, d env.Destination, name, specFlag string, od, pd []byte, override bool) error {
......
......@@ -24,8 +24,9 @@ import (
)
// RunEnvDescribe runs `env describe`
func RunEnvDescribe(ksApp app.App, envName string) error {
ed, err := NewEnvDescribe(ksApp, envName)
// func RunEnvDescribe(ksApp app.App, envName string) error {
func RunEnvDescribe(m map[string]interface{}) error {
ed, err := NewEnvDescribe(m)
if err != nil {
return err
}
......@@ -41,11 +42,18 @@ type EnvDescribe struct {
}
// 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{
app: ksApp,
envName: envName,
out: os.Stdout,
app: ol.loadApp(),
envName: ol.loadString(OptionEnvName),
out: os.Stdout,
}
if ol.err != nil {
return nil, ol.err
}
return ed, nil
......
......@@ -34,7 +34,12 @@ func TestEnvDescribe(t *testing.T) {
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)
var buf bytes.Buffer
......
......@@ -25,8 +25,8 @@ import (
)
// RunEnvList runs `env list`
func RunEnvList(ksApp app.App) error {
nl, err := NewEnvList(ksApp)
func RunEnvList(m map[string]interface{}) error {
nl, err := NewEnvList(m)
if err != nil {
return err
}
......@@ -41,12 +41,19 @@ type EnvList struct {
}
// 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{
app: ksApp,
app: ol.loadApp(),
out: os.Stdout,
}
if ol.err != nil {
return nil, ol.err
}
return nl, nil
}
......
......@@ -39,8 +39,11 @@ func TestEnvList(t *testing.T) {
}
appMock.On("Environments").Return(envs, nil)
in := map[string]interface{}{
OptionApp: appMock,
}
a, err := NewEnvList(appMock)
a, err := NewEnvList(in)
require.NoError(t, err)
var buf bytes.Buffer
......
......@@ -21,8 +21,8 @@ import (
)
// RunEnvRm runs `env rm`
func RunEnvRm(ksApp app.App, envName string, isOverride bool) error {
ea, err := NewEnvRm(ksApp, envName, isOverride)
func RunEnvRm(m map[string]interface{}) error {
ea, err := NewEnvRm(m)
if err != nil {
return err
}
......@@ -42,15 +42,21 @@ type EnvRm struct {
}
// NewEnvRm creates an instance of EnvRm.
func NewEnvRm(ksApp app.App, envName string, isOverride bool) (*EnvRm, error) {
func NewEnvRm(m map[string]interface{}) (*EnvRm, error) {
ol := newOptionLoader(m)
ea := &EnvRm{
app: ksApp,
envName: envName,
isOverride: isOverride,
app: ol.loadApp(),
envName: ol.loadString(OptionEnvName),
isOverride: ol.loadBool(OptionOverride),
envDeleteFn: env.Delete,
}
if ol.err != nil {
return nil, ol.err
}
return ea, nil
}
......
......@@ -29,7 +29,13 @@ func TestEnvRm(t *testing.T) {
aName := "my-app"
aIsOverride := false
a, err := NewEnvRm(appMock, aName, aIsOverride)
in := map[string]interface{}{
OptionApp: appMock,
OptionEnvName: aName,
OptionOverride: aIsOverride,
}
a, err := NewEnvRm(in)
require.NoError(t, err)
a.envDeleteFn = func(a app.App, name string, override bool) error {
......
......@@ -38,8 +38,9 @@ func EnvSetName(name string) EnvSetOpt {
type EnvSetOpt func(*EnvSet)
// RunEnvSet runs `env set`
func RunEnvSet(ksApp app.App, envName string, opts ...EnvSetOpt) error {
et, err := NewEnvSet(ksApp, envName, opts...)
// func RunEnvSet(ksApp app.App, envName string, opts ...EnvSetOpt) error {
func RunEnvSet(m map[string]interface{}) error {
et, err := NewEnvSet(m)
if err != nil {
return err
}
......@@ -54,21 +55,26 @@ type EnvSet struct {
newName string
newNsName string
envRename func(a app.App, from, to string, override bool) error
updateEnv func(a app.App, envName string, spec *app.EnvironmentSpec, override bool) error
envRenameFn func(a app.App, from, to string, override bool) error
updateEnvFn func(a app.App, envName string, spec *app.EnvironmentSpec, override bool) error
}
// NewEnvSet creates an instance of EnvSet.
func NewEnvSet(ksApp app.App, envName string, opts ...EnvSetOpt) (*EnvSet, error) {
func NewEnvSet(m map[string]interface{}) (*EnvSet, error) {
ol := newOptionLoader(m)
es := &EnvSet{
app: ksApp,
envRename: env.Rename,
updateEnv: updateEnv,
envName: envName,
app: ol.loadApp(),
envName: ol.loadString(OptionEnvName),
newName: ol.loadOptionalString(OptionNewEnvName),
newNsName: ol.loadOptionalString(OptionNamespaceName),
envRenameFn: env.Rename,
updateEnvFn: updateEnv,