New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues of multiple published ports mapping to the same target port #1835

Merged
merged 1 commit into from Jan 10, 2017

Conversation

Projects
None yet
5 participants
@yongtang
Member

yongtang commented Dec 27, 2016

This fix tries to address the issue raised in moby/moby#29730 where a service with multiple published ports mapping to the same target port (e.g., --publish 5000:80 --publish 5001:80) can't be allocated.

The reason for the issue is that, getPortConfigKey is used for both allocated ports and configured (may or may not be allocated) ports. However, getPortConfigKey will not take into consideration the PublishedPort field, which actually could be different for different allocated ports.

This fix saves a map of portKey:portNum:portState, instead of currently used portKey:portState so that multiple published ports could be processed.

A test case has been added in the unit test. The newly added test case will only work with this PR.

Signed-off-by: Yong Tang yong.tang.github@outlook.com

/cc @vdemeester @aaronlehmann @thaJeztah @stevvooe @mavenugo @icecrime @cpuguy83

@codecov-io

This comment has been minimized.

Show comment
Hide comment
@codecov-io

codecov-io Dec 27, 2016

Current coverage is 54.62% (diff: 94.87%)

Merging #1835 into master will decrease coverage by 0.02%

@@             master      #1835   diff @@
==========================================
  Files           102        102          
  Lines         17025      17041    +16   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           9304       9309     +5   
- Misses         6585       6593     +8   
- Partials       1136       1139     +3   

Sunburst

Powered by Codecov. Last update f355ca1...2f92077

codecov-io commented Dec 27, 2016

Current coverage is 54.62% (diff: 94.87%)

Merging #1835 into master will decrease coverage by 0.02%

@@             master      #1835   diff @@
==========================================
  Files           102        102          
  Lines         17025      17041    +16   
  Methods           0          0          
  Messages          0          0          
  Branches          0          0          
==========================================
+ Hits           9304       9309     +5   
- Misses         6585       6593     +8   
- Partials       1136       1139     +3   

Sunburst

Powered by Codecov. Last update f355ca1...2f92077

@aaronlehmann

This comment has been minimized.

Show comment
Hide comment
@aaronlehmann

aaronlehmann Dec 28, 2016

Collaborator

This looks correct, but I'm wondering we can do some refactoring to keep this long method from getting more complex.

Perhaps allocatedPorts could be its own type:

type allocatedPorts map[api.PortConfig]map[uint32]*api.PortConfig

It could have getter and setter methods defined on it abstract out tasks like creating the inner map and checking for a non-zero PublishedPort entry for a given PortConfig.

Just an idea and I'm not 100% sure it's the right way to go, but I imagine it will make this part of the code easier to read.

Also, it would be great to add a Docker integration test that tries to publish a port to two ingress ports, making sure it works end-to-end. I'm not sure if any other parts of the code make assumptions that would cause problems here. A test proving that it works would be valuable.

Collaborator

aaronlehmann commented Dec 28, 2016

This looks correct, but I'm wondering we can do some refactoring to keep this long method from getting more complex.

Perhaps allocatedPorts could be its own type:

type allocatedPorts map[api.PortConfig]map[uint32]*api.PortConfig

It could have getter and setter methods defined on it abstract out tasks like creating the inner map and checking for a non-zero PublishedPort entry for a given PortConfig.

Just an idea and I'm not 100% sure it's the right way to go, but I imagine it will make this part of the code easier to read.

Also, it would be great to add a Docker integration test that tries to publish a port to two ingress ports, making sure it works end-to-end. I'm not sure if any other parts of the code make assumptions that would cause problems here. A test proving that it works would be valuable.

@yongtang

This comment has been minimized.

Show comment
Hide comment
@yongtang

yongtang Dec 30, 2016

Member

Thanks @aaronlehmann @aboch @thaJeztah for the review. The PR has been updated. Now -p 80 -p 80 case should have been addressed as well. The way to address the mixture of -p 5000:80 -p 5001:80 -p 80 -p 80 is to remove saved allocated ports when it matches the portConfig. Also, non-dynamic ports are removed first. Dynamic ports are removed after that. This will prevent the dynamic ports config mapped to non-dynamic allocated ports.

A PR in docker has also been created to add the integration test:
moby/moby#29787

Please take a look and let me know if there are any issues.

Member

yongtang commented Dec 30, 2016

Thanks @aaronlehmann @aboch @thaJeztah for the review. The PR has been updated. Now -p 80 -p 80 case should have been addressed as well. The way to address the mixture of -p 5000:80 -p 5001:80 -p 80 -p 80 is to remove saved allocated ports when it matches the portConfig. Also, non-dynamic ports are removed first. Dynamic ports are removed after that. This will prevent the dynamic ports config mapped to non-dynamic allocated ports.

A PR in docker has also been created to add the integration test:
moby/moby#29787

Please take a look and let me know if there are any issues.

@aaronlehmann

This comment has been minimized.

Show comment
Hide comment
@aaronlehmann

aaronlehmann Jan 3, 2017

Collaborator

Overall LGTM, just some comments on typos and cosmetics.

Collaborator

aaronlehmann commented Jan 3, 2017

Overall LGTM, just some comments on typos and cosmetics.

@yongtang

This comment has been minimized.

Show comment
Hide comment
@yongtang

yongtang Jan 4, 2017

Member

Thanks @aaronlehmann for the review. The comments have been addressed. Please take a look.

Member

yongtang commented Jan 4, 2017

Thanks @aaronlehmann for the review. The comments have been addressed. Please take a look.

// For all other cases prefer the portConfig
portConfigs = append(portConfigs, portConfig)
// For all other cases prefer the portConfig
portConfigs = append(portConfigs, portConfig)

This comment has been minimized.

@aaronlehmann

aaronlehmann Jan 4, 2017

Collaborator

Same here; an if/else formulation might make the code ever so slightly clearer.

I apologize for picking nits over this kind of trivial thing. Normally I don't care very much about something like else vs continue. But this function is relatively complicated, and I'm trying to do all I can to make it intuitive.

@aaronlehmann

aaronlehmann Jan 4, 2017

Collaborator

Same here; an if/else formulation might make the code ever so slightly clearer.

I apologize for picking nits over this kind of trivial thing. Normally I don't care very much about something like else vs continue. But this function is relatively complicated, and I'm trying to do all I can to make it intuitive.

This comment has been minimized.

@yongtang

yongtang Jan 4, 2017

Member

Thanks @aaronlehmann. Also added additional comments to help explain the logic of the function.

@yongtang

yongtang Jan 4, 2017

Member

Thanks @aaronlehmann. Also added additional comments to help explain the logic of the function.

@aaronlehmann

This comment has been minimized.

Show comment
Hide comment
@aaronlehmann

aaronlehmann Jan 4, 2017

Collaborator

LGTM

Collaborator

aaronlehmann commented Jan 4, 2017

LGTM

@aaronlehmann

This comment has been minimized.

Show comment
Hide comment
@aaronlehmann

aaronlehmann Jan 6, 2017

Collaborator

ping @aboch @thaJeztah @LK4D4 for review

Collaborator

aaronlehmann commented Jan 6, 2017

ping @aboch @thaJeztah @LK4D4 for review

}
ps[portKey][p.PublishedPort] = p
}

This comment has been minimized.

@aboch

aboch Jan 6, 2017

It maybe only me but I feel it will help if we add a comment here saying what this method does and what it means if it return a nil or a non nil object. So to spare the reader from reading the implementation to understand that.

@aboch

aboch Jan 6, 2017

It maybe only me but I feel it will help if we add a comment here saying what this method does and what it means if it return a nil or a non nil object. So to spare the reader from reading the implementation to understand that.

@aboch

This comment has been minimized.

Show comment
Hide comment
@aboch

aboch Jan 6, 2017

Thanks @yongtang

Code changes look good to me.

Up to you if you want to improve the comments now.

aboch commented Jan 6, 2017

Thanks @yongtang

Code changes look good to me.

Up to you if you want to improve the comments now.

@yongtang

This comment has been minimized.

Show comment
Hide comment
@yongtang

yongtang Jan 7, 2017

Member

Thanks @aboch the PR has been updated with added comments.

Member

yongtang commented Jan 7, 2017

Thanks @aboch the PR has been updated with added comments.

Fix issues of multiple published ports mapping to the same target port
This fix tries to address the issue raised in moby/moby#29370
where a service with multiple published ports mapping to the same target
port (e.g., `--publish 5000:80 --publish 5001:80`) can't be allocated.

The reason for the issue is that, `getPortConfigKey` is used for both
allocated ports and configured (may or may not be allocated) ports.
However, `getPortConfigKey` will not take into consideration the
`PublishedPort` field, which actually could be different for different
allocated ports.

This fix saves a map of `portKey:portNum:portState`,  instead of currently
used `portKey:portState` so that multiple published ports could be processed.

A test case has been added in the unit test. The newly added test case
will only work with this PR.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

@aaronlehmann aaronlehmann merged commit c971468 into docker:master Jan 10, 2017

3 checks passed

ci/circleci Your tests passed on CircleCI!
Details
codecov/project 55.00% (target 0.00%)
Details
dco-signed All commits are signed

@yongtang yongtang deleted the yongtang:29730-multiple-published-port branch Jan 10, 2017

yongtang added a commit to yongtang/swarmkit that referenced this pull request Jan 30, 2017

Add `allocatedPorts` definition for cherry-pick
This commit adds the `allocatedPorts` for cherry-pick.
The `allocatedPorts` was added in PR docker#1835, which is
not part of the v1.13.1 cherry pick.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>

@aaronlehmann aaronlehmann added this to the 1.13.2 milestone Feb 18, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment