@@ -3,6 +3,7 @@ package service
33import (
44 "context"
55 "fmt"
6+ "slices"
67 "strconv"
78
89 "github.com/aws/aws-sdk-go-v2/aws"
@@ -19,16 +20,41 @@ func (t *defaultModelBuildTask) buildListeners(ctx context.Context, scheme elbv2
1920 return err
2021 }
2122
23+ // group by listener port number
24+ portMap := make (map [int32 ][]corev1.ServicePort )
2225 for _ , port := range t .service .Spec .Ports {
23- _ , err := t .buildListener (ctx , port , * cfg , scheme )
24- if err != nil {
25- return err
26+ key := port .Port
27+ if vals , exists := portMap [key ]; exists {
28+ portMap [key ] = append (vals , port )
29+ } else {
30+ portMap [key ] = []corev1.ServicePort {port }
2631 }
2732 }
33+
34+ // execute build listener
35+ for _ , port := range t .service .Spec .Ports {
36+ key := port .Port
37+ if vals , exists := portMap [key ]; exists {
38+ if len (vals ) > 1 {
39+ port , err = mergeServicePortsForListener (vals )
40+ if err != nil {
41+ return err
42+ }
43+ } else {
44+ port = vals [0 ]
45+ }
46+ _ , err := t .buildListener (ctx , port , cfg , scheme )
47+ if err != nil {
48+ return err
49+ }
50+ delete (portMap , key )
51+ }
52+ }
53+
2854 return nil
2955}
3056
31- func (t * defaultModelBuildTask ) buildListener (ctx context.Context , port corev1.ServicePort , cfg listenerConfig ,
57+ func (t * defaultModelBuildTask ) buildListener (ctx context.Context , port corev1.ServicePort , cfg * listenerConfig ,
3258 scheme elbv2model.LoadBalancerScheme ) (* elbv2model.Listener , error ) {
3359 lsSpec , err := t .buildListenerSpec (ctx , port , cfg , scheme )
3460 if err != nil {
@@ -39,7 +65,7 @@ func (t *defaultModelBuildTask) buildListener(ctx context.Context, port corev1.S
3965 return ls , nil
4066}
4167
42- func (t * defaultModelBuildTask ) buildListenerSpec (ctx context.Context , port corev1.ServicePort , cfg listenerConfig ,
68+ func (t * defaultModelBuildTask ) buildListenerSpec (ctx context.Context , port corev1.ServicePort , cfg * listenerConfig ,
4369 scheme elbv2model.LoadBalancerScheme ) (elbv2model.ListenerSpec , error ) {
4470 tgProtocol := elbv2model .Protocol (port .Protocol )
4571 listenerProtocol := elbv2model .Protocol (port .Protocol )
@@ -149,7 +175,7 @@ func validateTLSPortsSet(rawTLSPorts []string, ports []corev1.ServicePort) error
149175 return nil
150176}
151177
152- func (t * defaultModelBuildTask ) buildTLSPortsSet (_ context.Context ) (sets.String , error ) {
178+ func (t * defaultModelBuildTask ) buildTLSPortsSet (_ context.Context ) (sets.Set [ string ] , error ) {
153179 var rawTLSPorts []string
154180
155181 _ = t .annotationParser .ParseStringSliceAnnotation (annotations .SvcLBSuffixSSLPorts , & rawTLSPorts , t .service .Annotations )
@@ -160,7 +186,7 @@ func (t *defaultModelBuildTask) buildTLSPortsSet(_ context.Context) (sets.String
160186 return nil , err
161187 }
162188
163- return sets .NewString (rawTLSPorts ... ), nil
189+ return sets .New [ string ] (rawTLSPorts ... ), nil
164190}
165191
166192func (t * defaultModelBuildTask ) buildBackendProtocol (_ context.Context ) string {
@@ -191,7 +217,7 @@ func (t *defaultModelBuildTask) buildListenerALPNPolicy(ctx context.Context, lis
191217
192218type listenerConfig struct {
193219 certificates []elbv2model.Certificate
194- tlsPortsSet sets.String
220+ tlsPortsSet sets.Set [ string ]
195221 sslPolicy * string
196222 backendProtocol string
197223}
@@ -234,3 +260,20 @@ func (t *defaultModelBuildTask) buildListenerAttributes(ctx context.Context, svc
234260 }
235261 return attributes , nil
236262}
263+
264+ func mergeServicePortsForListener (ports []corev1.ServicePort ) (corev1.ServicePort , error ) {
265+ if len (ports ) != 2 {
266+ return corev1.ServicePort {}, fmt .Errorf ("Can only merge two ports, not %d (%+v)" , len (ports ), ports )
267+ }
268+ for _ , port := range ports {
269+ if ! slices .Contains ([]string {"TCP" , "UDP" }, string (port .Protocol )) {
270+ return corev1.ServicePort {}, fmt .Errorf ("Unsupported protocol for merging: %s" , port .Protocol )
271+ }
272+ }
273+ if ports [0 ].Protocol == ports [1 ].Protocol {
274+ return corev1.ServicePort {}, fmt .Errorf ("Protocols can't match for merging: %s" , ports [0 ].Protocol )
275+ }
276+ port := ports [0 ]
277+ port .Protocol = corev1 .Protocol ("TCP_UDP" )
278+ return port , nil
279+ }
0 commit comments