add --wide to show service detail
This commit is contained in:
parent
17a55bb41c
commit
b8b7305fc8
@ -17,11 +17,14 @@ goc list [flags]
|
||||
Run: list,
|
||||
}
|
||||
|
||||
var listWide bool
|
||||
|
||||
func init() {
|
||||
listCmd.Flags().StringVarP(&config.GocConfig.Host, "host", "", "127.0.0.1:7777", "specify the host of the goc server")
|
||||
listCmd.Flags().StringVar(&config.GocConfig.Host, "host", "127.0.0.1:7777", "specify the host of the goc server")
|
||||
listCmd.Flags().BoolVar(&listWide, "wide", false, "List all services with more information (such as pid)")
|
||||
rootCmd.AddCommand(listCmd)
|
||||
}
|
||||
|
||||
func list(cmd *cobra.Command, args []string) {
|
||||
client.NewWorker("http://" + config.GocConfig.Host).ListAgents()
|
||||
client.NewWorker("http://" + config.GocConfig.Host).ListAgents(listWide)
|
||||
}
|
||||
|
2
go.mod
2
go.mod
@ -10,7 +10,6 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/sirupsen/logrus v1.7.0
|
||||
github.com/spf13/cobra v1.1.3
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
@ -18,6 +17,7 @@ require (
|
||||
go.uber.org/zap v1.17.0
|
||||
golang.org/x/mod v0.4.2
|
||||
golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d
|
||||
golang.org/x/tools v0.1.3
|
||||
k8s.io/kubectl v0.21.2
|
||||
k8s.io/test-infra v0.0.0-20210618100605-34aa2f2aa75b
|
||||
|
1
go.sum
1
go.sum
@ -1100,7 +1100,6 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||
|
@ -2,21 +2,22 @@ package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/qiniu/goc/v2/pkg/log"
|
||||
"golang.org/x/term"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/qiniu/goc/v2/pkg/log"
|
||||
)
|
||||
|
||||
// Action provides methods to contact with the covered agent under test
|
||||
type Action interface {
|
||||
ListAgents()
|
||||
ListAgents(bool)
|
||||
}
|
||||
|
||||
const (
|
||||
@ -24,10 +25,6 @@ const (
|
||||
CoverAgentsListAPI = "/v2/rpcagents"
|
||||
)
|
||||
|
||||
var (
|
||||
ERROR_GOC_LIST = errors.New("goc list failed")
|
||||
)
|
||||
|
||||
type client struct {
|
||||
Host string
|
||||
client *http.Client
|
||||
@ -51,7 +48,7 @@ type gocCoveredAgent struct {
|
||||
func NewWorker(host string) Action {
|
||||
_, err := url.ParseRequestURI(host)
|
||||
if err != nil {
|
||||
log.Fatalf("Parse url %s failed, err: %v", host, err)
|
||||
log.Fatalf("parse url %s failed, err: %v", host, err)
|
||||
}
|
||||
return &client{
|
||||
Host: host,
|
||||
@ -59,33 +56,64 @@ func NewWorker(host string) Action {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *client) ListAgents() {
|
||||
func (c *client) ListAgents(wide bool) {
|
||||
u := fmt.Sprintf("%s%s", c.Host, CoverAgentsListAPI)
|
||||
_, body, err := c.do("GET", u, "", nil)
|
||||
if err != nil && isNetworkError(err) {
|
||||
_, body, err = c.do("GET", u, "", nil)
|
||||
}
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%w: %v", ERROR_GOC_LIST, err)
|
||||
err = fmt.Errorf("goc list failed: %v", err)
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
agents := gocListAgents{}
|
||||
err = json.Unmarshal(body, &agents)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%w: json unmarshal failed: %v", ERROR_GOC_LIST, err)
|
||||
err = fmt.Errorf("goc list failed: json unmarshal failed: %v", err)
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"ID", "RemoteIP", "Hostname", "Pid", "CMD"})
|
||||
table.SetAutoFormatHeaders(false)
|
||||
table.SetColumnAlignment([]int{tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER, tablewriter.ALIGN_CENTER})
|
||||
table.SetCenterSeparator("")
|
||||
table.SetColumnSeparator("")
|
||||
table.SetRowSeparator("")
|
||||
table.SetHeaderLine(false)
|
||||
table.SetBorder(false)
|
||||
table.SetTablePadding(" ") // pad with 3 blank spaces
|
||||
table.SetNoWhiteSpace(true)
|
||||
table.SetReflowDuringAutoWrap(false)
|
||||
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
|
||||
if wide {
|
||||
table.SetHeader([]string{"ID", "REMOTEIP", "HOSTNAME", "PID", "CMD"})
|
||||
table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
|
||||
} else {
|
||||
table.SetHeader([]string{"ID", "REMOTEIP", "CMD"})
|
||||
table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
|
||||
}
|
||||
for _, agent := range agents.Items {
|
||||
table.Append([]string{agent.Id, agent.RemoteIP, agent.Hostname, agent.Pid, agent.CmdLine})
|
||||
if wide {
|
||||
table.Append([]string{agent.Id, agent.RemoteIP, agent.Hostname, agent.Pid, agent.CmdLine})
|
||||
} else {
|
||||
preLen := len(agent.Id) + len(agent.RemoteIP) + 9
|
||||
table.Append([]string{agent.Id, agent.RemoteIP, getSimpleCmdLine(preLen, agent.CmdLine)})
|
||||
}
|
||||
}
|
||||
table.Render()
|
||||
return
|
||||
}
|
||||
|
||||
// getSimpleCmdLine
|
||||
func getSimpleCmdLine(preLen int, cmdLine string) string {
|
||||
pathLen := len(cmdLine)
|
||||
width, _, err := term.GetSize(int(os.Stdin.Fd()))
|
||||
if err != nil || width <= preLen+16 {
|
||||
width = 16 + preLen // show at least 16 words of the command
|
||||
}
|
||||
if pathLen > width-preLen {
|
||||
return cmdLine[:width-preLen]
|
||||
}
|
||||
return cmdLine
|
||||
}
|
||||
|
||||
func (c *client) do(method, url, contentType string, body io.Reader) (*http.Response, []byte, error) {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
|
@ -2,21 +2,18 @@ package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func captureStdout(f func()) string {
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("os pipe fail")
|
||||
}
|
||||
r, w, _ := os.Pipe()
|
||||
stdout := os.Stdout
|
||||
os.Stdout = w
|
||||
defer func() {
|
||||
@ -33,7 +30,7 @@ func captureStdout(f func()) string {
|
||||
}
|
||||
|
||||
func TestClientListAgents(t *testing.T) {
|
||||
mockAgents := `{"items": [{"id": "testID", "remoteip": "1.1.1.1", "hostname": "testHost", "cmdline": "testCmd", "pid": "0"}]}`
|
||||
mockAgents := `{"items": [{"id": "testID", "remoteip": "1.1.1.1", "hostname": "testHost", "cmdline": "./testCmd -f testArgs", "pid": "0"}]}`
|
||||
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(mockAgents))
|
||||
@ -41,14 +38,31 @@ func TestClientListAgents(t *testing.T) {
|
||||
defer mockServer.Close()
|
||||
|
||||
c := NewWorker(mockServer.URL)
|
||||
output := captureStdout(c.ListAgents)
|
||||
expected := `+--------+----------+----------+-----+---------+
|
||||
| ID | RemoteIP | Hostname | Pid | CMD |
|
||||
+--------+----------+----------+-----+---------+
|
||||
| testID | 1.1.1.1 | testHost | 0 | testCmd |
|
||||
+--------+----------+----------+-----+---------+
|
||||
`
|
||||
assert.Equal(t, output, expected)
|
||||
testCases := map[string]struct {
|
||||
input bool
|
||||
expected string
|
||||
}{
|
||||
"simple list": {
|
||||
false,
|
||||
`ID REMOTEIP CMD
|
||||
testID 1.1.1.1 ./testCmd -f tes
|
||||
`,
|
||||
},
|
||||
"wide list": {
|
||||
true,
|
||||
`ID REMOTEIP HOSTNAME PID CMD
|
||||
testID 1.1.1.1 testHost 0 ./testCmd -f testArgs
|
||||
`,
|
||||
},
|
||||
}
|
||||
for name, tt := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
f := func() { c.ListAgents(tt.input) }
|
||||
output := captureStdout(f)
|
||||
fmt.Println(output)
|
||||
assert.Equal(t, output, tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientDo(t *testing.T) {
|
||||
@ -58,3 +72,18 @@ func TestClientDo(t *testing.T) {
|
||||
_, _, err := c.do(" ", "http://127.0.0.1:7777", "", nil) // a invalid method
|
||||
assert.Contains(t, err.Error(), "invalid method")
|
||||
}
|
||||
|
||||
func TestGetSimpleSvcName(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
"short path": {"1234567890abc.go", "1234567890abc.go"},
|
||||
"long path": {"1234567890abcdef.go", "1234567890abcdef"},
|
||||
}
|
||||
for name, tt := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert.Equal(t, getSimpleCmdLine(0, tt.input), tt.expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user