Skip to content

Commit 898fffc

Browse files
committed
add secret watch for reconciliation on the key rotation cases
1 parent 56529d5 commit 898fffc

2 files changed

Lines changed: 504 additions & 1 deletion

File tree

internal/controller/metal3.io/baremetalhost_controller.go

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,22 @@ import (
4040
k8serrors "k8s.io/apimachinery/pkg/api/errors"
4141
"k8s.io/apimachinery/pkg/api/meta"
4242
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
43+
"k8s.io/apimachinery/pkg/types"
4344
"k8s.io/client-go/tools/record"
4445
ctrl "sigs.k8s.io/controller-runtime"
4546
"sigs.k8s.io/controller-runtime/pkg/builder"
4647
"sigs.k8s.io/controller-runtime/pkg/client"
4748
"sigs.k8s.io/controller-runtime/pkg/controller"
4849
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
4950
"sigs.k8s.io/controller-runtime/pkg/event"
51+
"sigs.k8s.io/controller-runtime/pkg/handler"
5052
"sigs.k8s.io/controller-runtime/pkg/predicate"
53+
"sigs.k8s.io/controller-runtime/pkg/reconcile"
5154
)
5255

5356
const (
57+
hostImageAuthSecretIndexField = ".spec.image.authSecretName"
58+
5459
hostErrorRetryDelay = time.Second * 10
5560
unmanagedRetryDelay = time.Minute * 10
5661
preprovImageRetryDelay = time.Minute * 5
@@ -2428,14 +2433,37 @@ func (r *BareMetalHostReconciler) updateEventHandler(e event.UpdateEvent) bool {
24282433
// SetupWithManager registers the reconciler to be run by the manager.
24292434
func (r *BareMetalHostReconciler) SetupWithManager(mgr ctrl.Manager, preprovImgEnable bool, maxConcurrentReconcile int) error {
24302435
r.Recorder = mgr.GetEventRecorderFor("baremetalhost-controller")
2436+
2437+
// Add index for image auth secret name to enable efficient secret-to-BMH lookups
2438+
if err := mgr.GetFieldIndexer().IndexField(
2439+
context.Background(),
2440+
&metal3api.BareMetalHost{},
2441+
hostImageAuthSecretIndexField,
2442+
func(obj client.Object) []string {
2443+
host := obj.(*metal3api.BareMetalHost)
2444+
if host.Spec.Image != nil && host.Spec.Image.AuthSecretName != nil && *host.Spec.Image.AuthSecretName != "" {
2445+
return []string{*host.Spec.Image.AuthSecretName}
2446+
}
2447+
return nil
2448+
},
2449+
); err != nil {
2450+
return fmt.Errorf("failed to create image auth secret index: %w", err)
2451+
}
2452+
24312453
controller := ctrl.NewControllerManagedBy(mgr).
24322454
For(&metal3api.BareMetalHost{}).
24332455
WithEventFilter(
24342456
predicate.Funcs{
24352457
UpdateFunc: r.updateEventHandler,
24362458
}).
24372459
WithOptions(controller.Options{MaxConcurrentReconciles: maxConcurrentReconcile}).
2438-
Owns(&corev1.Secret{}, builder.MatchEveryOwner)
2460+
Owns(&corev1.Secret{}, builder.MatchEveryOwner).
2461+
// Watch Secrets to trigger reconciliation when auth secrets are updated (key rotation)
2462+
Watches(
2463+
&corev1.Secret{},
2464+
handler.EnqueueRequestsFromMapFunc(r.findBMHsForAuthSecret),
2465+
builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}),
2466+
)
24392467

24402468
if preprovImgEnable {
24412469
// We use SetControllerReference() to set the owner reference, so no
@@ -2446,6 +2474,38 @@ func (r *BareMetalHostReconciler) SetupWithManager(mgr ctrl.Manager, preprovImgE
24462474
return controller.Complete(r)
24472475
}
24482476

2477+
// findBMHsForAuthSecret returns a list of reconcile requests for BareMetalHosts
2478+
// that reference the given Secret as their image auth secret.
2479+
// This enables auto-reconciliation when auth secrets are updated (key rotation).
2480+
func (r *BareMetalHostReconciler) findBMHsForAuthSecret(ctx context.Context, secret client.Object) []reconcile.Request {
2481+
// Only process secrets in the same namespace as BMHs
2482+
hosts := &metal3api.BareMetalHostList{}
2483+
if err := r.Client.List(
2484+
ctx,
2485+
hosts,
2486+
client.InNamespace(secret.GetNamespace()),
2487+
client.MatchingFields{hostImageAuthSecretIndexField: secret.GetName()},
2488+
); err != nil {
2489+
r.Log.Error(err, "failed to list BareMetalHosts for secret", "secret", secret.GetName())
2490+
return nil
2491+
}
2492+
2493+
requests := make([]reconcile.Request, len(hosts.Items))
2494+
for i, host := range hosts.Items {
2495+
requests[i] = reconcile.Request{
2496+
NamespacedName: types.NamespacedName{
2497+
Name: host.Name,
2498+
Namespace: host.Namespace,
2499+
},
2500+
}
2501+
r.Log.Info("queuing BMH reconcile due to auth secret change",
2502+
"baremetalhost", host.Name,
2503+
"secret", secret.GetName())
2504+
}
2505+
2506+
return requests
2507+
}
2508+
24492509
func (r *BareMetalHostReconciler) reconcileHostData(ctx context.Context, host *metal3api.BareMetalHost, request ctrl.Request) (result ctrl.Result, err error) {
24502510
reqLogger := r.Log.WithValues("baremetalhost", request.NamespacedName)
24512511

0 commit comments

Comments
 (0)