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 unit tests for version compatibility check #1096

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions pkg/descheduler/descheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ package descheduler

import (
"context"
"errors"
"fmt"
"math"
"strconv"
"strings"
"time"

"k8s.io/client-go/discovery"
componentbaseconfig "k8s.io/component-base/config"
"k8s.io/klog/v2"

Expand Down Expand Up @@ -76,7 +78,9 @@ func Run(ctx context.Context, rs *options.DeschedulerServer) error {
}

// Add k8s compatibility warnings to logs
versionCompatibilityCheck(rs)
if err := validateVersionCompatibility(rs.Client.Discovery(), version.Get()); err != nil {
klog.Warning(err.Error())
}

evictionPolicyGroupVersion, err := eutils.SupportEviction(rs.Client)
if err != nil || len(evictionPolicyGroupVersion) == 0 {
Expand All @@ -92,7 +96,7 @@ func Run(ctx context.Context, rs *options.DeschedulerServer) error {
}

if rs.LeaderElection.LeaderElect && rs.DryRun {
klog.V(1).InfoS("Warning: DryRun is set to True. You need to disable it to use Leader Election.")
klog.V(1).Info("Warning: DryRun is set to True. You need to disable it to use Leader Election.")
}

if rs.LeaderElection.LeaderElect && !rs.DryRun {
Expand All @@ -105,27 +109,34 @@ func Run(ctx context.Context, rs *options.DeschedulerServer) error {
return runFn()
}

func versionCompatibilityCheck(rs *options.DeschedulerServer) {
serverVersion, serverErr := rs.Client.Discovery().ServerVersion()
func validateVersionCompatibility(discovery discovery.DiscoveryInterface, versionInfo version.Info) error {
serverVersion, serverErr := discovery.ServerVersion()
if serverErr != nil {
klog.V(1).InfoS("Warning: Get Kubernetes server version fail")
return
return errors.New("failed to get Kubernetes server version")
}

deschedulerMinorVersion := strings.Split(version.Get().Minor, ".")[0]
deschedulerMinorVersion := strings.Split(versionInfo.Minor, ".")[0]
deschedulerMinorVersionFloat, err := strconv.ParseFloat(deschedulerMinorVersion, 64)
if err != nil {
klog.Warning("Warning: Convert Descheduler minor version to float fail")
return errors.New("failed to convert Descheduler minor version to float")
}

kubernetesMinorVersionFloat, err := strconv.ParseFloat(serverVersion.Minor, 64)
if err != nil {
klog.Warning("Warning: Convert Kubernetes server minor version to float fail")
return errors.New("failed to convert Kubernetes server minor version to float")
}

if math.Abs(deschedulerMinorVersionFloat-kubernetesMinorVersionFloat) > 3 {
klog.Warningf("Warning: Descheduler minor version %v is not supported on your version of Kubernetes %v.%v. See compatibility docs for more info: https://github.com/kubernetes-sigs/descheduler#compatibility-matrix", deschedulerMinorVersion, serverVersion.Major, serverVersion.Minor)
return fmt.Errorf(
"descheduler minor version %v is not supported on your version of Kubernetes %v.%v. "+
"See compatibility docs for more info: https://github.com/kubernetes-sigs/descheduler#compatibility-matrix",
deschedulerMinorVersion,
serverVersion.Major,
serverVersion.Minor,
)
}

return nil
}

func cachedClient(
Expand Down
58 changes: 58 additions & 0 deletions pkg/descheduler/descheduler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
apiversion "k8s.io/apimachinery/pkg/version"
fakediscovery "k8s.io/client-go/discovery/fake"
fakeclientset "k8s.io/client-go/kubernetes/fake"
core "k8s.io/client-go/testing"
"sigs.k8s.io/descheduler/cmd/descheduler/app/options"
Expand All @@ -20,6 +22,7 @@ import (
"sigs.k8s.io/descheduler/pkg/framework/plugins/defaultevictor"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removeduplicates"
"sigs.k8s.io/descheduler/pkg/framework/plugins/removepodsviolatingnodetaints"
deschedulerversion "sigs.k8s.io/descheduler/pkg/version"
"sigs.k8s.io/descheduler/test"
)

Expand Down Expand Up @@ -245,6 +248,61 @@ func TestRootCancelWithNoInterval(t *testing.T) {
}
}

func TestValidateVersionCompatibility(t *testing.T) {
type testCase struct {
name string
deschedulerMinor string
serverMinor string
expectError bool
}
testCases := []testCase{
{
name: "no error when descheduler minor equals to server minor",
deschedulerMinor: "26.0",
serverMinor: "26",
expectError: false,
},
{
name: "no error when descheduler minor is 3 behind server minor",
deschedulerMinor: "23.0",
serverMinor: "26",
expectError: false,
},
{
name: "no error when descheduler minor is 3 ahead of server minor",
deschedulerMinor: "26.0",
serverMinor: "23",
expectError: false,
},
{
name: "error when descheduler minor is 4 behind server minor",
deschedulerMinor: "22.0",
serverMinor: "26",
expectError: true,
},
{
name: "error when descheduler minor is 4 ahead of server minor",
deschedulerMinor: "27.0",
serverMinor: "23",
expectError: true,
},
}
client := fakeclientset.NewSimpleClientset()
fakeDiscovery, _ := client.Discovery().(*fakediscovery.FakeDiscovery)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
fakeDiscovery.FakedServerVersion = &apiversion.Info{Major: "1", Minor: tc.serverMinor}
deschedulerVersion := deschedulerversion.Info{Major: "0", Minor: tc.deschedulerMinor}
err := validateVersionCompatibility(fakeDiscovery, deschedulerVersion)

hasError := err != nil
if tc.expectError != hasError {
t.Error("unexpected version compatibility behavior")
}
})
}
}

func podEvictionReactionFuc(evictedPods *[]string) func(action core.Action) (bool, runtime.Object, error) {
return func(action core.Action) (bool, runtime.Object, error) {
if action.GetSubresource() == "eviction" {
Expand Down