Skip to content

Commit 91bd851

Browse files
authored
Merge pull request #43 from xrstf/fork-gentype
✨ Add cluster-aware versions of gentype and listers, update testing
2 parents 5ae6774 + 23a63b1 commit 91bd851

File tree

7 files changed

+1373
-143
lines changed

7 files changed

+1373
-143
lines changed

.prow.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ presubmits:
77
preset-goproxy: "true"
88
spec:
99
containers:
10-
- image: ghcr.io/kcp-dev/infra/build:1.23.4-1
10+
- image: ghcr.io/kcp-dev/infra/build:1.23.7-2
1111
command:
1212
- make
1313
- verify
@@ -20,7 +20,7 @@ presubmits:
2020
preset-goproxy: "true"
2121
spec:
2222
containers:
23-
- image: ghcr.io/kcp-dev/infra/build:1.23.4-1
23+
- image: ghcr.io/kcp-dev/infra/build:1.23.7-2
2424
command:
2525
- make
2626
- lint
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package gentype
18+
19+
import (
20+
"context"
21+
22+
"github.com/kcp-dev/logicalcluster/v3"
23+
24+
"k8s.io/apimachinery/pkg/api/meta"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
labels "k8s.io/apimachinery/pkg/labels"
27+
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/apimachinery/pkg/runtime/schema"
29+
watch "k8s.io/apimachinery/pkg/watch"
30+
31+
kcptesting "github.com/kcp-dev/client-go/third_party/k8s.io/client-go/testing"
32+
)
33+
34+
// FakeClusterClient represents a fake cluster client
35+
type FakeClusterClient[T objectWithMeta] struct {
36+
*kcptesting.Fake
37+
resource schema.GroupVersionResource
38+
kind schema.GroupVersionKind
39+
newObject func() T
40+
}
41+
42+
// FakeClusterClientWithList represents a fake cluster client with support for lists.
43+
type FakeClusterClientWithList[T objectWithMeta, L runtime.Object] struct {
44+
*FakeClusterClient[T]
45+
alsoFakeClusterLister[T, L]
46+
}
47+
48+
// Helper types for composition
49+
type alsoFakeClusterLister[T objectWithMeta, L runtime.Object] struct {
50+
client *FakeClusterClient[T]
51+
newList func() L
52+
copyListMeta func(L, L)
53+
getItems func(L) []T
54+
setItems func(L, []T)
55+
}
56+
57+
// NewFakeClient constructs a fake client, namespaced or not, with no support for lists or apply.
58+
// Non-namespaced clients are constructed by passing an empty namespace ("").
59+
func NewFakeClusterClient[T objectWithMeta](
60+
fake *kcptesting.Fake, resource schema.GroupVersionResource, kind schema.GroupVersionKind, emptyObjectCreator func() T,
61+
) *FakeClusterClient[T] {
62+
return &FakeClusterClient[T]{fake, resource, kind, emptyObjectCreator}
63+
}
64+
65+
// NewFakeClusterClientWithList constructs a namespaced client with support for lists.
66+
func NewFakeClusterClientWithList[T objectWithMeta, L runtime.Object](
67+
fake *kcptesting.Fake, resource schema.GroupVersionResource, kind schema.GroupVersionKind, emptyObjectCreator func() T,
68+
emptyListCreator func() L, listMetaCopier func(L, L), itemGetter func(L) []T, itemSetter func(L, []T),
69+
) *FakeClusterClientWithList[T, L] {
70+
fakeClusterClient := NewFakeClusterClient[T](fake, resource, kind, emptyObjectCreator)
71+
return &FakeClusterClientWithList[T, L]{
72+
fakeClusterClient,
73+
alsoFakeClusterLister[T, L]{fakeClusterClient, emptyListCreator, listMetaCopier, itemGetter, itemSetter},
74+
}
75+
}
76+
77+
// List takes label and field selectors, and returns the list of resources that match those selectors.
78+
func (l *alsoFakeClusterLister[T, L]) List(ctx context.Context, opts metav1.ListOptions) (result L, err error) {
79+
emptyResult := l.newList()
80+
obj, err := l.client.Fake.
81+
Invokes(kcptesting.NewListAction(l.client.resource, l.client.kind, logicalcluster.Wildcard, metav1.NamespaceAll, opts), emptyResult)
82+
if obj == nil {
83+
return emptyResult, err
84+
}
85+
86+
label, _, _ := kcptesting.ExtractFromListOptions(opts)
87+
if label == nil {
88+
// Everything matches
89+
return obj.(L), nil
90+
}
91+
list := l.newList()
92+
l.copyListMeta(list, obj.(L))
93+
var items []T
94+
for _, item := range l.getItems(obj.(L)) {
95+
itemMeta, err := meta.Accessor(item)
96+
if err != nil {
97+
// No ObjectMeta, nothing can match
98+
continue
99+
}
100+
if label.Matches(labels.Set(itemMeta.GetLabels())) {
101+
items = append(items, item)
102+
}
103+
}
104+
l.setItems(list, items)
105+
return list, err
106+
}
107+
108+
// Watch returns a watch.Interface that watches the requested resources.
109+
func (c *FakeClusterClient[T]) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
110+
opts.Watch = true
111+
return c.Fake.
112+
InvokesWatch(kcptesting.NewWatchAction(c.resource, logicalcluster.Wildcard, metav1.NamespaceAll, opts))
113+
}
114+
115+
func (c *FakeClusterClient[T]) Kind() schema.GroupVersionKind {
116+
return c.kind
117+
}
118+
119+
func (c *FakeClusterClient[T]) Resource() schema.GroupVersionResource {
120+
return c.resource
121+
}

0 commit comments

Comments
 (0)