diff --git a/Makefile b/Makefile index 45758e150..1722c7d08 100644 --- a/Makefile +++ b/Makefile @@ -301,7 +301,7 @@ e2e: ginkgo ## Build and run e2e tests. CONTROLLER_GEN = $(shell pwd)/bin/controller-gen controller-gen: ## Download controller-gen locally if necessary. - $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) + $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0) KUSTOMIZE = $(shell pwd)/bin/kustomize kustomize: ## Download kustomize locally if necessary. diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f43a3a39d..2246ef433 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* Copyright © 2023 Red Hat, Inc. diff --git a/bundle/manifests/lvm.topolvm.io_lvmclusters.yaml b/bundle/manifests/lvm.topolvm.io_lvmclusters.yaml index 9dbf48993..3727f4c3a 100644 --- a/bundle/manifests/lvm.topolvm.io_lvmclusters.yaml +++ b/bundle/manifests/lvm.topolvm.io_lvmclusters.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: lvmclusters.lvm.topolvm.io spec: @@ -176,10 +176,12 @@ spec: type: object type: array type: object + x-kubernetes-map-type: atomic type: array required: - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic thinPoolConfig: description: ThinPoolConfig contains configurations for the thin-pool @@ -333,5 +335,5 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/bundle/manifests/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml b/bundle/manifests/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml index f28b5357a..ea855e76d 100644 --- a/bundle/manifests/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml +++ b/bundle/manifests/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: lvmvolumegroupnodestatuses.lvm.topolvm.io spec: @@ -71,5 +71,5 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/bundle/manifests/lvm.topolvm.io_lvmvolumegroups.yaml b/bundle/manifests/lvm.topolvm.io_lvmvolumegroups.yaml index 8e6a46872..2849b3cf4 100644 --- a/bundle/manifests/lvm.topolvm.io_lvmvolumegroups.yaml +++ b/bundle/manifests/lvm.topolvm.io_lvmvolumegroups.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 + controller-gen.kubebuilder.io/version: v0.13.0 creationTimestamp: null name: lvmvolumegroups.lvm.topolvm.io spec: @@ -137,10 +137,12 @@ spec: type: object type: array type: object + x-kubernetes-map-type: atomic type: array required: - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic thinPoolConfig: description: ThinPoolConfig contains configurations for the thin-pool properties: @@ -180,5 +182,5 @@ status: acceptedNames: kind: "" plural: "" - conditions: [] - storedVersions: [] + conditions: null + storedVersions: null diff --git a/cmd/vgmanager/main.go b/cmd/vgmanager/main.go index 05fe4db51..e9747c543 100644 --- a/cmd/vgmanager/main.go +++ b/cmd/vgmanager/main.go @@ -21,6 +21,7 @@ import ( "os" lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1" + "github.com/openshift/lvm-operator/pkg/lvmd" "github.com/openshift/lvm-operator/pkg/vgmanager" "k8s.io/apimachinery/pkg/runtime" @@ -79,6 +80,7 @@ func main() { if err = (&vgmanager.VGReconciler{ Client: mgr.GetClient(), EventRecorder: mgr.GetEventRecorderFor(vgmanager.ControllerName), + LVMD: lvmd.DefaultConfigurator(), Scheme: mgr.GetScheme(), NodeName: os.Getenv("NODE_NAME"), Namespace: os.Getenv("POD_NAMESPACE"), diff --git a/config/crd/bases/lvm.topolvm.io_lvmclusters.yaml b/config/crd/bases/lvm.topolvm.io_lvmclusters.yaml index 1d4bc4a79..9dd8a935f 100644 --- a/config/crd/bases/lvm.topolvm.io_lvmclusters.yaml +++ b/config/crd/bases/lvm.topolvm.io_lvmclusters.yaml @@ -1,11 +1,9 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: lvmclusters.lvm.topolvm.io spec: group: lvm.topolvm.io @@ -174,10 +172,12 @@ spec: type: object type: array type: object + x-kubernetes-map-type: atomic type: array required: - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic thinPoolConfig: description: ThinPoolConfig contains configurations for the thin-pool @@ -327,9 +327,3 @@ spec: storage: true subresources: status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crd/bases/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml b/config/crd/bases/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml index ff299aa03..4567715f2 100644 --- a/config/crd/bases/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml +++ b/config/crd/bases/lvm.topolvm.io_lvmvolumegroupnodestatuses.yaml @@ -1,11 +1,9 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: lvmvolumegroupnodestatuses.lvm.topolvm.io spec: group: lvm.topolvm.io @@ -69,9 +67,3 @@ spec: storage: true subresources: status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crd/bases/lvm.topolvm.io_lvmvolumegroups.yaml b/config/crd/bases/lvm.topolvm.io_lvmvolumegroups.yaml index 6e19557ec..2cc3b6fd7 100644 --- a/config/crd/bases/lvm.topolvm.io_lvmvolumegroups.yaml +++ b/config/crd/bases/lvm.topolvm.io_lvmvolumegroups.yaml @@ -1,11 +1,9 @@ - --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.7.0 - creationTimestamp: null + controller-gen.kubebuilder.io/version: v0.13.0 name: lvmvolumegroups.lvm.topolvm.io spec: group: lvm.topolvm.io @@ -139,10 +137,12 @@ spec: type: object type: array type: object + x-kubernetes-map-type: atomic type: array required: - nodeSelectorTerms type: object + x-kubernetes-map-type: atomic thinPoolConfig: description: ThinPoolConfig contains configurations for the thin-pool properties: @@ -178,9 +178,3 @@ spec: storage: true subresources: status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index fe3f9f83d..b1069dd45 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -1,9 +1,7 @@ - --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - creationTimestamp: null name: manager-role rules: - apiGroups: diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 90d43e4bc..c92958ea7 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -1,9 +1,7 @@ - --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: - creationTimestamp: null name: validating-webhook-configuration webhooks: - admissionReviewVersions: diff --git a/pkg/lvmd/lvmd.go b/pkg/lvmd/lvmd.go new file mode 100644 index 000000000..625662d46 --- /dev/null +++ b/pkg/lvmd/lvmd.go @@ -0,0 +1,72 @@ +package lvmd + +import ( + "fmt" + "os" + + "github.com/topolvm/topolvm/lvmd" + lvmdCMD "github.com/topolvm/topolvm/pkg/lvmd/cmd" + "sigs.k8s.io/yaml" +) + +type Config = lvmdCMD.Config + +type DeviceClass = lvmd.DeviceClass +type ThinPoolConfig = lvmd.ThinPoolConfig + +var TypeThin = lvmd.TypeThin + +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() (*Config, error) + Save(config *Config) error + Delete() error +} + +type FileConfig struct { + path string +} + +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 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 + } +} + +func (c FileConfig) Save(config *Config) error { + out, err := yaml.Marshal(config) + if err == nil { + err = os.WriteFile(c.path, out, 0600) + } + if err != nil { + return fmt.Errorf("failed to save config file %s: %w", c.path, err) + } + return nil +} + +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 err +} diff --git a/pkg/vgmanager/vgmanager_controller.go b/pkg/vgmanager/vgmanager_controller.go index 1d1606d4b..8b272f9f6 100644 --- a/pkg/vgmanager/vgmanager_controller.go +++ b/pkg/vgmanager/vgmanager_controller.go @@ -19,18 +19,18 @@ package vgmanager import ( "context" "fmt" - "os" "strconv" "strings" "time" "github.com/google/go-cmp/cmp" + lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1" "github.com/openshift/lvm-operator/controllers" "github.com/openshift/lvm-operator/pkg/internal" "github.com/openshift/lvm-operator/pkg/lvm" - "github.com/topolvm/topolvm/lvmd" - lvmdCMD "github.com/topolvm/topolvm/pkg/lvmd/cmd" + "github.com/openshift/lvm-operator/pkg/lvmd" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +44,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/yaml" ) const ( @@ -87,6 +86,7 @@ type VGReconciler struct { record.EventRecorder Scheme *runtime.Scheme executor internal.Executor + LVMD lvmd.Configurator NodeName string Namespace string } @@ -144,7 +144,7 @@ func (r *VGReconciler) reconcile(ctx context.Context, volumeGroup *lvmv1alpha1.L } // Read the lvmd config file - lvmdConfig, err := loadLVMDConfig() + 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, err); err != nil { @@ -157,7 +157,7 @@ func (r *VGReconciler) reconcile(ctx context.Context, volumeGroup *lvmv1alpha1.L msg := "lvmd config file doesn't exist, will attempt to create a fresh config" logger.Info(msg) r.NormalEvent(ctx, volumeGroup, EventReasonLVMDConfigMissing, msg) - lvmdConfig = &lvmdCMD.Config{ + lvmdConfig = &lvmd.Config{ SocketName: controllers.DefaultLVMdSocket, } } @@ -279,7 +279,7 @@ func (r *VGReconciler) reconcile(ctx context.Context, volumeGroup *lvmv1alpha1.L // Apply and save lvmd config if !cmp.Equal(existingLvmdConfig, lvmdConfig) { - if err := saveLVMDConfig(lvmdConfig); err != nil { + if err := r.LVMD.Save(lvmdConfig); err != nil { err := fmt.Errorf("failed to update lvmd config file to update volume group %s: %w", volumeGroup.GetName(), err) if err := r.setVolumeGroupFailedStatus(ctx, volumeGroup, err); err != nil { logger.Error(err, "failed to set status to failed") @@ -304,7 +304,7 @@ func (r *VGReconciler) processDelete(ctx context.Context, volumeGroup *lvmv1alph logger := log.FromContext(ctx).WithValues("VGName", volumeGroup.Name) // Read the lvmd config file - lvmdConfig, err := loadLVMDConfig() + 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) @@ -373,14 +373,14 @@ func (r *VGReconciler) processDelete(ctx context.Context, volumeGroup *lvmv1alph // 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 = saveLVMDConfig(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 = deleteLVMDConfig(); 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" @@ -599,39 +599,3 @@ func (r *VGReconciler) matchesThisNode(ctx context.Context, selector *corev1.Nod } return NodeSelectorMatchesNodeLabels(node, selector) } - -func loadLVMDConfig() (*lvmdCMD.Config, error) { - - cfgBytes, err := os.ReadFile(controllers.LvmdConfigFile) - 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 load config file %s: %w", controllers.LvmdConfigFile, err) - } else { - lvmdconfig := &lvmdCMD.Config{} - if err = yaml.Unmarshal(cfgBytes, lvmdconfig); err != nil { - return nil, fmt.Errorf("failed to unmarshal config file %s: %w", controllers.LvmdConfigFile, err) - } - return lvmdconfig, nil - } -} - -func saveLVMDConfig(lvmdConfig *lvmdCMD.Config) error { - out, err := yaml.Marshal(lvmdConfig) - if err == nil { - err = os.WriteFile(controllers.LvmdConfigFile, out, 0600) - } - if err != nil { - return fmt.Errorf("failed to save config file %s: %w", controllers.LvmdConfigFile, err) - } - return nil -} - -func deleteLVMDConfig() error { - err := os.Remove(controllers.LvmdConfigFile) - if err != nil { - return fmt.Errorf("failed to delete config file %s: %w", controllers.LvmdConfigFile, err) - } - return err -}