1
16
17 package options
18
19 import (
20 "net"
21 "testing"
22
23 utilnet "k8s.io/apimachinery/pkg/util/net"
24 apiserveroptions "k8s.io/apiserver/pkg/server/options"
25 utilfeature "k8s.io/apiserver/pkg/util/feature"
26 featuregatetesting "k8s.io/component-base/featuregate/testing"
27 netutils "k8s.io/utils/net"
28
29 "k8s.io/kubernetes/pkg/features"
30 )
31
32 func makeOptionsWithCIDRs(serviceCIDR string, secondaryServiceCIDR string) *ServerRunOptions {
33 value := serviceCIDR
34 if len(secondaryServiceCIDR) > 0 {
35 value = value + "," + secondaryServiceCIDR
36 }
37
38 var primaryCIDR, secondaryCIDR net.IPNet
39 if len(serviceCIDR) > 0 {
40 _, cidr, _ := netutils.ParseCIDRSloppy(serviceCIDR)
41 if cidr != nil {
42 primaryCIDR = *(cidr)
43 }
44 }
45
46 if len(secondaryServiceCIDR) > 0 {
47 _, cidr, _ := netutils.ParseCIDRSloppy(secondaryServiceCIDR)
48 if cidr != nil {
49 secondaryCIDR = *(cidr)
50 }
51 }
52 return &ServerRunOptions{
53 Extra: Extra{
54 ServiceClusterIPRanges: value,
55 PrimaryServiceClusterIPRange: primaryCIDR,
56 SecondaryServiceClusterIPRange: secondaryCIDR,
57 },
58 }
59 }
60
61 func TestClusterServiceIPRange(t *testing.T) {
62 testCases := []struct {
63 name string
64 options *ServerRunOptions
65 expectErrors bool
66 gate bool
67 }{
68 {
69 name: "no service cidr",
70 expectErrors: true,
71 options: makeOptionsWithCIDRs("", ""),
72 },
73 {
74 name: "only secondary service cidr",
75 expectErrors: true,
76 options: makeOptionsWithCIDRs("", "10.0.0.0/16"),
77 },
78 {
79 name: "primary and secondary are provided but not dual stack v4-v4",
80 expectErrors: true,
81 options: makeOptionsWithCIDRs("10.0.0.0/16", "11.0.0.0/16"),
82 },
83 {
84 name: "primary and secondary are provided but not dual stack v6-v6",
85 expectErrors: true,
86 options: makeOptionsWithCIDRs("2000::/108", "3000::/108"),
87 },
88 {
89 name: "service cidr is too big",
90 expectErrors: true,
91 options: makeOptionsWithCIDRs("10.0.0.0/8", ""),
92 },
93 {
94 name: "service cidr IPv4 is too big but gate enbled",
95 expectErrors: false,
96 options: makeOptionsWithCIDRs("10.0.0.0/8", ""),
97 gate: true,
98 },
99 {
100 name: "service cidr IPv6 is too big but gate enbled",
101 expectErrors: false,
102 options: makeOptionsWithCIDRs("2001:db8::/64", ""),
103 gate: true,
104 },
105 {
106 name: "service cidr IPv6 is too big and gate enbled",
107 expectErrors: false,
108 options: makeOptionsWithCIDRs("2001:db8::/12", ""),
109 gate: true,
110 },
111 {
112 name: "dual-stack secondary cidr too big",
113 expectErrors: true,
114 options: makeOptionsWithCIDRs("10.0.0.0/16", "3000::/64"),
115 },
116 {
117 name: "dual-stack secondary cidr too big gate enabled",
118 expectErrors: false,
119 options: makeOptionsWithCIDRs("10.0.0.0/16", "3000::/48"),
120 gate: true,
121 },
122 {
123 name: "more than two entries",
124 expectErrors: true,
125 options: makeOptionsWithCIDRs("10.0.0.0/16,244.0.0.0/16", "3000::/108"),
126 },
127
128 {
129 name: "valid primary",
130 expectErrors: false,
131 options: makeOptionsWithCIDRs("10.0.0.0/16", ""),
132 },
133 {
134 name: "valid primary, class E range",
135 expectErrors: false,
136 options: makeOptionsWithCIDRs("244.0.0.0/16", ""),
137 },
138 {
139 name: "valid v4-v6 dual stack",
140 expectErrors: false,
141 options: makeOptionsWithCIDRs("10.0.0.0/16", "3000::/108"),
142 },
143 {
144 name: "valid v6-v4 dual stack",
145 expectErrors: false,
146 options: makeOptionsWithCIDRs("3000::/108", "10.0.0.0/16"),
147 },
148 }
149
150 for _, tc := range testCases {
151 t.Run(tc.name, func(t *testing.T) {
152 defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.MultiCIDRServiceAllocator, tc.gate)()
153
154 errs := validateClusterIPFlags(tc.options.Extra)
155 if len(errs) > 0 && !tc.expectErrors {
156 t.Errorf("expected no errors, errors found %+v", errs)
157 }
158
159 if len(errs) == 0 && tc.expectErrors {
160 t.Errorf("expected errors, no errors found")
161 }
162 })
163 }
164 }
165
166 func TestValidatePublicIPServiceClusterIPRangeIPFamilies(t *testing.T) {
167 _, ipv4cidr, err := netutils.ParseCIDRSloppy("192.168.0.0/24")
168 if err != nil {
169 t.Fatalf("Unexpected error %v", err)
170 }
171
172 _, ipv6cidr, err := netutils.ParseCIDRSloppy("2001:db8::/112")
173 if err != nil {
174 t.Fatalf("Unexpected error %v", err)
175 }
176
177 ipv4address := netutils.ParseIPSloppy("192.168.1.1")
178 ipv6address := netutils.ParseIPSloppy("2001:db8::1")
179
180 tests := []struct {
181 name string
182 generic apiserveroptions.ServerRunOptions
183 extra Extra
184 wantErr bool
185 }{
186 {
187 name: "master endpoint reconciler - IPv4 families",
188 extra: Extra{
189 EndpointReconcilerType: "master-count",
190 PrimaryServiceClusterIPRange: *ipv4cidr,
191 },
192 generic: apiserveroptions.ServerRunOptions{
193 AdvertiseAddress: ipv4address,
194 },
195 wantErr: false,
196 },
197 {
198 name: "master endpoint reconciler - IPv6 families",
199 extra: Extra{
200 EndpointReconcilerType: "master-count",
201 PrimaryServiceClusterIPRange: *ipv6cidr,
202 },
203 generic: apiserveroptions.ServerRunOptions{
204 AdvertiseAddress: ipv6address,
205 },
206 wantErr: false,
207 },
208 {
209 name: "master endpoint reconciler - wrong IP families",
210 extra: Extra{
211 EndpointReconcilerType: "master-count",
212 PrimaryServiceClusterIPRange: *ipv4cidr,
213 },
214 generic: apiserveroptions.ServerRunOptions{
215 AdvertiseAddress: ipv6address,
216 },
217 wantErr: true,
218 },
219 {
220 name: "master endpoint reconciler - wrong IP families",
221 extra: Extra{
222 EndpointReconcilerType: "master-count",
223 PrimaryServiceClusterIPRange: *ipv6cidr,
224 },
225 generic: apiserveroptions.ServerRunOptions{
226 AdvertiseAddress: ipv4address,
227 },
228 wantErr: true,
229 },
230 {
231 name: "lease endpoint reconciler - IPv4 families",
232 extra: Extra{
233 EndpointReconcilerType: "lease",
234 PrimaryServiceClusterIPRange: *ipv4cidr,
235 },
236 generic: apiserveroptions.ServerRunOptions{
237 AdvertiseAddress: ipv4address,
238 },
239 wantErr: false,
240 },
241 {
242 name: "lease endpoint reconciler - IPv6 families",
243 extra: Extra{
244 EndpointReconcilerType: "lease",
245 PrimaryServiceClusterIPRange: *ipv6cidr,
246 },
247 generic: apiserveroptions.ServerRunOptions{
248 AdvertiseAddress: ipv6address,
249 },
250 wantErr: false,
251 },
252 {
253 name: "lease endpoint reconciler - wrong IP families",
254 extra: Extra{
255 EndpointReconcilerType: "lease",
256 PrimaryServiceClusterIPRange: *ipv4cidr,
257 },
258 generic: apiserveroptions.ServerRunOptions{
259 AdvertiseAddress: ipv6address,
260 },
261 wantErr: true,
262 },
263 {
264 name: "lease endpoint reconciler - wrong IP families",
265 extra: Extra{
266 EndpointReconcilerType: "lease",
267 PrimaryServiceClusterIPRange: *ipv6cidr,
268 },
269 generic: apiserveroptions.ServerRunOptions{
270 AdvertiseAddress: ipv4address,
271 },
272 wantErr: true,
273 },
274 {
275 name: "none endpoint reconciler - wrong IP families",
276 extra: Extra{
277 EndpointReconcilerType: "none",
278 PrimaryServiceClusterIPRange: *ipv4cidr,
279 },
280 generic: apiserveroptions.ServerRunOptions{
281 AdvertiseAddress: ipv6address,
282 },
283 wantErr: false,
284 },
285 }
286 for _, tt := range tests {
287 t.Run(tt.name, func(t *testing.T) {
288 errs := validatePublicIPServiceClusterIPRangeIPFamilies(tt.extra, tt.generic)
289 if (len(errs) > 0) != tt.wantErr {
290 t.Fatalf("completedConfig.New() errors = %+v, wantErr %v", errs, tt.wantErr)
291 }
292 })
293 }
294 }
295
296 func getIPnetFromCIDR(cidr string) *net.IPNet {
297 _, ipnet, _ := netutils.ParseCIDRSloppy(cidr)
298 return ipnet
299 }
300
301 func TestValidateServiceNodePort(t *testing.T) {
302 testCases := []struct {
303 name string
304 options *ServerRunOptions
305 expectErrors bool
306 }{
307 {
308 name: "validate port less than 0",
309 options: makeOptionsWithPort(-1, 30065, 1),
310 expectErrors: true,
311 },
312 {
313 name: "validate port more than 65535",
314 options: makeOptionsWithPort(65536, 30065, 1),
315 expectErrors: true,
316 },
317 {
318 name: "validate port equal 0",
319 options: makeOptionsWithPort(0, 0, 1),
320 expectErrors: true,
321 },
322 {
323 name: "validate port less than base",
324 options: makeOptionsWithPort(30064, 30065, 1),
325 expectErrors: true,
326 },
327 {
328 name: "validate port minus base more than size",
329 options: makeOptionsWithPort(30067, 30065, 1),
330 expectErrors: true,
331 },
332 {
333 name: "validate success",
334 options: makeOptionsWithPort(30067, 30065, 5),
335 expectErrors: false,
336 },
337 }
338
339 for _, tc := range testCases {
340 t.Run(tc.name, func(t *testing.T) {
341 errs := validateServiceNodePort(tc.options.Extra)
342 if errs != nil && !tc.expectErrors {
343 t.Errorf("expected no errors, error found %+v", errs)
344 }
345 })
346 }
347 }
348
349 func makeOptionsWithPort(kubernetesServiceNodePort int, base int, size int) *ServerRunOptions {
350 var portRange = utilnet.PortRange{
351 Base: base,
352 Size: size,
353 }
354 return &ServerRunOptions{
355 Extra: Extra{
356 ServiceNodePortRange: portRange,
357 KubernetesServiceNodePort: kubernetesServiceNodePort,
358 },
359 }
360 }
361
362 func TestValidateMaxCIDRRange(t *testing.T) {
363 testCases := []struct {
364
365 name string
366 cidr net.IPNet
367 maxCIDRBits int
368 cidrFlag string
369 expectedErrorMessage string
370 expectErrors bool
371 }{
372 {
373 name: "valid ipv4 cidr",
374 cidr: *getIPnetFromCIDR("10.92.0.0/12"),
375 maxCIDRBits: 20,
376 cidrFlag: "--service-cluster-ip-range",
377 expectedErrorMessage: "",
378 expectErrors: false,
379 },
380 {
381 name: "valid ipv6 cidr",
382 cidr: *getIPnetFromCIDR("3000::/108"),
383 maxCIDRBits: 20,
384 cidrFlag: "--service-cluster-ip-range",
385 expectedErrorMessage: "",
386 expectErrors: false,
387 },
388 {
389 name: "ipv4 cidr too big",
390 cidr: *getIPnetFromCIDR("10.92.0.0/8"),
391 maxCIDRBits: 20,
392 cidrFlag: "--service-cluster-ip-range",
393 expectedErrorMessage: "specified --service-cluster-ip-range is too large; for 32-bit addresses, the mask must be >= 12",
394 expectErrors: true,
395 },
396 {
397 name: "ipv6 cidr too big",
398 cidr: *getIPnetFromCIDR("3000::/64"),
399 maxCIDRBits: 20,
400 cidrFlag: "--service-cluster-ip-range",
401 expectedErrorMessage: "specified --service-cluster-ip-range is too large; for 128-bit addresses, the mask must be >= 108",
402 expectErrors: true,
403 },
404 }
405
406 for _, tc := range testCases {
407 t.Run(tc.name, func(t *testing.T) {
408 err := validateMaxCIDRRange(tc.cidr, tc.maxCIDRBits, tc.cidrFlag)
409 if err != nil && !tc.expectErrors {
410 t.Errorf("expected no errors, error found %+v", err)
411 }
412
413 if err == nil && tc.expectErrors {
414 t.Errorf("expected errors, no errors found")
415 }
416
417 if err != nil && tc.expectErrors && err.Error() != tc.expectedErrorMessage {
418 t.Errorf("Expected error message: \"%s\"\nGot: \"%s\"", tc.expectedErrorMessage, err.Error())
419 }
420 })
421 }
422 }
423
View as plain text