1
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
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
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 }
248
View as plain text