mirror of
https://github.com/imjasonh/client-go2
synced 2026-07-07 00:33:49 +00:00
Fix controller example to implement correct interface method (#6)
* Fix controller example to implement correct interface method - Change ReconcileKind to Reconcile to match the Reconciler interface - Add nil check for secretLister to handle initialization timing - Fix OnError handler in e2e test to not fail immediately on expected errors This allows the controller-owned-lister example to compile and run correctly. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Update examples/controller-owned-lister/main.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
da1a422278
commit
6c7409049e
8 changed files with 25 additions and 19 deletions
|
|
@ -5,7 +5,7 @@ The `controller` package provides a generic Kubernetes controller framework insp
|
|||
## Features
|
||||
|
||||
- **Type-safe generic controllers** - Build controllers for any Kubernetes resource type
|
||||
- **Simple reconciler interface** - Just implement one method: `ReconcileKind` or pass a function.
|
||||
- **Simple reconciler interface** - Just implement one method: `Reconcile` or pass a function.
|
||||
- **Automatic update detection** - The framework detects and persists changes to your objects
|
||||
- **Built-in conflict resolution** - Automatic retry with exponential backoff
|
||||
- **Owner reference support** - Automatically reconcile owners when owned resources change
|
||||
|
|
@ -42,7 +42,7 @@ The core interface has just one method:
|
|||
|
||||
```go
|
||||
type Reconciler[T runtime.Object] interface {
|
||||
ReconcileKind(ctx context.Context, obj T) error
|
||||
Reconcile(ctx context.Context, obj T) error
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ The controller automatically detects and persists changes made during reconcilia
|
|||
Example:
|
||||
|
||||
```go
|
||||
func (r *MyReconciler) ReconcileKind(ctx context.Context, pod *corev1.Pod) error {
|
||||
func (r *MyReconciler) Reconcile(ctx context.Context, pod *corev1.Pod) error {
|
||||
// These changes will be automatically persisted
|
||||
pod.Labels["processed"] = "true"
|
||||
pod.Status.Phase = corev1.PodRunning
|
||||
|
|
@ -125,7 +125,7 @@ The controller can watch owned resources and reconcile owners when owned resourc
|
|||
|
||||
```go
|
||||
// In your reconciler, set owner references
|
||||
func (r *MyReconciler) ReconcileKind(ctx context.Context, pod *corev1.Pod) error {
|
||||
func (r *MyReconciler) Reconcile(ctx context.Context, pod *corev1.Pod) error {
|
||||
// Create a owned secret
|
||||
secret := &corev1.Secret{...}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ func (c *Controller[T]) processItem(ctx context.Context, key string) error {
|
|||
original := c.deepCopy(current)
|
||||
|
||||
// Call user's reconciler - they modify 'current' in place
|
||||
if err := c.reconciler.ReconcileKind(ctx, current); err != nil {
|
||||
if err := c.reconciler.Reconcile(ctx, current); err != nil {
|
||||
// Don't update if reconciler returned error
|
||||
return err
|
||||
}
|
||||
|
|
@ -228,7 +228,7 @@ func (c *Controller[T]) updateIfNeeded(ctx context.Context, original, current T)
|
|||
|
||||
// Warn if spec changed (not allowed)
|
||||
if specChanged {
|
||||
clog.WarnContext(ctx, "spec changes ignored in ReconcileKind",
|
||||
clog.WarnContext(ctx, "spec changes ignored in Reconcile",
|
||||
"namespace", origMeta.Namespace,
|
||||
"name", origMeta.Name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
// // dependencies
|
||||
// }
|
||||
//
|
||||
// func (r *MyReconciler) ReconcileKind(ctx context.Context, pod *corev1.Pod) error {
|
||||
// func (r *MyReconciler) Reconcile(ctx context.Context, pod *corev1.Pod) error {
|
||||
// // Complex reconciliation logic
|
||||
// return nil
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ type PodReconciler struct {
|
|||
// Add dependencies here
|
||||
}
|
||||
|
||||
// ReconcileKind implements the Reconciler interface.
|
||||
func (r *PodReconciler) ReconcileKind(ctx context.Context, pod *corev1.Pod) error {
|
||||
// Reconcile implements the Reconciler interface.
|
||||
func (r *PodReconciler) Reconcile(ctx context.Context, pod *corev1.Pod) error {
|
||||
// Complex reconciliation logic
|
||||
if pod.DeletionTimestamp != nil {
|
||||
// Handle deletion
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
// Reconciler is the interface for reconciling objects of type T.
|
||||
// Implementations should mutate the object in-place. The controller will
|
||||
// automatically persist any changes to the object's status and finalizers
|
||||
// after ReconcileKind returns successfully.
|
||||
// after Reconcile returns successfully.
|
||||
//
|
||||
// Important rules:
|
||||
// - DO modify obj.Status to update status (will be persisted)
|
||||
|
|
@ -17,7 +17,7 @@ import (
|
|||
// - DO NOT modify obj.Spec (changes will be ignored and logged)
|
||||
// - DO NOT modify obj.Metadata except for finalizers (changes will be ignored)
|
||||
type Reconciler[T runtime.Object] interface {
|
||||
ReconcileKind(ctx context.Context, obj T) error
|
||||
Reconcile(ctx context.Context, obj T) error
|
||||
}
|
||||
|
||||
// ReconcilerFunc is an adapter to allow ordinary functions to be used as Reconcilers.
|
||||
|
|
@ -25,7 +25,7 @@ type Reconciler[T runtime.Object] interface {
|
|||
// Reconciler[T] that calls f.
|
||||
type ReconcilerFunc[T runtime.Object] func(ctx context.Context, obj T) error
|
||||
|
||||
// ReconcileKind calls f(ctx, obj).
|
||||
func (f ReconcilerFunc[T]) ReconcileKind(ctx context.Context, obj T) error {
|
||||
// Reconcile calls f(ctx, obj).
|
||||
func (f ReconcilerFunc[T]) Reconcile(ctx context.Context, obj T) error {
|
||||
return f(ctx, obj)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func TestReconcilerFunc(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
err := fn.ReconcileKind(context.Background(), pod)
|
||||
err := fn.Reconcile(context.Background(), pod)
|
||||
if !called {
|
||||
t.Error("reconciler function was not called")
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ type testReconciler struct {
|
|||
err error
|
||||
}
|
||||
|
||||
func (r *testReconciler) ReconcileKind(ctx context.Context, pod *corev1.Pod) error {
|
||||
func (r *testReconciler) Reconcile(ctx context.Context, pod *corev1.Pod) error {
|
||||
r.called = true
|
||||
// Modify the pod to test automatic updates
|
||||
if pod.Status.Phase == "" {
|
||||
|
|
@ -63,7 +63,7 @@ func TestReconcilerInterface(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
err := r.ReconcileKind(context.Background(), pod)
|
||||
err := r.Reconcile(context.Background(), pod)
|
||||
if !r.called {
|
||||
t.Error("reconciler was not called")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,15 @@ type ConfigMapReconciler struct {
|
|||
secretLister *generic.Lister[*corev1.Secret]
|
||||
}
|
||||
|
||||
func (r *ConfigMapReconciler) ReconcileKind(ctx context.Context, cm *corev1.ConfigMap) error {
|
||||
func (r *ConfigMapReconciler) Reconcile(ctx context.Context, cm *corev1.ConfigMap) error {
|
||||
log := clog.FromContext(ctx)
|
||||
|
||||
// Check if secretLister is available
|
||||
if r.secretLister == nil {
|
||||
log.Info("Secret lister not available yet")
|
||||
return fmt.Errorf("secret lister not available")
|
||||
}
|
||||
|
||||
// List secrets in the same namespace
|
||||
secrets, err := r.secretLister.ByNamespace(cm.Namespace).List(labels.Everything())
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ type ConfigMapReconciler struct {
|
|||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// ReconcileKind implements the reconciliation logic for ConfigMaps.
|
||||
func (r *ConfigMapReconciler) ReconcileKind(ctx context.Context, cm *corev1.ConfigMap) error {
|
||||
// Reconcile implements the reconciliation logic for ConfigMaps.
|
||||
func (r *ConfigMapReconciler) Reconcile(ctx context.Context, cm *corev1.ConfigMap) error {
|
||||
r.logger.Info("reconciling configmap",
|
||||
"namespace", cm.Namespace,
|
||||
"name", cm.Name,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue