-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Viktor Kramarenko <[email protected]>
- Loading branch information
1 parent
084c1ae
commit 2e4a5e4
Showing
9 changed files
with
539 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
156 changes: 156 additions & 0 deletions
156
images/sds-health-watcher-controller/src/pkg/controller/block_device_labels_watcher.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package controller | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"reflect" | ||
|
||
"github.com/deckhouse/sds-node-configurator/api/v1alpha1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/labels" | ||
"k8s.io/apimachinery/pkg/types" | ||
"k8s.io/client-go/util/workqueue" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/controller" | ||
"sigs.k8s.io/controller-runtime/pkg/event" | ||
"sigs.k8s.io/controller-runtime/pkg/handler" | ||
"sigs.k8s.io/controller-runtime/pkg/manager" | ||
"sigs.k8s.io/controller-runtime/pkg/reconcile" | ||
"sigs.k8s.io/controller-runtime/pkg/source" | ||
|
||
"sds-health-watcher-controller/pkg/logger" | ||
) | ||
|
||
const ( | ||
BlockDeviceWatcherCtrlName = "block-device-labels-watcher-controller" | ||
|
||
// LVGUpdateTriggerLabel if you change this value, you must change its value in agent/src/internal/const.go as well | ||
LVGUpdateTriggerLabel = "update-trigger" | ||
) | ||
|
||
func RunBlockDeviceLabelsWatcher( | ||
mgr manager.Manager, | ||
log logger.Logger, | ||
) error { | ||
cl := mgr.GetClient() | ||
|
||
c, err := controller.New(BlockDeviceWatcherCtrlName, mgr, controller.Options{ | ||
Reconciler: reconcile.Func(func(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { | ||
log.Info(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] starts to reconcile the BlockDevice %s", request.Name)) | ||
|
||
bd := &v1alpha1.BlockDevice{} | ||
err := cl.Get(ctx, request.NamespacedName, bd) | ||
if err != nil { | ||
if errors.IsNotFound(err) { | ||
log.Warning(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] seems like the BlockDevice %s was removed as it was not found. Stop the reconcile", request.Name)) | ||
return reconcile.Result{}, nil | ||
} | ||
|
||
log.Error(err, fmt.Sprintf("[RunBlockDeviceLabelsWatcher] unable to get the BlockDevice %s", request.Name)) | ||
return reconcile.Result{}, err | ||
} | ||
|
||
err = ReconcileBlockDeviceLabels(ctx, cl, log, bd) | ||
if err != nil { | ||
log.Error(err, fmt.Sprintf("[RunBlockDeviceLabelsWatcher] unable to reconcile the BlockDevice %s", bd.Name)) | ||
return reconcile.Result{}, err | ||
} | ||
log.Info(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] the BlockDevice %s was successfully reconciled", bd.Name)) | ||
return reconcile.Result{}, nil | ||
}), | ||
}) | ||
if err != nil { | ||
log.Error(err, "[RunBlockDeviceLabelsWatcher] unable to create the controller") | ||
return err | ||
} | ||
|
||
err = c.Watch(source.Kind(mgr.GetCache(), &v1alpha1.BlockDevice{}, handler.TypedFuncs[*v1alpha1.BlockDevice, reconcile.Request]{ | ||
CreateFunc: func(_ context.Context, e event.TypedCreateEvent[*v1alpha1.BlockDevice], q workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
log.Debug(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] got a Create event for the BlockDevice %s", e.Object.Name)) | ||
q.Add(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: e.Object.GetNamespace(), Name: e.Object.GetName()}}) | ||
log.Debug(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] the BlockDevice %s was added to the Reconciler's queue", e.Object.Name)) | ||
}, | ||
UpdateFunc: func(_ context.Context, e event.TypedUpdateEvent[*v1alpha1.BlockDevice], q workqueue.TypedRateLimitingInterface[reconcile.Request]) { | ||
log.Debug(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] got an Update event for the BlockDevice %s", e.ObjectNew.Name)) | ||
|
||
if reflect.DeepEqual(e.ObjectOld.Labels, e.ObjectNew.Labels) { | ||
log.Debug(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] no need to reconcile the BlockDevice %s as its labels are the same", e.ObjectNew.Name)) | ||
return | ||
} | ||
|
||
q.Add(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: e.ObjectNew.GetNamespace(), Name: e.ObjectNew.GetName()}}) | ||
log.Debug(fmt.Sprintf("[RunBlockDeviceLabelsWatcher] the BlockDevice %s was added to the Reconciler's queue", e.ObjectNew.Name)) | ||
}, | ||
})) | ||
if err != nil { | ||
log.Error(err, "[RunBlockDeviceLabelsWatcher] unable to controller.Watch") | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func ReconcileBlockDeviceLabels(ctx context.Context, cl client.Client, log logger.Logger, blockDevice *v1alpha1.BlockDevice) error { | ||
log.Info(fmt.Sprintf("[ReconcileBlockDeviceLabels] starts the reconciliation for the BlockDevice %s", blockDevice.Name)) | ||
log.Debug("[ReconcileBlockDeviceLabels] tries to list LVMVolumeGroups") | ||
lvgList := &v1alpha1.LVMVolumeGroupList{} | ||
err := cl.List(ctx, lvgList) | ||
if err != nil { | ||
return err | ||
} | ||
log.Debug("[ReconcileBlockDeviceLabels] successfully listed LVMVolumeGroups") | ||
|
||
for _, lvg := range lvgList.Items { | ||
log.Debug(fmt.Sprintf("[ReconcileBlockDeviceLabels] tries to configure a selector from blockDeviceSelector of the LVMVolumeGroup %s", lvg.Name)) | ||
selector, err := metav1.LabelSelectorAsSelector(lvg.Spec.BlockDeviceSelector) | ||
if err != nil { | ||
return err | ||
} | ||
log.Debug(fmt.Sprintf("[ReconcileBlockDeviceLabels] successfully configured a selector from blockDeviceSelector of the LVMVolumeGroup %s", lvg.Name)) | ||
|
||
usedBdNames := make(map[string]struct{}, len(lvg.Status.Nodes[0].Devices)) | ||
for _, n := range lvg.Status.Nodes { | ||
for _, d := range n.Devices { | ||
usedBdNames[d.BlockDevice] = struct{}{} | ||
} | ||
} | ||
if lvg.Labels == nil { | ||
lvg.Labels = make(map[string]string) | ||
} | ||
if selector.Matches(labels.Set(blockDevice.Labels)) { | ||
log.Debug(fmt.Sprintf("[ReconcileBlockDeviceLabels] BlockDevice %s matches a blockDeviceSelector of the LVMVolumeGroup %s", blockDevice.Name, lvg.Name)) | ||
if _, used := usedBdNames[blockDevice.Name]; !used { | ||
log.Debug(fmt.Sprintf("[ReconcileBlockDeviceLabels] the BlockDevice %s matches the LVMVolumeGroup %s blockDeviceSelector, but is not used yet. Add the label %s to provide LVMVolumeGroup resource configuration update", blockDevice.Name, lvg.Name, LVGUpdateTriggerLabel)) | ||
lvg.Labels[LVGUpdateTriggerLabel] = "true" | ||
|
||
err = cl.Update(ctx, &lvg) | ||
if err != nil { | ||
return err | ||
} | ||
log.Info(fmt.Sprintf("[ReconcileBlockDeviceLabels] successfully added the label %s to provide LVMVolumeGroup %s resource configuration update", LVGUpdateTriggerLabel, lvg.Name)) | ||
continue | ||
} | ||
|
||
log.Info(fmt.Sprintf("[ReconcileBlockDeviceLabels] the BlockDevice %s matches the LVMVolumeGroup %s blockDeviceSelector and already used by the resource", blockDevice.Name, lvg.Name)) | ||
continue | ||
} | ||
|
||
log.Debug(fmt.Sprintf("[ReconcileBlockDeviceLabels] BlockDevice %s does not match a blockDeviceSelector of the LVMVolumeGroup %s", blockDevice.Name, lvg.Name)) | ||
if _, used := usedBdNames[blockDevice.Name]; used { | ||
log.Warning(fmt.Sprintf("[ReconcileBlockDeviceLabels] the BlockDevice %s does not match the LVMVolumeGroup %s blockDeviceSelector, but is used by the resource. Add the label %s to provide LVMVolumeGroup resource configuration update", blockDevice.Name, lvg.Name, LVGUpdateTriggerLabel)) | ||
lvg.Labels[LVGUpdateTriggerLabel] = "true" | ||
|
||
err = cl.Update(ctx, &lvg) | ||
if err != nil { | ||
return err | ||
} | ||
log.Info(fmt.Sprintf("[ReconcileBlockDeviceLabels] successfully added the label %s to provide LVMVolumeGroup %s resource configuration update", LVGUpdateTriggerLabel, lvg.Name)) | ||
continue | ||
} | ||
|
||
log.Info(fmt.Sprintf("[ReconcileBlockDeviceLabels] the BlockDevice %s does not match the LVMVolumeGroup %s blockDeviceSelector and is not used by the resource", blockDevice.Name, lvg.Name)) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.