k8s.io/kubernetes@v1.29.3/pkg/controller/endpointslicemirroring/utils_test.go (about) 1 /* 2 Copyright 2020 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 endpointslicemirroring 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 v1 "k8s.io/api/core/v1" 25 discovery "k8s.io/api/discovery/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/runtime" 28 "k8s.io/apimachinery/pkg/runtime/schema" 29 "k8s.io/apimachinery/pkg/util/rand" 30 "k8s.io/client-go/kubernetes/fake" 31 k8stesting "k8s.io/client-go/testing" 32 "k8s.io/utils/pointer" 33 ) 34 35 func TestNewEndpointSlice(t *testing.T) { 36 portName := "foo" 37 protocol := v1.ProtocolTCP 38 39 ports := []discovery.EndpointPort{{Name: &portName, Protocol: &protocol}} 40 addrType := discovery.AddressTypeIPv4 41 gvk := schema.GroupVersionKind{Version: "v1", Kind: "Endpoints"} 42 43 endpoints := v1.Endpoints{ 44 ObjectMeta: metav1.ObjectMeta{ 45 Name: "foo", 46 Namespace: "test", 47 }, 48 Subsets: []v1.EndpointSubset{{ 49 Ports: []v1.EndpointPort{{Port: 80}}, 50 }}, 51 } 52 ownerRef := metav1.NewControllerRef(&endpoints, gvk) 53 54 testCases := []struct { 55 name string 56 tweakEndpoint func(ep *v1.Endpoints) 57 expectedSlice discovery.EndpointSlice 58 }{ 59 { 60 name: "create slice from endpoints", 61 tweakEndpoint: func(ep *v1.Endpoints) { 62 }, 63 expectedSlice: discovery.EndpointSlice{ 64 ObjectMeta: metav1.ObjectMeta{ 65 Labels: map[string]string{ 66 discovery.LabelServiceName: endpoints.Name, 67 discovery.LabelManagedBy: controllerName, 68 }, 69 Annotations: map[string]string{}, 70 GenerateName: fmt.Sprintf("%s-", endpoints.Name), 71 Namespace: endpoints.Namespace, 72 OwnerReferences: []metav1.OwnerReference{*ownerRef}, 73 }, 74 Ports: ports, 75 AddressType: addrType, 76 Endpoints: []discovery.Endpoint{}, 77 }, 78 }, 79 { 80 name: "create slice from endpoints with annotations", 81 tweakEndpoint: func(ep *v1.Endpoints) { 82 annotations := map[string]string{"foo": "bar"} 83 ep.Annotations = annotations 84 }, 85 expectedSlice: discovery.EndpointSlice{ 86 ObjectMeta: metav1.ObjectMeta{ 87 Labels: map[string]string{ 88 discovery.LabelServiceName: endpoints.Name, 89 discovery.LabelManagedBy: controllerName, 90 }, 91 Annotations: map[string]string{"foo": "bar"}, 92 GenerateName: fmt.Sprintf("%s-", endpoints.Name), 93 Namespace: endpoints.Namespace, 94 OwnerReferences: []metav1.OwnerReference{*ownerRef}, 95 }, 96 Ports: ports, 97 AddressType: addrType, 98 Endpoints: []discovery.Endpoint{}, 99 }, 100 }, 101 { 102 name: "create slice from endpoints with labels", 103 tweakEndpoint: func(ep *v1.Endpoints) { 104 labels := map[string]string{"foo": "bar"} 105 ep.Labels = labels 106 }, 107 expectedSlice: discovery.EndpointSlice{ 108 ObjectMeta: metav1.ObjectMeta{ 109 Labels: map[string]string{ 110 "foo": "bar", 111 discovery.LabelServiceName: endpoints.Name, 112 discovery.LabelManagedBy: controllerName, 113 }, 114 Annotations: map[string]string{}, 115 GenerateName: fmt.Sprintf("%s-", endpoints.Name), 116 Namespace: endpoints.Namespace, 117 OwnerReferences: []metav1.OwnerReference{*ownerRef}, 118 }, 119 Ports: ports, 120 AddressType: addrType, 121 Endpoints: []discovery.Endpoint{}, 122 }, 123 }, 124 { 125 name: "create slice from endpoints with labels and annotations", 126 tweakEndpoint: func(ep *v1.Endpoints) { 127 labels := map[string]string{"foo": "bar"} 128 ep.Labels = labels 129 annotations := map[string]string{"foo2": "bar2"} 130 ep.Annotations = annotations 131 }, 132 expectedSlice: discovery.EndpointSlice{ 133 ObjectMeta: metav1.ObjectMeta{ 134 Labels: map[string]string{ 135 "foo": "bar", 136 discovery.LabelServiceName: endpoints.Name, 137 discovery.LabelManagedBy: controllerName, 138 }, 139 Annotations: map[string]string{"foo2": "bar2"}, 140 GenerateName: fmt.Sprintf("%s-", endpoints.Name), 141 Namespace: endpoints.Namespace, 142 OwnerReferences: []metav1.OwnerReference{*ownerRef}, 143 }, 144 Ports: ports, 145 AddressType: addrType, 146 Endpoints: []discovery.Endpoint{}, 147 }, 148 }, 149 { 150 name: "create slice from endpoints with labels and annotations triggertime", 151 tweakEndpoint: func(ep *v1.Endpoints) { 152 labels := map[string]string{"foo": "bar"} 153 ep.Labels = labels 154 annotations := map[string]string{ 155 "foo2": "bar2", 156 v1.EndpointsLastChangeTriggerTime: "date", 157 } 158 ep.Annotations = annotations 159 }, 160 expectedSlice: discovery.EndpointSlice{ 161 ObjectMeta: metav1.ObjectMeta{ 162 Labels: map[string]string{ 163 "foo": "bar", 164 discovery.LabelServiceName: endpoints.Name, 165 discovery.LabelManagedBy: controllerName, 166 }, 167 Annotations: map[string]string{"foo2": "bar2"}, 168 GenerateName: fmt.Sprintf("%s-", endpoints.Name), 169 Namespace: endpoints.Namespace, 170 OwnerReferences: []metav1.OwnerReference{*ownerRef}, 171 }, 172 Ports: ports, 173 AddressType: addrType, 174 Endpoints: []discovery.Endpoint{}, 175 }, 176 }, 177 } 178 for _, tc := range testCases { 179 t.Run(tc.name, func(t *testing.T) { 180 ep := endpoints.DeepCopy() 181 tc.tweakEndpoint(ep) 182 generatedSlice := newEndpointSlice(ep, ports, addrType, "") 183 assert.EqualValues(t, tc.expectedSlice, *generatedSlice) 184 if len(endpoints.Labels) > 1 { 185 t.Errorf("Expected Endpoints labels to not be modified, got %+v", endpoints.Labels) 186 } 187 }) 188 } 189 } 190 191 func TestAddressToEndpoint(t *testing.T) { 192 //name: "simple + gate enabled", 193 epAddress := v1.EndpointAddress{ 194 IP: "10.1.2.3", 195 Hostname: "foo", 196 NodeName: pointer.String("node-abc"), 197 TargetRef: &v1.ObjectReference{ 198 APIVersion: "v1", 199 Kind: "Pod", 200 Namespace: "default", 201 Name: "foo", 202 }, 203 } 204 ready := true 205 expectedEndpoint := discovery.Endpoint{ 206 Addresses: []string{"10.1.2.3"}, 207 Hostname: pointer.String("foo"), 208 Conditions: discovery.EndpointConditions{ 209 Ready: pointer.BoolPtr(true), 210 }, 211 TargetRef: &v1.ObjectReference{ 212 APIVersion: "v1", 213 Kind: "Pod", 214 Namespace: "default", 215 Name: "foo", 216 }, 217 NodeName: pointer.String("node-abc"), 218 } 219 220 ep := addressToEndpoint(epAddress, ready) 221 assert.EqualValues(t, expectedEndpoint, *ep) 222 } 223 224 // Test helpers 225 226 func newClientset() *fake.Clientset { 227 client := fake.NewSimpleClientset() 228 229 client.PrependReactor("create", "endpointslices", k8stesting.ReactionFunc(func(action k8stesting.Action) (bool, runtime.Object, error) { 230 endpointSlice := action.(k8stesting.CreateAction).GetObject().(*discovery.EndpointSlice) 231 232 if endpointSlice.ObjectMeta.GenerateName != "" { 233 endpointSlice.ObjectMeta.Name = fmt.Sprintf("%s-%s", endpointSlice.ObjectMeta.GenerateName, rand.String(8)) 234 endpointSlice.ObjectMeta.GenerateName = "" 235 } 236 endpointSlice.ObjectMeta.Generation = 1 237 238 return false, endpointSlice, nil 239 })) 240 client.PrependReactor("update", "endpointslices", k8stesting.ReactionFunc(func(action k8stesting.Action) (bool, runtime.Object, error) { 241 endpointSlice := action.(k8stesting.CreateAction).GetObject().(*discovery.EndpointSlice) 242 endpointSlice.ObjectMeta.Generation++ 243 return false, endpointSlice, nil 244 })) 245 246 return client 247 }