Skip to content

Commit

Permalink
feat: switch to SSA for resource reconciliation
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobmoellerdev committed Aug 23, 2023
1 parent aebdf45 commit 99cbdf8
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 161 deletions.
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

0 comments on commit 99cbdf8

Please sign in to comment.