From db8be0b06908b8d796f813050bacecd38fd16f93 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Thu, 13 Oct 2016 09:46:41 -0700 Subject: [PATCH] controlapi: Allow duplicate published ports when they use different protocols Fix controlapi to allow duplicate published ports as long as different protocols are in use. This is a 1.12.2 regression. Signed-off-by: Aaron Lehmann --- manager/controlapi/service.go | 12 +++++++++--- manager/controlapi/service_test.go | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/manager/controlapi/service.go b/manager/controlapi/service.go index 6cb69ff063..1731205d23 100644 --- a/manager/controlapi/service.go +++ b/manager/controlapi/service.go @@ -158,13 +158,19 @@ func validateEndpointSpec(epSpec *api.EndpointSpec) error { return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: ports can't be used with dnsrr mode") } - portSet := make(map[uint32]struct{}) + type portSpec struct { + publishedPort uint32 + protocol api.PortConfig_Protocol + } + + portSet := make(map[portSpec]struct{}) for _, port := range epSpec.Ports { - if _, ok := portSet[port.PublishedPort]; ok { + portSpec := portSpec{publishedPort: port.PublishedPort, protocol: port.Protocol} + if _, ok := portSet[portSpec]; ok { return grpc.Errorf(codes.InvalidArgument, "EndpointSpec: duplicate published ports provided") } - portSet[port.PublishedPort] = struct{}{} + portSet[portSpec] = struct{}{} } return nil diff --git a/manager/controlapi/service_test.go b/manager/controlapi/service_test.go index 58b054f6ab..40add8a5a7 100644 --- a/manager/controlapi/service_test.go +++ b/manager/controlapi/service_test.go @@ -296,6 +296,22 @@ func TestCreateService(t *testing.T) { }} _, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec4}) assert.NoError(t, err) + + // ensure no port conflict when different protocols are used + spec = createSpec("name6", "image", 1) + spec.Endpoint = &api.EndpointSpec{Ports: []*api.PortConfig{ + {PublishedPort: uint32(9100), TargetPort: uint32(9100), Protocol: api.PortConfig_Protocol(api.ProtocolTCP)}, + }} + r, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec}) + assert.NoError(t, err) + assert.NotEmpty(t, r.Service.ID) + + spec2 = createSpec("name7", "image", 1) + spec2.Endpoint = &api.EndpointSpec{Ports: []*api.PortConfig{ + {PublishedPort: uint32(9100), TargetPort: uint32(9100), Protocol: api.PortConfig_Protocol(api.ProtocolUDP)}, + }} + _, err = ts.Client.CreateService(context.Background(), &api.CreateServiceRequest{Spec: spec2}) + assert.NoError(t, err) } func TestGetService(t *testing.T) {