Skip to content

Commit fcd968d

Browse files
uzabanovdanail-branekov
authored andcommitted
Filter routes by app guid in client
Turned out that filtering on client side does not work because the paging results are changed. Instead Filtering the routes by app guid is done in the KLient. Filtering option is added and AppGUIDs column to CFRoute Table. In this way by setting the app destination guids to CFRoute Annotations by mutating webhook filtering the routes by app guid is possible without affeceting the paging results issue #4123
1 parent 8d0fb9d commit fcd968d

29 files changed

+711
-290
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package filter
2+
3+
import (
4+
"slices"
5+
"strings"
6+
7+
"github.com/BooleanCat/go-functional/v2/it"
8+
)
9+
10+
func RoutesByAppGUIDsPredicate(appGuids []string) func(value any) bool {
11+
return func(value any) bool {
12+
destinationAppGUIDsStr := value.(string)
13+
destinationAppGUIDs := strings.Split(destinationAppGUIDsStr, "\n")
14+
return haveCommonElements(appGuids, destinationAppGUIDs)
15+
}
16+
}
17+
18+
func haveCommonElements(appGuids, destinationAppGUIDs []string) bool {
19+
return it.Any(it.Map(slices.Values(appGuids), func(appGUID string) bool {
20+
return slices.Contains(destinationAppGUIDs, appGUID)
21+
}))
22+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package filter_test
2+
3+
import (
4+
"github.com/google/uuid"
5+
. "github.com/onsi/ginkgo/v2"
6+
. "github.com/onsi/gomega"
7+
8+
"code.cloudfoundry.org/korifi/api/repositories/filter"
9+
)
10+
11+
var _ = Describe("RoutesByAppGUID", func() {
12+
var (
13+
appGUID1 string
14+
appGUIDs []string
15+
filterResult bool
16+
)
17+
18+
BeforeEach(func() {
19+
appGUID1 = uuid.NewString()
20+
appGUIDs = []string{appGUID1}
21+
})
22+
23+
JustBeforeEach(func() {
24+
appGUID2 := uuid.NewString()
25+
filterResult = filter.RoutesByAppGUIDsPredicate(appGUIDs)(appGUID1 + "\n" + appGUID2)
26+
})
27+
28+
It("returns true", func() {
29+
Expect(filterResult).To(BeTrue())
30+
})
31+
32+
When("guid is not in the list", func() {
33+
BeforeEach(func() {
34+
appGUIDs = []string{"some-other-guid"}
35+
})
36+
37+
It("returns false", func() {
38+
Expect(filterResult).To(BeFalse())
39+
})
40+
})
41+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package filter_test
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestFiltering(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Filtering Suite")
13+
}

api/repositories/k8sklient/descriptors/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
type ResultSetDescriptor interface {
1717
GUIDs() ([]string, error)
1818
Sort(column string, desc bool) error
19+
Filter(columnName string, filterFunc func(value any) bool) error
1920
}
2021

2122
type Pluralizer interface {

api/repositories/k8sklient/descriptors/fake/result_set_descriptor.go

Lines changed: 74 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/repositories/k8sklient/descriptors/table.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ func (d *TableResultSetDescriptor) Sort(column string, desc bool) error {
3939
return nil
4040
}
4141

42+
func (d *TableResultSetDescriptor) Filter(columnName string, filterFunc func(value any) bool) error {
43+
columnIndex, _, err := d.getColumn(columnName)
44+
if err != nil {
45+
return err
46+
}
47+
48+
d.Table.Rows = slices.Collect(it.Filter(slices.Values(d.Table.Rows), func(row metav1.TableRow) bool {
49+
return filterFunc(row.Cells[columnIndex])
50+
}))
51+
52+
return nil
53+
}
54+
4255
func (d *TableResultSetDescriptor) getColumn(column string) (int, metav1.TableColumnDefinition, error) {
4356
for i, columnDef := range d.Table.ColumnDefinitions {
4457
if columnDef.Name == column {

api/repositories/k8sklient/descriptors/table_test.go

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package descriptors_test
22

33
import (
4+
"slices"
5+
46
"code.cloudfoundry.org/korifi/api/repositories/k8sklient/descriptors"
57
. "github.com/onsi/ginkgo/v2"
68
. "github.com/onsi/gomega"
@@ -11,6 +13,7 @@ var _ = Describe("TableResultSetDescriptor", func() {
1113
var (
1214
results descriptors.TableResultSetDescriptor
1315
guids []string
16+
column string
1417
guidsErr error
1518
)
1619

@@ -47,7 +50,6 @@ var _ = Describe("TableResultSetDescriptor", func() {
4750

4851
Describe("Sort", func() {
4952
var (
50-
column string
5153
desc bool
5254
sortErr error
5355
)
@@ -171,4 +173,35 @@ var _ = Describe("TableResultSetDescriptor", func() {
171173
})
172174
})
173175
})
176+
177+
Describe("Filter", func() {
178+
var filterErr error
179+
BeforeEach(func() {
180+
column = "Hobbies"
181+
})
182+
183+
JustBeforeEach(func() {
184+
filterErr = results.Filter(column, func(value any) bool {
185+
hobbies := value.([]string)
186+
return slices.Contains(hobbies, "hiking") || slices.Contains(hobbies, "gaming")
187+
})
188+
guids, guidsErr = results.GUIDs()
189+
Expect(guidsErr).NotTo(HaveOccurred())
190+
})
191+
192+
It("filters the table by specified column", func() {
193+
Expect(filterErr).NotTo(HaveOccurred())
194+
Expect(guids).To(Equal([]string{"Alice", "Bob"}))
195+
})
196+
197+
When("filter column is not found", func() {
198+
BeforeEach(func() {
199+
column = "NonExistentColumn"
200+
})
201+
202+
It("returns an error", func() {
203+
Expect(filterErr).To(MatchError(ContainSubstring("not found")))
204+
})
205+
})
206+
})
174207
})

api/repositories/k8sklient/klient.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (k *K8sKlient) List(ctx context.Context, list client.ObjectList, opts ...re
126126
}
127127

128128
func isSimpleList(listOpts repositories.ListOptions) bool {
129-
return listOpts.Sort == nil && listOpts.Paging == nil
129+
return listOpts.Sort == nil && listOpts.Paging == nil && listOpts.Filter == nil
130130
}
131131

132132
func (k *K8sKlient) listViaUserClient(ctx context.Context, list client.ObjectList, opts ...client.ListOption) (descriptors.PageInfo, error) {

api/repositories/k8sklient/klient_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,22 @@ var _ = Describe("Klient", func() {
359359
})
360360
})
361361

362+
When("filtering is requested", func() {
363+
BeforeEach(func() {
364+
listOpts = append(listOpts, repositories.WithFiltering("foo", func(value any) bool {
365+
return value == "bar"
366+
}))
367+
})
368+
369+
It("delegates to the descriptor based lister", func() {
370+
Expect(err).NotTo(HaveOccurred())
371+
Expect(descriptorBasedLister.ListCallCount()).To(Equal(1))
372+
_, _, actualListOptions := descriptorBasedLister.ListArgsForCall(0)
373+
Expect(actualListOptions.Filter.By).To(Equal("foo"))
374+
Expect(actualListOptions.Filter.FilterFunc("bar")).To(BeTrue())
375+
})
376+
})
377+
362378
When("a list option errors", func() {
363379
BeforeEach(func() {
364380
listOpts = []repositories.ListOption{repositories.ErroringListOption("list-opt-err")}

api/repositories/k8sklient/lister.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ func (k *DescriptorsBasedLister) fetchObjectGUIDs(ctx context.Context, listObjec
100100
}
101101
}
102102

103+
if listOpts.Filter != nil {
104+
if err = objectDescriptors.Filter(listOpts.Filter.By, listOpts.Filter.FilterFunc); err != nil {
105+
return nil, fmt.Errorf("failed to filter object descriptors: %w", err)
106+
}
107+
}
108+
103109
objectGUIDs, err := objectDescriptors.GUIDs()
104110
if err != nil {
105111
return nil, fmt.Errorf("failed to get sorted object GUIDs: %w", err)

0 commit comments

Comments
 (0)