Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCPVE-613: feat: switch to SSA for resource reconciliation #395

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions controllers/lvm_volumegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ import (
lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1"
k8serror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
cutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

Expand All @@ -32,7 +35,7 @@ const (
lvmvgFinalizer = "lvm.openshift.io/lvmvolumegroup"
)

type lvmVG struct{}
type lvmVG struct{ *runtime.Scheme }

func (c lvmVG) getName() string {
return lvmVGName
Expand All @@ -43,30 +46,23 @@ func (c lvmVG) ensureCreated(r *LVMClusterReconciler, ctx context.Context, lvmCl
lvmVolumeGroups := lvmVolumeGroups(r.Namespace, lvmCluster.Spec.Storage.DeviceClasses)

for _, volumeGroup := range lvmVolumeGroups {
existingVolumeGroup := &lvmv1alpha1.LVMVolumeGroup{
ObjectMeta: metav1.ObjectMeta{
Name: volumeGroup.Name,
Namespace: volumeGroup.Namespace,
},
if versioned, err := c.Scheme.ConvertToVersion(volumeGroup,
runtime.GroupVersioner(schema.GroupVersions(c.Scheme.PrioritizedVersionsAllGroups()))); err == nil {
volumeGroup = versioned.(*lvmv1alpha1.LVMVolumeGroup)
}

err := cutil.SetControllerReference(lvmCluster, existingVolumeGroup, r.Scheme)
err := cutil.SetControllerReference(lvmCluster, volumeGroup, r.Scheme)
if err != nil {
r.Log.Error(err, "failed to set controller reference to LVMVolumeGroup with name", volumeGroup.Name)
return err
}

result, err := cutil.CreateOrUpdate(ctx, r.Client, existingVolumeGroup, func() error {
existingVolumeGroup.Finalizers = volumeGroup.Finalizers
existingVolumeGroup.Spec = volumeGroup.Spec
return nil
})

err = r.Client.Patch(ctx, volumeGroup, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName))
if err != nil {
r.Log.Error(err, "failed to reconcile LVMVolumeGroup", "name", volumeGroup.Name)
return err
}
r.Log.Info("successfully reconciled LVMVolumeGroup", "operation", result, "name", volumeGroup.Name)
r.Log.Info("successfully reconciled LVMVolumeGroup", "name", volumeGroup.Name)
}
return nil
}
Expand Down Expand Up @@ -138,7 +134,7 @@ func lvmVolumeGroups(namespace string, deviceClasses []lvmv1alpha1.DeviceClass)
NodeSelector: deviceClass.NodeSelector,
DeviceSelector: deviceClass.DeviceSelector,
ThinPoolConfig: deviceClass.ThinPoolConfig,
Default: len(deviceClasses) == 1 || deviceClass.Default, //True if there is only one device class or default is explicitly set.
Default: len(deviceClasses) == 1 || deviceClass.Default, // True if there is only one device class or default is explicitly set.
},
}
lvmVolumeGroups = append(lvmVolumeGroups, lvmVolumeGroup)
Expand Down
21 changes: 11 additions & 10 deletions controllers/lvmcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func (r *LVMClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request)
// errors returned by this will be updated in the reconcileSucceeded condition of the LVMCluster
func (r *LVMClusterReconciler) reconcile(ctx context.Context, instance *lvmv1alpha1.LVMCluster) (ctrl.Result, error) {

//The resource was deleted
// The resource was deleted
if !instance.DeletionTimestamp.IsZero() {
// Check for existing LogicalVolumes
lvsExist, err := r.logicalVolumesExist(ctx, instance)
Expand Down Expand Up @@ -198,14 +198,14 @@ func (r *LVMClusterReconciler) reconcile(ctx context.Context, instance *lvmv1alp
}

resourceCreationList := []resourceManager{
&csiDriver{},
&topolvmController{r.TopoLVMLeaderElectionPassthrough},
&openshiftSccs{},
&topolvmNode{},
&vgManager{},
&lvmVG{},
&topolvmStorageClass{},
&topolvmVolumeSnapshotClass{},
&csiDriver{r.Scheme},
&topolvmController{r.Scheme, r.TopoLVMLeaderElectionPassthrough},
&openshiftSccs{r.Scheme},
&topolvmNode{r.Scheme},
&vgManager{r.Scheme},
&lvmVG{r.Scheme},
&topolvmStorageClass{r.Scheme},
&topolvmVolumeSnapshotClass{r.Scheme},
}

// handle create/update
Expand Down Expand Up @@ -290,7 +290,8 @@ func (r *LVMClusterReconciler) updateLVMClusterStatus(ctx context.Context, insta

instance.Status.DeviceClassStatuses = allVgStatuses
// Apply status changes
err = r.Client.Status().Update(ctx, instance)
instance.SetManagedFields(nil)
err = r.Client.Status().Patch(ctx, instance, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName))
if err != nil {
if errors.IsNotFound(err) {
r.Log.Error(err, "failed to update status")
Expand Down
3 changes: 2 additions & 1 deletion controllers/scc.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

const (
sccName = "topolvm-scc"
)

type openshiftSccs struct{}
type openshiftSccs struct{ *runtime.Scheme }

// openshiftSccs unit satisfies resourceManager interface
var _ resourceManager = openshiftSccs{}
Expand Down
36 changes: 19 additions & 17 deletions controllers/topolvm_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ package controllers
import (
"context"
"fmt"
v1 "github.com/openshift/api/config/v1"
"path/filepath"

v1 "github.com/openshift/api/config/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/client"

lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
Expand All @@ -39,6 +43,7 @@ const (
)

type topolvmController struct {
*runtime.Scheme
topoLVMLeaderElectionPassthrough v1.LeaderElection
}

Expand All @@ -54,30 +59,25 @@ func (c topolvmController) getName() string {
func (c topolvmController) ensureCreated(r *LVMClusterReconciler, ctx context.Context, lvmCluster *lvmv1alpha1.LVMCluster) error {

// get the desired state of topolvm controller deployment
desiredDeployment := getControllerDeployment(lvmCluster, r.Namespace, r.ImageName, c.topoLVMLeaderElectionPassthrough)
existingDeployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: desiredDeployment.Name,
Namespace: desiredDeployment.Namespace,
},
deploy := getControllerDeployment(lvmCluster, r.Namespace, r.ImageName, c.topoLVMLeaderElectionPassthrough)

if versioned, err := c.Scheme.ConvertToVersion(deploy,
runtime.GroupVersioner(schema.GroupVersions(c.Scheme.PrioritizedVersionsAllGroups()))); err == nil {
deploy = versioned.(*appsv1.Deployment)
}

err := cutil.SetControllerReference(lvmCluster, existingDeployment, r.Scheme)
err := cutil.SetControllerReference(lvmCluster, deploy, r.Scheme)
if err != nil {
r.Log.Error(err, "failed to set controller reference to topolvm controller deployment with name", existingDeployment.Name)
r.Log.Error(err, "failed to set controller reference to topolvm controller deployment with name", deploy.Name)
return err
}

result, err := cutil.CreateOrUpdate(ctx, r.Client, existingDeployment, func() error {
return c.setTopolvmControllerDesiredState(existingDeployment, desiredDeployment)
})

if err != nil {
r.Log.Error(err, "csi controller reconcile failure", "name", desiredDeployment.Name)
if err := r.Client.Patch(ctx, deploy, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName)); err != nil {
r.Log.Error(err, "csi controller reconcile failure", "name", deploy.Name)
return err
}

r.Log.Info("csi controller", "operation", result, "name", desiredDeployment.Name)
r.Log.Info("csi controller", "name", deploy.Name)
return nil
}

Expand Down Expand Up @@ -159,7 +159,7 @@ func getControllerDeployment(lvmCluster *lvmv1alpha1.LVMCluster, namespace strin
AppKubernetesComponentLabel: TopolvmControllerLabelVal,
}

return &appsv1.Deployment{
deploy := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: TopolvmControllerDeploymentName,
Namespace: namespace,
Expand All @@ -186,6 +186,8 @@ func getControllerDeployment(lvmCluster *lvmv1alpha1.LVMCluster, namespace strin
},
},
}

return deploy
}

func initContainer(initImage string) corev1.Container {
Expand Down
26 changes: 16 additions & 10 deletions controllers/topolvm_csi_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,19 @@ import (
storagev1 "k8s.io/api/storage/v1"
k8serror "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
cutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
driverName = "topolvm-csi-driver"
)

type csiDriver struct{}
type csiDriver struct {
*runtime.Scheme
}

// csiDriver unit satisfies resourceManager interface
var _ resourceManager = csiDriver{}
Expand All @@ -43,20 +47,22 @@ func (c csiDriver) getName() string {

//+kubebuilder:rbac:groups=storage.k8s.io,resources=csidrivers,verbs=get;create;delete;watch;list

func (c csiDriver) ensureCreated(r *LVMClusterReconciler, ctx context.Context, lvmCluster *lvmv1alpha1.LVMCluster) error {
csiDriverResource := getCSIDriverResource()
func (c csiDriver) ensureCreated(r *LVMClusterReconciler, ctx context.Context, _ *lvmv1alpha1.LVMCluster) error {
driver := getCSIDriverResource()

if versioned, err := c.Scheme.ConvertToVersion(driver,
runtime.GroupVersioner(schema.GroupVersions(c.Scheme.PrioritizedVersionsAllGroups()))); err == nil {
driver = versioned.(*storagev1.CSIDriver)
}

result, err := cutil.CreateOrUpdate(ctx, r.Client, csiDriverResource, func() error {
// no need to mutate any field
return nil
})
err := r.Client.Patch(ctx, driver, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName))

if err != nil {
r.Log.Error(err, "csi driver reconcile failure", "name", csiDriverResource.Name)
r.Log.Error(err, "csi driver reconcile failure", "name", driver.Name)
return err
}

r.Log.Info("csi driver", "operation", result, "name", csiDriverResource.Name)
r.Log.Info("csi driver", "name", driver.Name)
return nil
}

Expand Down
47 changes: 11 additions & 36 deletions controllers/topolvm_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,19 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
cutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

const (
topolvmNodeName = "topolvm-node"
)

type topolvmNode struct{}
type topolvmNode struct{ *runtime.Scheme }

func (n topolvmNode) getName() string {
return topolvmNodeName
Expand All @@ -49,14 +52,10 @@ func (n topolvmNode) ensureCreated(r *LVMClusterReconciler, ctx context.Context,
unitLogger := r.Log.WithValues("topolvmNode", n.getName())

// get desired daemonSet spec
dsTemplate := getNodeDaemonSet(lvmCluster, r.Namespace, r.ImageName)

// create desired daemonSet or update mutable fields on existing one
ds := &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: dsTemplate.Name,
Namespace: dsTemplate.Namespace,
},
ds := getNodeDaemonSet(lvmCluster, r.Namespace, r.ImageName)
if versioned, err := n.Scheme.ConvertToVersion(ds,
runtime.GroupVersioner(schema.GroupVersions(n.Scheme.PrioritizedVersionsAllGroups()))); err == nil {
ds = versioned.(*appsv1.DaemonSet)
}

err := cutil.SetControllerReference(lvmCluster, ds, r.Scheme)
Expand All @@ -65,37 +64,13 @@ func (n topolvmNode) ensureCreated(r *LVMClusterReconciler, ctx context.Context,
return err
}

unitLogger.Info("running CreateOrUpdate")
result, err := cutil.CreateOrUpdate(ctx, r.Client, ds, func() error {
// at creation, deep copy the whole daemonSet
if ds.CreationTimestamp.IsZero() {
dsTemplate.DeepCopyInto(ds)
return nil
}
// if update, update only mutable fields
// For topolvm Node, we have containers, initcontainers, node selector and toleration terms

// containers
ds.Spec.Template.Spec.Containers = dsTemplate.Spec.Template.Spec.Containers

// initcontainers
ds.Spec.Template.Spec.InitContainers = dsTemplate.Spec.Template.Spec.InitContainers

// tolerations
ds.Spec.Template.Spec.Tolerations = dsTemplate.Spec.Template.Spec.Tolerations

// nodeSelector if non-nil
if dsTemplate.Spec.Template.Spec.Affinity != nil {
setDaemonsetNodeSelector(dsTemplate.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution, ds)
}

return nil
})
unitLogger.Info("Apply")
err = r.Client.Patch(ctx, ds, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName))

if err != nil {
r.Log.Error(err, fmt.Sprintf("%s reconcile failure", topolvmNodeName), "name", ds.Name)
} else {
r.Log.Info(topolvmNodeName, "operation", result, "name", ds.Name)
r.Log.Info(topolvmNodeName, "name", ds.Name)
}
return err
}
Expand Down
14 changes: 10 additions & 4 deletions controllers/topolvm_snapshotclass.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,18 @@ import (
lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/discovery"
cutil "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
vscName = "topolvm-volumeSnapshotClass"
)

type topolvmVolumeSnapshotClass struct{}
type topolvmVolumeSnapshotClass struct{ *runtime.Scheme }

// topolvmVolumeSnapshotClass unit satisfies resourceManager interface
var _ resourceManager = topolvmVolumeSnapshotClass{}
Expand All @@ -50,9 +52,13 @@ func (s topolvmVolumeSnapshotClass) ensureCreated(r *LVMClusterReconciler, ctx c
// one volume snapshot class for every deviceClass based on CR is created
topolvmSnapshotClasses := getTopolvmSnapshotClasses(lvmCluster)
for _, vsc := range topolvmSnapshotClasses {
if versioned, err := s.Scheme.ConvertToVersion(vsc,
runtime.GroupVersioner(schema.GroupVersions(s.Scheme.PrioritizedVersionsAllGroups()))); err == nil {
vsc = versioned.(*snapapi.VolumeSnapshotClass)
}

// we anticipate no edits to volume snapshot class
result, err := cutil.CreateOrUpdate(ctx, r.Client, vsc, func() error { return nil })
err := r.Client.Patch(ctx, vsc, client.Apply, client.ForceOwnership, client.FieldOwner(ControllerName))
if err != nil {
// this is necessary in case the VolumeSnapshotClass CRDs are not registered in the Distro, e.g. for OpenShift Local
if discovery.IsGroupDiscoveryFailedError(errors.Unwrap(err)) {
Expand All @@ -62,7 +68,7 @@ func (s topolvmVolumeSnapshotClass) ensureCreated(r *LVMClusterReconciler, ctx c
r.Log.Error(err, "topolvm volume snapshot class reconcile failure", "name", vsc.Name)
return err
} else {
r.Log.Info("topolvm volume snapshot class", "operation", result, "name", vsc.Name)
r.Log.Info("topolvm volume snapshot class", "name", vsc.Name)
}
}
return nil
Expand Down
Loading