diff --git a/manager/controlapi/service.go b/manager/controlapi/service.go index 1731205d23..d484ced37e 100644 --- a/manager/controlapi/service.go +++ b/manager/controlapi/service.go @@ -165,6 +165,12 @@ func validateEndpointSpec(epSpec *api.EndpointSpec) error { portSet := make(map[portSpec]struct{}) for _, port := range epSpec.Ports { + // If published port is not specified, it does not conflict + // with any others. + if port.PublishedPort == 0 { + continue + } + portSpec := portSpec{publishedPort: port.PublishedPort, protocol: port.Protocol} if _, ok := portSet[portSpec]; ok { return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: duplicate published ports provided") diff --git a/manager/controlapi/service_test.go b/manager/controlapi/service_test.go index 40add8a5a7..fadcc30602 100644 --- a/manager/controlapi/service_test.go +++ b/manager/controlapi/service_test.go @@ -576,6 +576,47 @@ func TestValidateEndpointSpec(t *testing.T) { }, } + // duplicated published port but different protocols, valid + endPointSpec4 := &api.EndpointSpec{ + Mode: api.ResolutionModeVirtualIP, + Ports: []*api.PortConfig{ + { + Name: "dns", + TargetPort: 53, + PublishedPort: 8002, + Protocol: api.ProtocolTCP, + }, + { + Name: "dns", + TargetPort: 53, + PublishedPort: 8002, + Protocol: api.ProtocolUDP, + }, + }, + } + + // multiple randomly assigned published ports + endPointSpec5 := &api.EndpointSpec{ + Mode: api.ResolutionModeVirtualIP, + Ports: []*api.PortConfig{ + { + Name: "http", + TargetPort: 80, + Protocol: api.ProtocolTCP, + }, + { + Name: "dns", + TargetPort: 53, + Protocol: api.ProtocolUDP, + }, + { + Name: "dns", + TargetPort: 53, + Protocol: api.ProtocolTCP, + }, + }, + } + err := validateEndpointSpec(endPointSpec1) assert.Error(t, err) assert.Equal(t, codes.InvalidArgument, grpc.Code(err)) @@ -586,6 +627,12 @@ func TestValidateEndpointSpec(t *testing.T) { err = validateEndpointSpec(endPointSpec3) assert.Error(t, err) assert.Equal(t, codes.InvalidArgument, grpc.Code(err)) + + err = validateEndpointSpec(endPointSpec4) + assert.NoError(t, err) + + err = validateEndpointSpec(endPointSpec5) + assert.NoError(t, err) } func TestServiceEndpointSpecUpdate(t *testing.T) {