istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/kube/krt/index_test.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package krt_test 16 17 import ( 18 "strings" 19 "testing" 20 21 corev1 "k8s.io/api/core/v1" 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 24 "istio.io/istio/pkg/kube" 25 "istio.io/istio/pkg/kube/kclient" 26 "istio.io/istio/pkg/kube/kclient/clienttest" 27 "istio.io/istio/pkg/kube/krt" 28 "istio.io/istio/pkg/ptr" 29 "istio.io/istio/pkg/slices" 30 "istio.io/istio/pkg/test" 31 "istio.io/istio/pkg/test/util/assert" 32 ) 33 34 func TestIndex(t *testing.T) { 35 c := kube.NewFakeClient() 36 kpc := kclient.New[*corev1.Pod](c) 37 pc := clienttest.Wrap(t, kpc) 38 pods := krt.WrapClient[*corev1.Pod](kpc) 39 stop := test.NewStop(t) 40 c.RunAndWait(stop) 41 SimplePods := SimplePodCollection(pods) 42 tt := assert.NewTracker[string](t) 43 IPIndex := krt.NewIndex[SimplePod, string](SimplePods, func(o SimplePod) []string { 44 return []string{o.IP} 45 }) 46 fetchSorted := func(ip string) []SimplePod { 47 return slices.SortBy(IPIndex.Lookup(ip), func(t SimplePod) string { 48 return t.ResourceName() 49 }) 50 } 51 52 SimplePods.Register(TrackerHandler[SimplePod](tt)) 53 54 pod := &corev1.Pod{ 55 ObjectMeta: metav1.ObjectMeta{ 56 Name: "name", 57 Namespace: "namespace", 58 }, 59 Status: corev1.PodStatus{PodIP: "1.2.3.4"}, 60 } 61 pc.CreateOrUpdateStatus(pod) 62 tt.WaitUnordered("add/namespace/name") 63 assert.Equal(t, fetchSorted("1.2.3.4"), []SimplePod{{NewNamed(pod), Labeled{}, "1.2.3.4"}}) 64 65 pod.Status.PodIP = "1.2.3.5" 66 pc.UpdateStatus(pod) 67 tt.WaitUnordered("update/namespace/name") 68 assert.Equal(t, fetchSorted("1.2.3.4"), []SimplePod{}) 69 assert.Equal(t, fetchSorted("1.2.3.5"), []SimplePod{{NewNamed(pod), Labeled{}, "1.2.3.5"}}) 70 71 pod2 := &corev1.Pod{ 72 ObjectMeta: metav1.ObjectMeta{ 73 Name: "name2", 74 Namespace: "namespace", 75 }, 76 Status: corev1.PodStatus{PodIP: "1.2.3.5"}, 77 } 78 pc.CreateOrUpdateStatus(pod2) 79 tt.WaitUnordered("add/namespace/name2") 80 assert.Equal(t, fetchSorted("1.2.3.5"), []SimplePod{ 81 {NewNamed(pod), Labeled{}, "1.2.3.5"}, 82 {NewNamed(pod2), Labeled{}, "1.2.3.5"}, 83 }) 84 85 pc.Delete(pod.Name, pod.Namespace) 86 pc.Delete(pod2.Name, pod2.Namespace) 87 tt.WaitUnordered("delete/namespace/name", "delete/namespace/name2") 88 assert.Equal(t, fetchSorted("1.2.3.4"), []SimplePod{}) 89 } 90 91 func TestIndexCollection(t *testing.T) { 92 c := kube.NewFakeClient() 93 kpc := kclient.New[*corev1.Pod](c) 94 pc := clienttest.Wrap(t, kpc) 95 pods := krt.WrapClient[*corev1.Pod](kpc) 96 stop := test.NewStop(t) 97 c.RunAndWait(stop) 98 SimplePods := SimplePodCollection(pods) 99 tt := assert.NewTracker[string](t) 100 IPIndex := krt.NewIndex[SimplePod, string](SimplePods, func(o SimplePod) []string { 101 return []string{o.IP} 102 }) 103 Collection := krt.NewSingleton[string](func(ctx krt.HandlerContext) *string { 104 pods := krt.Fetch(ctx, SimplePods, krt.FilterIndex(IPIndex, "1.2.3.5")) 105 names := slices.Sort(slices.Map(pods, SimplePod.ResourceName)) 106 return ptr.Of(strings.Join(names, ",")) 107 }) 108 Collection.AsCollection().Synced().WaitUntilSynced(stop) 109 fetchSorted := func(ip string) []SimplePod { 110 return slices.SortBy(IPIndex.Lookup(ip), func(t SimplePod) string { 111 return t.ResourceName() 112 }) 113 } 114 115 SimplePods.Register(TrackerHandler[SimplePod](tt)) 116 117 pod := &corev1.Pod{ 118 ObjectMeta: metav1.ObjectMeta{ 119 Name: "name", 120 Namespace: "namespace", 121 }, 122 Status: corev1.PodStatus{PodIP: "1.2.3.4"}, 123 } 124 pc.CreateOrUpdateStatus(pod) 125 tt.WaitUnordered("add/namespace/name") 126 assert.Equal(t, Collection.Get(), ptr.Of("")) 127 128 pod.Status.PodIP = "1.2.3.5" 129 pc.UpdateStatus(pod) 130 tt.WaitUnordered("update/namespace/name") 131 assert.Equal(t, Collection.Get(), ptr.Of("namespace/name")) 132 133 pod2 := &corev1.Pod{ 134 ObjectMeta: metav1.ObjectMeta{ 135 Name: "name2", 136 Namespace: "namespace", 137 }, 138 Status: corev1.PodStatus{PodIP: "1.2.3.5"}, 139 } 140 pc.CreateOrUpdateStatus(pod2) 141 tt.WaitUnordered("add/namespace/name2") 142 assert.Equal(t, Collection.Get(), ptr.Of("namespace/name,namespace/name2")) 143 144 pc.Delete(pod.Name, pod.Namespace) 145 pc.Delete(pod2.Name, pod2.Namespace) 146 tt.WaitUnordered("delete/namespace/name", "delete/namespace/name2") 147 assert.Equal(t, fetchSorted("1.2.3.4"), []SimplePod{}) 148 }