Skip to content

Commit 4772e38

Browse files
committed
refactor display options
1 parent 245f6a0 commit 4772e38

File tree

4 files changed

+131
-111
lines changed

4 files changed

+131
-111
lines changed

cmd/flow_capture.go

Lines changed: 13 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,6 @@ var (
3434
flowsToShow = 35
3535
regexes = []string{}
3636
lastFlows = []config.GenericMap{}
37-
38-
rawDisplay = "Raw"
39-
standardDisplay = "Standard"
40-
exclusiveDisplays = []string{rawDisplay, standardDisplay}
41-
pktDropDisplay = "pktDrop"
42-
dnsDisplay = "dnsTracking"
43-
rttDisplay = "flowRTT"
44-
networkEventsDisplay = "networkEvents"
45-
displays = []string{pktDropDisplay, dnsDisplay, rttDisplay, networkEventsDisplay}
46-
display = []string{standardDisplay}
47-
48-
noEnrichment = "None"
49-
exclusiveEnrichments = []string{noEnrichment}
50-
clusterEnrichment = "Cluster"
51-
zoneEnrichment = "Zone"
52-
hostEnrichment = "Host"
53-
ownerEnrichment = "Owner"
54-
resourceEnrichment = "Resource"
55-
subnetLabelEnrichment = "SubnetLabel"
56-
enrichments = []string{clusterEnrichment, zoneEnrichment, hostEnrichment, ownerEnrichment, resourceEnrichment, subnetLabelEnrichment}
57-
enrichment = []string{resourceEnrichment}
5837
)
5938

6039
func runFlowCapture(_ *cobra.Command, _ []string) {
@@ -246,16 +225,16 @@ func updateTable() {
246225
}
247226
if strings.Contains(options, "background=true") {
248227
fmt.Printf("Showing last: %d\n", flowsToShow)
249-
fmt.Printf("Display: %s\n", toShortTitleStr(display))
250-
fmt.Printf("Enrichment: %s\n", toShortTitleStr(enrichment))
228+
fmt.Printf("Display: %s\n", display.getCurrentItem().name)
229+
fmt.Printf("Enrichment: %s\n", enrichment.getCurrentItem().name)
251230
} else {
252231
fmt.Printf("Showing last: %d Use Up / Down keyboard arrows to increase / decrease limit\n", flowsToShow)
253-
fmt.Printf("Display: %s Use Left / Right keyboard arrows to cycle views\n", toShortTitleStr(display))
254-
fmt.Printf("Enrichment: %s Use Page Up / Page Down keyboard keys to cycle enrichment scopes\n", toShortTitleStr(enrichment))
232+
fmt.Printf("Display: %s Use Left / Right keyboard arrows to cycle views\n", display.getCurrentItem().name)
233+
fmt.Printf("Enrichment: %s Use Page Up / Page Down keyboard keys to cycle enrichment scopes\n", enrichment.getCurrentItem().name)
255234
}
256235
}
257236

258-
if slices.Contains(display, rawDisplay) {
237+
if display.getCurrentItem().name == rawDisplay {
259238
fmt.Print("Raw flow logs:\n")
260239
for _, flow := range lastFlows {
261240
fmt.Printf("%v\n", flow)
@@ -272,23 +251,8 @@ func updateTable() {
272251
}
273252

274253
// enrichment fields
275-
if !slices.Contains(enrichment, noEnrichment) {
276-
for _, enr := range enrichment {
277-
var fieldMatch string
278-
if enr == resourceEnrichment {
279-
fieldMatch = "K8S_Name"
280-
} else if enr == subnetLabelEnrichment {
281-
fieldMatch = "SubnetLabel"
282-
} else {
283-
fieldMatch = fmt.Sprintf("K8S_%s", enr)
284-
}
285-
286-
for _, col := range cfg.Columns {
287-
if strings.Contains(col.Field, fieldMatch) {
288-
colIDs = append(colIDs, col.ID)
289-
}
290-
}
291-
}
254+
if enrichment.getCurrentItem().name != noOptions {
255+
colIDs = append(colIDs, enrichment.getCurrentItem().ids...)
292256
} else {
293257
// TODO: add a new flag in the config to identify these as default non enriched fields
294258
colIDs = append(colIDs,
@@ -300,16 +264,15 @@ func updateTable() {
300264
}
301265

302266
// standard / feature fields
303-
if !slices.Contains(display, standardDisplay) {
267+
if display.getCurrentItem().name != standardDisplay {
304268
for _, col := range cfg.Columns {
305-
if slices.Contains(display, col.Feature) {
269+
if slices.Contains(display.getCurrentItem().ids, col.Feature) {
306270
colIDs = append(colIDs, col.ID)
307271
}
308272
}
309273
} else {
310274
// TODO: add a new flag in the config to identify these as default feature fields
311275
colIDs = append(colIDs,
312-
"FlowDirection",
313276
"Interfaces",
314277
"Proto",
315278
"Dscp",
@@ -356,30 +319,6 @@ func updateTable() {
356319
}
357320
}
358321

359-
func cycleOption(selection []string, exclusiveOptions []string, options []string, incr int) []string {
360-
allOptions := slices.Concat(exclusiveOptions, options)
361-
362-
var index int
363-
if len(selection) == 1 {
364-
index = slices.Index(allOptions, selection[0])
365-
if index+incr < 0 || index+incr > len(allOptions)-1 {
366-
index = -1
367-
} else {
368-
index += incr
369-
}
370-
} else if incr < 0 {
371-
index = len(allOptions) - 1
372-
}
373-
374-
if index != -1 {
375-
selection = []string{allOptions[index]}
376-
} else {
377-
selection = slices.Clone(options)
378-
}
379-
380-
return selection
381-
}
382-
383322
func scanner() {
384323
if err := keyboard.Open(); err != nil {
385324
keyboardError = fmt.Sprintf("Keyboard not supported %v", err)
@@ -406,13 +345,13 @@ func scanner() {
406345
flowsToShow = flowsToShow - 1
407346
}
408347
} else if key == keyboard.KeyArrowRight {
409-
display = cycleOption(display, exclusiveDisplays, displays, 1)
348+
display.next()
410349
} else if key == keyboard.KeyArrowLeft {
411-
display = cycleOption(display, exclusiveDisplays, displays, -1)
350+
display.prev()
412351
} else if key == keyboard.KeyPgup {
413-
enrichment = cycleOption(enrichment, exclusiveEnrichments, enrichments, 1)
352+
enrichment.next()
414353
} else if key == keyboard.KeyPgdn {
415-
enrichment = cycleOption(enrichment, exclusiveEnrichments, enrichments, -1)
354+
enrichment.prev()
416355
} else if key == keyboard.KeyBackspace || key == keyboard.KeyBackspace2 {
417356
if len(regexes) > 0 {
418357
lastIndex := len(regexes) - 1

cmd/flow_capture_test.go

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func TestFlowTableDefaultDisplay(t *testing.T) {
3939
rows := strings.Split(buf.String(), "\n")
4040

4141
assert.Equal(t, 4, len(rows))
42-
assert.Equal(t, `End Time Src Name Src Namespace Dst Name Dst Namespace Node Dir Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
43-
assert.Equal(t, `17:25:28.703000 src-pod first-namespace dst-pod second-namespace Ingress f18b970c2ce8fdd TCP Standard 456B 5 `, rows[1])
44-
assert.Equal(t, `--------------- --------------- --------------- --------------- --------------- ---------- ---------- ---------- ---------- ----- ----- `, rows[2])
42+
assert.Equal(t, `End Time Src Kind Dst Kind Src Name Dst Name Src Namespace Dst Namespace Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
43+
assert.Equal(t, `17:25:28.703000 Pod Pod src-pod dst-pod first-namespace second-namespace f18b970c2ce8fdd TCP Standard 456B 5 `, rows[1])
44+
assert.Equal(t, `--------------- ---------- ---------- --------------- --------------- --------------- --------------- ---------- ---------- ---------- ----- ----- `, rows[2])
4545
assert.Empty(t, rows[3])
4646
}
4747

@@ -53,8 +53,8 @@ func TestFlowTableMultipleFlows(t *testing.T) {
5353
setOutputBuffer(&buf)
5454

5555
// set display to standard without enrichment
56-
display = []string{standardDisplay}
57-
enrichment = []string{noEnrichment}
56+
display.current = 1
57+
enrichment.current = 0
5858

5959
// set time and bytes per flow
6060
flowTime := 1704063600000
@@ -86,16 +86,16 @@ func TestFlowTableMultipleFlows(t *testing.T) {
8686
rows := strings.Split(buf.String(), "\n")
8787
// table must display only 38 rows (35 flows + header + footer + empty line)
8888
assert.Equal(t, 38, len(rows))
89-
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Node Dir Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
89+
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
9090
// first flow is the 6th one that came to the display
91-
assert.Equal(t, `00:00:06.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 6KB 1 `, rows[1])
92-
assert.Equal(t, `00:00:07.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 7KB 1 `, rows[2])
93-
assert.Equal(t, `00:00:08.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 8KB 1 `, rows[3])
94-
assert.Equal(t, `00:00:09.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 9KB 1 `, rows[4])
95-
assert.Equal(t, `00:00:10.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 10KB 1 `, rows[5])
91+
assert.Equal(t, `00:00:06.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 6KB 1 `, rows[1])
92+
assert.Equal(t, `00:00:07.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 7KB 1 `, rows[2])
93+
assert.Equal(t, `00:00:08.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 8KB 1 `, rows[3])
94+
assert.Equal(t, `00:00:09.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 9KB 1 `, rows[4])
95+
assert.Equal(t, `00:00:10.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 10KB 1 `, rows[5])
9696
// last flow is the 40th one
97-
assert.Equal(t, `00:00:40.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a n/a 40KB 1 `, rows[35])
98-
assert.Equal(t, `--------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----- ----- `, rows[36])
97+
assert.Equal(t, `00:00:40.000000 10.0.0.5 n/a 10.0.0.6 n/a n/a n/a n/a 40KB 1 `, rows[35])
98+
assert.Equal(t, `--------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----- ----- `, rows[36])
9999
assert.Empty(t, rows[37])
100100

101101
}
@@ -108,10 +108,21 @@ func TestFlowTableAdvancedDisplay(t *testing.T) {
108108
setOutputBuffer(&buf)
109109

110110
// getRows function cleanup everything and redraw table with sample flow
111-
getRows := func(d []string, e []string) []string {
111+
getRows := func(displayName string, displayIds []string, enrichmentName string, enrichmentIds []string) []string {
112112
// prepare display options
113-
display = d
114-
enrichment = e
113+
display = option{
114+
all: []optionItem{
115+
{name: displayName, ids: displayIds},
116+
},
117+
current: 0,
118+
}
119+
120+
enrichment = option{
121+
all: []optionItem{
122+
{name: enrichmentName, ids: enrichmentIds},
123+
},
124+
current: 0,
125+
}
115126

116127
// clear filters and previous flows
117128
regexes = []string{}
@@ -127,24 +138,24 @@ func TestFlowTableAdvancedDisplay(t *testing.T) {
127138
}
128139

129140
// set display without enrichment
130-
rows := getRows([]string{pktDropDisplay, dnsDisplay, rttDisplay, networkEventsDisplay}, []string{noEnrichment})
141+
rows := getRows(allOptions, []string{pktDropFeature, dnsFeature, rttFeature, networkEventsDisplay}, noOptions, []string{})
131142
assert.Equal(t, 4, len(rows))
132143
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Dropped Bytes Dropped Packets Drop State Drop Cause Drop Flags DNS Id DNS Latency DNS RCode DNS Error Flow RTT Network Events `, rows[0])
133144
assert.Equal(t, `17:25:28.703000 10.128.0.29 1234 10.129.0.26 5678 32B 1 TCP_INVALID_STATE SKB_DROP_REASON_TCP_INVALID_SEQUENCE 16 31319 1ms NoError 0 10µs hello `, rows[1])
134145
assert.Equal(t, `--------------- ---------- ---------- ---------- ---------- ----- ----- ---------- ---------- ---------- ----- ----- ----- ----- ----- --------------- `, rows[2])
135146
assert.Empty(t, rows[3])
136147

137148
// set display to standard
138-
rows = getRows([]string{standardDisplay}, []string{noEnrichment})
149+
rows = getRows(standardDisplay, []string{}, noOptions, []string{})
139150

140151
assert.Equal(t, 4, len(rows))
141-
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Node Dir Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
142-
assert.Equal(t, `17:25:28.703000 10.128.0.29 1234 10.129.0.26 5678 Ingress f18b970c2ce8fdd TCP Standard 456B 5 `, rows[1])
143-
assert.Equal(t, `--------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----- ----- `, rows[2])
152+
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Interfaces L3 Layer Protocol L3 Layer DSCP Bytes Packets `, rows[0])
153+
assert.Equal(t, `17:25:28.703000 10.128.0.29 1234 10.129.0.26 5678 f18b970c2ce8fdd TCP Standard 456B 5 `, rows[1])
154+
assert.Equal(t, `--------------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----- ----- `, rows[2])
144155
assert.Empty(t, rows[3])
145156

146157
// set display to pktDrop
147-
rows = getRows([]string{pktDropDisplay}, []string{noEnrichment})
158+
rows = getRows("Packet drops", []string{pktDropFeature}, noOptions, []string{})
148159

149160
assert.Equal(t, 4, len(rows))
150161
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Dropped Bytes Dropped Packets Drop State Drop Cause Drop Flags `, rows[0])
@@ -153,7 +164,7 @@ func TestFlowTableAdvancedDisplay(t *testing.T) {
153164
assert.Empty(t, rows[3])
154165

155166
// set display to DNS
156-
rows = getRows([]string{dnsDisplay}, []string{noEnrichment})
167+
rows = getRows("DNS", []string{dnsFeature}, noOptions, []string{})
157168

158169
assert.Equal(t, 4, len(rows))
159170
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port DNS Id DNS Latency DNS RCode DNS Error `, rows[0])
@@ -162,7 +173,7 @@ func TestFlowTableAdvancedDisplay(t *testing.T) {
162173
assert.Empty(t, rows[3])
163174

164175
// set display to RTT
165-
rows = getRows([]string{rttDisplay}, []string{noEnrichment})
176+
rows = getRows("RTT", []string{rttFeature}, noOptions, []string{})
166177

167178
assert.Equal(t, 4, len(rows))
168179
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Flow RTT `, rows[0])
@@ -171,7 +182,7 @@ func TestFlowTableAdvancedDisplay(t *testing.T) {
171182
assert.Empty(t, rows[3])
172183

173184
// set display to NetworkEvents
174-
rows = getRows([]string{networkEventsDisplay}, []string{noEnrichment})
185+
rows = getRows("Network events", []string{networkEventsDisplay}, noOptions, []string{})
175186
assert.Equal(t, 4, len(rows))
176187
assert.Equal(t, `End Time Src IP Src Port Dst IP Dst Port Network Events `, rows[0])
177188
assert.Equal(t, `17:25:28.703000 10.128.0.29 1234 10.129.0.26 5678 hello `, rows[1])

cmd/map_format.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -431,18 +431,6 @@ func toTimeString(genericMap config.GenericMap, fieldName string) string {
431431
return emptyText
432432
}
433433

434-
func toTitles(strs []string) []string {
435-
titleCaseStrs := []string{}
436-
for _, s := range strs {
437-
titleCaseStrs = append(titleCaseStrs, fmt.Sprintf("%s%s", strings.ToUpper(s[:1]), s[1:]))
438-
}
439-
return titleCaseStrs
440-
}
441-
442-
func toShortTitleStr(strs []string) string {
443-
return replacer.Replace(strings.Join(toTitles(strs), ","))
444-
}
445-
446434
func ToTableColName(id string) string {
447435
name := id
448436
colIndex := slices.IndexFunc(cfg.Columns, func(c *ColumnConfig) bool { return c.ID == id })

cmd/options.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package cmd
2+
3+
type option struct {
4+
all []optionItem
5+
current int
6+
}
7+
8+
type optionItem struct {
9+
name string
10+
ids []string
11+
}
12+
13+
var (
14+
allOptions = "All"
15+
noOptions = "None"
16+
17+
// displays
18+
rawDisplay = "Raw"
19+
standardDisplay = "Standard"
20+
pktDropFeature = "pktDrop"
21+
dnsFeature = "dnsTracking"
22+
rttFeature = "flowRTT"
23+
networkEventsDisplay = "networkEvents"
24+
display = option{
25+
all: []optionItem{
26+
// exclusive displays
27+
{name: rawDisplay},
28+
{name: standardDisplay},
29+
// per feature displays
30+
{name: "Packet drops", ids: []string{pktDropFeature}},
31+
{name: "DNS", ids: []string{dnsFeature}},
32+
{name: "RTT", ids: []string{rttFeature}},
33+
{name: "Network events", ids: []string{networkEventsDisplay}},
34+
// all features display
35+
{name: allOptions, ids: []string{pktDropFeature, dnsFeature, rttFeature, networkEventsDisplay}},
36+
},
37+
// standard display by default
38+
current: 1,
39+
}
40+
41+
// enrichments
42+
enrichment = option{
43+
all: []optionItem{
44+
// no enrichment
45+
{name: noOptions},
46+
// per field enrichments
47+
{name: "Cluster", ids: []string{"ClusterName"}},
48+
{name: "Zone", ids: []string{"SrcZone", "DstZone"}},
49+
{name: "Host", ids: []string{"SrcK8S_HostIP", "DstK8S_HostIP", "SrcK8S_HostName", "DstK8S_HostName", "FlowDirection"}},
50+
{name: "Namespace", ids: []string{"SrcK8S_Namespace", "DstK8S_Namespace"}},
51+
{name: "Owner", ids: []string{"SrcK8S_OwnerType", "DstK8S_OwnerType", "SrcK8S_OwnerName", "DstK8S_OwnerName", "SrcK8S_Namespace", "DstK8S_Namespace"}},
52+
{name: "Resource", ids: []string{"SrcK8S_Type", "DstK8S_Type", "SrcK8S_Name", "DstK8S_Name", "SrcK8S_Namespace", "DstK8S_Namespace"}},
53+
{name: "SubnetLabel", ids: []string{"SrcSubnetLabel", "DstSubnetLabel"}},
54+
// all fields
55+
{name: allOptions, ids: []string{
56+
"ClusterName",
57+
"SrcZone", "DstZone",
58+
"SrcK8S_HostIP", "DstK8S_HostIP", "SrcK8S_HostName", "DstK8S_HostName",
59+
"SrcK8S_Namespace", "DstK8S_Namespace",
60+
"SrcK8S_OwnerType", "DstK8S_OwnerType", "SrcK8S_OwnerName", "DstK8S_OwnerName",
61+
"SrcK8S_Type", "DstK8S_Type", "SrcK8S_Name", "DstK8S_Name",
62+
"SrcSubnetLabel", "DstSubnetLabel",
63+
}},
64+
},
65+
// resource enrichment by default
66+
current: 6,
67+
}
68+
)
69+
70+
func (opt *option) getCurrentItem() optionItem {
71+
return opt.all[opt.current]
72+
}
73+
74+
func (opt *option) prev() {
75+
opt.current += len(opt.all) - 1
76+
opt.current %= len(opt.all)
77+
}
78+
79+
func (opt *option) next() {
80+
opt.current++
81+
opt.current %= len(opt.all)
82+
}

0 commit comments

Comments
 (0)