Add printJsonTable
This makes cnetstat's table-printing functions generic to the type of data being printed. This will let us print either connections or summary statistics using the same code.
This commit is contained in:
Родитель
807dfc56f1
Коммит
4cb0a6f4f9
57
cnetstat.go
57
cnetstat.go
|
@ -23,32 +23,6 @@ type KubeConnection struct {
|
|||
container ContainerPath
|
||||
}
|
||||
|
||||
// I'm not using the standard json module for JSON output because I
|
||||
// want to flatten the KubeConnection before printing it
|
||||
func writeKubeConnectionAsJSON(kc *KubeConnection, w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w,
|
||||
"{\"protocol\": %v,"+
|
||||
"\"local_host\": %v, "+
|
||||
"\"local_port\": %v, "+
|
||||
"\"remote_host\": %v, "+
|
||||
"\"remote_port\": %v, "+
|
||||
"\"connection_state\": %v, "+
|
||||
"\"pod_namespace\": %v, "+
|
||||
"\"pod_name\": %v, "+
|
||||
"\"container_name\": %v}",
|
||||
kc.conn.protocol,
|
||||
kc.conn.localHost,
|
||||
kc.conn.localPort,
|
||||
kc.conn.remoteHost,
|
||||
kc.conn.remotePort,
|
||||
kc.conn.connectionState,
|
||||
kc.container.PodNamespace,
|
||||
kc.container.PodName,
|
||||
kc.container.ContainerName)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
const subprocessTimeout = 5 * time.Second
|
||||
|
||||
const ppidColon string = "PPid:"
|
||||
|
@ -123,14 +97,6 @@ func getKubeConnections(connections []Connection, pidMap map[int]ContainerPath)
|
|||
return kubeConnections
|
||||
}
|
||||
|
||||
// Convert empty strings to "-". Why? Because that's what netstat does
|
||||
func emptyToDash(val string) string {
|
||||
if len(val) > 0 {
|
||||
return val
|
||||
} else {
|
||||
return "-"
|
||||
}
|
||||
}
|
||||
|
||||
var kubeConnectionHeaders = []string{
|
||||
"Namespace", "Pod", "Container", "Protocol",
|
||||
|
@ -140,9 +106,9 @@ var kubeConnectionHeaders = []string{
|
|||
|
||||
func (kc KubeConnection) Fields() []string {
|
||||
return []string{
|
||||
emptyToDash(kc.container.PodNamespace),
|
||||
emptyToDash(kc.container.PodName),
|
||||
emptyToDash(kc.container.ContainerName),
|
||||
kc.container.PodNamespace,
|
||||
kc.container.PodName,
|
||||
kc.container.ContainerName,
|
||||
kc.conn.protocol,
|
||||
kc.conn.localHost,
|
||||
kc.conn.localPort,
|
||||
|
@ -227,20 +193,15 @@ func cnetstat() error {
|
|||
|
||||
kubeConnections := getKubeConnections(allConnections, pidMap)
|
||||
|
||||
table := make([]Fielder, len(kubeConnections))
|
||||
for i, _ := range kubeConnections {
|
||||
table[i] = &kubeConnections[i]
|
||||
}
|
||||
|
||||
switch format {
|
||||
case "json":
|
||||
for _, conn := range kubeConnections {
|
||||
err := writeKubeConnectionAsJSON(&conn, os.Stdout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Stdout.WriteString("\n")
|
||||
}
|
||||
printJsonTable(table, kubeConnectionHeaders, os.Stdout)
|
||||
case "table":
|
||||
table := make([]Fielder, len(kubeConnections))
|
||||
for i, _ := range kubeConnections {
|
||||
table[i] = &kubeConnections[i]
|
||||
}
|
||||
prettyPrintTable(table, kubeConnectionHeaders, os.Stdout)
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,18 @@ func max(a, b int) int {
|
|||
return a
|
||||
}
|
||||
|
||||
// Convert empty strings to "-". Why? Because that's what netstat does
|
||||
func emptyToDash(val string) string {
|
||||
if len(val) > 0 {
|
||||
return val
|
||||
} else {
|
||||
return "-"
|
||||
}
|
||||
}
|
||||
|
||||
// Print a table. The fields will print in the order returned by
|
||||
// Fielder.Fields(). header is the first row of fields to print, which
|
||||
// can be used for column titles.
|
||||
// can be used for column titles. Empty fields will be printed as "-".
|
||||
func prettyPrintTable(rows []Fielder, header []string, f io.Writer) {
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
|
@ -49,9 +58,32 @@ func prettyPrintTable(rows []Fielder, header []string, f io.Writer) {
|
|||
w.WriteString("\n")
|
||||
for _, row := range rows {
|
||||
for i, field := range row.Fields() {
|
||||
fmt.Fprintf(w, "%-*s", fieldWidths[i], field)
|
||||
fmt.Fprintf(w, "%-*s", fieldWidths[i], emptyToDash(field))
|
||||
}
|
||||
w.WriteString("\n")
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
|
||||
// Print a table as a series of JSON rows, one row per line of
|
||||
// output. Each row will be a JSON object where property names come
|
||||
// from header and values come from the row being printed.
|
||||
func printJsonTable(rows []Fielder, fieldNames []string, f io.Writer) {
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
for _, row := range rows {
|
||||
w.WriteString("{")
|
||||
for i, field := range row.Fields() {
|
||||
// Using fprintf with a buffered writer
|
||||
// results in two buffers, but this still
|
||||
// seems better than the alternatives.
|
||||
fmt.Fprintf(w, "\"%s\": \"%s\"", fieldNames[i], field)
|
||||
if i < (len(fieldNames) - 1) {
|
||||
w.WriteString(", ")
|
||||
}
|
||||
}
|
||||
w.WriteString("}\n")
|
||||
}
|
||||
|
||||
w.Flush()
|
||||
}
|
||||
|
|
|
@ -15,22 +15,41 @@ func (t TestTable) Fields() []string {
|
|||
return []string{t.a, t.b, t.c}
|
||||
}
|
||||
|
||||
var testTable = []Fielder{
|
||||
&TestTable{a: "a", b: "b", c: "cc"},
|
||||
&TestTable{a: "aaa", b: "b", c: "c"},
|
||||
&TestTable{a: "A", b: "", c: "c"},
|
||||
}
|
||||
|
||||
var testFields = []string{"AAA", "B", "C"}
|
||||
|
||||
const expectedTable = `AAA B C
|
||||
a b cc
|
||||
aaa b c
|
||||
A - c
|
||||
`
|
||||
|
||||
func TestPrettyPrintTable(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
table := []Fielder{
|
||||
&TestTable{a: "a", b: "b", c: "cc"},
|
||||
&TestTable{a: "aaa", b: "b", c: "c"},
|
||||
}
|
||||
|
||||
prettyPrintTable(table, []string{"AAA", "B", "C"}, &buf)
|
||||
prettyPrintTable(testTable, testFields, &buf)
|
||||
written := buf.String()
|
||||
if written != expectedTable {
|
||||
t.Errorf("prettyPrintTable wrote %#v, expected %#v", written, expectedTable)
|
||||
}
|
||||
}
|
||||
|
||||
const expectedJson = `{"AAA": "a", "B": "b", "C": "cc"}
|
||||
{"AAA": "aaa", "B": "b", "C": "c"}
|
||||
{"AAA": "A", "B": "", "C": "c"}
|
||||
`
|
||||
|
||||
func testPrintJsonTable(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
|
||||
printJsonTable(testTable, testFields, &buf)
|
||||
written := buf.String()
|
||||
if written != expectedJson {
|
||||
t.Errorf("printJsonTable wrote %#v, expected %#v", written, expectedJson)
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче