-
Notifications
You must be signed in to change notification settings - Fork 40.2k
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: kubectl expose fails for apps with same-port, different-protocol #114909
Conversation
/sig cli |
/assign anggao Can you review the code for me |
@aimuz: GitHub didn't allow me to assign the following users: anggao. Note that only kubernetes members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time. In response to this:
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. |
serviceName := o.Name | ||
if len(serviceName) == 0 { | ||
serviceName = o.DefaultName | ||
if len(serviceName) == 0 { |
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 is to avoid the misunderstanding of duplicate names. In the loop, name is also used. To avoid misunderstanding, I renamed it
name := servicePortName | ||
if len(portStringSlice) > 1 { | ||
name = fmt.Sprintf("%s-%d", strings.ToLower(protocol), 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.
Compared with the naming of prot-i, this method may be easier to understand, which is also to distinguish between different protocols on the same port
/assign @anggao |
@aimuz: GitHub didn't allow me to assign the following users: anggao. Note that only kubernetes members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time. In response to this:
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. |
f6b61cc
to
4cabc1e
Compare
@@ -1722,8 +1756,8 @@ func TestGenerateService(t *testing.T) { | |||
service, err := exposeServiceOptions.createService() | |||
if test.expectErr == "" { | |||
require.NoError(t, err) | |||
if !apiequality.Semantic.DeepEqual(service, test.expected) { | |||
t.Errorf("\nexpected:\n%#v\ngot:\n%#v", test.expected, service) | |||
if diff := cmp.Diff(test.expected, service); diff != "" { |
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 will output more intuitive differences
/test pull-kubernetes-integration |
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 for the fix and the effort you invested.
Maybe it is better to do less changes to fix that issue without touching generated files.
to prevent accidental merging;
/hold
} | ||
selector, err := parseLabels(o.Selector) | ||
obj, err := versioned.GenerateService(opts) |
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 unusual. What is the reason of this change?
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.
Repetitive code implementation, which I extract as a public method
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.
See my comment above. We don't want to use the generators.
portProtocolMap[portProtocol[0]] = portProtocol[1] | ||
} | ||
return portProtocolMap, nil | ||
return obj, 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.
What is the reason of these changes with respect to the referenced issue?
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.
Repetitive code implementation, which I extract as a public method
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.
Is this something required for fixing the bug or is this refactoring?.
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.
Refactoring was done while fixing the bug
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 you start with just fixing the bug, with minimal or no refactoring at first? Then maybe do the refactor later if needed.
It's more complicated to review a bug fix and refactor together.
@@ -67,7 +67,7 @@ var MapBasedSelectorForObjectFn MapBasedSelectorForObjectFunc = mapBasedSelector | |||
|
|||
// ProtocolsForObjectFunc will call the provided function on the protocols for the object, | |||
// return nil-map if no protocols for the object, or return an error. | |||
type ProtocolsForObjectFunc func(object runtime.Object) (map[string]string, error) | |||
type ProtocolsForObjectFunc func(object runtime.Object) (map[string][]string, 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.
Is this backward compatible?
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, but I don't think this change will have any impact. Only kubectl will use 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.
It is public and it looks like people are using it (via github search, but possibly more elsewhere)...
https://github.com/search?q=ProtocolsForObjectFunc&type=code
Can we leave the existing function as-is and create a new one with the new behavior?
Perhaps mark the old one as deprecated, with an explanation that it doesn't support multiple protocols per port, and that code should use the new function instead?
As far as I can see, integration test failure is real. |
Yes, the best way is to complete the bug repair with the least code For example, I can roll back the changes to the portname, which will reduce the number of changes, but this will result in inconsistent portname naming. For example, for public method extraction, I can roll back this part and only modify the required part, but it will be difficult to maintain. For the same logic code, modify and maintain multiple copies. @ardaguclu If you need to do so, please let me know at any time, and it will be rolled back |
The Kubernetes project currently lacks enough contributors to adequately respond to all PRs. This bot triages PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
/remove-lifecycle stale |
/pin @brianpursley |
/ping @brianpursley @ardaguclu |
expected: map[string][]string{"101": {"TCP"}}, | ||
}, | ||
{ | ||
name: "unsupported object", |
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.
Does portsforobject
also return expectErr
true?
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
This is the code for portsforobject
func portsForObject(object runtime.Object) ([]string, error) {
switch t := object.(type) {
case *corev1.ReplicationController:
return getPorts(t.Spec.Template.Spec), nil
case *corev1.Pod:
return getPorts(t.Spec), nil
case *corev1.Service:
return getServicePorts(t.Spec), nil
case *extensionsv1beta1.Deployment:
return getPorts(t.Spec.Template.Spec), nil
case *appsv1.Deployment:
return getPorts(t.Spec.Template.Spec), nil
case *appsv1beta2.Deployment:
return getPorts(t.Spec.Template.Spec), nil
case *appsv1beta1.Deployment:
return getPorts(t.Spec.Template.Spec), nil
case *extensionsv1beta1.ReplicaSet:
return getPorts(t.Spec.Template.Spec), nil
case *appsv1.ReplicaSet:
return getPorts(t.Spec.Template.Spec), nil
case *appsv1beta2.ReplicaSet:
return getPorts(t.Spec.Template.Spec), nil
default:
return nil, fmt.Errorf("cannot extract ports from %T", object)
}
}
for _, port := range container.Ports { | ||
// Empty protocol must be defaulted (TCP) | ||
if len(port.Protocol) == 0 { | ||
port.Protocol = corev1.ProtocolTCP |
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.
Although port.Protocol
is value type(it looks safe), I think, we should avoid such assignments to objects inside corev1.PodSpec
.
Instead, I'd rather prefer;
protocol := corev1.ProtocolTCP
if len(port.Protocol) > 0 {
protocol = port.Protocol
}
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.
@ardaguclu done
for _, servicePort := range spec.Ports { | ||
// Empty protocol must be defaulted (TCP) | ||
if len(servicePort.Protocol) == 0 { | ||
servicePort.Protocol = corev1.ProtocolTCP |
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.
same above
Fixed: kubernetes#114402 Signed-off-by: aimuz <mr.imuz@gmail.com>
Thanks @aimuz /lgtm I'm deferring to @brianpursley for last approval, if he wants to check. |
LGTM label has been added. Git tree hash: c399785bd6ad0c6770a0bab6a2abd7a85a4f843f
|
/pin @brianpursley Do you have time for a code review, thank you |
great 👏 |
/hold cancel |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: aimuz, ardaguclu 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 |
Thank you all for your hard work! |
Does this need to be Cherry-picked to another branch? |
Fixed: #114402
Signed-off-by: aimuz mr.imuz@gmail.com
What type of PR is this?
/kind bug
What this PR does / why we need it:
Which issue(s) this PR fixes:
Fixes #114402
Special notes for your reviewer:
Does this PR introduce a user-facing change?
Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.: