feat: list command - improved output (#205)

Signed-off-by: Zbynek Roubalik <zroubali@redhat.com>
This commit is contained in:
Zbynek Roubalik 2020-11-04 13:15:06 +01:00 committed by GitHub
parent 745640d9b4
commit 29ca07768c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 29 deletions

View File

@ -67,7 +67,15 @@ type Remover interface {
// Lister of deployed services.
type Lister interface {
// List the Functions currently deployed.
List() ([]string, error)
List() ([]ListItem, error)
}
type ListItem struct {
Name string `json:"name" yaml:"name"`
Runtime string `json:"runtime" yaml:"runtime"`
URL string `json:"url" yaml:"url"`
KService string `json:"kservice" yaml:"kservice"`
Ready string `json:"ready" yaml:"ready"`
}
// ProgressListener is notified of task progress.
@ -476,7 +484,7 @@ func (c *Client) Run(root string) error {
}
// List currently deployed Functions.
func (c *Client) List() ([]string, error) {
func (c *Client) List() ([]ListItem, error) {
// delegate to concrete implementation of lister entirely.
return c.lister.List()
}
@ -549,7 +557,7 @@ func (n *noopRemover) Remove(string) error { return nil }
type noopLister struct{ output io.Writer }
func (n *noopLister) List() ([]string, error) { return []string{}, nil }
func (n *noopLister) List() ([]ListItem, error) { return []ListItem{}, nil }
type noopDNSProvider struct{ output io.Writer }

View File

@ -18,12 +18,15 @@ func CompleteFunctionList(cmd *cobra.Command, args []string, toComplete string)
directive = cobra.ShellCompDirectiveError
return
}
s, err := lister.List()
list, err := lister.List()
if err != nil {
directive = cobra.ShellCompDirectiveError
return
}
strings = s
for _, item := range list{
strings = append(strings, item.Name)
}
directive = cobra.ShellCompDirectiveDefault
return
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"os"
"text/tabwriter"
"github.com/ory/viper"
"github.com/spf13/cobra"
@ -54,12 +55,13 @@ func runList(cmd *cobra.Command, args []string) (err error) {
faas.WithVerbose(config.Verbose),
faas.WithLister(lister))
nn, err := client.List()
items, err := client.List()
if err != nil {
return
}
write(os.Stdout, names(nn), config.Format)
write(os.Stdout, listItems(items), config.Format)
return
}
@ -83,30 +85,33 @@ func newListConfig() listConfig {
// Output Formatting (serializers)
// -------------------------------
type names []string
type listItems []faas.ListItem
func (nn names) Human(w io.Writer) error {
return nn.Plain(w)
func (items listItems) Human(w io.Writer) error {
return items.Plain(w)
}
func (nn names) Plain(w io.Writer) error {
for _, name := range nn {
fmt.Fprintln(w, name)
func (items listItems) Plain(w io.Writer) error {
// minwidth, tabwidth, padding, padchar, flags
tabWriter := tabwriter.NewWriter(w, 0, 8, 2, ' ', 0)
defer tabWriter.Flush()
fmt.Fprintf(tabWriter, "%s\t%s\t%s\t%s\t%s\n", "NAME", "RUNTIME", "URL", "KSERVICE", "READY")
for _, item := range items {
fmt.Fprintf(tabWriter, "%s\t%s\t%s\t%s\t%s\n", item.Name, item.Runtime, item.URL, item.KService, item.Ready)
}
return nil
}
func (nn names) JSON(w io.Writer) error {
return json.NewEncoder(w).Encode(nn)
func (items listItems) JSON(w io.Writer) error {
return json.NewEncoder(w).Encode(items)
}
func (nn names) XML(w io.Writer) error {
return xml.NewEncoder(w).Encode(nn)
func (items listItems) XML(w io.Writer) error {
return xml.NewEncoder(w).Encode(items)
}
func (nn names) YAML(w io.Writer) error {
// the yaml.v2 package refuses to directly serialize a []string unless
// exposed as a public struct member; so an inline anonymous is used.
ff := struct{ Names []string }{nn}
return yaml.NewEncoder(w).Encode(ff.Names)
func (items listItems) YAML(w io.Writer) error {
return yaml.NewEncoder(w).Encode(items)
}

1
go.mod
View File

@ -15,6 +15,7 @@ require (
k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible
knative.dev/client v0.17.2
knative.dev/eventing v0.17.5
knative.dev/pkg v0.0.0-20200831162708-14fb2347fb77
knative.dev/serving v0.17.3
)

View File

@ -1,8 +1,11 @@
package knative
import (
corev1 "k8s.io/api/core/v1"
clientservingv1 "knative.dev/client/pkg/serving/v1"
"knative.dev/pkg/apis"
"github.com/boson-project/faas"
"github.com/boson-project/faas/k8s"
)
@ -28,7 +31,7 @@ func NewLister(namespaceOverride string) (l *Lister, err error) {
return
}
func (l *Lister) List() (names []string, err error) {
func (l *Lister) List() (items []faas.ListItem, err error) {
client, err := NewServingClient(l.namespace)
if err != nil {
@ -41,13 +44,32 @@ func (l *Lister) List() (names []string, err error) {
}
for _, service := range lst.Items {
// Convert the "subdomain-encoded" (i.e. kube-service-friendly) name
// back out to a fully qualified service name.
n, err := k8s.FromK8sAllowedName(service.Name)
name, err := k8s.FromK8sAllowedName(service.Name)
if err != nil {
return names, err
return items, err
}
names = append(names, n)
// get status
ready := corev1.ConditionUnknown
for _, con := range service.Status.Conditions {
if con.Type == apis.ConditionReady {
ready = con.Status
break
}
}
listItem := faas.ListItem{
Name: name,
Runtime: service.Labels["boson.dev/runtime"],
KService: service.Name,
URL: service.Status.URL.String(),
Ready: string(ready),
}
items = append(items, listItem)
}
return
}

View File

@ -1,17 +1,19 @@
package mock
import "github.com/boson-project/faas"
type Lister struct {
ListInvoked bool
ListFn func() ([]string, error)
ListFn func() ([]faas.ListItem, error)
}
func NewLister() *Lister {
return &Lister{
ListFn: func() ([]string, error) { return []string{}, nil },
ListFn: func() ([]faas.ListItem, error) { return []faas.ListItem{}, nil },
}
}
func (l *Lister) List() ([]string, error) {
func (l *Lister) List() ([]faas.ListItem, error) {
l.ListInvoked = true
return l.ListFn()
}