Skip to content

Commit 40231bd

Browse files
authored
Merge pull request #410 from ingvagabund/release-0.1-backport-311
🐛 Enable labels list options in fake client
2 parents 52ef898 + e1ec14f commit 40231bd

File tree

4 files changed

+109
-21
lines changed

4 files changed

+109
-21
lines changed

pkg/cache/internal/cache_reader.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"k8s.io/apimachinery/pkg/selection"
3131
"k8s.io/client-go/tools/cache"
3232
"sigs.k8s.io/controller-runtime/pkg/client"
33+
"sigs.k8s.io/controller-runtime/pkg/internal/objectutil"
3334
)
3435

3536
// CacheReader is a CacheReader
@@ -115,33 +116,30 @@ func (c *CacheReader) List(_ context.Context, opts *client.ListOptions, out runt
115116
labelSel = opts.LabelSelector
116117
}
117118

118-
outItems, err := c.getListItems(objs, labelSel)
119+
filteredItems, err := c.filterListItems(objs, labelSel)
119120
if err != nil {
120121
return err
121122
}
122-
return apimeta.SetList(out, outItems)
123+
124+
return apimeta.SetList(out, filteredItems)
123125
}
124126

125-
func (c *CacheReader) getListItems(objs []interface{}, labelSel labels.Selector) ([]runtime.Object, error) {
126-
outItems := make([]runtime.Object, 0, len(objs))
127+
func (c *CacheReader) filterListItems(objs []interface{}, labelSel labels.Selector) ([]runtime.Object, error) {
128+
runtimeObjs := make([]runtime.Object, 0, len(objs))
127129
for _, item := range objs {
128130
obj, isObj := item.(runtime.Object)
129131
if !isObj {
130132
return nil, fmt.Errorf("cache contained %T, which is not an Object", obj)
131133
}
132-
meta, err := apimeta.Accessor(obj)
133-
if err != nil {
134-
return nil, err
135-
}
136-
if labelSel != nil {
137-
lbls := labels.Set(meta.GetLabels())
138-
if !labelSel.Matches(lbls) {
139-
continue
140-
}
141-
}
142-
outItems = append(outItems, obj.DeepCopyObject())
134+
runtimeObjs = append(runtimeObjs, obj)
143135
}
144-
return outItems, nil
136+
137+
filteredItems, err := objectutil.FilterWithLabels(runtimeObjs, labelSel)
138+
if err != nil {
139+
return nil, err
140+
}
141+
142+
return filteredItems, nil
145143
}
146144

147145
// objectKeyToStorageKey converts an object key to store key.

pkg/client/fake/client.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ import (
2424
"strings"
2525

2626
"k8s.io/apimachinery/pkg/api/meta"
27+
"k8s.io/apimachinery/pkg/labels"
2728
"k8s.io/apimachinery/pkg/runtime"
2829
"k8s.io/apimachinery/pkg/runtime/schema"
2930
"k8s.io/client-go/kubernetes/scheme"
3031
"k8s.io/client-go/testing"
3132

3233
"sigs.k8s.io/controller-runtime/pkg/client"
3334
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
35+
"sigs.k8s.io/controller-runtime/pkg/internal/objectutil"
3436
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
3537
)
3638

@@ -110,7 +112,30 @@ func (c *fakeClient) List(ctx context.Context, opts *client.ListOptions, list ru
110112
}
111113
decoder := scheme.Codecs.UniversalDecoder()
112114
_, _, err = decoder.Decode(j, nil, list)
113-
return err
115+
if err != nil {
116+
return err
117+
}
118+
119+
if opts.LabelSelector != nil {
120+
return filterListItems(list, opts.LabelSelector)
121+
}
122+
return nil
123+
}
124+
125+
func filterListItems(list runtime.Object, labSel labels.Selector) error {
126+
objs, err := meta.ExtractList(list)
127+
if err != nil {
128+
return err
129+
}
130+
filteredObjs, err := objectutil.FilterWithLabels(objs, labSel)
131+
if err != nil {
132+
return err
133+
}
134+
err = meta.SetList(list, filteredObjs)
135+
if err != nil {
136+
return err
137+
}
138+
return nil
114139
}
115140

116141
func (c *fakeClient) Create(ctx context.Context, obj runtime.Object) error {

pkg/client/fake/client_test.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030

3131
var _ = Describe("Fake client", func() {
3232
var dep *appsv1.Deployment
33+
var dep2 *appsv1.Deployment
3334
var cm *corev1.ConfigMap
3435
var cl client.Client
3536

@@ -40,6 +41,15 @@ var _ = Describe("Fake client", func() {
4041
Namespace: "ns1",
4142
},
4243
}
44+
dep2 = &appsv1.Deployment{
45+
ObjectMeta: metav1.ObjectMeta{
46+
Name: "test-deployment-2",
47+
Namespace: "ns1",
48+
Labels: map[string]string{
49+
"test-label": "label-value",
50+
},
51+
},
52+
}
4353
cm = &corev1.ConfigMap{
4454
ObjectMeta: metav1.ObjectMeta{
4555
Name: "test-cm",
@@ -71,8 +81,20 @@ var _ = Describe("Fake client", func() {
7181
Namespace: "ns1",
7282
}, list)
7383
Expect(err).To(BeNil())
84+
Expect(list.Items).To(HaveLen(2))
85+
Expect(list.Items).To(ConsistOf(*dep, *dep2))
86+
})
87+
88+
It("should support filtering by labels", func() {
89+
By("Listing deployments with a particular label")
90+
list := &appsv1.DeploymentList{}
91+
err := cl.List(nil,
92+
client.InNamespace("ns1").MatchingLabels(map[string]string{
93+
"test-label": "label-value",
94+
}), list)
95+
Expect(err).To(BeNil())
7496
Expect(list.Items).To(HaveLen(1))
75-
Expect(list.Items).To(ConsistOf(*dep))
97+
Expect(list.Items).To(ConsistOf(*dep2))
7698
})
7799

78100
It("should be able to Create", func() {
@@ -133,13 +155,14 @@ var _ = Describe("Fake client", func() {
133155
Namespace: "ns1",
134156
}, list)
135157
Expect(err).To(BeNil())
136-
Expect(list.Items).To(HaveLen(0))
158+
Expect(list.Items).To(HaveLen(1))
159+
Expect(list.Items).To(ConsistOf(*dep2))
137160
})
138161
}
139162

140163
Context("with default scheme.Scheme", func() {
141164
BeforeEach(func(done Done) {
142-
cl = NewFakeClient(dep, cm)
165+
cl = NewFakeClient(dep, dep2, cm)
143166
close(done)
144167
})
145168
AssertClientBehavior()
@@ -150,7 +173,7 @@ var _ = Describe("Fake client", func() {
150173
scheme := runtime.NewScheme()
151174
corev1.AddToScheme(scheme)
152175
appsv1.AddToScheme(scheme)
153-
cl = NewFakeClientWithScheme(scheme, dep, cm)
176+
cl = NewFakeClientWithScheme(scheme, dep, dep2, cm)
154177
close(done)
155178
})
156179
AssertClientBehavior()

pkg/internal/objectutil/filter.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright 2018 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 objectutil
18+
19+
import (
20+
apimeta "k8s.io/apimachinery/pkg/api/meta"
21+
"k8s.io/apimachinery/pkg/labels"
22+
"k8s.io/apimachinery/pkg/runtime"
23+
)
24+
25+
// FilterWithLabels returns a copy of the items in objs matching labelSel
26+
func FilterWithLabels(objs []runtime.Object, labelSel labels.Selector) ([]runtime.Object, error) {
27+
outItems := make([]runtime.Object, 0, len(objs))
28+
for _, obj := range objs {
29+
meta, err := apimeta.Accessor(obj)
30+
if err != nil {
31+
return nil, err
32+
}
33+
if labelSel != nil {
34+
lbls := labels.Set(meta.GetLabels())
35+
if !labelSel.Matches(lbls) {
36+
continue
37+
}
38+
}
39+
outItems = append(outItems, obj.DeepCopyObject())
40+
}
41+
return outItems, nil
42+
}

0 commit comments

Comments
 (0)