-
Notifications
You must be signed in to change notification settings - Fork 472
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
Webhook: validate the combination of port, protocol, and hostname are unique for each listener. #1457
Webhook: validate the combination of port, protocol, and hostname are unique for each listener. #1457
Conversation
Hi @gyohuangxin. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
@robscott I make it a draft PR because I have some question:
but then you give an example:
They are a bit inconsistent, but my understanding is the webhook should separately validate unique port, protocol per hostname for gateway listeners. Is it correct? Is it needed to verify unique port, protocol across hostnames? Is it needed to verify unique hostname per listener?
|
bb83aa7
to
91fe519
Compare
@gyohuangxin where are we at with this one? Is there anything we can do to help the progression here? Looks like maybe we're still waiting on some feedback requested from @robscott? |
Yes, it's on hold because I'm still confused with the first question, I'm not sure my thought is close to the reality.
|
apis/v1beta1/validation/gateway.go
Outdated
hostnameProtocolMap := make(map[gatewayv1b1.Hostname][]gatewayv1b1.ProtocolType) | ||
hostnamePortMap := make(map[gatewayv1b1.Hostname][]gatewayv1b1.PortNumber) |
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.
Hey @gyohuangxin, I think there's a simpler way to do this. All that we really want to do is ensure that the combination of port, protocol, and name are unique. So for example, the following would be valid:
- port: 80
hostname: foo.com
protocol: HTTP
- port: 443
hostname: foo.com
protocol: HTTP
But the following would not be valid:
- port: 80
hostname: foo.com
protocol: HTTP
- port: 80
hostname: foo.com
protocol: HTTP
I think what you have is slightly different than that, requiring that for the same hostname (foo.com), both port and protocol must be different for each listener. The spec as it's written today only requires that one of them is different.
A simple way to accomplish this would be to use something like fmt.Sprintf("%s:%s:%d", protocol, hostname, port)
for each listener and then use k8s sets util to see if the value for that listener duplicated any listeners you'd already looked at within the same Gateway. Hopefully that makes sense, sorry for the delay on this!
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.
@robscott Thanks for your clear comments, don't worry about the delay. I also like the simple implementation, thanks!
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.
should this webhook attempt to reject one of these tuples (80, http, *.com) and (80, http, *.foo.com) :) ?
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.
@arkodg I think it will very hard to accomplish. How would you decide if regexA (*.com in this case) is overlapping with regexB(*foo.com).
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 its hard, but I wanted to highlight the case.
Since the API calls out any regex match to be implementation specific, even adding language in the API for this might be tricky
cc @robscott
Thanks for the work on this @gyohuangxin! Sorry I lost track of this, don't hesitate to ping me if I can help explain anything better. |
@@ -0,0 +1,41 @@ | |||
/* | |||
Copyright 2022 The Kubernetes Authors. |
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.
2023
|
||
// ContainsInPortSlice checks whether the provided Port | ||
// is in the target Port slice. | ||
func ContainsInPortSlice(items []gatewayv1b1.PortNumber, item *gatewayv1b1.PortNumber) bool { |
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.
pass value type of PortNumber
|
||
// ContainsInProtocolSlice checks whether the provided Protocol | ||
// is in the target Protocol slice. | ||
func ContainsInProtocolSlice(items []gatewayv1b1.ProtocolType, item *gatewayv1b1.ProtocolType) bool { |
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.
value type instead of pointer
apis/v1beta1/validation/gateway.go
Outdated
} | ||
if listener.Port != 0 { | ||
if portSlice, ok := hostnamePortMap[targetHostname]; ok { | ||
if utils.ContainsInPortSlice(portSlice, &listener.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.
can use Slices.Contains
from golang.org/x/exp/slices
91fe519
to
25dc9ca
Compare
…port, protocol, and name are unique for each listener. Signed-off-by: Huang Xin <xin1.huang@intel.com>
25dc9ca
to
a7b6059
Compare
Signed-off-by: Huang Xin <xin1.huang@intel.com>
Thanks @gyohuangxin ! This Looks good to me. over to @robscott for a final review and approval. |
Sorry for missing the PR description, updated. Thanks for reminding 💯 |
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.
LGTM thanks !
Based on this comment it seems like we should take into consideration the tls properties attached to a listener when determing uniqueness |
Thanks for your comments @dprotaso . As said in @robscott 's #1842 (comment), the "Hostname" can be different for shared Port and Protocol, like the TLS example on the website: https://gateway-api.sigs.k8s.io/guides/tls/#wildcard-tls-listeners So, I think it can cover the use cases. Please let me know if there are some use cases that use the same combination of port, protocol and hostname but use distinct |
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.
Thanks @gyohuangxin! Would like a few more test cases but otherwise LGTM.
mutate: func(gw *gatewayv1b1.Gateway) { | ||
hostnameFoo := gatewayv1b1.Hostname("foo.com") | ||
gw.Spec.Listeners[0].Name = "foo" | ||
gw.Spec.Listeners[0].Hostname = &hostnameFoo |
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.
Since hostname is optional can you add one more test case that shows that the same setup fails when both listeners have separate hostnames?
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.
Similarly, it would be helpful to have additional test cases where everything was the same except for one of the fields (port, protocol, or hostname) to ensure those are all still valid.
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.
Since hostname is optional can you add one more test case that shows that the same setup fails when both listeners have separate hostnames?
Do you mean to test the combination of port and protocol are unique when hostnames not set? If yes, I've add one: d75ab56#diff-e3c0a139e14037364db162e955588e8153e795f4cbe84b6fce32149d62ca2a73R170-R184
Similarly, it would be helpful to have additional test cases where everything was the same except for one of the fields (port, protocol, or hostname) to ensure those are all still valid.
Updated, thank you!
Signed-off-by: Huang Xin <xin1.huang@intel.com>
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.
Thanks @gyohuangxin! Just a couple tiny nits but otherwise LGTM.
Thanks @gyohuangxin! /approve |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: arkodg, gyohuangxin, robscott The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
What type of PR is this?
/kind feature
What this PR does / why we need it:
Add validation to validate the combination of port, protocol, and hostname are unique for each listener.
Which issue(s) this PR fixes:
Fixes #847
Does this PR introduce a user-facing change?: