diff --git a/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go b/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go index e23c00de38e..3ca90c459aa 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go +++ b/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go @@ -3924,6 +3924,9 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS if len(apiService.Spec.Ports) == 0 { return nil, fmt.Errorf("requested load balancer with no ports") } + if err := checkMixedProtocol(apiService.Spec.Ports); err != nil { + return nil, err + } // Figure out what mappings we want on the load balancer listeners := []*elb.Listener{} v2Mappings := []nlbPortMapping{} @@ -5010,6 +5013,19 @@ func (c *Cloud) nodeNameToProviderID(nodeName types.NodeName) (InstanceID, error return KubernetesInstanceID(node.Spec.ProviderID).MapToAWSInstanceID() } +func checkMixedProtocol(ports []v1.ServicePort) error { + if len(ports) == 0 { + return nil + } + firstProtocol := ports[0].Protocol + for _, port := range ports[1:] { + if port.Protocol != firstProtocol { + return fmt.Errorf("mixed protocol is not supported for LoadBalancer") + } + } + return nil +} + func checkProtocol(port v1.ServicePort, annotations map[string]string) error { // nlb supports tcp, udp if isNLB(annotations) && (port.Protocol == v1.ProtocolTCP || port.Protocol == v1.ProtocolUDP) { diff --git a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_test.go b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_test.go index 10a725b7864..8330df2919d 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_test.go @@ -1711,6 +1711,65 @@ func TestDescribeLoadBalancerOnEnsure(t *testing.T) { c.EnsureLoadBalancer(context.TODO(), TestClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "myservice", UID: "id"}}, []*v1.Node{}) } +func TestCheckMixedProtocol(t *testing.T) { + tests := []struct { + name string + annotations map[string]string + ports []v1.ServicePort + wantErr error + }{ + { + name: "TCP", + annotations: make(map[string]string), + ports: []v1.ServicePort{ + { + Protocol: v1.ProtocolTCP, + Port: int32(8080), + }, + }, + wantErr: nil, + }, + { + name: "UDP", + annotations: map[string]string{ServiceAnnotationLoadBalancerType: "nlb"}, + ports: []v1.ServicePort{ + { + Protocol: v1.ProtocolUDP, + Port: int32(8080), + }, + }, + wantErr: nil, + }, + { + name: "TCP and UDP", + annotations: map[string]string{ServiceAnnotationLoadBalancerType: "nlb"}, + ports: []v1.ServicePort{ + { + Protocol: v1.ProtocolUDP, + Port: int32(53), + }, + { + Protocol: v1.ProtocolTCP, + Port: int32(53), + }, + }, + wantErr: errors.New("mixed protocol is not supported for LoadBalancer"), + }, + } + for _, test := range tests { + tt := test + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + err := checkMixedProtocol(tt.ports) + if tt.wantErr != nil { + assert.EqualError(t, err, tt.wantErr.Error()) + } else { + assert.Equal(t, err, nil) + } + }) + } +} + func TestCheckProtocol(t *testing.T) { tests := []struct { name string