diff --git a/bundle/manifests/lvms-operator.clusterserviceversion.yaml b/bundle/manifests/lvms-operator.clusterserviceversion.yaml index 3141ce8b2..e5dbe5332 100644 --- a/bundle/manifests/lvms-operator.clusterserviceversion.yaml +++ b/bundle/manifests/lvms-operator.clusterserviceversion.yaml @@ -824,6 +824,14 @@ spec: - patch - update - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - delete + - list + - watch - apiGroups: - lvm.topolvm.io resources: @@ -872,18 +880,6 @@ spec: - create - patch - update - - apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch serviceAccountName: vg-manager strategy: deployment installModes: diff --git a/cmd/vgmanager/vgmanager.go b/cmd/vgmanager/vgmanager.go index f7a7971e1..a5d53c232 100644 --- a/cmd/vgmanager/vgmanager.go +++ b/cmd/vgmanager/vgmanager.go @@ -37,6 +37,7 @@ import ( // to ensure that exec-entrypoint and run can make use of them. _ "k8s.io/client-go/plugin/pkg/client/auth" + corev1 "k8s.io/api/core/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" @@ -122,10 +123,17 @@ func run(cmd *cobra.Command, _ []string, opts *Options) error { return fmt.Errorf("unable to start manager: %w", err) } + if err := mgr.GetFieldIndexer().IndexField(cmd.Context(), &corev1.Pod{}, "spec.nodeName", func(rawObj client.Object) []string { + pod := rawObj.(*corev1.Pod) + return []string{pod.Spec.NodeName} + }); err != nil { + return err + } + if err = (&vgmanager.Reconciler{ Client: mgr.GetClient(), EventRecorder: mgr.GetEventRecorderFor(vgmanager.ControllerName), - LVMD: lvmd.NewFileConfigurator(mgr.GetClient(), operatorNamespace), + LVMD: lvmd.DefaultConfigurator(), Scheme: mgr.GetScheme(), LSBLK: lsblk.NewDefaultHostLSBLK(), Wipefs: wipefs.NewDefaultHostWipefs(), diff --git a/config/rbac/vg_manager_role.yaml b/config/rbac/vg_manager_role.yaml index 4e8cde82f..a6257b225 100644 --- a/config/rbac/vg_manager_role.yaml +++ b/config/rbac/vg_manager_role.yaml @@ -18,6 +18,14 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - pods + verbs: + - delete + - list + - watch - apiGroups: - lvm.topolvm.io resources: @@ -66,15 +74,3 @@ rules: - create - patch - update -- apiGroups: - - "" - resources: - - configmaps - verbs: - - create - - delete - - get - - list - - patch - - update - - watch diff --git a/internal/controllers/constants/constants.go b/internal/controllers/constants/constants.go index 33fb8c4ee..80465d325 100644 --- a/internal/controllers/constants/constants.go +++ b/internal/controllers/constants/constants.go @@ -71,10 +71,6 @@ const ( DefaultCSISocket = "/run/topolvm/csi-topolvm.sock" DeviceClassKey = "topolvm.io/device-class" - LVMDConfigMapName = "lvmd-config" - LVMDDefaultConfigDir = "/etc/topolvm" - LVMDDefaultFileConfigPath = "/etc/topolvm/lvmd.yaml" - // name of the lvm-operator container LVMOperatorContainerName = "manager" diff --git a/internal/controllers/lvmcluster/resource/topolvm_node.go b/internal/controllers/lvmcluster/resource/topolvm_node.go index 061f1f97e..fa6ff0fd1 100644 --- a/internal/controllers/lvmcluster/resource/topolvm_node.go +++ b/internal/controllers/lvmcluster/resource/topolvm_node.go @@ -25,6 +25,7 @@ import ( lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1" "github.com/openshift/lvm-operator/internal/controllers/constants" "github.com/openshift/lvm-operator/internal/controllers/lvmcluster/selector" + "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lvmd" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -156,12 +157,9 @@ func getNodeDaemonSet(lvmCluster *lvmv1alpha1.LVMCluster, namespace string, args Type: &hostPathDirectoryOrCreateType}}}, {Name: "lvmd-config-dir", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: constants.LVMDConfigMapName, - }, - }, - }}, + HostPath: &corev1.HostPathVolumeSource{ + Path: filepath.Dir(lvmd.DefaultFileConfigPath), + Type: &hostPathDirectory}}}, {Name: "metrics-cert", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ @@ -233,7 +231,7 @@ func getNodeContainer(args []string) *corev1.Container { command := []string{ "/topolvm-node", "--embed-lvmd", - fmt.Sprintf("--config=%s", constants.LVMDDefaultFileConfigPath), + fmt.Sprintf("--config=%s", lvmd.DefaultFileConfigPath), } command = append(command, args...) @@ -249,7 +247,7 @@ func getNodeContainer(args []string) *corev1.Container { volumeMounts := []corev1.VolumeMount{ {Name: "node-plugin-dir", MountPath: filepath.Dir(constants.DefaultCSISocket)}, - {Name: "lvmd-config-dir", MountPath: constants.LVMDDefaultConfigDir}, + {Name: "lvmd-config-dir", MountPath: filepath.Dir(lvmd.DefaultFileConfigPath)}, {Name: "pod-volumes-dir", MountPath: fmt.Sprintf("%spods", getAbsoluteKubeletPath(constants.CSIKubeletRootDir)), MountPropagation: &mountPropagationMode}, diff --git a/internal/controllers/vgmanager/controller.go b/internal/controllers/vgmanager/controller.go index 398323ece..db1c78570 100644 --- a/internal/controllers/vgmanager/controller.go +++ b/internal/controllers/vgmanager/controller.go @@ -25,6 +25,7 @@ import ( "github.com/google/go-cmp/cmp" lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1" + "github.com/openshift/lvm-operator/internal/controllers/constants" "github.com/openshift/lvm-operator/internal/controllers/vgmanager/dmsetup" "github.com/openshift/lvm-operator/internal/controllers/vgmanager/filter" "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lsblk" @@ -35,6 +36,8 @@ import ( corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" @@ -44,10 +47,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" - "sigs.k8s.io/controller-runtime/pkg/reconcile" ) const ( @@ -83,38 +84,9 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&lvmv1alpha1.LVMVolumeGroup{}). Owns(&lvmv1alpha1.LVMVolumeGroupNodeStatus{}, builder.MatchEveryOwner, builder.WithPredicates(predicate.GenerationChangedPredicate{})). - Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(r.getObjsInNamespaceForReconcile)). Complete(r) } -// getObjsInNamespaceForReconcile reconciles the object anytime the given object is in the same namespace -// as the available LVMVolumeGroups. -func (r *Reconciler) getObjsInNamespaceForReconcile(ctx context.Context, obj client.Object) []reconcile.Request { - foundLVMVolumeGroupList := &lvmv1alpha1.LVMVolumeGroupList{} - listOps := &client.ListOptions{ - Namespace: obj.GetNamespace(), - } - - if err := r.List(ctx, foundLVMVolumeGroupList, listOps); err != nil { - log.FromContext(ctx).Error(err, "getObjsInNamespaceForReconcile: Failed to get LVMVolumeGroup objs") - return []reconcile.Request{} - } - if len(foundLVMVolumeGroupList.Items) < 1 { - return []reconcile.Request{} - } - - var requests []reconcile.Request - for _, lvmVG := range foundLVMVolumeGroupList.Items { - requests = append(requests, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: lvmVG.GetName(), - Namespace: lvmVG.GetNamespace(), - }, - }) - } - return requests -} - type Reconciler struct { client.Client Scheme *runtime.Scheme @@ -326,7 +298,7 @@ func (r *Reconciler) applyLVMDConfig(ctx context.Context, volumeGroup *lvmv1alph logger := log.FromContext(ctx).WithValues("VGName", volumeGroup.Name) // Read the lvmd config file - lvmdConfig, err := r.LVMD.Load(ctx) + lvmdConfig, err := r.LVMD.Load() if err != nil { err = fmt.Errorf("failed to read the lvmd config file: %w", err) if _, err := r.setVolumeGroupFailedStatus(ctx, volumeGroup, nil, err); err != nil { @@ -392,12 +364,32 @@ func (r *Reconciler) updateLVMDConfigAfterReconcile( r.NormalEvent(ctx, volumeGroup, EventReasonLVMDConfigMissing, msg) } - if err := r.LVMD.Save(ctx, newCFG); err != nil { + if err := r.LVMD.Save(newCFG); err != nil { return fmt.Errorf("failed to update lvmd config file to update volume group %s: %w", volumeGroup.GetName(), err) } - msg := "updated lvmd config with new deviceClasses" + msg := "updated lvmd config with new deviceClasses, restarting TopoLVM Node pods" logger.Info(msg) r.NormalEvent(ctx, volumeGroup, EventReasonLVMDConfigUpdated, msg) + + nodePodList := &corev1.PodList{} + listOptions := &client.ListOptions{ + Namespace: r.Namespace, + LabelSelector: labels.SelectorFromSet(map[string]string{constants.AppKubernetesComponentLabel: constants.TopolvmNodeLabelVal}), + FieldSelector: fields.OneTermEqualSelector("spec.nodeName", r.NodeName), + } + err := r.List(ctx, nodePodList, listOptions) + if err != nil { + return fmt.Errorf("failed to list TopoLVM Node pods: %w", err) + } + if len(nodePodList.Items) < 1 { + return fmt.Errorf("could not find any TopoLVM Node pods on %s namespace and on %s node", r.Namespace, r.NodeName) + } + for _, pod := range nodePodList.Items { + err := r.Delete(ctx, &pod) + if err != nil { + return fmt.Errorf("failed to remove TopoLVM Node pod %s: %w", pod.Name, err) + } + } } return nil } @@ -407,7 +399,7 @@ func (r *Reconciler) processDelete(ctx context.Context, volumeGroup *lvmv1alpha1 logger.Info("deleting") // Read the lvmd config file - lvmdConfig, err := r.LVMD.Load(ctx) + lvmdConfig, err := r.LVMD.Load() if err != nil { // Failed to read lvmdconfig file. Reconcile again return fmt.Errorf("failed to read the lvmd config file: %w", err) @@ -475,14 +467,14 @@ func (r *Reconciler) processDelete(ctx context.Context, volumeGroup *lvmv1alpha1 // if there was no config file in the first place, nothing has to be removed. if lvmdConfig != nil { if len(lvmdConfig.DeviceClasses) > 0 { - if err = r.LVMD.Save(ctx, lvmdConfig); err != nil { + if err = r.LVMD.Save(lvmdConfig); err != nil { return fmt.Errorf("failed to update lvmd.conf file for volume group %s: %w", volumeGroup.GetName(), err) } msg := "updated lvmd config after deviceClass was removed" logger.Info(msg) r.NormalEvent(ctx, volumeGroup, EventReasonLVMDConfigUpdated, msg) } else { - if err = r.LVMD.Delete(ctx); err != nil { + if err = r.LVMD.Delete(); err != nil { return fmt.Errorf("failed to delete lvmd.conf file for volume group %s: %w", volumeGroup.GetName(), err) } msg := "removed lvmd config after last deviceClass was removed" diff --git a/internal/controllers/vgmanager/controller_test.go b/internal/controllers/vgmanager/controller_test.go index 0629bb7bb..76bcfe6a3 100644 --- a/internal/controllers/vgmanager/controller_test.go +++ b/internal/controllers/vgmanager/controller_test.go @@ -16,6 +16,7 @@ import ( configv1 "github.com/openshift/api/config/v1" secv1 "github.com/openshift/api/security/v1" lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1" + "github.com/openshift/lvm-operator/internal/controllers/constants" "github.com/openshift/lvm-operator/internal/controllers/vgmanager/filter" "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lsblk" lsblkmocks "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lsblk/mocks" @@ -24,15 +25,11 @@ import ( "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lvmd" lvmdmocks "github.com/openshift/lvm-operator/internal/controllers/vgmanager/lvmd/mocks" wipefsmocks "github.com/openshift/lvm-operator/internal/controllers/vgmanager/wipefs/mocks" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" topolvmv1 "github.com/topolvm/topolvm/api/v1" - corev1 "k8s.io/api/core/v1" "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" @@ -111,6 +108,7 @@ func setupInstances() testInstances { mockLSBLK := lsblkmocks.NewMockLSBLK(t) mockLVM := lvmmocks.NewMockLVM(t) mockWipefs := wipefsmocks.NewMockWipefs(t) + testLVMD := lvmd.NewFileConfigurator(filepath.Join(t.TempDir(), "lvmd.yaml")) hostname := "test-host.vgmanager.test.io" hostnameLabelKey := "kubernetes.io/hostname" @@ -119,15 +117,25 @@ func setupInstances() testInstances { node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test-node", Labels: map[string]string{ hostnameLabelKey: hostname, }}} + topolvmNodePod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "topolvm-node", Namespace: namespace.GetName(), Labels: map[string]string{ + constants.AppKubernetesComponentLabel: constants.TopolvmNodeLabelVal, + }}, + Spec: corev1.PodSpec{ + NodeName: node.GetName(), + }, + } fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme). - WithObjects(node, namespace). + WithObjects(node, namespace, topolvmNodePod). + WithIndex(&corev1.Pod{}, "spec.nodeName", func(rawObj client.Object) []string { + pod := rawObj.(*corev1.Pod) + return []string{pod.Spec.NodeName} + }). Build() fakeRecorder := record.NewFakeRecorder(100) fakeRecorder.IncludeObject = true - testLVMD := lvmd.NewFileConfigurator(fakeClient, namespace.GetName()) - return testInstances{ LVM: mockLVM, LSBLK: mockLSBLK, @@ -307,7 +315,7 @@ func testMockedBlockDeviceOnHost(ctx context.Context) { By("verifying the lvmd config generation", func() { checkDistributedEvent(corev1.EventTypeNormal, "lvmd config file doesn't exist, will attempt to create a fresh config") checkDistributedEvent(corev1.EventTypeNormal, "updated lvmd config with new deviceClasses") - lvmdConfig, err := instances.LVMD.Load(ctx) + lvmdConfig, err := instances.LVMD.Load() Expect(err).ToNot(HaveOccurred()) Expect(lvmdConfig).ToNot(BeNil()) Expect(lvmdConfig.DeviceClasses).ToNot(BeNil()) @@ -397,7 +405,7 @@ func testMockedBlockDeviceOnHost(ctx context.Context) { _, err := instances.Reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: client.ObjectKeyFromObject(vg)}) Expect(err).ToNot(HaveOccurred()) Expect(instances.client.Get(ctx, client.ObjectKeyFromObject(vg), vg)).ToNot(Succeed()) - lvmdConfig, err := instances.LVMD.Load(ctx) + lvmdConfig, err := instances.LVMD.Load() Expect(err).ToNot(HaveOccurred()) Expect(lvmdConfig).To(BeNil()) }) @@ -552,13 +560,13 @@ func testLVMD(ctx context.Context) { mockLVM := lvmmocks.NewMockLVM(GinkgoT()) r.LVM = mockLVM - mockLVMD.EXPECT().Load(ctx).Once().Return(nil, fmt.Errorf("mock load failure")) + mockLVMD.EXPECT().Load().Once().Return(nil, fmt.Errorf("mock load failure")) mockLVM.EXPECT().ListVGs().Once().Return(nil, fmt.Errorf("mock list failure")) err := r.applyLVMDConfig(ctx, vg, devices) Expect(err).To(HaveOccurred(), "should error if lvmd config cannot be loaded and/or status cannot be set") - mockLVMD.EXPECT().Load(ctx).Once().Return(&lvmd.Config{}, nil) - mockLVMD.EXPECT().Save(ctx, mock.Anything).Once().Return(fmt.Errorf("mock save failure")) + mockLVMD.EXPECT().Load().Once().Return(&lvmd.Config{}, nil) + mockLVMD.EXPECT().Save(mock.Anything).Once().Return(fmt.Errorf("mock save failure")) mockLVM.EXPECT().ListVGs().Once().Return(nil, fmt.Errorf("mock list failure")) err = r.applyLVMDConfig(ctx, vg, devices) Expect(err).To(HaveOccurred(), "should error if lvmd config cannot be saved and/or status cannot be set") @@ -854,52 +862,3 @@ func testReconcileFailure(ctx context.Context) { Expect(err).To(HaveOccurred()) }) } - -func TestGetObjsInNamespaceForReconcile(t *testing.T) { - tests := []struct { - name string - objs []client.Object - list error - expect []reconcile.Request - }{ - { - name: "test lvmvolumegroup not fetch error", - list: assert.AnError, - }, - { - name: "test lvmvolumegroup found in a different namespace", - objs: []client.Object{ - &lvmv1alpha1.LVMVolumeGroup{ObjectMeta: metav1.ObjectMeta{Name: "test-vg", Namespace: "not-test"}}, - }, - }, - { - name: "test lvmvolumegroup found in the same namespace", - objs: []client.Object{ - &lvmv1alpha1.LVMVolumeGroup{ObjectMeta: metav1.ObjectMeta{Name: "test-vg", Namespace: "test"}}, - }, - expect: []reconcile.Request{{NamespacedName: types.NamespacedName{Name: "test-vg", Namespace: "test"}}}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - newScheme := runtime.NewScheme() - assert.NoError(t, lvmv1alpha1.AddToScheme(newScheme)) - assert.NoError(t, corev1.AddToScheme(newScheme)) - clnt := fake.NewClientBuilder().WithObjects(tt.objs...). - WithScheme(newScheme).WithInterceptorFuncs(interceptor.Funcs{ - List: func(ctx context.Context, client client.WithWatch, list client.ObjectList, opts ...client.ListOption) error { - if tt.list != nil { - return tt.list - } - return client.List(ctx, list, opts...) - }, - }).Build() - - r := &Reconciler{Client: clnt} - requests := r.getObjsInNamespaceForReconcile(context.Background(), - &corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "test-vg", Namespace: "test"}}) - assert.ElementsMatch(t, tt.expect, requests) - }) - } -} diff --git a/internal/controllers/vgmanager/lvmd/lvmd.go b/internal/controllers/vgmanager/lvmd/lvmd.go index 0ca096d46..625662d46 100644 --- a/internal/controllers/vgmanager/lvmd/lvmd.go +++ b/internal/controllers/vgmanager/lvmd/lvmd.go @@ -1,20 +1,11 @@ package lvmd import ( - "context" "fmt" "os" - "github.com/openshift/lvm-operator/internal/controllers/constants" "github.com/topolvm/topolvm/lvmd" lvmdCMD "github.com/topolvm/topolvm/pkg/lvmd/cmd" - - corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/yaml" ) @@ -25,89 +16,57 @@ type ThinPoolConfig = lvmd.ThinPoolConfig var TypeThin = lvmd.TypeThin -func NewFileConfigurator(client client.Client, namespace string) FileConfig { - return FileConfig{Client: client, Namespace: namespace} +const DefaultFileConfigPath = "/etc/topolvm/lvmd.yaml" + +func DefaultConfigurator() FileConfig { + return NewFileConfigurator(DefaultFileConfigPath) +} + +func NewFileConfigurator(path string) FileConfig { + return FileConfig{path: path} } type Configurator interface { - Load(ctx context.Context) (*Config, error) - Save(ctx context.Context, config *Config) error - Delete(ctx context.Context) error + Load() (*Config, error) + Save(config *Config) error + Delete() error } type FileConfig struct { - client.Client - Namespace string + path string } -func (c FileConfig) Load(ctx context.Context) (*Config, error) { - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: constants.LVMDConfigMapName, - Namespace: c.Namespace, - }, - } - err := c.Client.Get(ctx, client.ObjectKeyFromObject(cm), cm) - if k8serrors.IsNotFound(err) { +func (c FileConfig) Load() (*Config, error) { + cfgBytes, err := os.ReadFile(c.path) + if os.IsNotExist(err) { // If the file does not exist, return nil for both return nil, nil } else if err != nil { - return nil, fmt.Errorf("failed to get ConfigMap %s: %w", cm.Name, err) - } - - config := &Config{} - if err = yaml.Unmarshal([]byte(cm.Data["lvmd.yaml"]), config); err != nil { - return nil, fmt.Errorf("failed to unmarshal config file: %w", err) + return nil, fmt.Errorf("failed to load config file %s: %w", c.path, err) + } else { + config := &Config{} + if err = yaml.Unmarshal(cfgBytes, config); err != nil { + return nil, fmt.Errorf("failed to unmarshal config file %s: %w", c.path, err) + } + return config, nil } - return config, nil } -func (c FileConfig) Save(ctx context.Context, config *Config) error { - logger := log.FromContext(ctx) - // TODO: removing the old config file is added for seamless upgrades from 4.14 to 4.15, and should be deleted in 4.16 - // remove the old config file if it still exists - _, err := os.ReadFile(constants.LVMDDefaultFileConfigPath) - if err == nil { - if err = os.Remove(constants.LVMDDefaultFileConfigPath); err != nil { - logger.Info("failed to remove the old lvmd config file", "filePath", constants.LVMDDefaultFileConfigPath, "error", err) - } - } +func (c FileConfig) Save(config *Config) error { out, err := yaml.Marshal(config) - if err != nil { - return fmt.Errorf("failed to marshal config file: %w", err) - } - - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: constants.LVMDConfigMapName, - Namespace: c.Namespace, - }, + if err == nil { + err = os.WriteFile(c.path, out, 0600) } - _, err = ctrl.CreateOrUpdate(ctx, c.Client, cm, func() error { - cm.Data = map[string]string{"lvmd.yaml": string(out)} - return nil - }) if err != nil { - return fmt.Errorf("failed to apply ConfigMap %s: %w", cm.GetName(), err) + return fmt.Errorf("failed to save config file %s: %w", c.path, err) } - return nil } -func (c FileConfig) Delete(ctx context.Context) error { - cm := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: constants.LVMDConfigMapName, - Namespace: c.Namespace, - }, - } - if err := c.Client.Delete(ctx, cm); err != nil { - if k8serrors.IsNotFound(err) { - // If the file does not exist, return nil - return nil - } - return fmt.Errorf("failed to delete ConfigMap: %w", err) +func (c FileConfig) Delete() error { + err := os.Remove(c.path) + if err != nil { + return fmt.Errorf("failed to delete config file %s: %w", c.path, err) } - - return nil + return err } diff --git a/internal/controllers/vgmanager/lvmd/mocks/mock_configurator.go b/internal/controllers/vgmanager/lvmd/mocks/mock_configurator.go index 27d162b32..1905efe98 100644 --- a/internal/controllers/vgmanager/lvmd/mocks/mock_configurator.go +++ b/internal/controllers/vgmanager/lvmd/mocks/mock_configurator.go @@ -3,8 +3,6 @@ package lvmd import ( - context "context" - cmd "github.com/topolvm/topolvm/pkg/lvmd/cmd" mock "github.com/stretchr/testify/mock" @@ -23,13 +21,13 @@ func (_m *MockConfigurator) EXPECT() *MockConfigurator_Expecter { return &MockConfigurator_Expecter{mock: &_m.Mock} } -// Delete provides a mock function with given fields: ctx -func (_m *MockConfigurator) Delete(ctx context.Context) error { - ret := _m.Called(ctx) +// Delete provides a mock function with given fields: +func (_m *MockConfigurator) Delete() error { + ret := _m.Called() var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() } else { r0 = ret.Error(0) } @@ -43,14 +41,13 @@ type MockConfigurator_Delete_Call struct { } // Delete is a helper method to define mock.On call -// - ctx context.Context -func (_e *MockConfigurator_Expecter) Delete(ctx interface{}) *MockConfigurator_Delete_Call { - return &MockConfigurator_Delete_Call{Call: _e.mock.On("Delete", ctx)} +func (_e *MockConfigurator_Expecter) Delete() *MockConfigurator_Delete_Call { + return &MockConfigurator_Delete_Call{Call: _e.mock.On("Delete")} } -func (_c *MockConfigurator_Delete_Call) Run(run func(ctx context.Context)) *MockConfigurator_Delete_Call { +func (_c *MockConfigurator_Delete_Call) Run(run func()) *MockConfigurator_Delete_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) + run() }) return _c } @@ -60,30 +57,30 @@ func (_c *MockConfigurator_Delete_Call) Return(_a0 error) *MockConfigurator_Dele return _c } -func (_c *MockConfigurator_Delete_Call) RunAndReturn(run func(context.Context) error) *MockConfigurator_Delete_Call { +func (_c *MockConfigurator_Delete_Call) RunAndReturn(run func() error) *MockConfigurator_Delete_Call { _c.Call.Return(run) return _c } -// Load provides a mock function with given fields: ctx -func (_m *MockConfigurator) Load(ctx context.Context) (*cmd.Config, error) { - ret := _m.Called(ctx) +// Load provides a mock function with given fields: +func (_m *MockConfigurator) Load() (*cmd.Config, error) { + ret := _m.Called() var r0 *cmd.Config var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*cmd.Config, error)); ok { - return rf(ctx) + if rf, ok := ret.Get(0).(func() (*cmd.Config, error)); ok { + return rf() } - if rf, ok := ret.Get(0).(func(context.Context) *cmd.Config); ok { - r0 = rf(ctx) + if rf, ok := ret.Get(0).(func() *cmd.Config); ok { + r0 = rf() } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*cmd.Config) } } - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() } else { r1 = ret.Error(1) } @@ -97,14 +94,13 @@ type MockConfigurator_Load_Call struct { } // Load is a helper method to define mock.On call -// - ctx context.Context -func (_e *MockConfigurator_Expecter) Load(ctx interface{}) *MockConfigurator_Load_Call { - return &MockConfigurator_Load_Call{Call: _e.mock.On("Load", ctx)} +func (_e *MockConfigurator_Expecter) Load() *MockConfigurator_Load_Call { + return &MockConfigurator_Load_Call{Call: _e.mock.On("Load")} } -func (_c *MockConfigurator_Load_Call) Run(run func(ctx context.Context)) *MockConfigurator_Load_Call { +func (_c *MockConfigurator_Load_Call) Run(run func()) *MockConfigurator_Load_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) + run() }) return _c } @@ -114,18 +110,18 @@ func (_c *MockConfigurator_Load_Call) Return(_a0 *cmd.Config, _a1 error) *MockCo return _c } -func (_c *MockConfigurator_Load_Call) RunAndReturn(run func(context.Context) (*cmd.Config, error)) *MockConfigurator_Load_Call { +func (_c *MockConfigurator_Load_Call) RunAndReturn(run func() (*cmd.Config, error)) *MockConfigurator_Load_Call { _c.Call.Return(run) return _c } -// Save provides a mock function with given fields: ctx, config -func (_m *MockConfigurator) Save(ctx context.Context, config *cmd.Config) error { - ret := _m.Called(ctx, config) +// Save provides a mock function with given fields: config +func (_m *MockConfigurator) Save(config *cmd.Config) error { + ret := _m.Called(config) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *cmd.Config) error); ok { - r0 = rf(ctx, config) + if rf, ok := ret.Get(0).(func(*cmd.Config) error); ok { + r0 = rf(config) } else { r0 = ret.Error(0) } @@ -139,15 +135,14 @@ type MockConfigurator_Save_Call struct { } // Save is a helper method to define mock.On call -// - ctx context.Context // - config *cmd.Config -func (_e *MockConfigurator_Expecter) Save(ctx interface{}, config interface{}) *MockConfigurator_Save_Call { - return &MockConfigurator_Save_Call{Call: _e.mock.On("Save", ctx, config)} +func (_e *MockConfigurator_Expecter) Save(config interface{}) *MockConfigurator_Save_Call { + return &MockConfigurator_Save_Call{Call: _e.mock.On("Save", config)} } -func (_c *MockConfigurator_Save_Call) Run(run func(ctx context.Context, config *cmd.Config)) *MockConfigurator_Save_Call { +func (_c *MockConfigurator_Save_Call) Run(run func(config *cmd.Config)) *MockConfigurator_Save_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*cmd.Config)) + run(args[0].(*cmd.Config)) }) return _c } @@ -157,7 +152,7 @@ func (_c *MockConfigurator_Save_Call) Return(_a0 error) *MockConfigurator_Save_C return _c } -func (_c *MockConfigurator_Save_Call) RunAndReturn(run func(context.Context, *cmd.Config) error) *MockConfigurator_Save_Call { +func (_c *MockConfigurator_Save_Call) RunAndReturn(run func(*cmd.Config) error) *MockConfigurator_Save_Call { _c.Call.Return(run) return _c }