Skip to content

Commit 7310705

Browse files
ON-15452: Add more unit tests for "dirty" environments
Adds two new tests that ensure the operands are updated as expected (but not removed and re-added). Also adds a new type of test that adds a Node to the envtest cluster. These tests test how the controller handles starting when the operands and node labels might not be as expected.
1 parent dc95693 commit 7310705

File tree

1 file changed

+187
-17
lines changed

1 file changed

+187
-17
lines changed

controllers/onload_controller_test.go

+187-17
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,9 @@ var _ = Describe("Recovery from a non-clean state", func() {
861861
// General definitions for tests
862862
var (
863863
onload onloadv1alpha1.Onload
864+
devicePlugin appsv1.DaemonSet
864865
devicePluginName types.NamespacedName
866+
module kmm.Module
865867
)
866868

867869
BeforeEach(func() {
@@ -875,7 +877,7 @@ var _ = Describe("Recovery from a non-clean state", func() {
875877
},
876878
Spec: onloadv1alpha1.Spec{
877879
Selector: map[string]string{
878-
"key": "",
880+
"key": "value",
879881
},
880882
Onload: onloadv1alpha1.OnloadSpec{
881883
KernelMappings: []onloadv1alpha1.OnloadKernelMapping{
@@ -885,7 +887,7 @@ var _ = Describe("Recovery from a non-clean state", func() {
885887
},
886888
},
887889
UserImage: "image:tag",
888-
Version: "",
890+
Version: "old",
889891
},
890892
DevicePlugin: onloadv1alpha1.DevicePluginSpec{
891893
DevicePluginImage: "image:tag",
@@ -898,18 +900,9 @@ var _ = Describe("Recovery from a non-clean state", func() {
898900
Name: onload.Name + "-onload-device-plugin-ds",
899901
Namespace: onload.Namespace,
900902
}
901-
})
902-
903-
AfterEach(func() {
904-
cancel()
905-
err := testEnv.Stop()
906-
Expect(err).NotTo(HaveOccurred())
907-
})
908-
909-
It("shouldn't remove existing operands", func() {
910903

911904
dsLabels := map[string]string{"onload.amd.com/name": devicePluginName.Name}
912-
dp := appsv1.DaemonSet{
905+
devicePlugin = appsv1.DaemonSet{
913906
ObjectMeta: metav1.ObjectMeta{
914907
Name: devicePluginName.Name,
915908
Namespace: devicePluginName.Namespace,
@@ -925,26 +918,203 @@ var _ = Describe("Recovery from a non-clean state", func() {
925918
Containers: []corev1.Container{
926919
{Name: "foo", Image: "bar"},
927920
},
921+
InitContainers: []corev1.Container{
922+
{
923+
Name: "init", Image: onload.Spec.Onload.UserImage,
924+
},
925+
},
928926
},
929927
},
930928
},
931929
}
932930

931+
module = kmm.Module{
932+
ObjectMeta: metav1.ObjectMeta{
933+
Name: onload.Name + onloadModuleNameSuffix,
934+
Namespace: onload.Namespace,
935+
},
936+
Spec: kmm.ModuleSpec{
937+
Selector: onload.Spec.Selector,
938+
ModuleLoader: kmm.ModuleLoaderSpec{
939+
Container: kmm.ModuleLoaderContainerSpec{
940+
KernelMappings: []kmm.KernelMapping{{}},
941+
},
942+
},
943+
},
944+
}
945+
})
946+
947+
AfterEach(func() {
948+
cancel()
949+
err := testEnv.Stop()
950+
Expect(err).NotTo(HaveOccurred())
951+
})
952+
953+
It("shouldn't remove existing operands", func() {
933954
Expect(k8sClient.Create(ctx, &onload)).Should(Succeed())
934955

935-
Expect(ctrl.SetControllerReference(&onload, &dp, testEnv.Scheme)).Should(Succeed())
936-
Expect(k8sClient.Create(ctx, &dp)).Should(Succeed())
956+
Expect(ctrl.SetControllerReference(&onload, &devicePlugin, testEnv.Scheme)).Should(Succeed())
957+
Expect(k8sClient.Create(ctx, &devicePlugin)).Should(Succeed())
937958

938959
startReconciler(k8sManager, ctx)
939960

940-
devicePlugin := appsv1.DaemonSet{}
961+
// Create a new object so we can compare the old and new versions of the
962+
// object
963+
newDevicePlugin := appsv1.DaemonSet{}
941964

942965
Eventually(func() bool {
943-
err := k8sClient.Get(ctx, devicePluginName, &devicePlugin)
966+
err := k8sClient.Get(ctx, devicePluginName, &newDevicePlugin)
944967
return err == nil
945968
}, timeout, pollingInterval).Should(BeTrue())
946969

947-
Expect(dp.UID).To(Equal(devicePlugin.UID))
970+
Expect(newDevicePlugin.UID).To(Equal(devicePlugin.UID))
971+
})
972+
973+
// Currently we can't test the node labelling which has the bulk of the
974+
// upgrade logic. So we are restricted to testing the upgrading of the
975+
// operands.
976+
It("should continue upgrade process (device plugin)", func() {
977+
978+
// Fake the upgrade, the device plugin is still using the old values
979+
onload.Spec.Onload.Version = "new"
980+
onload.Spec.Onload.UserImage = "foo:bar"
981+
982+
Expect(onload.Spec.Onload.Version).ShouldNot(Equal(devicePlugin.Labels[onloadVersionLabel]))
983+
984+
Expect(k8sClient.Create(ctx, &onload)).Should(Succeed())
985+
986+
Expect(ctrl.SetControllerReference(&onload, &devicePlugin, testEnv.Scheme)).Should(Succeed())
987+
Expect(k8sClient.Create(ctx, &devicePlugin)).Should(Succeed())
988+
989+
startReconciler(k8sManager, ctx)
990+
991+
// Create a new object so we can compare the old and new versions of the
992+
// object
993+
newDevicePlugin := appsv1.DaemonSet{}
994+
995+
Eventually(func(g Gomega) {
996+
g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&devicePlugin), &newDevicePlugin)).Should(Succeed())
997+
g.Expect(newDevicePlugin.UID).To(Equal(devicePlugin.UID))
998+
g.Expect(newDevicePlugin.Labels[onloadVersionLabel]).ShouldNot(Equal(devicePlugin.Labels[onloadVersionLabel]))
999+
g.Expect(newDevicePlugin.Labels[onloadVersionLabel]).Should(Equal(onload.Spec.Onload.Version))
1000+
}, timeout, pollingInterval).Should(Succeed())
1001+
1002+
})
1003+
1004+
It("should continue upgrade process (module)", func() {
1005+
// Fake the upgrade, the operand is still using the old values
1006+
onload.Spec.Onload.Version = "new"
1007+
onload.Spec.Onload.UserImage = "foo:bar"
1008+
1009+
Expect(onload.Spec.Onload.Version).ShouldNot(Equal(module.Spec.ModuleLoader.Container.Version))
1010+
1011+
Expect(k8sClient.Create(ctx, &onload)).Should(Succeed())
1012+
1013+
Expect(ctrl.SetControllerReference(&onload, &module, testEnv.Scheme)).Should(Succeed())
1014+
Expect(k8sClient.Create(ctx, &module)).Should(Succeed())
1015+
1016+
startReconciler(k8sManager, ctx)
1017+
1018+
// Create a new object so we can compare the old and new versions of the
1019+
// object
1020+
newModule := kmm.Module{}
1021+
1022+
Eventually(func(g Gomega) {
1023+
g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&module), &newModule)).Should(Succeed())
1024+
g.Expect(newModule.UID).To(Equal(module.UID))
1025+
g.Expect(newModule.Spec.ModuleLoader.Container.Version).ShouldNot(Equal(module.Spec.ModuleLoader.Container.Version))
1026+
g.Expect(newModule.Spec.ModuleLoader.Container.Version).Should(Equal(onload.Spec.Onload.Version))
1027+
}, timeout, pollingInterval).Should(Succeed())
1028+
1029+
})
1030+
1031+
Describe("Node-based tests", func() {
1032+
1033+
var (
1034+
node corev1.Node
1035+
kmmOnloadLabel string
1036+
dpOnloadLabel string
1037+
)
1038+
1039+
BeforeEach(func() {
1040+
node = corev1.Node{
1041+
ObjectMeta: metav1.ObjectMeta{
1042+
Name: "test-node",
1043+
Labels: map[string]string{
1044+
"key": "value",
1045+
},
1046+
},
1047+
}
1048+
1049+
kmmOnloadLabel = kmmOnloadLabelName(onload.Name, onload.Namespace)
1050+
dpOnloadLabel = onloadLabelName(onload.Name, onload.Namespace)
1051+
})
1052+
1053+
It("should add the initial labels", func() {
1054+
1055+
Expect(k8sClient.Create(ctx, &node)).Should(Succeed())
1056+
1057+
Expect(k8sClient.Create(ctx, &onload)).Should(Succeed())
1058+
1059+
startReconciler(k8sManager, ctx)
1060+
1061+
newNode := corev1.Node{}
1062+
Eventually(func(g Gomega) {
1063+
g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&node), &newNode)).Should(Succeed())
1064+
g.Expect(newNode.Labels[kmmOnloadLabel]).Should(Equal(onload.Spec.Onload.Version))
1065+
g.Expect(newNode.Labels[dpOnloadLabel]).Should(Equal(onload.Spec.Onload.Version))
1066+
}, timeout, pollingInterval).Should(Succeed())
1067+
})
1068+
1069+
// Want to test 3 different values for each label/version: unset, old and new
1070+
DescribeTable("controller starting at different points during upgrade",
1071+
func(label1, label2 string) {
1072+
if label1 != "" {
1073+
node.Labels[kmmOnloadLabel] = label1
1074+
}
1075+
1076+
if label2 != "" {
1077+
node.Labels[dpOnloadLabel] = label2
1078+
}
1079+
1080+
Expect(k8sClient.Create(ctx, &node)).Should(Succeed())
1081+
1082+
onload.Spec.Onload.Version = "new"
1083+
onload.Spec.Onload.UserImage = "foo:bar"
1084+
Expect(k8sClient.Create(ctx, &onload)).Should(Succeed())
1085+
1086+
if label1 != "" {
1087+
module.Spec.ModuleLoader.Container.Version = label1
1088+
}
1089+
Expect(ctrl.SetControllerReference(&onload, &module, testEnv.Scheme)).Should(Succeed())
1090+
1091+
if label2 != "" {
1092+
devicePlugin.Labels[onloadVersionLabel] = label2
1093+
}
1094+
Expect(ctrl.SetControllerReference(&onload, &devicePlugin, testEnv.Scheme)).Should(Succeed())
1095+
1096+
Expect(k8sClient.Create(ctx, &module)).Should(Succeed())
1097+
Expect(k8sClient.Create(ctx, &devicePlugin)).Should(Succeed())
1098+
1099+
startReconciler(k8sManager, ctx)
1100+
1101+
newNode := corev1.Node{}
1102+
Eventually(func(g Gomega) {
1103+
g.Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&node), &newNode)).Should(Succeed())
1104+
g.Expect(newNode.Labels[kmmOnloadLabel]).Should(Equal(onload.Spec.Onload.Version))
1105+
g.Expect(newNode.Labels[dpOnloadLabel]).Should(Equal(onload.Spec.Onload.Version))
1106+
}, timeout, pollingInterval).Should(Succeed())
1107+
},
1108+
Entry("00", "", ""),
1109+
Entry("01", "", "old"), // I don't think this should be able to happen
1110+
Entry("02", "", "new"),
1111+
Entry("10", "old", ""),
1112+
Entry("11", "old", "old"),
1113+
Entry("12", "old", "new"),
1114+
Entry("20", "new", ""),
1115+
Entry("21", "new", "old"), // I don't think this should be able to happen
1116+
Entry("22", "new", "new"),
1117+
)
9481118
})
9491119

9501120
})

0 commit comments

Comments
 (0)