mirror of https://github.com/knative/func.git
chore: list command namespace (#1370)
* chore: list command namespace - Adds namespace test to list command - Moves namespace flag into list command for - Better help text - Easier testing - Sets static default namespace for flag to "default" * regen docs * list test default from kubeconfig
This commit is contained in:
parent
7e75157373
commit
f9dc8b659f
53
cmd/list.go
53
cmd/list.go
|
@ -14,6 +14,7 @@ import (
|
|||
"gopkg.in/yaml.v2"
|
||||
|
||||
fn "knative.dev/func"
|
||||
"knative.dev/func/config"
|
||||
)
|
||||
|
||||
func NewListCmd(newClient ClientFactory) *cobra.Command {
|
||||
|
@ -35,12 +36,18 @@ Lists all deployed functions in a given namespace.
|
|||
{{.Name}} list --all-namespaces --output json
|
||||
`,
|
||||
SuggestFor: []string{"ls", "lsit"},
|
||||
PreRunE: bindEnv("all-namespaces", "output"),
|
||||
PreRunE: bindEnv("all-namespaces", "output", "namespace"),
|
||||
}
|
||||
|
||||
// Config
|
||||
cfg, err := config.NewDefault()
|
||||
if err != nil {
|
||||
fmt.Fprintf(cmd.OutOrStdout(), "error loading config at '%v'. %v\n", config.File(), err)
|
||||
}
|
||||
|
||||
// Flags
|
||||
cmd.Flags().BoolP("all-namespaces", "A", false, "List functions in all namespaces. If set, the --namespace flag is ignored.")
|
||||
cmd.Flags().StringP("namespace", "n", "", "The namespace for which to list functions. (Env: $FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("namespace", "n", cfg.Namespace, "The namespace for which to list functions. (Env: $FUNC_NAMESPACE)")
|
||||
cmd.Flags().StringP("output", "o", "human", "Output format (human|plain|json|xml|yaml) (Env: $FUNC_OUTPUT)")
|
||||
|
||||
if err := cmd.RegisterFlagCompletionFunc("output", CompleteOutputFormatList); err != nil {
|
||||
|
@ -57,13 +64,13 @@ Lists all deployed functions in a given namespace.
|
|||
}
|
||||
|
||||
func runList(cmd *cobra.Command, _ []string, newClient ClientFactory) (err error) {
|
||||
config := newListConfig()
|
||||
cfg := newListConfig()
|
||||
|
||||
if err := config.Validate(); err != nil {
|
||||
if err := cfg.Validate(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, done := newClient(ClientConfig{Namespace: config.Namespace, Verbose: config.Verbose})
|
||||
client, done := newClient(ClientConfig{Namespace: cfg.Namespace, Verbose: cfg.Verbose})
|
||||
defer done()
|
||||
|
||||
items, err := client.List(cmd.Context())
|
||||
|
@ -72,18 +79,15 @@ func runList(cmd *cobra.Command, _ []string, newClient ClientFactory) (err error
|
|||
}
|
||||
|
||||
if len(items) == 0 {
|
||||
// TODO(lkingland): this isn't particularly script friendly. Suggest this
|
||||
// prints bo only on --verbose. Possible future tweak, as I don't want to
|
||||
// make functional changes during a refactor.
|
||||
if config.Namespace != "" && !config.AllNamespaces {
|
||||
fmt.Printf("no functions found in namespace '%v'\n", config.Namespace)
|
||||
if cfg.Namespace != "" {
|
||||
fmt.Printf("no functions found in namespace '%v'\n", cfg.Namespace)
|
||||
} else {
|
||||
fmt.Println("no functions found")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
write(os.Stdout, listItems(items), config.Output)
|
||||
write(os.Stdout, listItems(items), cfg.Output)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -92,23 +96,28 @@ func runList(cmd *cobra.Command, _ []string, newClient ClientFactory) (err error
|
|||
// ------------------------------
|
||||
|
||||
type listConfig struct {
|
||||
Namespace string
|
||||
Output string
|
||||
AllNamespaces bool
|
||||
Verbose bool
|
||||
Namespace string
|
||||
Output string
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
func newListConfig() listConfig {
|
||||
return listConfig{
|
||||
Namespace: viper.GetString("namespace"),
|
||||
Output: viper.GetString("output"),
|
||||
AllNamespaces: viper.GetBool("all-namespaces"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
c := listConfig{
|
||||
Namespace: viper.GetString("namespace"),
|
||||
Output: viper.GetString("output"),
|
||||
Verbose: viper.GetBool("verbose"),
|
||||
}
|
||||
// Lister instantiated by newClient explicitly expects "" namespace to
|
||||
// inidicate it should list from all namespaces, so remove default "default"
|
||||
// when -A.
|
||||
if viper.GetBool("all-namespaces") {
|
||||
c.Namespace = ""
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (c listConfig) Validate() error {
|
||||
if c.Namespace != "" && c.AllNamespaces {
|
||||
func (c listConfig) Validate(cmd *cobra.Command) error {
|
||||
if cmd.Flags().Changed("namespace") && viper.GetBool("all-namespaces") {
|
||||
return errors.New("Both --namespace and --all-namespaces specified.")
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
fn "knative.dev/func"
|
||||
"knative.dev/func/mock"
|
||||
)
|
||||
|
||||
// TestList_Namespace ensures that list command options for specifying a
|
||||
// namespace (--namespace) or all namespaces (--all-namespacs) are properly
|
||||
// evaluated.
|
||||
func TestList_Namespace(t *testing.T) {
|
||||
_ = fromTempDirectory(t)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
all bool // --all-namespaces
|
||||
namespace string // use specific namespace
|
||||
expected string // expected
|
||||
err bool // expected error
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
expected: "func", // see ./testdata/default_kubeconfig
|
||||
},
|
||||
{
|
||||
name: "namespace provided",
|
||||
namespace: "ns",
|
||||
expected: "ns",
|
||||
},
|
||||
{
|
||||
name: "all namespaces",
|
||||
all: true,
|
||||
expected: "", // blank is implemented by lister as meaning all
|
||||
},
|
||||
{
|
||||
name: "both flags error",
|
||||
namespace: "ns",
|
||||
all: true,
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
var (
|
||||
lister = mock.NewLister()
|
||||
client = fn.New(fn.WithLister(lister))
|
||||
)
|
||||
cmd := NewListCmd(func(cc ClientConfig, options ...fn.Option) (*fn.Client, func()) {
|
||||
if cc.Namespace != test.expected {
|
||||
t.Fatalf("expected '%v', got '%v'", test.expected, cc.Namespace)
|
||||
}
|
||||
return client, func() {}
|
||||
})
|
||||
args := []string{}
|
||||
if test.namespace != "" {
|
||||
args = append(args, "--namespace", test.namespace)
|
||||
}
|
||||
if test.all {
|
||||
args = append(args, "-A")
|
||||
}
|
||||
cmd.SetArgs(args)
|
||||
|
||||
err := cmd.Execute()
|
||||
if err != nil && !test.err {
|
||||
// TODO: typed error for --namespace with -A. Perhaps ErrFlagConflict?
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err == nil && test.err {
|
||||
t.Fatalf("did not receive expected error ")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ func list --all-namespaces --output json
|
|||
```
|
||||
-A, --all-namespaces List functions in all namespaces. If set, the --namespace flag is ignored.
|
||||
-h, --help help for list
|
||||
-n, --namespace string The namespace for which to list functions. (Env: $FUNC_NAMESPACE)
|
||||
-n, --namespace string The namespace for which to list functions. (Env: $FUNC_NAMESPACE) (default "default")
|
||||
-o, --output string Output format (human|plain|json|xml|yaml) (Env: $FUNC_OUTPUT) (default "human")
|
||||
```
|
||||
|
||||
|
|
Loading…
Reference in New Issue