Skip to content
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

Merged

Conversation

haircommander
Copy link
Member

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 11, 2024
@openshift-ci openshift-ci bot requested review from deads2k and harche October 11, 2024 20:45
@haircommander haircommander force-pushed the min-kubelet-version branch 3 times, most recently from 21ccc58 to 10f3207 Compare October 18, 2024 16:32
@haircommander
Copy link
Member Author

/retest

1 similar comment
@haircommander
Copy link
Member Author

/retest

@haircommander haircommander changed the title WIP: add support for minimumKubeletVersion add support for minimumKubeletVersion Nov 4, 2024
@haircommander
Copy link
Member Author

api changes merged, so this is ready

@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 4, 2024
}

fieldPath := field.NewPath("spec", "minimumKubeletVersion")
nodes, err := nodesGetter.Nodes().List(context.TODO(), metav1.ListOptions{})
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated!

@haircommander haircommander force-pushed the min-kubelet-version branch 2 times, most recently from de7feb4 to d53287b Compare November 4, 2024 17:23
@haircommander
Copy link
Member Author

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

@benluddy
Copy link
Contributor

benluddy commented Nov 4, 2024

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 NodeList has type []Node, not []*Node, so the caller would have to transform one to the other anyway.

@haircommander
Copy link
Member Author

/retest

@haircommander
Copy link
Member Author

any other thoughts @benluddy ??

@haircommander haircommander force-pushed the min-kubelet-version branch 2 times, most recently from 43e3c1e to e0b2031 Compare November 5, 2024 22:03
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")
Copy link
Contributor

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.

Comment on lines 73 to 77
if !cmp.Equal(test.expectedObservedConfig, actualObservedConfig) {
t.Fatalf("unexpected configuration, diff = %v", cmp.Diff(test.expectedObservedConfig, actualObservedConfig))
}
Copy link
Contributor

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:

Suggested change
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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

@benluddy
Copy link
Contributor

/lgtm

@haircommander
Copy link
Member Author

/retest

@benluddy
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Nov 18, 2024
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Nov 19, 2024
@haircommander
Copy link
Member Author

@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)

if !apierrors.IsNotFound(err) {
errs = append(errs, err)
} else { // but raise a warning
recorder.Warningf("ObserveMinimumKubeletVersion", "nodes.%s/cluster not found", configv1.GroupName)
Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed!

pkg/config/node/minimum_kubelet_version.go Outdated Show resolved Hide resolved
pkg/config/node/minimum_kubelet_version.go Outdated Show resolved Hide resolved
pkg/config/node/minimum_kubelet_version.go Outdated Show resolved Hide resolved
pkg/config/node/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"))
Copy link
Contributor

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.

Copy link
Member Author

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

Copy link
Member

@bertinatto bertinatto left a 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) {
Copy link
Member

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

Copy link
Member Author

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)
Copy link
Member

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/config/node/minimum_kubelet_version.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 {
Copy link
Member

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.

Copy link
Member Author

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)

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Nov 20, 2024
@haircommander haircommander force-pushed the min-kubelet-version branch 2 times, most recently from 3396de1 to 512a9b6 Compare November 20, 2024 14:55
@haircommander
Copy link
Member Author

thanks @bertinatto and @p0lyn0mial ! I have updated / addressed your comments, PTAL again :)

pkg/config/node/minimum_kubelet_version_test.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)
Copy link
Contributor

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.

@p0lyn0mial
Copy link
Contributor

I left a few suggestions, but overall, this PR looks great, thanks!

Copy link
Contributor

openshift-ci bot commented Nov 21, 2024

@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.

Copy link
Contributor

@p0lyn0mial p0lyn0mial left a 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
Copy link
Contributor

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 {
Copy link
Contributor

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"			 
  }
}

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Nov 22, 2024
Copy link
Contributor

openshift-ci bot commented Nov 22, 2024

[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:
  • OWNERS [bertinatto,p0lyn0mial]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot openshift-merge-bot bot merged commit c450187 into openshift:master Nov 22, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants