kubectl: add test coverage for cordon command (#129202)

* kubectl: add test coverage for cordon command

Signed-off-by: Omer Aplatony <omerap12@gmail.com>

* using cmp.Diff

Signed-off-by: Omer Aplatony <omerap12@gmail.com>

---------

Signed-off-by: Omer Aplatony <omerap12@gmail.com>

Kubernetes-commit: 3ec97a445f036a38bfec6291dee661954138bac9
This commit is contained in:
Omer Aplatony 2024-12-17 07:30:51 +02:00 committed by Kubernetes Publisher
parent 088003e485
commit 120105a0a9
3 changed files with 150 additions and 3 deletions

2
go.mod
View File

@ -34,7 +34,7 @@ require (
k8s.io/api v0.0.0-20241214014715-eac45518d7fe
k8s.io/apimachinery v0.0.0-20241214014415-767f17a6afea
k8s.io/cli-runtime v0.0.0-20241214022530-e4532273187e
k8s.io/client-go v0.0.0-20241214015128-61ee2c5802c7
k8s.io/client-go v0.0.0-20241215015103-67da6d1a4174
k8s.io/component-base v0.0.0-20241214020124-b7fbd0d55e44
k8s.io/component-helpers v0.0.0-20241214020249-81a0289f4873
k8s.io/klog/v2 v2.130.1

4
go.sum
View File

@ -206,8 +206,8 @@ k8s.io/apimachinery v0.0.0-20241214014415-767f17a6afea h1:ZUHj/k511rdZLx69atS9F5
k8s.io/apimachinery v0.0.0-20241214014415-767f17a6afea/go.mod h1:vmecNW2HWfNZboIXS3Vg/3qp+T42YyW6jCpcdhnas9s=
k8s.io/cli-runtime v0.0.0-20241214022530-e4532273187e h1:Ie/aQEIDo9fPuITJKm5xetW+8JGsD8Zvj7Zm63urQWw=
k8s.io/cli-runtime v0.0.0-20241214022530-e4532273187e/go.mod h1:zBvvuqEnbfCG7dmlroXrfVhDrCGEtz7MfknRnmp8Kpg=
k8s.io/client-go v0.0.0-20241214015128-61ee2c5802c7 h1:W2NxcoEN3y/P48IBQdJgBj2nWlU+dyXvRQKjRYdV6y8=
k8s.io/client-go v0.0.0-20241214015128-61ee2c5802c7/go.mod h1:9DOj9Eg/2wdCibOBBR8J+SamkzoU+TVr9bk5B7KAbgM=
k8s.io/client-go v0.0.0-20241215015103-67da6d1a4174 h1:NcD7ZRs38+ChK6qTJN5ahkVq7MWuNaZZiO1AspZLwck=
k8s.io/client-go v0.0.0-20241215015103-67da6d1a4174/go.mod h1:9DOj9Eg/2wdCibOBBR8J+SamkzoU+TVr9bk5B7KAbgM=
k8s.io/component-base v0.0.0-20241214020124-b7fbd0d55e44 h1:UGwTOasY4f/2bmwNlInBJjkhZw3lWGy+gk+w5tQOAvc=
k8s.io/component-base v0.0.0-20241214020124-b7fbd0d55e44/go.mod h1:u4F22/ZnzBZX8Sw10wXHts7D9Ak81nBSrbdckaDcvjE=
k8s.io/component-helpers v0.0.0-20241214020249-81a0289f4873 h1:xoV3np7eRxerPwLtt56i6mpBTXVDQa1HLMZFJINO9Cc=

147
pkg/drain/cordon_test.go Normal file
View File

@ -0,0 +1,147 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package drain
import (
"testing"
"github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
type newCordonHelperFromRuntimeObjectTestCase struct {
name string
nodeObject runtime.Object
expectError bool
expected *CordonHelper
}
func TestNewCordonHelperFromRuntimeObject(t *testing.T) {
tests := []newCordonHelperFromRuntimeObjectTestCase{
{
name: "valid node object",
nodeObject: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "test-node",
},
},
expectError: false,
expected: &CordonHelper{
node: &corev1.Node{
TypeMeta: metav1.TypeMeta{
Kind: "Node",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-node",
},
},
},
},
{
name: "invalid object type",
nodeObject: &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "test-pod",
},
},
expectError: true,
expected: nil,
},
}
scheme := runtime.NewScheme()
_ = corev1.AddToScheme(scheme)
gvk := schema.GroupVersionKind{
Group: "",
Version: "v1",
Kind: "Node",
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
helper, err := NewCordonHelperFromRuntimeObject(tt.nodeObject, scheme, gvk)
if tt.expectError && err == nil {
t.Error("Expected error but got none")
}
if !tt.expectError && err != nil {
t.Errorf("Unexpected error: %v", err)
}
if !tt.expectError && helper == nil {
t.Error("Expected non-nil helper")
}
if tt.expected != nil && helper != nil {
if diff := cmp.Diff(tt.expected.node, helper.node); diff != "" {
t.Errorf("Node mismatch (-want +got):\n%s", diff)
}
}
})
}
}
type updateIfRequiredTestCase struct {
name string
currentState bool
desiredState bool
expectUpdated bool
}
func TestUpdateIfRequired(t *testing.T) {
tests := []updateIfRequiredTestCase{
{
name: "no change required",
currentState: true,
desiredState: true,
expectUpdated: false,
},
{
name: "update required - cordon",
currentState: false,
desiredState: true,
expectUpdated: true,
},
{
name: "update required - uncordon",
currentState: true,
desiredState: false,
expectUpdated: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
node := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "test-node",
},
Spec: corev1.NodeSpec{
Unschedulable: tt.currentState,
},
}
helper := NewCordonHelper(node)
updated := helper.UpdateIfRequired(tt.desiredState)
if updated != tt.expectUpdated {
t.Errorf("Expected UpdateIfRequired to return %v, got %v", tt.expectUpdated, updated)
}
if helper.desired != tt.desiredState {
t.Errorf("Expected desired state to be %v, got %v", tt.desiredState, helper.desired)
}
})
}
}