Skip to content

⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0#5378

Merged
camilamacedo86 merged 1 commit intokubernetes-sigs:masterfrom
camilamacedo86:upgrade-controll-runtime
Jan 20, 2026
Merged

⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0#5378
camilamacedo86 merged 1 commit intokubernetes-sigs:masterfrom
camilamacedo86:upgrade-controll-runtime

Conversation

@camilamacedo86
Copy link
Member

@camilamacedo86 camilamacedo86 commented Jan 19, 2026

Controller-Runtime v0.23.0 Breaking Changes

Description

Bump controller-runtime to v0.23.0.

controller-runtime v0.23.0 introduces breaking changes including type-safe webhook APIs, new events API, and test environment teardown improvements. This PR updates Kubebuilder's scaffolding/templates to match the new APIs, while keeping legacy scaffolding working.

Release notes: https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.23.0

Breaking Changes Summary

controller-runtime v0.23.0 introduced three major breaking changes:

  1. Type-safe webhook builder API - Webhooks now use generics for type safety
  2. New Events API - Migrated from tools/record to tools/events
  3. ENVTEST Teardown - testEnv.Stop() requires Eventually wrapper for graceful shutdown

1. (go/v4) Webhooks - Type-Safe API

Before (controller-runtime < v0.23.0)

import (
    "context"
    "fmt"
    
    "k8s.io/apimachinery/pkg/runtime"
    "sigs.k8s.io/controller-runtime/pkg/webhook"
    "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

func SetupCaptainWebhookWithManager(mgr ctrl.Manager) error {
    return ctrl.NewWebhookManagedBy(mgr).
        For(&crewv1.Captain{}).
        WithDefaulter(&CaptainCustomDefaulter{}).
        Complete()
}

var _ webhook.CustomDefaulter = &CaptainCustomDefaulter{}

func (d *CaptainCustomDefaulter) Default(_ context.Context, obj runtime.Object) error {
    captain, ok := obj.(*crewv1.Captain)
    if !ok {
        return fmt.Errorf("expected a Captain object but got %T", obj)
    }
    // ... use captain
}

var _ webhook.CustomValidator = &CaptainCustomValidator{}

func (v *CaptainCustomValidator) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) {
    captain, ok := obj.(*crewv1.Captain)
    if !ok {
        return nil, fmt.Errorf("expected a Captain object but got %T", obj)
    }
    // ... use captain
}

After (controller-runtime >= v0.23.0)

import (
    "context"
    
    "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

func SetupCaptainWebhookWithManager(mgr ctrl.Manager) error {
    return ctrl.NewWebhookManagedBy(mgr, &crewv1.Captain{}).
        WithDefaulter(&CaptainCustomDefaulter{}).
        Complete()
}

// Type-safe - no interface check needed
func (d *CaptainCustomDefaulter) Default(_ context.Context, obj *crewv1.Captain) error {
    // obj is already the correct type - no assertion needed
    // ... use obj directly
}

// Type-safe validation
func (v *CaptainCustomValidator) ValidateCreate(_ context.Context, obj *crewv1.Captain) (admission.Warnings, error) {
    // obj is already the correct type - no assertion needed
    // ... use obj directly
}

Key Changes

  • Type is now passed directly to NewWebhookManagedBy(mgr, &Type{}) instead of using .For(&Type{})
  • Webhook methods receive obj *Type instead of obj runtime.Object
  • No type assertions needed - full type safety
  • Less boilerplate, fewer runtime errors

Legacy Path Support: The --legacy flag still works with the new API.

Files Affected

  • Webhook files: internal/webhook/<version>/<kind>_webhook.go

2. (deploy-image/v1-alpha) Events Recorder API

(Only valid for those who create APIs with the DeployImage Plugin)

controller-runtime v0.23 migrates event recording toward the newer events.k8s.io API. As part of this, mgr.GetEventRecorderFor(...) is deprecated and triggers SA1019 in generated/sample projects.

Updates included in this PR:

  • Replace mgr.GetEventRecorderFor("...") with mgr.GetEventRecorder("...") in scaffolded cmd/main.go (including projects scaffolded with the deploy-image plugin).
  • Update the reconciler Recorder field type/imports accordingly (new events recorder API).
  • If a controller emits events, update any Recorder.Event* calls to the new signature.
  • Ensure RBAC for Events targets the events.k8s.io API group when required.

Before (controller-runtime < v0.23.0)

import (
    "k8s.io/client-go/tools/record"
    corev1 "k8s.io/api/core/v1"
)

type MemcachedReconciler struct {
    client.Client
    Scheme   *runtime.Scheme
    Recorder record.EventRecorder
}

// Setup
if err := (&controller.MemcachedReconciler{
    Client:   mgr.GetClient(),
    Scheme:   mgr.GetScheme(),
    Recorder: mgr.GetEventRecorderFor("memcached-controller"),
}).SetupWithManager(mgr); err != nil {
    // ...
}

// Usage
r.Recorder.Event(cr, "Warning", "Deleting", 
    fmt.Sprintf("Custom Resource %s is being deleted", cr.Name))

// RBAC
// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch

After (controller-runtime >= v0.23.0)

import (
    "k8s.io/client-go/tools/events"
    corev1 "k8s.io/api/core/v1"
)

type MemcachedReconciler struct {
    client.Client
    Scheme   *runtime.Scheme
    Recorder events.EventRecorder
}

// Setup
if err := (&controller.MemcachedReconciler{
    Client:   mgr.GetClient(),
    Scheme:   mgr.GetScheme(),
    Recorder: mgr.GetEventRecorder("memcached-controller"),
}).SetupWithManager(mgr); err != nil {
    // ...
}

// Usage (new signature with regarding/related objects)
r.Recorder.Eventf(cr, nil, corev1.EventTypeWarning, "Deleting", "DeleteCR",
    "Custom Resource %s is being deleted from the namespace %s",
    cr.Name, cr.Namespace)

// RBAC (updated API group)
// +kubebuilder:rbac:groups=events.k8s.io,resources=events,verbs=create;patch

Key Changes

  • Import: k8s.io/client-go/tools/recordk8s.io/client-go/tools/events
  • Type: record.EventRecorderevents.EventRecorder
  • Setup: mgr.GetEventRecorderFor()mgr.GetEventRecorder()
  • Usage: Event()Eventf() with new signature (regarding, related objects)
  • RBAC: groups=coregroups=events.k8s.io

Files Affected

  • Main file: cmd/main.go
  • Controller files: internal/controller/<kind>_controller.go

3. ENVTEST Teardown - AfterSuite with Eventually

controller-runtime v0.23.0 introduced timing changes in the test environment teardown process. Without using Eventually, testEnv.Stop() can fail intermittently with errors related to graceful shutdown timing.

Issue: Direct calls to testEnv.Stop() may return errors if the cleanup isn't complete immediately, causing test suite failures during teardown.

Solution: Wrap testEnv.Stop() in Eventually with a reasonable timeout to allow proper cleanup.

Before (controller-runtime < v0.23.0)

var _ = AfterSuite(func() {
    By("tearing down the test environment")
    cancel()
    err := testEnv.Stop()
    Expect(err).NotTo(HaveOccurred())
})

After (controller-runtime >= v0.23.0)

var _ = AfterSuite(func() {
    By("tearing down the test environment")
    cancel()
    Eventually(func() error {
        return testEnv.Stop()
    }, time.Minute, time.Second).Should(Succeed())
})

Why This Change

The Eventually wrapper retries the stop operation for up to 1 minute (checking every second), ensuring the test environment has sufficient time to clean up resources gracefully. This prevents flaky test failures during suite teardown.

Files Affected

  • Controller suite tests: internal/controller/suite_test.go
  • Webhook suite tests: internal/webhook/<version>/<kind>_webhook_suite_test.go

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 19, 2026
@k8s-ci-robot k8s-ci-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Jan 19, 2026
@camilamacedo86 camilamacedo86 force-pushed the upgrade-controll-runtime branch from 5ff681b to 5d1a725 Compare January 19, 2026 20:37
@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jan 19, 2026
@camilamacedo86 camilamacedo86 force-pushed the upgrade-controll-runtime branch 3 times, most recently from fc97a79 to ca77b70 Compare January 20, 2026 00:10
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR upgrades controller-runtime from v0.22.4 to v0.23.0, introducing breaking changes for type-safe webhook APIs using generics and migrating to the new Events API. The changes update all webhook scaffolding, templates, and testdata projects to use the new APIs while maintaining backward compatibility through legacy path support.

Changes:

  • Webhook API migration to type-safe generics, removing runtime.Object type assertions and interface checks
  • Events API migration from k8s.io/client-go/tools/record to k8s.io/client-go/tools/events with updated RBAC permissions
  • Test suite improvements using Eventually pattern for graceful webhook server shutdown

Reviewed changes

Copilot reviewed 89 out of 99 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pkg/plugins/golang/v4/scaffolds/init.go Updates ControllerRuntimeVersion constant to v0.23.0
pkg/plugins/golang/v4/scaffolds/internal/templates/webhooks/*.go Updates webhook templates with type-safe generics and removes type assertions
pkg/plugins/golang/deploy-image/v1alpha1/scaffolds/internal/templates/controllers/controller.go Migrates to new Events API with updated RBAC and Eventf signature
testdata/project-v4*/*_webhook.go Updates all webhook implementations to use type-safe generics
testdata/project-v4*/webhook_suite_test.go Adds Eventually pattern for graceful test environment shutdown
testdata/project-v4*/*_controller.go Updates controller-runtime documentation URLs and Events API usage
testdata/project-v4*/go.mod Upgrades controller-runtime to v0.23.0 and related dependencies
testdata/project-v4*/config/rbac/role.yaml Updates RBAC from core to events.k8s.io API group
test/e2e/utils/webhooks.go Updates test utilities to use generic object parameter naming
cmd/version.go Updates kubernetesVendorVersion to 1.35.0
build/.goreleaser.yml Updates KUBERNETES_VERSION to 1.35.0

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@vitorfloriano
Copy link
Contributor

Hi @camilamacedo86 shouldn't we change the implementation in testdata and documentation as well?

See: https://github.com/search?q=repo%3Acamilamacedo86%2Fkubebuilder+obj.%28*&type=code
and: https://github.com/search?q=repo%3Acamilamacedo86%2Fkubebuilder%20For(%26&type=code
and: https://github.com/search?q=repo%3Acamilamacedo86%2Fkubebuilder+record.E&type=code

@camilamacedo86 camilamacedo86 changed the title ⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0 ⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0 and add support to k8s 1.35 Jan 20, 2026
@camilamacedo86 camilamacedo86 force-pushed the upgrade-controll-runtime branch from f250e7b to 692b651 Compare January 20, 2026 08:51
@camilamacedo86
Copy link
Member Author

Hi @vitorfloriano

Thank you a lot for your help.
I think all is addressed now.

Could you please give a look and help us with this one for we are able to unblock the release?
If you are ok with can you please LGTM ?

@camilamacedo86 camilamacedo86 changed the title ⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0 and add support to k8s 1.35 ⚠️ Upgrade controller-runtime from v0.22.4 to v0.23.0 Jan 20, 2026
@camilamacedo86
Copy link
Member Author

/override APIDiff

(ignore it)

@k8s-ci-robot

This comment was marked as resolved.

@camilamacedo86
Copy link
Member Author

/test pull-kubebuilder-e2e-k8s-1-34-0

Copy link
Contributor

@vitorfloriano vitorfloriano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Jan 20, 2026
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: camilamacedo86, vitorfloriano

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@camilamacedo86 camilamacedo86 merged commit 5391809 into kubernetes-sigs:master Jan 20, 2026
38 of 40 checks passed
@camilamacedo86 camilamacedo86 deleted the upgrade-controll-runtime branch January 20, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants