From 8baa8d620a1857595e9feb57542c40193bea2832 Mon Sep 17 00:00:00 2001 From: Yevgeny Shnaidman <60741237+yevgeny-shnaidman@users.noreply.github.com> Date: Thu, 17 Aug 2023 17:38:52 +0300 Subject: [PATCH] Module deleted scenario in Module-NMC controller (#518) (#700) When a Module is deleted, all its ModuleConfigs in all the NMCs should be removed. In order not to miss the delete event when the controller is dow, we do the following: 1) adding finalizer to the Module 2) whenever module is being deleted we remove module from all relevant NMCs, and if all the operations are successfull, we remove the finalizer also --- controllers/mock_module_nmc_reconciler.go | 28 +++ controllers/module_nmc_reconciler.go | 70 +++++- controllers/module_nmc_reconciler_test.go | 222 +++++++++++++++++- .../pod_node_module_reconciler_test.go | 2 +- internal/constants/constants.go | 2 + 5 files changed, 312 insertions(+), 12 deletions(-) diff --git a/controllers/mock_module_nmc_reconciler.go b/controllers/mock_module_nmc_reconciler.go index 26f8b81fc..17dc17992 100644 --- a/controllers/mock_module_nmc_reconciler.go +++ b/controllers/mock_module_nmc_reconciler.go @@ -66,6 +66,20 @@ func (mr *MockmoduleNMCReconcilerHelperAPIMockRecorder) enableModuleOnNode(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "enableModuleOnNode", reflect.TypeOf((*MockmoduleNMCReconcilerHelperAPI)(nil).enableModuleOnNode), ctx, mld, nodeName, kernelVersion) } +// finalizeModule mocks base method. +func (m *MockmoduleNMCReconcilerHelperAPI) finalizeModule(ctx context.Context, mod *v1beta1.Module) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "finalizeModule", ctx, mod) + ret0, _ := ret[0].(error) + return ret0 +} + +// finalizeModule indicates an expected call of finalizeModule. +func (mr *MockmoduleNMCReconcilerHelperAPIMockRecorder) finalizeModule(ctx, mod interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "finalizeModule", reflect.TypeOf((*MockmoduleNMCReconcilerHelperAPI)(nil).finalizeModule), ctx, mod) +} + // getNodesList mocks base method. func (m *MockmoduleNMCReconcilerHelperAPI) getNodesList(ctx context.Context) ([]v1.Node, error) { m.ctrl.T.Helper() @@ -96,6 +110,20 @@ func (mr *MockmoduleNMCReconcilerHelperAPIMockRecorder) getRequestedModule(ctx, return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "getRequestedModule", reflect.TypeOf((*MockmoduleNMCReconcilerHelperAPI)(nil).getRequestedModule), ctx, namespacedName) } +// setFinalizer mocks base method. +func (m *MockmoduleNMCReconcilerHelperAPI) setFinalizer(ctx context.Context, mod *v1beta1.Module) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "setFinalizer", ctx, mod) + ret0, _ := ret[0].(error) + return ret0 +} + +// setFinalizer indicates an expected call of setFinalizer. +func (mr *MockmoduleNMCReconcilerHelperAPIMockRecorder) setFinalizer(ctx, mod interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "setFinalizer", reflect.TypeOf((*MockmoduleNMCReconcilerHelperAPI)(nil).setFinalizer), ctx, mod) +} + // shouldModuleRunOnNode mocks base method. func (m *MockmoduleNMCReconcilerHelperAPI) shouldModuleRunOnNode(node v1.Node, mld *api.ModuleLoaderData) (bool, error) { m.ctrl.T.Helper() diff --git a/controllers/module_nmc_reconciler.go b/controllers/module_nmc_reconciler.go index db07d358c..ae9ab461a 100644 --- a/controllers/module_nmc_reconciler.go +++ b/controllers/module_nmc_reconciler.go @@ -10,6 +10,7 @@ import ( kmmv1beta1 "github.com/rh-ecosystem-edge/kernel-module-management/api/v1beta1" "github.com/rh-ecosystem-edge/kernel-module-management/internal/api" "github.com/rh-ecosystem-edge/kernel-module-management/internal/auth" + "github.com/rh-ecosystem-edge/kernel-module-management/internal/constants" "github.com/rh-ecosystem-edge/kernel-module-management/internal/filter" "github.com/rh-ecosystem-edge/kernel-module-management/internal/module" "github.com/rh-ecosystem-edge/kernel-module-management/internal/nmc" @@ -56,7 +57,6 @@ func NewModuleNMCReconciler(client client.Client, } func (mnr *ModuleNMCReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { - // get the reconciled module logger := log.FromContext(ctx) logger.Info("Starting Module-NMS reconcilation", "module name and namespace", req.NamespacedName) @@ -64,11 +64,24 @@ func (mnr *ModuleNMCReconciler) Reconcile(ctx context.Context, req ctrl.Request) mod, err := mnr.reconHelper.getRequestedModule(ctx, req.NamespacedName) if err != nil { if k8serrors.IsNotFound(err) { - logger.Info("Module deleted") + logger.Info("Module deleted, nothing to do") return ctrl.Result{}, nil } return ctrl.Result{}, fmt.Errorf("failed to get the requested %s Module: %v", req.NamespacedName, err) } + if mod.GetDeletionTimestamp() != nil { + //Module is being deleted + err = mnr.reconHelper.finalizeModule(ctx, mod) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed to finalize %s Module: %v", req.NamespacedName, err) + } + return ctrl.Result{}, nil + } + + err = mnr.reconHelper.setFinalizer(ctx, mod) + if err != nil { + return ctrl.Result{}, fmt.Errorf("failed to set finalizer on %s Module: %v", req.NamespacedName, err) + } // get all nodes nodes, err := mnr.reconHelper.getNodesList(ctx) @@ -109,8 +122,10 @@ func (mnr *ModuleNMCReconciler) Reconcile(ctx context.Context, req ctrl.Request) //go:generate mockgen -source=module_nmc_reconciler.go -package=controllers -destination=mock_module_nmc_reconciler.go moduleNMCReconcilerHelperAPI type moduleNMCReconcilerHelperAPI interface { + setFinalizer(ctx context.Context, mod *kmmv1beta1.Module) error getRequestedModule(ctx context.Context, namespacedName types.NamespacedName) (*kmmv1beta1.Module, error) getNodesList(ctx context.Context) ([]v1.Node, error) + finalizeModule(ctx context.Context, mod *kmmv1beta1.Module) error shouldModuleRunOnNode(node v1.Node, mld *api.ModuleLoaderData) (bool, error) enableModuleOnNode(ctx context.Context, mld *api.ModuleLoaderData, nodeName, kernelVersion string) error disableModuleOnNode(ctx context.Context, modNamespace, modName, nodeName string) error @@ -135,6 +150,19 @@ func newModuleNMCReconcilerHelper(client client.Client, } } +func (mnrh *moduleNMCReconcilerHelper) setFinalizer(ctx context.Context, mod *kmmv1beta1.Module) error { + if controllerutil.ContainsFinalizer(mod, constants.ModuleFinalizer) { + return nil + } + + logger := log.FromContext(ctx) + logger.Info("Adding finalizer", "module name", mod.Name, "module namespace", mod.Namespace) + + modCopy := mod.DeepCopy() + controllerutil.AddFinalizer(mod, constants.ModuleFinalizer) + return mnrh.client.Patch(ctx, mod, client.MergeFrom(modCopy)) +} + func (mnrh *moduleNMCReconcilerHelper) getRequestedModule(ctx context.Context, namespacedName types.NamespacedName) (*kmmv1beta1.Module, error) { mod := kmmv1beta1.Module{} @@ -144,6 +172,34 @@ func (mnrh *moduleNMCReconcilerHelper) getRequestedModule(ctx context.Context, n return &mod, nil } +func (mnrh *moduleNMCReconcilerHelper) finalizeModule(ctx context.Context, mod *kmmv1beta1.Module) error { + nmcList := kmmv1beta1.NodeModulesConfigList{} + err := mnrh.client.List(ctx, &nmcList) + if err != nil { + return fmt.Errorf("failed to list NMCs in the cluster: %v", err) + } + + var sumErr *multierror.Error + // errs := make([]error, 0, len(nmcList.Items)) + for _, nmc := range nmcList.Items { + err = mnrh.removeModuleFromNMC(ctx, &nmc, mod.Namespace, mod.Name) + sumErr = multierror.Append(sumErr, err) + //errs = append(errs, err) + } + + //err = errors.Join(errs...) + err = sumErr.ErrorOrNil() + if err != nil { + return fmt.Errorf("failed to remove %s/%s module from some of NMCs: %v", mod.Namespace, mod.Name, err) + } + + // remove finalizer + modCopy := mod.DeepCopy() + controllerutil.RemoveFinalizer(mod, constants.ModuleFinalizer) + + return mnrh.client.Patch(ctx, mod, client.MergeFrom(modCopy)) +} + func (mnrh *moduleNMCReconcilerHelper) getNodesList(ctx context.Context) ([]v1.Node, error) { nodes := v1.NodeList{} err := mnrh.client.List(ctx, &nodes) @@ -203,7 +259,6 @@ func (mnrh *moduleNMCReconcilerHelper) enableModuleOnNode(ctx context.Context, m } func (mnrh *moduleNMCReconcilerHelper) disableModuleOnNode(ctx context.Context, modNamespace, modName, nodeName string) error { - logger := log.FromContext(ctx) nmc, err := mnrh.nmcHelper.Get(ctx, nodeName) if err != nil { if k8serrors.IsNotFound(err) { @@ -213,15 +268,20 @@ func (mnrh *moduleNMCReconcilerHelper) disableModuleOnNode(ctx context.Context, return fmt.Errorf("failed to get the NodeModulesConfig for node %s: %v", nodeName, err) } + return mnrh.removeModuleFromNMC(ctx, nmc, modNamespace, modName) +} + +func (mnrh *moduleNMCReconcilerHelper) removeModuleFromNMC(ctx context.Context, nmc *kmmv1beta1.NodeModulesConfig, modNamespace, modName string) error { + logger := log.FromContext(ctx) opRes, err := controllerutil.CreateOrPatch(ctx, mnrh.client, nmc, func() error { return mnrh.nmcHelper.RemoveModuleConfig(ctx, nmc, modNamespace, modName) }) if err != nil { - return fmt.Errorf("failed to diable module %s/%s in NMC %s: %v", modNamespace, modName, nodeName, err) + return fmt.Errorf("failed to disable module %s/%s in NMC %s: %v", modNamespace, modName, nmc.Name, err) } - logger.Info("Disable module in NMC", "name", modName, "namespace", modNamespace, "node", nodeName, "result", opRes) + logger.Info("Disabled module in NMC", "name", modName, "namespace", modNamespace, "NMC", nmc.Name, "result", opRes) return nil } diff --git a/controllers/module_nmc_reconciler_test.go b/controllers/module_nmc_reconciler_test.go index 6f75f8684..0c5730f72 100644 --- a/controllers/module_nmc_reconciler_test.go +++ b/controllers/module_nmc_reconciler_test.go @@ -10,6 +10,7 @@ import ( "github.com/rh-ecosystem-edge/kernel-module-management/internal/api" "github.com/rh-ecosystem-edge/kernel-module-management/internal/auth" "github.com/rh-ecosystem-edge/kernel-module-management/internal/client" + "github.com/rh-ecosystem-edge/kernel-module-management/internal/constants" "github.com/rh-ecosystem-edge/kernel-module-management/internal/module" "github.com/rh-ecosystem-edge/kernel-module-management/internal/nmc" "github.com/rh-ecosystem-edge/kernel-module-management/internal/registry" @@ -20,6 +21,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -63,7 +65,22 @@ var _ = Describe("ModuleNMCReconciler_Reconcile", func() { Expect(err).NotTo(HaveOccurred()) }) + It("should run finalization in case module is being deleted", func() { + mod := kmmv1beta1.Module{} + mod.SetDeletionTimestamp(&metav1.Time{}) + gomock.InOrder( + mockReconHelper.EXPECT().getRequestedModule(ctx, nsn).Return(&mod, nil), + mockReconHelper.EXPECT().finalizeModule(ctx, &mod).Return(nil), + ) + + res, err := mnr.Reconcile(ctx, req) + + Expect(res).To(Equal(reconcile.Result{})) + Expect(err).NotTo(HaveOccurred()) + }) + DescribeTable("check error flows", func(getModuleError, + setFinalizerError, getNodesError, getMLDError, shouldRunOnNodeError, @@ -81,6 +98,11 @@ var _ = Describe("ModuleNMCReconciler_Reconcile", func() { goto executeTestFunction } mockReconHelper.EXPECT().getRequestedModule(ctx, nsn).Return(&mod, nil) + if setFinalizerError { + mockReconHelper.EXPECT().setFinalizer(ctx, &mod).Return(returnedError) + goto executeTestFunction + } + mockReconHelper.EXPECT().setFinalizer(ctx, &mod).Return(nil) if getNodesError { mockReconHelper.EXPECT().getNodesList(ctx).Return(nil, returnedError) goto executeTestFunction @@ -109,12 +131,13 @@ var _ = Describe("ModuleNMCReconciler_Reconcile", func() { Expect(err).To(HaveOccurred()) }, - Entry("getRequestedModule failed", true, false, false, false, false), - Entry("getNodesList failed", false, true, false, false, false), - Entry("getModuleLoaderDataForKernel failed", false, false, true, false, false), - Entry("shouldModuleRunOnNode failed", false, false, false, true, false), - Entry("enableModuleOnNode failed", false, false, false, false, true), - Entry("disableModuleOnNode failed", false, false, false, false, false), + Entry("getRequestedModule failed", true, false, false, false, false, false), + Entry("setFinalizer failed", false, true, false, false, false, false), + Entry("getNodesList failed", false, false, true, false, false, false), + Entry("getModuleLoaderDataForKernel failed", false, false, false, true, false, false), + Entry("shouldModuleRunOnNode failed", false, false, false, false, true, false), + Entry("enableModuleOnNode failed", false, false, false, false, false, true), + Entry("disableModuleOnNode failed", false, false, false, false, false, false), ) It("Good flow, kernel mapping exists, should run on node", func() { @@ -127,6 +150,7 @@ var _ = Describe("ModuleNMCReconciler_Reconcile", func() { mld := api.ModuleLoaderData{KernelVersion: kernelVersion} gomock.InOrder( mockReconHelper.EXPECT().getRequestedModule(ctx, nsn).Return(&mod, nil), + mockReconHelper.EXPECT().setFinalizer(ctx, &mod).Return(nil), mockReconHelper.EXPECT().getNodesList(ctx).Return([]v1.Node{node}, nil), mockKernel.EXPECT().GetModuleLoaderDataForKernel(&mod, kernelVersion).Return(&mld, nil), mockReconHelper.EXPECT().shouldModuleRunOnNode(node, &mld).Return(true, nil), @@ -148,6 +172,7 @@ var _ = Describe("ModuleNMCReconciler_Reconcile", func() { } gomock.InOrder( mockReconHelper.EXPECT().getRequestedModule(ctx, nsn).Return(&mod, nil), + mockReconHelper.EXPECT().setFinalizer(ctx, &mod).Return(nil), mockReconHelper.EXPECT().getNodesList(ctx).Return([]v1.Node{node}, nil), mockKernel.EXPECT().GetModuleLoaderDataForKernel(&mod, kernelVersion).Return(nil, module.ErrNoMatchingKernelMapping), mockReconHelper.EXPECT().shouldModuleRunOnNode(node, nil).Return(false, nil), @@ -204,6 +229,44 @@ var _ = Describe("ModuleReconciler_getRequestedModule", func() { }) +var _ = Describe("ModuleReconciler_setFinalizer", func() { + var ( + ctrl *gomock.Controller + clnt *client.MockClient + mnrh moduleNMCReconcilerHelperAPI + mod kmmv1beta1.Module + ) + + BeforeEach(func() { + ctrl = gomock.NewController(GinkgoT()) + clnt = client.NewMockClient(ctrl) + mnrh = newModuleNMCReconcilerHelper(clnt, nil, nil, nil) + mod = kmmv1beta1.Module{} + }) + + ctx := context.Background() + + It("finalizer is already set", func() { + controllerutil.AddFinalizer(&mod, constants.ModuleFinalizer) + err := mnrh.setFinalizer(ctx, &mod) + Expect(err).NotTo(HaveOccurred()) + }) + + It("finalizer is not set", func() { + clnt.EXPECT().Patch(ctx, &mod, gomock.Any()).Return(nil) + + err := mnrh.setFinalizer(ctx, &mod) + Expect(err).NotTo(HaveOccurred()) + }) + + It("finalizer is not set, failed to patch the Module", func() { + clnt.EXPECT().Patch(ctx, &mod, gomock.Any()).Return(fmt.Errorf("some error")) + + err := mnrh.setFinalizer(ctx, &mod) + Expect(err).To(HaveOccurred()) + }) +}) + var _ = Describe("ModuleReconciler_getNodes", func() { var ( ctrl *gomock.Controller @@ -246,6 +309,93 @@ var _ = Describe("ModuleReconciler_getNodes", func() { }) }) +var _ = Describe("finalizeModule", func() { + var ( + ctx context.Context + ctrl *gomock.Controller + clnt *client.MockClient + helper *nmc.MockHelper + mnrh moduleNMCReconcilerHelperAPI + mod *kmmv1beta1.Module + ) + + BeforeEach(func() { + ctx = context.Background() + ctrl = gomock.NewController(GinkgoT()) + clnt = client.NewMockClient(ctrl) + helper = nmc.NewMockHelper(ctrl) + mnrh = newModuleNMCReconcilerHelper(clnt, nil, helper, nil) + mod = &kmmv1beta1.Module{ + ObjectMeta: metav1.ObjectMeta{Name: "moduleName", Namespace: "moduleNamespace"}, + } + }) + + It("failed to get list of NMCs", func() { + clnt.EXPECT().List(ctx, gomock.Any()).Return(fmt.Errorf("some error")) + + err := mnrh.finalizeModule(ctx, mod) + + Expect(err).To(HaveOccurred()) + }) + + It("multiple errors occurred", func() { + nmc1 := kmmv1beta1.NodeModulesConfig{ + ObjectMeta: metav1.ObjectMeta{Name: "nmc1"}, + } + nmc2 := kmmv1beta1.NodeModulesConfig{ + ObjectMeta: metav1.ObjectMeta{Name: "nmc2"}, + } + + gomock.InOrder( + clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ interface{}, list *kmmv1beta1.NodeModulesConfigList, _ ...interface{}) error { + list.Items = []kmmv1beta1.NodeModulesConfig{nmc1, nmc2} + return nil + }, + ), + clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(fmt.Errorf("some error")), + clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(fmt.Errorf("some error")), + ) + + err := mnrh.finalizeModule(ctx, mod) + + Expect(err).To(HaveOccurred()) + + }) + + It("no nmcs, patch successfull", func() { + gomock.InOrder( + clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ interface{}, list *kmmv1beta1.NodeModulesConfigList, _ ...interface{}) error { + list.Items = []kmmv1beta1.NodeModulesConfig{} + return nil + }, + ), + clnt.EXPECT().Patch(ctx, mod, gomock.Any()).Return(nil), + ) + + err := mnrh.finalizeModule(ctx, mod) + + Expect(err).NotTo(HaveOccurred()) + }) + + It("no nmcs, failed", func() { + gomock.InOrder( + clnt.EXPECT().List(ctx, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ interface{}, list *kmmv1beta1.NodeModulesConfigList, _ ...interface{}) error { + list.Items = []kmmv1beta1.NodeModulesConfig{} + return nil + }, + ), + clnt.EXPECT().Patch(ctx, mod, gomock.Any()).Return(fmt.Errorf("some error")), + ) + + err := mnrh.finalizeModule(ctx, mod) + + Expect(err).To(HaveOccurred()) + }) +}) + var _ = Describe("shouldModuleRunOnNode", func() { var ( mnrh moduleNMCReconcilerHelperAPI @@ -489,3 +639,63 @@ var _ = Describe("disableModuleOnNode", func() { Expect(err).NotTo(HaveOccurred()) }) }) + +var _ = Describe("removeModuleFromNMC", func() { + var ( + ctx context.Context + ctrl *gomock.Controller + clnt *client.MockClient + mnrh *moduleNMCReconcilerHelper + helper *nmc.MockHelper + nmcName string + moduleName string + moduleNamespace string + ) + + BeforeEach(func() { + ctx = context.Background() + ctrl = gomock.NewController(GinkgoT()) + clnt = client.NewMockClient(ctrl) + helper = nmc.NewMockHelper(ctrl) + mnrh = &moduleNMCReconcilerHelper{client: clnt, nmcHelper: helper} + nmcName = "NMC name" + moduleName = "moduleName" + moduleNamespace = "moduleNamespace" + }) + + It("good flow", func() { + nmc := &kmmv1beta1.NodeModulesConfig{ + ObjectMeta: metav1.ObjectMeta{Name: nmcName}, + } + gomock.InOrder( + clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ interface{}, _ interface{}, nmc *kmmv1beta1.NodeModulesConfig, _ ...ctrlclient.GetOption) error { + nmc.SetName(nmcName) + return nil + }, + ), + helper.EXPECT().RemoveModuleConfig(ctx, nmc, moduleNamespace, moduleName).Return(nil), + ) + + err := mnrh.removeModuleFromNMC(ctx, nmc, moduleNamespace, moduleName) + Expect(err).NotTo(HaveOccurred()) + }) + + It("bad flow", func() { + nmc := &kmmv1beta1.NodeModulesConfig{ + ObjectMeta: metav1.ObjectMeta{Name: nmcName}, + } + gomock.InOrder( + clnt.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).DoAndReturn( + func(_ interface{}, _ interface{}, nmc *kmmv1beta1.NodeModulesConfig, _ ...ctrlclient.GetOption) error { + nmc.SetName(nmcName) + return nil + }, + ), + helper.EXPECT().RemoveModuleConfig(ctx, nmc, moduleNamespace, moduleName).Return(fmt.Errorf("some error")), + ) + + err := mnrh.removeModuleFromNMC(ctx, nmc, moduleNamespace, moduleName) + Expect(err).To(HaveOccurred()) + }) +}) diff --git a/controllers/pod_node_module_reconciler_test.go b/controllers/pod_node_module_reconciler_test.go index d303dbd84..fae1aff1a 100644 --- a/controllers/pod_node_module_reconciler_test.go +++ b/controllers/pod_node_module_reconciler_test.go @@ -168,7 +168,7 @@ var _ = Describe("PodNodeModuleReconciler", func() { ), mockDC.EXPECT().GetNodeLabelFromPod(gomock.Any(), moduleName, false).Return(nodeLabel), mockDC.EXPECT().GetNodeLabelFromPod(gomock.Any(), moduleName, true).Return(deprecatedNodeLabel), - kubeClient.EXPECT().Patch(context.TODO(), gomock.AssignableToTypeOf(&v1.Pod{}), gomock.Any()).Do(patchRemoveFinalizerFunc), + kubeClient.EXPECT().Patch(ctx, gomock.AssignableToTypeOf(&v1.Pod{}), gomock.Any()).Do(patchRemoveFinalizerFunc), ) _, err := r.Reconcile(ctx, req) diff --git a/internal/constants/constants.go b/internal/constants/constants.go index ddf7e2143..e5a545fc3 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -14,6 +14,8 @@ const ( DevicePluginVersionLabelPrefix = "beta.kmm.node.kubernetes.io/version-device-plugin" ModuleVersionLabelPrefix = "kmm.node.kubernetes.io/version-module" + ModuleFinalizer = "kmm.node.kubernetes.io/module-finalizer" + ManagedClusterModuleNameLabel = "kmm.node.kubernetes.io/managedclustermodule.name" KernelVersionsClusterClaimName = "kernel-versions.kmm.node.kubernetes.io" DockerfileCMKey = "dockerfile"