k8s.io/client-go@v0.31.1/dynamic/dynamiclister/lister_test.go (about) 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 dynamiclister_test 18 19 import ( 20 "reflect" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 25 "k8s.io/apimachinery/pkg/labels" 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 "k8s.io/client-go/dynamic/dynamiclister" 29 "k8s.io/client-go/tools/cache" 30 ) 31 32 func TestNamespaceGetMethod(t *testing.T) { 33 tests := []struct { 34 name string 35 existingObjects []runtime.Object 36 namespaceToSync string 37 gvrToSync schema.GroupVersionResource 38 objectToGet string 39 expectedObject *unstructured.Unstructured 40 expectError bool 41 }{ 42 { 43 name: "scenario 1: gets name-foo1 resource from the indexer from ns-foo namespace", 44 existingObjects: []runtime.Object{ 45 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 46 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 47 newUnstructured("group/version", "TheKind", "ns-bar", "name-bar"), 48 }, 49 namespaceToSync: "ns-foo", 50 gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}, 51 objectToGet: "name-foo1", 52 expectedObject: newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 53 }, 54 { 55 name: "scenario 2: gets name-foo-non-existing resource from the indexer from ns-foo namespace", 56 existingObjects: []runtime.Object{ 57 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 58 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 59 newUnstructured("group/version", "TheKind", "ns-bar", "name-bar"), 60 }, 61 namespaceToSync: "ns-foo", 62 gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}, 63 objectToGet: "name-foo-non-existing", 64 expectError: true, 65 }, 66 } 67 68 for _, test := range tests { 69 t.Run(test.name, func(t *testing.T) { 70 // test data 71 indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) 72 for _, obj := range test.existingObjects { 73 err := indexer.Add(obj) 74 if err != nil { 75 t.Fatal(err) 76 } 77 } 78 // act 79 target := dynamiclister.New(indexer, test.gvrToSync).Namespace(test.namespaceToSync) 80 actualObject, err := target.Get(test.objectToGet) 81 82 // validate 83 if test.expectError { 84 if err == nil { 85 t.Fatal("expected to get an error but non was returned") 86 } 87 return 88 } 89 if err != nil { 90 t.Fatal(err) 91 } 92 if !reflect.DeepEqual(test.expectedObject, actualObject) { 93 t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", test.expectedObject, actualObject, cmp.Diff(test.expectedObject, actualObject)) 94 } 95 }) 96 } 97 } 98 99 func TestNamespaceListMethod(t *testing.T) { 100 // test data 101 objs := []runtime.Object{ 102 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 103 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 104 newUnstructured("group/version", "TheKind", "ns-bar", "name-bar"), 105 } 106 indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) 107 for _, obj := range objs { 108 err := indexer.Add(obj) 109 if err != nil { 110 t.Fatal(err) 111 } 112 } 113 expectedOutput := []*unstructured.Unstructured{ 114 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 115 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 116 } 117 namespaceToList := "ns-foo" 118 119 // act 120 target := dynamiclister.New(indexer, schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}).Namespace(namespaceToList) 121 actualOutput, err := target.List(labels.Everything()) 122 123 // validate 124 if err != nil { 125 t.Fatal(err) 126 } 127 assertListOrDie(expectedOutput, actualOutput, t) 128 } 129 130 func TestListerGetMethod(t *testing.T) { 131 tests := []struct { 132 name string 133 existingObjects []runtime.Object 134 namespaceToSync string 135 gvrToSync schema.GroupVersionResource 136 objectToGet string 137 expectedObject *unstructured.Unstructured 138 expectError bool 139 }{ 140 { 141 name: "scenario 1: gets name-foo1 resource from the indexer", 142 existingObjects: []runtime.Object{ 143 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 144 newUnstructured("group/version", "TheKind", "", "name-foo1"), 145 newUnstructured("group/version", "TheKind", "ns-bar", "name-bar"), 146 }, 147 namespaceToSync: "", 148 gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}, 149 objectToGet: "name-foo1", 150 expectedObject: newUnstructured("group/version", "TheKind", "", "name-foo1"), 151 }, 152 { 153 name: "scenario 2: doesn't get name-foo resource from the indexer from ns-foo namespace", 154 existingObjects: []runtime.Object{ 155 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 156 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), 157 newUnstructured("group/version", "TheKind", "ns-bar", "name-bar"), 158 }, 159 namespaceToSync: "ns-foo", 160 gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}, 161 objectToGet: "name-foo", 162 expectError: true, 163 }, 164 } 165 166 for _, test := range tests { 167 t.Run(test.name, func(t *testing.T) { 168 // test data 169 indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) 170 for _, obj := range test.existingObjects { 171 err := indexer.Add(obj) 172 if err != nil { 173 t.Fatal(err) 174 } 175 } 176 // act 177 target := dynamiclister.New(indexer, test.gvrToSync) 178 actualObject, err := target.Get(test.objectToGet) 179 180 // validate 181 if test.expectError { 182 if err == nil { 183 t.Fatal("expected to get an error but non was returned") 184 } 185 return 186 } 187 if err != nil { 188 t.Fatal(err) 189 } 190 if !reflect.DeepEqual(test.expectedObject, actualObject) { 191 t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", test.expectedObject, actualObject, cmp.Diff(test.expectedObject, actualObject)) 192 } 193 }) 194 } 195 } 196 197 func TestListerListMethod(t *testing.T) { 198 // test data 199 objs := []runtime.Object{ 200 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 201 newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"), 202 } 203 indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) 204 for _, obj := range objs { 205 err := indexer.Add(obj) 206 if err != nil { 207 t.Fatal(err) 208 } 209 } 210 expectedOutput := []*unstructured.Unstructured{ 211 newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"), 212 newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"), 213 } 214 215 // act 216 target := dynamiclister.New(indexer, schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}) 217 actualOutput, err := target.List(labels.Everything()) 218 219 // validate 220 if err != nil { 221 t.Fatal(err) 222 } 223 assertListOrDie(expectedOutput, actualOutput, t) 224 } 225 226 func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured { 227 return &unstructured.Unstructured{ 228 Object: map[string]interface{}{ 229 "apiVersion": apiVersion, 230 "kind": kind, 231 "metadata": map[string]interface{}{ 232 "namespace": namespace, 233 "name": name, 234 }, 235 }, 236 } 237 } 238 239 func assertListOrDie(expected, actual []*unstructured.Unstructured, t *testing.T) { 240 if len(actual) != len(expected) { 241 t.Fatalf("unexpected number of items returned, expected = %d, actual = %d", len(expected), len(actual)) 242 } 243 for _, expectedObject := range expected { 244 found := false 245 for _, actualObject := range actual { 246 if actualObject.GetName() == expectedObject.GetName() { 247 if !reflect.DeepEqual(expectedObject, actualObject) { 248 t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", expectedObject, actualObject, cmp.Diff(expectedObject, actualObject)) 249 } 250 found = true 251 } 252 } 253 if !found { 254 t.Fatalf("the resource with the name = %s was not found in the returned output", expectedObject.GetName()) 255 } 256 } 257 }