@@ -21,11 +21,15 @@ import (
21
21
"fmt"
22
22
23
23
. "github.com/onsi/ginkgo"
24
+ . "github.com/onsi/ginkgo/extensions/table"
24
25
. "github.com/onsi/gomega"
26
+
25
27
kcorev1 "k8s.io/api/core/v1"
26
28
"k8s.io/apimachinery/pkg/api/errors"
27
29
kmetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28
30
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
31
+ "k8s.io/apimachinery/pkg/fields"
32
+ "k8s.io/apimachinery/pkg/labels"
29
33
"k8s.io/apimachinery/pkg/runtime/schema"
30
34
kscheme "k8s.io/client-go/kubernetes/scheme"
31
35
"k8s.io/client-go/rest"
@@ -42,15 +46,17 @@ const testNamespaceThree = "test-namespace-3"
42
46
43
47
// TODO(community): Pull these helper functions into testenv.
44
48
// Restart policy is included to allow indexing on that field.
45
- func createPod (name , namespace string , restartPolicy kcorev1.RestartPolicy ) client.Object {
49
+ func createPodWithLabels (name , namespace string , restartPolicy kcorev1.RestartPolicy , labels map [ string ] string ) client.Object {
46
50
three := int64 (3 )
51
+ if labels == nil {
52
+ labels = map [string ]string {}
53
+ }
54
+ labels ["test-label" ] = name
47
55
pod := & kcorev1.Pod {
48
56
ObjectMeta : kmetav1.ObjectMeta {
49
57
Name : name ,
50
58
Namespace : namespace ,
51
- Labels : map [string ]string {
52
- "test-label" : name ,
53
- },
59
+ Labels : labels ,
54
60
},
55
61
Spec : kcorev1.PodSpec {
56
62
Containers : []kcorev1.Container {{Name : "nginx" , Image : "nginx" }},
@@ -65,6 +71,10 @@ func createPod(name, namespace string, restartPolicy kcorev1.RestartPolicy) clie
65
71
return pod
66
72
}
67
73
74
+ func createPod (name , namespace string , restartPolicy kcorev1.RestartPolicy ) client.Object {
75
+ return createPodWithLabels (name , namespace , restartPolicy , nil )
76
+ }
77
+
68
78
func deletePod (pod client.Object ) {
69
79
cl , err := client .New (cfg , client.Options {})
70
80
Expect (err ).NotTo (HaveOccurred ())
@@ -110,8 +120,8 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
110
120
// Includes restart policy since these objects are indexed on this field.
111
121
knownPod1 = createPod ("test-pod-1" , testNamespaceOne , kcorev1 .RestartPolicyNever )
112
122
knownPod2 = createPod ("test-pod-2" , testNamespaceTwo , kcorev1 .RestartPolicyAlways )
113
- knownPod3 = createPod ("test-pod-3" , testNamespaceTwo , kcorev1 .RestartPolicyOnFailure )
114
- knownPod4 = createPod ("test-pod-4" , testNamespaceThree , kcorev1 .RestartPolicyNever )
123
+ knownPod3 = createPodWithLabels ("test-pod-3" , testNamespaceTwo , kcorev1 .RestartPolicyOnFailure , map [ string ] string { "common-label" : "common" } )
124
+ knownPod4 = createPodWithLabels ("test-pod-4" , testNamespaceThree , kcorev1 .RestartPolicyNever , map [ string ] string { "common-label" : "common" } )
115
125
podGVK := schema.GroupVersionKind {
116
126
Kind : "Pod" ,
117
127
Version : "v1" ,
@@ -284,6 +294,7 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
284
294
Expect (err ).To (HaveOccurred ())
285
295
Expect (errors .IsTimeout (err )).To (BeTrue ())
286
296
})
297
+
287
298
})
288
299
Context ("with unstructured objects" , func () {
289
300
It ("should be able to list objects that haven't been watched previously" , func () {
@@ -709,6 +720,113 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
709
720
Expect (err ).To (HaveOccurred ())
710
721
})
711
722
})
723
+ type selectorsTestCase struct {
724
+ fieldSelectors map [string ]string
725
+ labelSelectors map [string ]string
726
+ expectedPods []string
727
+ }
728
+ DescribeTable (" and cache with selectors" , func (tc selectorsTestCase ) {
729
+ By ("creating the cache" )
730
+ builder := cache .BuilderWithOptions (
731
+ cache.Options {
732
+ SelectorsByObject : cache.SelectorsByObject {
733
+ & kcorev1.Pod {}: {
734
+ Label : labels .Set (tc .labelSelectors ).AsSelector (),
735
+ Field : fields .Set (tc .fieldSelectors ).AsSelector (),
736
+ },
737
+ },
738
+ },
739
+ )
740
+ informer , err := builder (cfg , cache.Options {})
741
+ Expect (err ).NotTo (HaveOccurred ())
742
+
743
+ By ("running the cache and waiting for it to sync" )
744
+ go func () {
745
+ defer GinkgoRecover ()
746
+ Expect (informer .Start (informerCacheCtx )).To (Succeed ())
747
+ }()
748
+ Expect (informer .WaitForCacheSync (informerCacheCtx )).NotTo (BeFalse ())
749
+
750
+ By ("Checking with structured" )
751
+ obtainedStructuredPodList := kcorev1.PodList {}
752
+ Expect (informer .List (context .Background (), & obtainedStructuredPodList )).To (Succeed ())
753
+ Expect (obtainedStructuredPodList .Items ).Should (WithTransform (func (pods []kcorev1.Pod ) []string {
754
+ obtainedPodNames := []string {}
755
+ for _ , pod := range pods {
756
+ obtainedPodNames = append (obtainedPodNames , pod .Name )
757
+ }
758
+ return obtainedPodNames
759
+ }, ConsistOf (tc .expectedPods )))
760
+
761
+ By ("Checking with unstructured" )
762
+ obtainedUnstructuredPodList := unstructured.UnstructuredList {}
763
+ obtainedUnstructuredPodList .SetGroupVersionKind (schema.GroupVersionKind {
764
+ Group : "" ,
765
+ Version : "v1" ,
766
+ Kind : "PodList" ,
767
+ })
768
+ err = informer .List (context .Background (), & obtainedUnstructuredPodList )
769
+ Expect (err ).To (Succeed ())
770
+ Expect (obtainedUnstructuredPodList .Items ).Should (WithTransform (func (pods []unstructured.Unstructured ) []string {
771
+ obtainedPodNames := []string {}
772
+ for _ , pod := range pods {
773
+ obtainedPodNames = append (obtainedPodNames , pod .GetName ())
774
+ }
775
+ return obtainedPodNames
776
+ }, ConsistOf (tc .expectedPods )))
777
+
778
+ By ("Checking with metadata" )
779
+ obtainedMetadataPodList := kmetav1.PartialObjectMetadataList {}
780
+ obtainedMetadataPodList .SetGroupVersionKind (schema.GroupVersionKind {
781
+ Group : "" ,
782
+ Version : "v1" ,
783
+ Kind : "PodList" ,
784
+ })
785
+ err = informer .List (context .Background (), & obtainedMetadataPodList )
786
+ Expect (err ).To (Succeed ())
787
+ Expect (obtainedMetadataPodList .Items ).Should (WithTransform (func (pods []kmetav1.PartialObjectMetadata ) []string {
788
+ obtainedPodNames := []string {}
789
+ for _ , pod := range pods {
790
+ obtainedPodNames = append (obtainedPodNames , pod .Name )
791
+ }
792
+ return obtainedPodNames
793
+ }, ConsistOf (tc .expectedPods )))
794
+ },
795
+ Entry ("when selectors are empty it has to inform about all the pods" , selectorsTestCase {
796
+ fieldSelectors : map [string ]string {},
797
+ labelSelectors : map [string ]string {},
798
+ expectedPods : []string {"test-pod-1" , "test-pod-2" , "test-pod-3" , "test-pod-4" },
799
+ }),
800
+ Entry ("when field matches one pod it has to inform about it" , selectorsTestCase {
801
+ fieldSelectors : map [string ]string {"metadata.name" : "test-pod-2" },
802
+ expectedPods : []string {"test-pod-2" },
803
+ }),
804
+ Entry ("when field matches multiple pods it has to infor about all of them" , selectorsTestCase {
805
+ fieldSelectors : map [string ]string {"metadata.namespace" : testNamespaceTwo },
806
+ expectedPods : []string {"test-pod-2" , "test-pod-3" },
807
+ }),
808
+ Entry ("when label matches one pod it has to inform about it" , selectorsTestCase {
809
+ labelSelectors : map [string ]string {"test-label" : "test-pod-4" },
810
+ expectedPods : []string {"test-pod-4" },
811
+ }),
812
+ Entry ("when label matches multiple pods it has to infor about all of them" , selectorsTestCase {
813
+ labelSelectors : map [string ]string {"common-label" : "common" },
814
+ expectedPods : []string {"test-pod-3" , "test-pod-4" },
815
+ }),
816
+ Entry ("when label and field matches one pod it has to infor about about it" , selectorsTestCase {
817
+ labelSelectors : map [string ]string {"common-label" : "common" },
818
+ fieldSelectors : map [string ]string {"metadata.namespace" : testNamespaceTwo },
819
+ expectedPods : []string {"test-pod-3" },
820
+ }),
821
+ Entry ("when label does not match it does not has to inform" , selectorsTestCase {
822
+ labelSelectors : map [string ]string {"new-label" : "new" },
823
+ expectedPods : []string {},
824
+ }),
825
+ Entry ("when field does not match it does not has to inform" , selectorsTestCase {
826
+ fieldSelectors : map [string ]string {"metadata.namespace" : "new" },
827
+ expectedPods : []string {},
828
+ }),
829
+ )
712
830
})
713
831
Describe ("as an Informer" , func () {
714
832
Context ("with structured objects" , func () {
@@ -789,7 +907,6 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca
789
907
Eventually (out ).Should (Receive (Equal (pod )))
790
908
close (done )
791
909
})
792
-
793
910
It ("should be able to index an object field then retrieve objects by that field" , func () {
794
911
By ("creating the cache" )
795
912
informer , err := cache .New (cfg , cache.Options {})
0 commit comments