-
Notifications
You must be signed in to change notification settings - Fork 170
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
[balancer] Don't force 80 to be the default if port is not provided #662
Conversation
714e914
to
ab2ff03
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good but it might need a bit of reorganization to cleanup the API. Good job !
CHANGELOG.md
Outdated
|
||
### Changed | ||
|
||
- Changed the way `resty.balancer` sets the default port, in case no port is specified for the upstream [PR #662](https://github.com/3scale/apicast/pull/662) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changelog should say how and not what. So it should say it uses default port for the scheme.
gateway/src/resty/balancer.lua
Outdated
@@ -30,7 +30,7 @@ local function new_peer(server, port) | |||
|
|||
return { | |||
address, | |||
tonumber(server.port or port or 80, 10) | |||
tonumber(server.port or port, 10) or nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for or nil
gateway/src/resty/balancer.lua
Outdated
@@ -87,7 +87,7 @@ function _M.select_peer(self, peers) | |||
return peer | |||
end | |||
|
|||
function _M.set_peer(self, peers) | |||
function _M.set_peer(self, peers, default_port) | |||
local balancer = self.balancer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not really convinced by the API.
Shouldn’t this function extract the default port?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract from where? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the best approach is to not use set_peer
but rather select_peer
+ balancer.set_current_peer
.
gateway/src/apicast/balancer.lua
Outdated
function _M.call(_, _, balancer) | ||
balancer = balancer or _M.default_balancer | ||
local host = ngx.var.proxy_host -- NYI: return to lower frame | ||
local peers = balancer:peers(ngx.ctx[host]) | ||
|
||
local peer, err = balancer:set_peer(peers) | ||
local port = get_default_port(ngx.var.proxy_pass) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the nginx docs and looks like there is no built in variable to get scheme of the upstream server. Pity.
We should evaluate this only when the port is missing.
65f52d9
to
3ae3e38
Compare
gateway/src/apicast/balancer.lua
Outdated
ngx.log(ngx.ERR, "failed to set current backend peer: ", err) | ||
ngx.exit(ngx.status) | ||
ngx.log(ngx.ERR, 'could not select peer: ', err) | ||
exit_service_unavailable() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to signal it returns by doing return exit_service_unavailable()
as recommended in the ngx.exit documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I thought about it, but for some reason didn't put it. Will fix, thanks.
9e6cbe8
to
a121fdf
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
assert.spy(b.balancer.set_current_peer).was.called_with('127.0.0.2', 443) | ||
end) | ||
end) | ||
end) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mm? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: There's no newline at the end of the file.
local function get_default_port(upstream_url) | ||
local url = resty_url.split(upstream_url) or empty | ||
local scheme = url[1] or 'http' | ||
return resty_url.default_port(scheme) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to clarify, I think this only works with http and https: https://github.com/3scale/lua-resty-url#default_port
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. Do you think it needs to be documented somewhere in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well spotted. I think it does not need to be documented (because we don't really support other protocols), but handled with a proper error message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, set_current_peer
will set port to 0
if not provided: https://github.com/openresty/lua-resty-core/blob/a39b8d68b3b1c93f22259f95925c9dc854d69c1c/lib/ngx/balancer.lua#L113
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess then we can just leave it to that and just have a test to verify what it does when no port is provided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the balancer has a default and would return an error then there is no need to handle this case by us. And to verify that it works it is necessary to have a test. IMO it is better to have a test to see how it works than code to maintain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried it, but turns out that:
-
setting
unsupported://example.com
in the upstream policy config will fail here, because trying to parse a URL with unsupported scheme returns anil
. -
If I force upstream to push the invalid URL forward, APIcast throws an error:
[error] 4373#0: *5 invalid URL prefix in "unsupported://upstream"
So, I am not sure how I can test it in either integration or unit test :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mayorova fail how? throw an exception? then it should be handled and we can test it is being handled by asserting an entry in the error log and some status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mikz 1. will throw an exception...
My point is – I don't see a way to test how balancer will act if the incorrect scheme is passed, because the execution will not even reach the balancer point, and will fail before that.
Or should I add a failing test for the upstream policy instead? (I would consider it as a different PR - handle exception in upstream policy and add test)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gateway/src/apicast/balancer.lua
Outdated
port = get_default_port(ngx.var.proxy_pass) | ||
end | ||
|
||
local _ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks strange.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah :/
before it was an ok
, but codeclimate complained about an unused variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe err = balancer.balancer.set_current_peer(address, port)[2]
?... because we don't care about the ok
value (or maybe we should)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we should care about ok
.
gateway/src/apicast/balancer.lua
Outdated
local peer, err = balancer:set_peer(peers) | ||
local peer, err = balancer:select_peer(peers) | ||
|
||
local address, port |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can move this below the if
.
gateway/src/apicast/balancer.lua
Outdated
end | ||
|
||
if not port then | ||
port = get_default_port(ngx.var.proxy_pass) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if this can return nil
because of the limitations of resty_url.default_port that I pointed out in another comment.
Not sure if that would be a problem later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it can, but not sure what we should do in this case.
Defaulting to some specific port doesn't sound too good either. I guess here we can accept that apicast will return a 5xx error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed in #662 (comment) the port will be set to 0. So we just need to to have a test to see what it really does and we might not need to handle anything.
@mayorova The PR looks good 👍 |
58adfba
to
55e4339
Compare
…cer sets default port by scheme
55e4339
to
d1a0937
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job 👍 🥇
An alternative (and a more generic) way to solve the issue with the upstream policy: #647