Skip to content

Commit 7e9fde3

Browse files
committed
add a footer to tables
1 parent 54efeb0 commit 7e9fde3

File tree

1 file changed

+93
-18
lines changed

1 file changed

+93
-18
lines changed

cmd/sshproxyctl/sshproxyctl.go

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/cea-hpc/sshproxy/pkg/utils"
3030

3131
"github.com/olekukonko/tablewriter"
32+
"github.com/olekukonko/tablewriter/tw"
3233
)
3334

3435
var (
@@ -76,12 +77,18 @@ func displayJSON(objs interface{}) {
7677
}
7778
}
7879

79-
func displayTable(headers []string, rows [][]string) {
80+
func displayTable(headers []string, rows [][]string, footers []string) {
8081
table := tablewriter.NewTable(os.Stdout,
8182
tablewriter.WithConfig(tablewriter.Config{
8283
MaxWidth: 200,
84+
Row: tw.CellConfig{
85+
Formatting: tw.CellFormatting{
86+
Alignment: tw.AlignRight,
87+
},
88+
},
8389
}))
8490
table.Header(headers)
91+
table.Footer(footers)
8592
table.Bulk(rows)
8693
table.Render()
8794
}
@@ -98,28 +105,42 @@ type aggConnection struct {
98105

99106
type aggregatedConnections []*aggConnection
100107

101-
func (ac aggregatedConnections) toRows(passthrough bool) [][]string {
108+
func (ac aggregatedConnections) toRows(passthrough bool) ([][]string, map[string]string) {
102109
rows := make([][]string, len(ac))
110+
totalConnections := 0
111+
totalIn := 0
112+
totalOut := 0
103113

104114
for i, c := range ac {
105115
rows[i] = []string{
106116
c.User,
107117
c.Service,
108118
c.Dest,
109-
strconv.Itoa(c.N),
119+
fmt.Sprintf("%d", c.N),
110120
c.Last.Format("2006-01-02 15:04:05"),
111121
byteToHuman(c.BwIn, passthrough),
112122
byteToHuman(c.BwOut, passthrough),
113123
}
124+
totalConnections += c.N
125+
totalIn += c.BwIn
126+
totalOut += c.BwOut
127+
}
128+
footer := map[string]string{
129+
"connections": fmt.Sprintf("%d", totalConnections),
130+
"in": byteToHuman(totalIn, passthrough),
131+
"out": byteToHuman(totalOut, passthrough),
114132
}
115133

116-
return rows
134+
return rows, footer
117135
}
118136

119137
type flatConnections []*utils.FlatConnection
120138

121-
func (fc flatConnections) getAllConnections(passthrough bool) [][]string {
139+
func (fc flatConnections) getAllConnections(passthrough bool) ([][]string, map[string]string) {
122140
rows := make([][]string, len(fc))
141+
totalConnections := 0
142+
totalIn := 0
143+
totalOut := 0
123144

124145
for i, c := range fc {
125146
rows[i] = []string{
@@ -131,9 +152,17 @@ func (fc flatConnections) getAllConnections(passthrough bool) [][]string {
131152
byteToHuman(c.BwIn, passthrough),
132153
byteToHuman(c.BwOut, passthrough),
133154
}
155+
totalConnections += 1
156+
totalIn += c.BwIn
157+
totalOut += c.BwOut
158+
}
159+
footer := map[string]string{
160+
"connections": fmt.Sprintf("%d", totalConnections),
161+
"in": byteToHuman(totalIn, passthrough),
162+
"out": byteToHuman(totalOut, passthrough),
134163
}
135164

136-
return rows
165+
return rows, footer
137166
}
138167

139168
func (fc flatConnections) getAggregatedConnections() aggregatedConnections {
@@ -203,9 +232,9 @@ func (fc flatConnections) displayCSV(allFlag bool) {
203232
var rows [][]string
204233

205234
if allFlag {
206-
rows = fc.getAllConnections(true)
235+
rows, _ = fc.getAllConnections(true)
207236
} else {
208-
rows = fc.getAggregatedConnections().toRows(true)
237+
rows, _ = fc.getAggregatedConnections().toRows(true)
209238
}
210239

211240
displayCSV(rows)
@@ -225,21 +254,25 @@ func (fc flatConnections) displayJSON(allFlag bool) {
225254

226255
func (fc flatConnections) displayTable(allFlag bool) {
227256
var rows [][]string
257+
var footer map[string]string
228258

229259
if allFlag {
230-
rows = fc.getAllConnections(false)
260+
rows, footer = fc.getAllConnections(false)
231261
} else {
232-
rows = fc.getAggregatedConnections().toRows(false)
262+
rows, footer = fc.getAggregatedConnections().toRows(false)
233263
}
234264

235265
var headers []string
266+
var footers []string
236267
if allFlag {
237268
headers = []string{"User", "Service", "From", "Destination", "Start time", "Bw in", "Bw out"}
269+
footers = []string{"", "", "", "Totals", footer["connections"], footer["in"], footer["out"]}
238270
} else {
239271
headers = []string{"User", "Service", "Destination", "# of conns", "Last connection", "Bw in", "Bw out"}
272+
footers = []string{"", "", "Totals", footer["connections"], "", footer["in"], footer["out"]}
240273
}
241274

242-
displayTable(headers, rows)
275+
displayTable(headers, rows, footers)
243276
}
244277

245278
func showConnections(configFile string, csvFlag bool, jsonFlag bool, allFlag bool) {
@@ -271,8 +304,12 @@ type flatUserLight struct {
271304

272305
type flatUsers []*utils.FlatUser
273306

274-
func (fu flatUsers) getAllUsers(allFlag bool, passthrough bool) [][]string {
307+
func (fu flatUsers) getAllUsers(allFlag bool, passthrough bool) ([][]string, map[string]string) {
275308
rows := make([][]string, len(fu))
309+
totalConnections := 0
310+
totalIn := 0
311+
totalOut := 0
312+
276313
for i, v := range fu {
277314
if allFlag {
278315
rows[i] = []string{
@@ -294,6 +331,9 @@ func (fu flatUsers) getAllUsers(allFlag bool, passthrough bool) [][]string {
294331
byteToHuman(v.BwOut, passthrough),
295332
}
296333
}
334+
totalConnections += v.N
335+
totalIn += v.BwIn
336+
totalOut += v.BwOut
297337
}
298338

299339
sort.Slice(rows, func(i, j int) bool {
@@ -303,8 +343,13 @@ func (fu flatUsers) getAllUsers(allFlag bool, passthrough bool) [][]string {
303343
return rows[i][0] < rows[j][0]
304344
}
305345
})
346+
footer := map[string]string{
347+
"connections": fmt.Sprintf("%d", totalConnections),
348+
"in": byteToHuman(totalIn, passthrough),
349+
"out": byteToHuman(totalOut, passthrough),
350+
}
306351

307-
return rows
352+
return rows, footer
308353
}
309354

310355
func (fu flatUsers) displayJSON(allFlag bool) {
@@ -326,22 +371,25 @@ func (fu flatUsers) displayJSON(allFlag bool) {
326371
}
327372

328373
func (fu flatUsers) displayCSV(allFlag bool) {
329-
rows := fu.getAllUsers(allFlag, true)
374+
rows, _ := fu.getAllUsers(allFlag, true)
330375

331376
displayCSV(rows)
332377
}
333378

334379
func (fu flatUsers) displayTable(allFlag bool) {
335-
rows := fu.getAllUsers(allFlag, false)
380+
rows, footer := fu.getAllUsers(allFlag, false)
336381

337382
var headers []string
383+
var footers []string
338384
if allFlag {
339385
headers = []string{"User", "Service", "Groups", "# of conns", "Bw in", "Bw out", "Persist to", "Persist TTL"}
386+
footers = []string{"", "", "Totals", footer["connections"], footer["in"], footer["out"], "", ""}
340387
} else {
341388
headers = []string{"User", "Groups", "# of conns", "Bw in", "Bw out"}
389+
footers = []string{"", "Totals", footer["connections"], footer["in"], footer["out"]}
342390
}
343391

344-
displayTable(headers, rows)
392+
displayTable(headers, rows, footers)
345393
}
346394

347395
func showUsers(configFile string, csvFlag bool, jsonFlag bool, allFlag bool) {
@@ -431,13 +479,14 @@ func (fg flatGroups) displayTable(allFlag bool) {
431479
rows := fg.getAllGroups(allFlag, false)
432480

433481
var headers []string
482+
var footers []string
434483
if allFlag {
435484
headers = []string{"Group", "Service", "Users", "# of conns", "Bw in", "Bw out"}
436485
} else {
437486
headers = []string{"Group", "Users", "# of conns", "Bw in", "Bw out"}
438487
}
439488

440-
displayTable(headers, rows)
489+
displayTable(headers, rows, footers)
441490
}
442491

443492
func showGroups(configFile string, csvFlag bool, jsonFlag bool, allFlag bool) {
@@ -474,6 +523,10 @@ func showHosts(configFile string, csvFlag bool, jsonFlag bool) {
474523
}
475524

476525
rows := make([][]string, len(hosts))
526+
totalConns := 0
527+
totalIn := 0
528+
totalOut := 0
529+
totalPersist := 0
477530

478531
for i, h := range hosts {
479532
rows[i] = []string{
@@ -485,12 +538,34 @@ func showHosts(configFile string, csvFlag bool, jsonFlag bool) {
485538
byteToHuman(h.BwOut, csvFlag),
486539
fmt.Sprintf("%d", h.HistoryN),
487540
}
541+
totalConns += h.N
542+
totalIn += h.BwIn
543+
totalOut += h.BwOut
544+
totalPersist += h.HistoryN
488545
}
489546

490547
if csvFlag {
491548
displayCSV(rows)
492549
} else {
493-
displayTable([]string{"Host", "State", "Last check", "# of conns", "Bw in", "Bw out", "# persist"}, rows)
550+
headers := []string{
551+
"Host",
552+
"State",
553+
"Last check",
554+
"# of conns",
555+
"Bw in",
556+
"Bw out",
557+
"# persist",
558+
}
559+
footers := []string{
560+
"",
561+
"",
562+
"Totals",
563+
fmt.Sprintf("%d", totalConns),
564+
byteToHuman(totalIn, false),
565+
byteToHuman(totalOut, false),
566+
fmt.Sprintf("%d", totalPersist),
567+
}
568+
displayTable(headers, rows, footers)
494569
}
495570
}
496571

0 commit comments

Comments
 (0)