Skip to content

Commit 635989c

Browse files
committed
TargetConfigReconciler: extend TestSync with a condition check for DevKubeVirtRelieveAndMigrate operator profile
1 parent 2d87a5d commit 635989c

File tree

1 file changed

+125
-83
lines changed

1 file changed

+125
-83
lines changed

pkg/operator/target_config_reconciler_test.go

Lines changed: 125 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/google/go-cmp/cmp"
1111
configv1 "github.com/openshift/api/config/v1"
12+
operatorv1 "github.com/openshift/api/operator/v1"
1213
routev1 "github.com/openshift/api/route/v1"
1314
"github.com/openshift/library-go/pkg/operator/events"
1415
appsv1 "k8s.io/api/apps/v1"
@@ -30,7 +31,8 @@ import (
3031
fakeroutev1client "github.com/openshift/client-go/route/clientset/versioned/fake"
3132
routev1informers "github.com/openshift/client-go/route/informers/externalversions"
3233
deschedulerv1 "github.com/openshift/cluster-kube-descheduler-operator/pkg/apis/descheduler/v1"
33-
operatorconfigclient "github.com/openshift/cluster-kube-descheduler-operator/pkg/generated/clientset/versioned/fake"
34+
operatorconfigclient "github.com/openshift/cluster-kube-descheduler-operator/pkg/generated/clientset/versioned"
35+
operatorconfigclientfake "github.com/openshift/cluster-kube-descheduler-operator/pkg/generated/clientset/versioned/fake"
3436
operatorclientinformers "github.com/openshift/cluster-kube-descheduler-operator/pkg/generated/informers/externalversions"
3537
"github.com/openshift/cluster-kube-descheduler-operator/pkg/operator/operatorclient"
3638
bindata "github.com/openshift/cluster-kube-descheduler-operator/pkg/operator/testdata"
@@ -56,12 +58,55 @@ var configHighNodeUtilization = &configv1.Scheduler{
5658
},
5759
}
5860

61+
func initTargetConfigReconciler(ctx context.Context, kubeClientObjects, configObjects, routesObjects, deschedulerObjects []runtime.Object) (*TargetConfigReconciler, operatorconfigclient.Interface) {
62+
fakeKubeClient := fake.NewSimpleClientset(kubeClientObjects...)
63+
operatorConfigClient := operatorconfigclientfake.NewSimpleClientset(deschedulerObjects...)
64+
operatorConfigInformers := operatorclientinformers.NewSharedInformerFactory(operatorConfigClient, 10*time.Minute)
65+
deschedulerClient := &operatorclient.DeschedulerClient{
66+
Ctx: ctx,
67+
SharedInformer: operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers().Informer(),
68+
OperatorClient: operatorConfigClient.KubedeschedulersV1(),
69+
}
70+
openshiftConfigClient := fakeconfigv1client.NewSimpleClientset(configObjects...)
71+
configInformers := configv1informers.NewSharedInformerFactory(openshiftConfigClient, 10*time.Minute)
72+
openshiftRouteClient := fakeroutev1client.NewSimpleClientset(routesObjects...)
73+
routeInformers := routev1informers.NewSharedInformerFactory(openshiftRouteClient, 10*time.Minute)
74+
coreInformers := coreinformers.NewSharedInformerFactory(fakeKubeClient, 10*time.Minute)
75+
scheme := runtime.NewScheme()
76+
77+
targetConfigReconciler := NewTargetConfigReconciler(
78+
ctx,
79+
"RELATED_IMAGE_OPERAND_IMAGE",
80+
"RELATED_IMAGE_SOFTTAINTER_IMAGE",
81+
operatorConfigClient.KubedeschedulersV1(),
82+
operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers(),
83+
deschedulerClient,
84+
fakeKubeClient,
85+
dynamicfake.NewSimpleDynamicClient(scheme),
86+
configInformers,
87+
routeInformers,
88+
coreInformers,
89+
NewFakeRecorder(1024),
90+
)
91+
92+
operatorConfigInformers.Start(ctx.Done())
93+
configInformers.Start(ctx.Done())
94+
routeInformers.Start(ctx.Done())
95+
coreInformers.Start(ctx.Done())
96+
97+
operatorConfigInformers.WaitForCacheSync(ctx.Done())
98+
configInformers.WaitForCacheSync(ctx.Done())
99+
routeInformers.WaitForCacheSync(ctx.Done())
100+
coreInformers.WaitForCacheSync(ctx.Done())
101+
102+
return targetConfigReconciler, operatorConfigClient
103+
}
104+
59105
func TestManageConfigMap(t *testing.T) {
60106
fm, _ := time.ParseDuration("5m")
61107
fiveMinutes := metav1.Duration{Duration: fm}
62108
priority := int32(1000)
63109

64-
fakeRecorder := NewFakeRecorder(1024)
65110
tests := []struct {
66111
name string
67112
schedulerConfig *configv1.Scheduler
@@ -816,47 +861,8 @@ func TestManageConfigMap(t *testing.T) {
816861

817862
ctx, cancelFunc := context.WithCancel(context.TODO())
818863
defer cancelFunc()
819-
operatorConfigClient := operatorconfigclient.NewSimpleClientset()
820-
operatorConfigInformers := operatorclientinformers.NewSharedInformerFactory(operatorConfigClient, 10*time.Minute)
821-
deschedulerClient := &operatorclient.DeschedulerClient{
822-
Ctx: ctx,
823-
SharedInformer: operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers().Informer(),
824-
OperatorClient: operatorConfigClient.KubedeschedulersV1(),
825-
}
826-
fakeKubeClient := fake.NewSimpleClientset(objects...)
827-
828-
openshiftConfigClient := fakeconfigv1client.NewSimpleClientset(tt.schedulerConfig)
829-
configInformers := configv1informers.NewSharedInformerFactory(openshiftConfigClient, 10*time.Minute)
830-
openshiftRouteClient := fakeroutev1client.NewSimpleClientset(tt.routes...)
831-
routeInformers := routev1informers.NewSharedInformerFactory(openshiftRouteClient, 10*time.Minute)
832-
coreInformers := coreinformers.NewSharedInformerFactory(fakeKubeClient, 10*time.Minute)
833-
834-
scheme := runtime.NewScheme()
835-
836-
targetConfigReconciler := NewTargetConfigReconciler(
837-
ctx,
838-
"RELATED_IMAGE_OPERAND_IMAGE",
839-
"RELATED_IMAGE_SOFTTAINTER_IMAGE",
840-
operatorConfigClient.KubedeschedulersV1(),
841-
operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers(),
842-
deschedulerClient,
843-
fakeKubeClient,
844-
dynamicfake.NewSimpleDynamicClient(scheme),
845-
configInformers,
846-
routeInformers,
847-
coreInformers,
848-
fakeRecorder,
849-
)
850864

851-
operatorConfigInformers.Start(ctx.Done())
852-
configInformers.Start(ctx.Done())
853-
routeInformers.Start(ctx.Done())
854-
coreInformers.Start(ctx.Done())
855-
856-
operatorConfigInformers.WaitForCacheSync(ctx.Done())
857-
configInformers.WaitForCacheSync(ctx.Done())
858-
routeInformers.WaitForCacheSync(ctx.Done())
859-
coreInformers.WaitForCacheSync(ctx.Done())
865+
targetConfigReconciler, _ := initTargetConfigReconciler(ctx, objects, []runtime.Object{tt.schedulerConfig}, tt.routes, nil)
860866

861867
got, forceDeployment, err := targetConfigReconciler.manageConfigMap(tt.descheduler)
862868
if tt.err != nil {
@@ -1067,7 +1073,6 @@ func TestManageDeployment(t *testing.T) {
10671073
func TestManageSoftTainterDeployment(t *testing.T) {
10681074
ctx, cancelFunc := context.WithCancel(context.TODO())
10691075
defer cancelFunc()
1070-
fakeRecorder := NewFakeRecorder(1024)
10711076
expectedSoftTainterDeployment := &appsv1.Deployment{
10721077
TypeMeta: metav1.TypeMeta{APIVersion: "apps/v1", Kind: "Deployment"},
10731078
ObjectMeta: metav1.ObjectMeta{
@@ -1327,45 +1332,8 @@ func TestManageSoftTainterDeployment(t *testing.T) {
13271332

13281333
for _, tt := range tests {
13291334
t.Run(tt.name, func(t *testing.T) {
1330-
fakeKubeClient := fake.NewSimpleClientset(tt.objects...)
1331-
operatorConfigClient := operatorconfigclient.NewSimpleClientset()
1332-
operatorConfigInformers := operatorclientinformers.NewSharedInformerFactory(operatorConfigClient, 10*time.Minute)
1333-
deschedulerClient := &operatorclient.DeschedulerClient{
1334-
Ctx: ctx,
1335-
SharedInformer: operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers().Informer(),
1336-
OperatorClient: operatorConfigClient.KubedeschedulersV1(),
1337-
}
1338-
openshiftConfigClient := fakeconfigv1client.NewSimpleClientset()
1339-
configInformers := configv1informers.NewSharedInformerFactory(openshiftConfigClient, 10*time.Minute)
1340-
openshiftRouteClient := fakeroutev1client.NewSimpleClientset()
1341-
routeInformers := routev1informers.NewSharedInformerFactory(openshiftRouteClient, 10*time.Minute)
1342-
coreInformers := coreinformers.NewSharedInformerFactory(fakeKubeClient, 10*time.Minute)
1343-
scheme := runtime.NewScheme()
1344-
1345-
targetConfigReconciler := NewTargetConfigReconciler(
1346-
ctx,
1347-
"RELATED_IMAGE_OPERAND_IMAGE",
1348-
"RELATED_IMAGE_SOFTTAINTER_IMAGE",
1349-
operatorConfigClient.KubedeschedulersV1(),
1350-
operatorConfigInformers.Kubedeschedulers().V1().KubeDeschedulers(),
1351-
deschedulerClient,
1352-
fakeKubeClient,
1353-
dynamicfake.NewSimpleDynamicClient(scheme),
1354-
configInformers,
1355-
routeInformers,
1356-
coreInformers,
1357-
fakeRecorder,
1358-
)
1359-
1360-
operatorConfigInformers.Start(ctx.Done())
1361-
configInformers.Start(ctx.Done())
1362-
routeInformers.Start(ctx.Done())
1363-
coreInformers.Start(ctx.Done())
13641335

1365-
operatorConfigInformers.WaitForCacheSync(ctx.Done())
1366-
configInformers.WaitForCacheSync(ctx.Done())
1367-
routeInformers.WaitForCacheSync(ctx.Done())
1368-
coreInformers.WaitForCacheSync(ctx.Done())
1336+
targetConfigReconciler, _ := initTargetConfigReconciler(ctx, tt.objects, nil, nil, nil)
13691337

13701338
enabled, err := targetConfigReconciler.isSoftTainterNeeded(tt.descheduler)
13711339
if err != nil {
@@ -1401,6 +1369,7 @@ func TestSync(t *testing.T) {
14011369
targetConfigReconciler *TargetConfigReconciler
14021370
descheduler *deschedulerv1.KubeDescheduler
14031371
err error
1372+
condition *operatorv1.OperatorCondition
14041373
}{
14051374
{
14061375
name: "Invalid priority threshold configuration",
@@ -1425,12 +1394,63 @@ func TestSync(t *testing.T) {
14251394
},
14261395
err: fmt.Errorf("It is invalid to set both .spec.profileCustomizations.thresholdPriority and .spec.profileCustomizations.ThresholdPriorityClassName fields"),
14271396
},
1397+
{
1398+
name: "TargetConfigControllerDegraded kubevirt not deployed with RelieveAndMigrate profile",
1399+
targetConfigReconciler: &TargetConfigReconciler{
1400+
ctx: context.TODO(),
1401+
kubeClient: fake.NewSimpleClientset(),
1402+
eventRecorder: fakeRecorder,
1403+
configSchedulerLister: &fakeSchedConfigLister{
1404+
Items: map[string]*configv1.Scheduler{"cluster": configLowNodeUtilization},
1405+
},
1406+
},
1407+
descheduler: &deschedulerv1.KubeDescheduler{
1408+
TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: "KubeDescheduler"},
1409+
ObjectMeta: metav1.ObjectMeta{
1410+
Name: operatorclient.OperatorConfigName,
1411+
Namespace: operatorclient.OperatorNamespace,
1412+
},
1413+
Spec: deschedulerv1.KubeDeschedulerSpec{
1414+
DeschedulingIntervalSeconds: utilptr.To[int32](10),
1415+
Profiles: []deschedulerv1.DeschedulerProfile{deschedulerv1.RelieveAndMigrate},
1416+
ProfileCustomizations: &deschedulerv1.ProfileCustomizations{},
1417+
},
1418+
},
1419+
condition: &operatorv1.OperatorCondition{
1420+
Type: "TargetConfigControllerDegraded",
1421+
Status: operatorv1.ConditionTrue,
1422+
Reason: fmt.Sprintf("profile %v can only be used when KubeVirt is properly deployed", deschedulerv1.RelieveAndMigrate),
1423+
},
1424+
},
14281425
}
14291426

14301427
for _, tt := range tests {
14311428
t.Run(tt.name, func(t *testing.T) {
1432-
tt.targetConfigReconciler.operatorClient = operatorconfigclient.NewSimpleClientset(tt.descheduler).KubedeschedulersV1()
1433-
err := tt.targetConfigReconciler.sync()
1429+
1430+
ctx := context.TODO()
1431+
1432+
targetConfigReconciler, operatorClient := initTargetConfigReconciler(
1433+
ctx,
1434+
[]runtime.Object{
1435+
&appsv1.Deployment{
1436+
ObjectMeta: metav1.ObjectMeta{
1437+
Name: operatorclient.OperandName,
1438+
Namespace: operatorclient.OperatorNamespace,
1439+
},
1440+
Spec: appsv1.DeploymentSpec{
1441+
Replicas: utilptr.To[int32](1),
1442+
Template: corev1.PodTemplateSpec{
1443+
Spec: corev1.PodSpec{},
1444+
},
1445+
},
1446+
},
1447+
},
1448+
[]runtime.Object{configLowNodeUtilization},
1449+
nil,
1450+
[]runtime.Object{tt.descheduler},
1451+
)
1452+
1453+
err := targetConfigReconciler.sync()
14341454
if tt.err != nil {
14351455
if err == nil {
14361456
t.Fatalf("Expected error, not nil\n")
@@ -1443,6 +1463,28 @@ func TestSync(t *testing.T) {
14431463
if err != nil {
14441464
t.Fatalf("Unexpected error: %v\n", err)
14451465
}
1466+
if tt.condition != nil {
1467+
kubeDeschedulerObj, err := operatorClient.KubedeschedulersV1().KubeDeschedulers(operatorclient.OperatorNamespace).Get(ctx, operatorclient.OperatorConfigName, metav1.GetOptions{})
1468+
if err != nil {
1469+
t.Fatalf("Unable to get kubedescheduler object: %v", err)
1470+
}
1471+
found := false
1472+
for _, condition := range kubeDeschedulerObj.Status.Conditions {
1473+
if condition.Type == tt.condition.Type {
1474+
found = true
1475+
if condition.Status != tt.condition.Status {
1476+
t.Fatalf("Expected %q condition status to be %v, got %v instead", condition.Type, tt.condition.Status, condition.Status)
1477+
}
1478+
if condition.Reason != tt.condition.Reason {
1479+
t.Fatalf("Expected %q condition reason to be %q, got %q instead", condition.Type, tt.condition.Reason, condition.Reason)
1480+
}
1481+
break
1482+
}
1483+
}
1484+
if !found {
1485+
t.Fatalf("Unable to find %q condition in the kubedescheduler's status", tt.condition.Type)
1486+
}
1487+
}
14461488
})
14471489
}
14481490
}

0 commit comments

Comments
 (0)