-
Notifications
You must be signed in to change notification settings - Fork 228
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
add support for minimumKubeletVersion #1831
add support for minimumKubeletVersion #1831
Conversation
21ccc58
to
10f3207
Compare
10f3207
to
2b2ffda
Compare
/retest |
1 similar comment
/retest |
2b2ffda
to
271a103
Compare
api changes merged, so this is ready |
} | ||
|
||
fieldPath := field.NewPath("spec", "minimumKubeletVersion") | ||
nodes, err := nodesGetter.Nodes().List(context.TODO(), metav1.ListOptions{}) |
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 this be made to accept the lister interface instead of the client interface? Listing all nodes as part of validating an API field is probably more expensive than we would like.
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.
updated!
de7feb4
to
d53287b
Compare
I dropped the field references and also I thought about it more and being opinonated about the of the nodes (node lister vs nodesGetter) began to feel weird so I now just have it taking a slice of nodes and the various callers can decide where to get them. left in a separate commit in case you liked it the old way @benluddy |
That's OK, but note that the items field in |
/retest |
699007c
to
d54530a
Compare
any other thoughts @benluddy ?? |
43e3c1e
to
e0b2031
Compare
if !apierrors.IsNotFound(err) { | ||
errs = append(errs, err) | ||
} else { // but raise a warning | ||
klog.Warningf("nodes.config.openshift.io/cluster object could not be found") |
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 would be pretty weird if it lasts very long. It's probably reasonable to emit a warning with the events.Recorder
so that it gets noticed. I see us doing that for similar cases in other config observers.
if !cmp.Equal(test.expectedObservedConfig, actualObservedConfig) { | ||
t.Fatalf("unexpected configuration, diff = %v", cmp.Diff(test.expectedObservedConfig, actualObservedConfig)) | ||
} |
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.
Nit, the contract of Diff(a, b) guarantees that it returns the empty string IFF Equal(a, b), so you can do:
if !cmp.Equal(test.expectedObservedConfig, actualObservedConfig) { | |
t.Fatalf("unexpected configuration, diff = %v", cmp.Diff(test.expectedObservedConfig, actualObservedConfig)) | |
} | |
if diff := cmp.Diff(test.expectedObservedConfig, actualObservedConfig); diff != "" { | |
t.Fatalf("unexpected configuration, diff = %v", diff) | |
} |
) | ||
|
||
// ValidateMinimumKubeletVersion takes a list of nodes and a currently set min version. | ||
// It parsees the min version and iterates through the nodes, comparing the version of the kubelets |
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 parsees the min version and iterates through the nodes, comparing the version of the kubelets | |
// It parses the min version and iterates through the nodes, comparing the version of the kubelets |
e0b2031
to
31c75c3
Compare
/lgtm |
6990d22
to
12c30bb
Compare
/retest |
/lgtm |
12c30bb
to
a050054
Compare
@benluddy sorry for the churn, but I've updated the Is*TooOld functions to only return an error (and a specific one if the node is too old) so callers can only check one value (most were anyway, and openshift/kubernetes#2104 (comment) lead me in that direction) |
a050054
to
4f2e854
Compare
pkg/operator/configobserver/node/observe_minimum_kubelet_version.go
Outdated
Show resolved
Hide resolved
if !apierrors.IsNotFound(err) { | ||
errs = append(errs, err) | ||
} else { // but raise a warning | ||
recorder.Warningf("ObserveMinimumKubeletVersion", "nodes.%s/cluster not found", configv1.GroupName) |
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.
How often will the observer be called? If the node cluster object is not found, won't this cause event spam?
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.
Important question, although I see this being done in the other observers as well. I think we never reach this code patch because by the time observers start running, these objects are always available.
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 would remove the event recording. Fabio is right, the resource is always present. When it isn’t, we will have more issues.
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.
removed!
pkg/operator/configobserver/node/observe_minimum_kubelet_version.go
Outdated
Show resolved
Hide resolved
// ParseKubeletVersion parses it into a semver.Version object, stripping | ||
// any information in the version that isn't "major.minor.patch". | ||
func ParseKubeletVersion(kubeletVersion string) (*semver.Version, error) { | ||
version, err := semver.Parse(strings.TrimPrefix(kubeletVersion, "v")) |
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 there is no test case that prefixes the version with v
.
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.
added that to all the tests, because kubelet will always send with a v afaict
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.
Added a few comments, but overall LGTM. I'll let the final tag for Lukasz.
/approve
// we got an error so without the node object we are not able to determine minimumKubeletVersion | ||
if err != nil { | ||
// if config/v1/node/cluster object is not found, that can be treated as a non-error case | ||
if !apierrors.IsNotFound(err) { |
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.
nit:
if apierrors.IsNotFound(err) {
(...)
}
if err != nil {
(...)
}
is easier to read
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 reordered the cases but left the else
because adding an additional return didn't look any better
if !apierrors.IsNotFound(err) { | ||
errs = append(errs, err) | ||
} else { // but raise a warning | ||
recorder.Warningf("ObserveMinimumKubeletVersion", "nodes.%s/cluster not found", configv1.GroupName) |
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.
Important question, although I see this being done in the other observers as well. I think we never reach this code patch because by the time observers start running, these objects are always available.
pkg/operator/configobserver/node/observe_minimum_kubelet_version.go
Outdated
Show resolved
Hide resolved
pkg/operator/configobserver/node/observe_minimum_kubelet_version_test.go
Outdated
Show resolved
Hide resolved
// node is older than min version. | ||
// When the node is too old, it returns the error ErrKubeletOutdated. If a different error occurs, an error is returned. | ||
// If the node is new enough and no error happens, nil is returned. | ||
func IsNodeTooOld(node *corev1.Node, minVersion *semver.Version) 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.
Do we actually need this function? Currently it does the same thing as IsKubeletVerisionTooOld, just with a different signature.
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 thouht it was cleaner than needing to make a fake node object in openshift/hypershift#4980 (where we just pass around the lowest kubelet version in the hosted cluster)
3396de1
to
512a9b6
Compare
thanks @bertinatto and @p0lyn0mial ! I have updated / addressed your comments, PTAL again :) |
if !apierrors.IsNotFound(err) { | ||
errs = append(errs, err) | ||
} else { // but raise a warning | ||
recorder.Warningf("ObserveMinimumKubeletVersion", "nodes.%s/cluster not found", configv1.GroupName) |
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 would remove the event recording. Fabio is right, the resource is always present. When it isn’t, we will have more issues.
pkg/operator/configobserver/node/observe_minimum_kubelet_version_test.go
Show resolved
Hide resolved
I left a few suggestions, but overall, this PR looks great, thanks! |
512a9b6
to
e3952f3
Compare
Signed-off-by: Peter Hunt <[email protected]>
Signed-off-by: Peter Hunt <[email protected]>
Signed-off-by: Peter Hunt <[email protected]>
e3952f3
to
6f09d18
Compare
@haircommander: all tests passed! Full PR test history. Your PR dashboard. 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-sigs/prow repository. I understand the commands that are listed here. |
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.
Left a few more suggestions that can be addressed in a new PR.
/lgtm
name string | ||
version string | ||
shouldReject bool | ||
tooOld 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.
unused, can be removed.
err := ValidateMinimumKubeletVersion(testCase.nodes, testCase.version) | ||
assert.Equal(t, testCase.shouldReject, err != nil, "minimum kubelet version %q %s rejected", testCase.version, shouldStr) | ||
|
||
if testCase.shouldReject { |
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 would remove testCase.shouldReject
as well and update the code to:
if err == nil && scenario.expectedError != nil {
t.Fatal("expected to get an error")
}
if err != nil && scenario.expectedError == nil {
t.Fatal(err) // unexpected error
}
if err != nil && scenario.expectedError != nil {
if err.Error() != scenario.expectedError.Error() {
t.Fatalf("unexpected error = %v, expected = %v", err, scenario.expectedError)
}
if strings.Contains(err.Error(), ErrKubeletOutdated.Error()) {
assert.True(t, errors.Is(err, ErrKubeletOutdated), "error message should be ErrKubeletOutdated"
}
}
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: benluddy, bertinatto, haircommander, p0lyn0mial 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 |
carrying openshift/api#2059