Skip to content

Commit 555f91b

Browse files
Adjust UI disaply of Global, Public, Private (#10014)
1 parent e507d11 commit 555f91b

File tree

5 files changed

+124
-22
lines changed

5 files changed

+124
-22
lines changed

goldmane/pkg/aggregator/index.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package aggregator
1616

1717
import (
1818
"math"
19+
"slices"
1920
"sort"
2021

2122
"github.com/sirupsen/logrus"
@@ -195,9 +196,9 @@ func (idx *index[E]) Remove(d *types.DiachronicFlow) {
195196
// The DiachronicFlow at the returned index is the same as the DiachronicFlow to be removed.
196197
// Remove it from the index.
197198
if logrus.IsLevelEnabled(logrus.DebugLevel) {
198-
logrus.WithFields(d.Key.Fields()).Debug("Removing diachronic flow from index")
199+
logrus.WithFields(d.Key.Fields()).Debug("Removing flow from index")
199200
}
200-
idx.diachronics = append(idx.diachronics[:index], idx.diachronics[index+1:]...)
201+
idx.diachronics = slices.Delete(idx.diachronics, index, index+1)
201202
return
202203
} else {
203204
// The DiachronicFlow at the returned index is not the same as the DiachronicFlow to be removed.

goldmane/pkg/types/filters.go

+52-9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,41 @@ import (
2121
"github.com/projectcalico/calico/goldmane/proto"
2222
)
2323

24+
const (
25+
pub = "pub"
26+
pvt = "pvt"
27+
global = "Global"
28+
)
29+
30+
// The UI displays some values differently than they are stored within Goldmane. As such,
31+
// users may sends filters for the UI displayed values, but we need to match against the
32+
// actual stored values. For example, the UI displays "PUBLIC NETWORK" but the stored value
33+
// is "pub".
34+
func names(valFn func() string) func() []string {
35+
return func() []string {
36+
n := valFn()
37+
switch n {
38+
case pub:
39+
return []string{"PUBLIC NETWORK", pub}
40+
case pvt:
41+
return []string{"PRIVATE NETWORK", pvt}
42+
43+
}
44+
return []string{n}
45+
}
46+
}
47+
48+
func namespaces(valFn func() string) func() []string {
49+
return func() []string {
50+
n := valFn()
51+
switch n {
52+
case global:
53+
return []string{"-", global}
54+
}
55+
return []string{n}
56+
}
57+
}
58+
2459
// Matches returns true if the given flow Matches the given filter.
2560
func Matches(filter *proto.Filter, key *FlowKey) bool {
2661
if filter == nil {
@@ -29,11 +64,11 @@ func Matches(filter *proto.Filter, key *FlowKey) bool {
2964
}
3065

3166
comps := []matcher{
32-
&stringComparison{filter: filter.SourceNames, valFn: key.SourceName},
33-
&stringComparison{filter: filter.DestNames, valFn: key.DestName},
34-
&stringComparison{filter: filter.SourceNamespaces, valFn: key.SourceNamespace},
35-
&stringComparison{filter: filter.DestNamespaces, valFn: key.DestNamespace},
36-
&stringComparison{filter: filter.Protocols, valFn: key.Proto},
67+
&stringComparison{filter: filter.SourceNames, genVals: names(key.SourceName)},
68+
&stringComparison{filter: filter.DestNames, genVals: names(key.DestName)},
69+
&stringComparison{filter: filter.SourceNamespaces, genVals: namespaces(key.SourceNamespace)},
70+
&stringComparison{filter: filter.DestNamespaces, genVals: namespaces(key.DestNamespace)},
71+
&stringComparison{filter: filter.Protocols, genVals: func() []string { return []string{key.Proto()} }},
3772
&actionMatch{filter: filter.Actions, key: key},
3873
&portComparison{filter: filter.DestPorts, key: key},
3974
&policyComparison{filter: filter.Policies, key: key},
@@ -86,7 +121,10 @@ func (p *portComparison) matches() bool {
86121

87122
type stringComparison struct {
88123
filter []*proto.StringMatch
89-
valFn func() string
124+
125+
// genVals returns a list of values on the underlying object to compare against the filter.
126+
// If any of the values match, the comparison is considered a match.
127+
genVals func() []string
90128
}
91129

92130
func (c stringComparison) matches() bool {
@@ -99,14 +137,19 @@ func (c stringComparison) matches() bool {
99137
}
100138

101139
func (c stringComparison) matchFilter(filter *proto.StringMatch) bool {
102-
val := c.valFn()
140+
vals := c.genVals()
103141

104142
if filter.Type == proto.MatchType_Exact {
105-
return val == filter.Value
143+
return slices.Contains(vals, filter.Value)
106144
}
107145

108146
// Match type is not exact, so we need to do a substring match.
109-
return strings.Contains(val, filter.Value)
147+
for _, val := range vals {
148+
if strings.Contains(val, filter.Value) {
149+
return true
150+
}
151+
}
152+
return false
110153
}
111154

112155
type policyComparison struct {

whisker-backend/pkg/apis/v1/flows.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,10 @@ func (a Actions) AsProtos() []proto.Action {
116116
return protos
117117
}
118118

119-
type SortBy proto.SortBy
120-
type SortBys []SortBy
119+
type (
120+
SortBy proto.SortBy
121+
SortBys []SortBy
122+
)
121123

122124
func (p SortBy) String() string { return proto.SortBy(p).String() }
123125
func (p SortBy) MarshalJSON() ([]byte, error) { return marshalToBytes(p) }

whisker-backend/pkg/handlers/v1/flows.go

+6
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ func (hdlr *flowsHdlr) ListFilterHints(ctx apictx.Context, params whiskerv1.Flow
139139

140140
hints := make([]whiskerv1.FlowFilterHintResponse, len(gmhints))
141141
for i, hint := range gmhints {
142+
switch params.Type.AsProto() {
143+
case proto.FilterType_FilterTypeSourceNamespace, proto.FilterType_FilterTypeDestNamespace:
144+
hint.Value = protoToNamespace(hint.Value)
145+
case proto.FilterType_FilterTypeSourceName, proto.FilterType_FilterTypeDestName:
146+
hint.Value = protoToName(hint.Value)
147+
}
142148
hints[i] = whiskerv1.FlowFilterHintResponse{Value: hint.Value}
143149
}
144150

whisker-backend/pkg/handlers/v1/protoconvert.go

+59-9
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,25 @@ import (
2222
whiskerv1 "github.com/projectcalico/calico/whisker-backend/pkg/apis/v1"
2323
)
2424

25-
func toProtoStringMatches(matches []whiskerv1.FilterMatch[string]) []*proto.StringMatch {
25+
const (
26+
global = "Global"
27+
28+
publicNetwork = "PUBLIC NETWORK"
29+
privateNetwork = "PRIVATE NETWORK"
30+
31+
pub = "pub"
32+
pvt = "pvt"
33+
)
34+
35+
func toProtoStringMatches(matches []whiskerv1.FilterMatch[string], conv func(string) string) []*proto.StringMatch {
2636
var protos []*proto.StringMatch
2737
for _, match := range matches {
38+
val := match.V
39+
if conv != nil {
40+
val = conv(val)
41+
}
2842
protos = append(protos, &proto.StringMatch{
29-
Value: match.V,
43+
Value: val,
3044
Type: match.Type.AsProto(),
3145
})
3246
}
@@ -63,11 +77,11 @@ func toProtoSortByOptions(sortBys whiskerv1.SortBys) []*proto.SortOption {
6377

6478
func toProtoFilter(filters whiskerv1.Filters) *proto.Filter {
6579
return &proto.Filter{
66-
SourceNames: toProtoStringMatches(filters.SourceNames),
67-
SourceNamespaces: toProtoStringMatches(filters.SourceNamespaces),
68-
DestNames: toProtoStringMatches(filters.DestNames),
69-
DestNamespaces: toProtoStringMatches(filters.DestNamespaces),
70-
Protocols: toProtoStringMatches(filters.Protocols),
80+
SourceNames: toProtoStringMatches(filters.SourceNames, toProtoName),
81+
SourceNamespaces: toProtoStringMatches(filters.SourceNamespaces, toProtoNamespace),
82+
DestNames: toProtoStringMatches(filters.DestNames, toProtoName),
83+
DestNamespaces: toProtoStringMatches(filters.DestNamespaces, toProtoNamespace),
84+
Protocols: toProtoStringMatches(filters.Protocols, nil),
7185
DestPorts: toProtoPorts(filters.DestPorts),
7286
Actions: filters.Actions.AsProtos(),
7387
Policies: toProtoPolicyMatch(filters.Policies),
@@ -130,11 +144,11 @@ func protoToFlow(flow *proto.Flow) whiskerv1.FlowResponse {
130144
EndTime: time.Unix(flow.EndTime, 0),
131145
Action: whiskerv1.Action(flow.Key.Action),
132146

133-
SourceName: flow.Key.SourceName,
147+
SourceName: protoToName(flow.Key.SourceName),
134148
SourceNamespace: flow.Key.SourceNamespace,
135149
SourceLabels: strings.Join(flow.SourceLabels, " | "),
136150

137-
DestName: flow.Key.DestName,
151+
DestName: protoToName(flow.Key.DestName),
138152
DestNamespace: flow.Key.DestNamespace,
139153
DestLabels: strings.Join(flow.DestLabels, " | "),
140154

@@ -148,3 +162,39 @@ func protoToFlow(flow *proto.Flow) whiskerv1.FlowResponse {
148162
BytesOut: flow.BytesOut,
149163
}
150164
}
165+
166+
// The Goldmane API uses an empty namespace to represent "no namespace", but the UI wants a value.
167+
func protoToNamespace(namespace string) string {
168+
if namespace == "" || namespace == "-" {
169+
return global
170+
}
171+
return namespace
172+
}
173+
174+
func toProtoNamespace(namespace string) string {
175+
if namespace == global {
176+
return "-"
177+
}
178+
return namespace
179+
}
180+
181+
// The Goldmane API uses "pub" and "pvt" for special names - for public and private network spaces.
182+
func protoToName(name string) string {
183+
switch name {
184+
case pub:
185+
return publicNetwork
186+
case pvt:
187+
return privateNetwork
188+
}
189+
return name
190+
}
191+
192+
func toProtoName(name string) string {
193+
switch name {
194+
case publicNetwork:
195+
return pub
196+
case privateNetwork:
197+
return pvt
198+
}
199+
return name
200+
}

0 commit comments

Comments
 (0)