Skip to content

Commit 0608a41

Browse files
pmalekprogrammer04
andauthored
feat(dataplane): allow setting DataPlane's NodePort port number (#1516)
* feat(dataplane): allow setting DataPlane's NodePort port number * chore: make generate --------- Co-authored-by: Jakub Warczarek <[email protected]>
1 parent 55e92b3 commit 0608a41

File tree

7 files changed

+166
-11
lines changed

7 files changed

+166
-11
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
[#1409](https://github.com/Kong/gateway-operator/pull/1409)
6464
- Support `NodePort` as ingress service type for `DataPlane`
6565
[#1430](https://github.com/Kong/gateway-operator/pull/1430)
66+
- Allow setting `NodePort` port number for ingress service for `DataPlane`.
67+
[#1516](https://github.com/Kong/gateway-operator/pull/1516)
6668
- Bump default `DataPlane` image to 3.10
6769
Default image changes from `kong` to `kong/kong-gateway`.
6870
[#1405](https://github.com/Kong/gateway-operator/pull/1405)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
apiVersion: gateway-operator.konghq.com/v1beta1
2+
kind: DataPlane
3+
metadata:
4+
name: dataplane-node-port
5+
spec:
6+
deployment:
7+
podTemplateSpec:
8+
spec:
9+
containers:
10+
- name: proxy
11+
# renovate: datasource=docker versioning=docker
12+
image: kong/kong-gateway:3.10
13+
env:
14+
- name: KONG_LOG_LEVEL
15+
value: debug
16+
- name: KONG_PROXY_LISTEN
17+
value: 0.0.0.0:9000 reuseport backlog=16384
18+
- name: KONG_PORT_MAPS
19+
value: 8080:9000
20+
resources:
21+
requests:
22+
memory: "64Mi"
23+
cpu: "250m"
24+
limits:
25+
memory: "1024Mi"
26+
cpu: "1000m"
27+
readinessProbe:
28+
initialDelaySeconds: 1
29+
periodSeconds: 1
30+
network:
31+
services:
32+
ingress:
33+
annotations:
34+
foo: bar
35+
ports:
36+
- name: http
37+
port: 8080
38+
targetPort: 9000
39+
- name: http
40+
port: 8083
41+
targetPort: 9000
42+
nodePort: 30083

controller/dataplane/owned_resources.go

+42-5
Original file line numberDiff line numberDiff line change
@@ -364,11 +364,7 @@ func ensureIngressServiceForDataPlane(
364364
existingService.Spec.Selector = generatedService.Spec.Selector
365365
updated = true
366366
}
367-
if !cmp.Equal(generatedService.Spec.Ports, existingService.Spec.Ports, cmp.FilterPath(func(p cmp.Path) bool {
368-
// We need to check all the service values but the NodePort, as this field is assigned by
369-
// the K8S controlplane components.
370-
return p.Last().String() == ".NodePort"
371-
}, cmp.Ignore())) {
367+
if !comparePorts(existingService.Spec.Ports, generatedService.Spec.Ports, dataPlane) {
372368
existingService.Spec.Ports = generatedService.Spec.Ports
373369
updated = true
374370
}
@@ -385,3 +381,44 @@ func ensureIngressServiceForDataPlane(
385381

386382
return op.Created, generatedService, cl.Create(ctx, generatedService)
387383
}
384+
385+
// comparePorts compares the ports of two services.
386+
// It returns true if the ports are equal, ignoring the NodePort field
387+
// for the ingress service if it was not set in the dataplane spec.
388+
func comparePorts(
389+
a, b []corev1.ServicePort,
390+
dataPlane *operatorv1beta1.DataPlane,
391+
) bool {
392+
if len(a) != len(b) {
393+
return false
394+
}
395+
for i := range a {
396+
if a[i].Name != b[i].Name {
397+
return false
398+
}
399+
if a[i].Protocol != b[i].Protocol {
400+
return false
401+
}
402+
if a[i].Port != b[i].Port {
403+
return false
404+
}
405+
if a[i].TargetPort != b[i].TargetPort {
406+
return false
407+
}
408+
if a[i].AppProtocol != b[i].AppProtocol {
409+
return false
410+
}
411+
412+
if a[i].NodePort != b[i].NodePort {
413+
if dataPlane != nil &&
414+
dataPlane.Spec.Network.Services != nil &&
415+
dataPlane.Spec.Network.Services.Ingress != nil &&
416+
len(dataPlane.Spec.Network.Services.Ingress.Ports) > i &&
417+
dataPlane.Spec.Network.Services.Ingress.Ports[i].NodePort != 0 {
418+
return false
419+
}
420+
}
421+
422+
}
423+
return true
424+
}

controller/dataplane/owned_resources_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,76 @@ func TestEnsureIngressServiceForDataPlane(t *testing.T) {
331331
})
332332
}
333333
}
334+
335+
func TestComparePorts(t *testing.T) {
336+
testCases := []struct {
337+
name string
338+
a []corev1.ServicePort
339+
b []corev1.ServicePort
340+
dataPlane *operatorv1beta1.DataPlane
341+
expected bool
342+
}{
343+
{
344+
name: "should return true when NodePort differs but not specified in DataPlane spec",
345+
a: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30080}},
346+
b: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30081}},
347+
dataPlane: builder.NewDataPlaneBuilder().
348+
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
349+
{
350+
Name: "http",
351+
Port: 80,
352+
TargetPort: intstr.FromInt(8000),
353+
// NodePort not specified
354+
},
355+
}).Build(),
356+
expected: true,
357+
},
358+
{
359+
name: "should return false when NodePort differs and is specified in DataPlane spec",
360+
a: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30080}},
361+
b: []corev1.ServicePort{{Name: "port-80", Port: 80, NodePort: 30081}},
362+
dataPlane: builder.NewDataPlaneBuilder().
363+
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
364+
{
365+
Name: "http",
366+
Port: 80,
367+
TargetPort: intstr.FromInt(8000),
368+
NodePort: 30080,
369+
},
370+
}).Build(),
371+
expected: false,
372+
},
373+
{
374+
name: "should return true when multiple ports match except NodePort which is not specified",
375+
a: []corev1.ServicePort{
376+
{Name: "port-80", Port: 80, NodePort: 30080},
377+
{Name: "port-443", Port: 443, NodePort: 30443},
378+
},
379+
b: []corev1.ServicePort{
380+
{Name: "port-80", Port: 80, NodePort: 30081},
381+
{Name: "port-443", Port: 443, NodePort: 30444},
382+
},
383+
dataPlane: builder.NewDataPlaneBuilder().
384+
WithIngressServicePorts([]operatorv1beta1.DataPlaneServicePort{
385+
{
386+
Name: "http",
387+
Port: 80,
388+
TargetPort: intstr.FromInt(8000),
389+
},
390+
{
391+
Name: "https",
392+
Port: 443,
393+
TargetPort: intstr.FromInt(8443),
394+
},
395+
}).Build(),
396+
expected: true,
397+
},
398+
}
399+
400+
for _, tc := range testCases {
401+
t.Run(tc.name, func(t *testing.T) {
402+
actual := comparePorts(tc.a, tc.b, tc.dataPlane)
403+
require.Equal(t, tc.expected, actual)
404+
})
405+
}
406+
}

go.mod

+4-4
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ require (
259259
replace (
260260
k8s.io/api => k8s.io/api v0.32.3
261261
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.32.3
262-
k8s.io/apimachinery => k8s.io/apimachinery v0.32.3
262+
k8s.io/apimachinery => k8s.io/apimachinery v0.32.4
263263
k8s.io/apiserver => k8s.io/apiserver v0.32.3
264264
k8s.io/cli-runtime => k8s.io/cli-runtime v0.32.3
265265
k8s.io/client-go => k8s.io/client-go v0.32.3
@@ -269,12 +269,12 @@ replace (
269269
k8s.io/component-base => k8s.io/component-base v0.32.3
270270
k8s.io/component-helpers => k8s.io/component-helpers v0.32.3
271271
k8s.io/controller-manager => k8s.io/controller-manager v0.32.3
272-
k8s.io/cri-api => k8s.io/cri-api v0.32.3
272+
k8s.io/cri-api => k8s.io/cri-api v0.32.4
273273
k8s.io/cri-client => k8s.io/cri-client v0.32.3
274274
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.32.3
275275
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.32.3
276276
k8s.io/endpointslice => k8s.io/endpointslice v0.32.3
277-
k8s.io/externaljwt => k8s.io/externaljwt v0.32.3
277+
k8s.io/externaljwt => k8s.io/externaljwt v0.32.4
278278
k8s.io/kms => k8s.io/kms v0.32.3
279279
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.32.3
280280
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.32.3
@@ -284,7 +284,7 @@ replace (
284284
k8s.io/kubelet => k8s.io/kubelet v0.32.3
285285
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
286286
k8s.io/metrics => k8s.io/metrics v0.32.3
287-
k8s.io/mount-utils => k8s.io/mount-utils v0.32.3
287+
k8s.io/mount-utils => k8s.io/mount-utils v0.32.4
288288
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.32.3
289289
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.32.3
290290
k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.32.3

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,8 @@ k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
686686
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
687687
k8s.io/apiextensions-apiserver v0.32.3 h1:4D8vy+9GWerlErCwVIbcQjsWunF9SUGNu7O7hiQTyPY=
688688
k8s.io/apiextensions-apiserver v0.32.3/go.mod h1:8YwcvVRMVzw0r1Stc7XfGAzB/SIVLunqApySV5V7Dss=
689-
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
690-
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
689+
k8s.io/apimachinery v0.32.4 h1:8EEksaxA7nd7xWJkkwLDN4SvWS5ot9g6Z/VZb3ju25I=
690+
k8s.io/apimachinery v0.32.4/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
691691
k8s.io/apiserver v0.32.3 h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
692692
k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc=
693693
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=

pkg/utils/kubernetes/resources/services.go

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ func ServicePortsFromDataPlaneIngressOpt(dataplane *operatorv1beta1.DataPlane) S
158158
Protocol: corev1.ProtocolTCP, // Currently, only TCP protocol supported.
159159
Port: p.Port,
160160
TargetPort: targetPort,
161+
NodePort: p.NodePort,
161162
})
162163
alreadyUsedPorts[p.Port] = struct{}{}
163164
}

0 commit comments

Comments
 (0)