You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/11/10 00:05:52 UTC

[skywalking-cli] 27/29: Abstract display layer and support json/yaml/table display styles

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git

commit 79165a6ddbc7c3a07c24c6bd57773e851b90274d
Author: kezhenxu94 <ke...@163.com>
AuthorDate: Sun Nov 10 03:15:26 2019 +0800

    Abstract display layer and support json/yaml/table display styles
---
 commands/service/list.go                   | 13 ++------
 config/config.go => display/display.go     | 34 ++++++++++++++++---
 config/config.go => display/json/json.go   | 17 +++++++---
 config/config.go => display/table/table.go | 38 ++++++++++++++++++---
 config/config.go => display/yaml/yaml.go   | 17 +++++++---
 go.mod                                     |  1 +
 go.sum                                     |  6 ++++
 graphql/client/client.go                   |  9 ++---
 swctl/main.go                              | 53 ++++++++++++++++++++----------
 9 files changed, 140 insertions(+), 48 deletions(-)

diff --git a/commands/service/list.go b/commands/service/list.go
index d57f970..60d2912 100644
--- a/commands/service/list.go
+++ b/commands/service/list.go
@@ -19,11 +19,10 @@
 package service
 
 import (
-	"encoding/json"
-	"fmt"
 	"github.com/apache/skywalking-cli/commands/flags"
 	"github.com/apache/skywalking-cli/commands/interceptor"
 	"github.com/apache/skywalking-cli/commands/model"
+	"github.com/apache/skywalking-cli/display"
 	"github.com/apache/skywalking-cli/graphql/client"
 	"github.com/apache/skywalking-cli/graphql/schema"
 	"github.com/urfave/cli"
@@ -41,18 +40,12 @@ var ListCommand = cli.Command{
 		end := ctx.String("end")
 		start := ctx.String("start")
 		step := ctx.Generic("step")
-		services := client.Services(schema.Duration{
+		services := client.Services(ctx, schema.Duration{
 			Start: start,
 			End:   end,
 			Step:  step.(*model.StepEnumValue).Selected,
 		})
 
-		if bytes, e := json.Marshal(services); e == nil {
-			fmt.Printf("%v\n", string(bytes))
-		} else {
-			return e
-		}
-
-		return nil
+		return display.Display(ctx, services)
 	},
 }
diff --git a/config/config.go b/display/display.go
similarity index 52%
copy from config/config.go
copy to display/display.go
index 0565fee..3d54f6b 100644
--- a/config/config.go
+++ b/display/display.go
@@ -16,10 +16,36 @@
  *
  */
 
-package config
+package display
 
-var Config struct {
-	Global struct {
-		BaseURL string `yaml:"base-url"`
+import (
+	"errors"
+	"fmt"
+	"github.com/apache/skywalking-cli/display/json"
+	"github.com/apache/skywalking-cli/display/table"
+	"github.com/apache/skywalking-cli/display/yaml"
+	"github.com/urfave/cli"
+	"strings"
+)
+
+const (
+	Json  string = "json"
+	Yaml  string = "yaml"
+	Table string = "table"
+)
+
+// Display the object in the style specified in flag --display
+func Display(ctx *cli.Context, object interface{}) error {
+	displayStyle := ctx.GlobalString("display")
+
+	switch strings.ToLower(displayStyle) {
+	case Json:
+		return json.Display(object)
+	case Yaml:
+		return yaml.Display(object)
+	case Table:
+		return table.Display(object)
+	default:
+		return errors.New(fmt.Sprintf("unsupported display style: %s", displayStyle))
 	}
 }
diff --git a/config/config.go b/display/json/json.go
similarity index 79%
copy from config/config.go
copy to display/json/json.go
index 0565fee..9cda203 100644
--- a/config/config.go
+++ b/display/json/json.go
@@ -16,10 +16,19 @@
  *
  */
 
-package config
+package json
 
-var Config struct {
-	Global struct {
-		BaseURL string `yaml:"base-url"`
+import (
+	"encoding/json"
+	"fmt"
+)
+
+func Display(object interface{}) error {
+	if bytes, e := json.Marshal(object); e == nil {
+		fmt.Printf("%v\n", string(bytes))
+	} else {
+		return e
 	}
+
+	return nil
 }
diff --git a/config/config.go b/display/table/table.go
similarity index 56%
copy from config/config.go
copy to display/table/table.go
index 0565fee..b460f9d 100644
--- a/config/config.go
+++ b/display/table/table.go
@@ -16,10 +16,40 @@
  *
  */
 
-package config
+package table
 
-var Config struct {
-	Global struct {
-		BaseURL string `yaml:"base-url"`
+import (
+	"encoding/json"
+	"github.com/olekukonko/tablewriter"
+	"os"
+)
+
+func Display(object interface{}) error {
+	var objMaps []map[string]string
+
+	bytes, _ := json.Marshal(object)
+	_ = json.Unmarshal(bytes, &objMaps)
+
+	var header []string
+
+	for k := range objMaps[0] {
+		header = append(header, k)
 	}
+
+	var data [][]string
+
+	for _, objMap := range objMaps {
+		var datum []string
+		for _, key := range header {
+			datum = append(datum, objMap[key])
+		}
+		data = append(data, datum)
+	}
+
+	table := tablewriter.NewWriter(os.Stdout)
+	table.SetHeader(header)
+	table.AppendBulk(data)
+	table.Render()
+
+	return nil
 }
diff --git a/config/config.go b/display/yaml/yaml.go
similarity index 79%
rename from config/config.go
rename to display/yaml/yaml.go
index 0565fee..d2e0661 100644
--- a/config/config.go
+++ b/display/yaml/yaml.go
@@ -16,10 +16,19 @@
  *
  */
 
-package config
+package yaml
 
-var Config struct {
-	Global struct {
-		BaseURL string `yaml:"base-url"`
+import (
+	"fmt"
+	"gopkg.in/yaml.v2"
+)
+
+func Display(object interface{}) error {
+	if bytes, e := yaml.Marshal(object); e == nil {
+		fmt.Printf("%v", string(bytes))
+	} else {
+		return e
 	}
+
+	return nil
 }
diff --git a/go.mod b/go.mod
index ad56fce..c859fb1 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.13
 
 require (
 	github.com/machinebox/graphql v0.2.2
+	github.com/olekukonko/tablewriter v0.0.2
 	github.com/pkg/errors v0.8.1 // indirect
 	github.com/sirupsen/logrus v1.4.2
 	github.com/urfave/cli v1.22.1
diff --git a/go.sum b/go.sum
index 7627702..0b55309 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,4 @@
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@@ -7,6 +8,11 @@ github.com/lytics/logrus v0.0.0-20170528191427-4389a17ed024 h1:QaKVrqyQRNPbdBNCp
 github.com/lytics/logrus v0.0.0-20170528191427-4389a17ed024/go.mod h1:SkQviJ2s7rFyzyuxdVp6osZceHOabU91ZhKsEXF0RWg=
 github.com/machinebox/graphql v0.2.2 h1:dWKpJligYKhYKO5A2gvNhkJdQMNZeChZYyBbrZkBZfo=
 github.com/machinebox/graphql v0.2.2/go.mod h1:F+kbVMHuwrQ5tYgU9JXlnskM8nOaFxCAEolaQybkjWA=
+github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
+github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
+github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
+github.com/olekukonko/tablewriter v0.0.2 h1:sq53g+DWf0J6/ceFUHpQ0nAEb6WgM++fq16MZ91cS6o=
+github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ=
 github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
diff --git a/graphql/client/client.go b/graphql/client/client.go
index d74f5c3..2bbb412 100644
--- a/graphql/client/client.go
+++ b/graphql/client/client.go
@@ -20,15 +20,14 @@ package client
 
 import (
 	"context"
-	"github.com/apache/skywalking-cli/config"
 	"github.com/apache/skywalking-cli/graphql/schema"
 	"github.com/apache/skywalking-cli/logger"
 	"github.com/machinebox/graphql"
+	"github.com/urfave/cli"
 )
 
-func Services(duration schema.Duration) []schema.Service {
-	ctx := context.Background()
-	client := graphql.NewClient(config.Config.Global.BaseURL)
+func Services(cliCtx *cli.Context, duration schema.Duration) []schema.Service {
+	client := graphql.NewClient(cliCtx.GlobalString("base-url"))
 	client.Log = func(msg string) {
 		logger.Log.Debugln(msg)
 	}
@@ -42,6 +41,8 @@ func Services(duration schema.Duration) []schema.Service {
 		}
 	`)
 	request.Var("duration", duration)
+
+	ctx := context.Background()
 	if err := client.Run(ctx, request, &response); err != nil {
 		logger.Log.Fatalln(err)
 		panic(err)
diff --git a/swctl/main.go b/swctl/main.go
index 2f3f967..0667211 100644
--- a/swctl/main.go
+++ b/swctl/main.go
@@ -19,14 +19,13 @@
 package main
 
 import (
-	"encoding/json"
+	"github.com/apache/skywalking-cli/commands/interceptor"
 	"github.com/apache/skywalking-cli/commands/service"
-	"github.com/apache/skywalking-cli/config"
 	"github.com/apache/skywalking-cli/logger"
 	"github.com/apache/skywalking-cli/util"
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli"
-	"gopkg.in/yaml.v2"
+	"github.com/urfave/cli/altsrc"
 	"io/ioutil"
 	"os"
 )
@@ -40,46 +39,64 @@ func init() {
 func main() {
 	app := cli.NewApp()
 	app.Usage = "The CLI (Command Line Interface) for Apache SkyWalking."
-	app.Flags = []cli.Flag{
-		cli.StringFlag{
+
+	flags := []cli.Flag{
+		altsrc.NewStringFlag(cli.StringFlag{
 			Name:  "config",
 			Value: "~/.skywalking.yml",
 			Usage: "load configuration `FILE`",
-		},
-		cli.BoolFlag{
+		}),
+		altsrc.NewStringFlag(cli.StringFlag{
+			Name:     "base-url",
+			Required: false,
+			Usage:    "base `url` of the OAP backend graphql",
+			Value:    "http://127.0.0.1:12800/graphql",
+		}),
+		altsrc.NewBoolFlag(cli.BoolFlag{
 			Name:     "debug",
 			Required: false,
 			Usage:    "enable debug mode, will print more detailed logs",
-		},
+		}),
+		altsrc.NewStringFlag(cli.StringFlag{
+			Name:     "display",
+			Required: false,
+			Usage:    "display `style` of the result, supported styles are: json, yaml",
+		}),
 	}
+
 	app.Commands = []cli.Command{
 		service.Command,
 	}
 
-	app.Before = beforeCommand
+	app.Before = interceptor.BeforeChain([]cli.BeforeFunc{
+		expandConfigFile,
+		altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("config")),
+		setUpCommandLineContext,
+	})
+
+	app.Flags = flags
 
 	if err := app.Run(os.Args); err != nil {
 		log.Fatalln(err)
 	}
 }
 
-func beforeCommand(c *cli.Context) error {
+func expandConfigFile(c *cli.Context) error {
+	return c.Set("config", util.ExpandFilePath(c.String("config")))
+}
+
+func setUpCommandLineContext(c *cli.Context) error {
 	if c.Bool("debug") {
 		log.SetLevel(logrus.DebugLevel)
 		log.Debugln("Debug mode is enabled")
 	}
 
-	configFile := util.ExpandFilePath(c.String("config"))
-	log.Debugln("Using configuration file:", configFile)
+	configFile := c.String("config")
 
 	if bytes, err := ioutil.ReadFile(configFile); err != nil {
 		return err
-	} else if err := yaml.Unmarshal(bytes, &config.Config); err != nil {
-		return err
-	}
-
-	if bytes, err := json.Marshal(config.Config); err == nil {
-		log.Debugln("Configurations: ", string(bytes))
+	} else {
+		log.Debug("Using configurations:\n", string(bytes))
 	}
 
 	return nil