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 <kezhenx...@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