Skip to content

Commit 8caf641

Browse files
committed
feat(hypershift-operator): migrate webhooks to controller-runtime v0.24 generic API
Update webhook registrations to use the typed generic builder introduced in controller-runtime v0.23: - NewWebhookManagedBy(mgr).For(&obj{}) → NewWebhookManagedBy(mgr, &obj{}) - Validator/Defaulter methods now use concrete types instead of runtime.Object (e.g. *hyperv1.HostedCluster, *hyperv1.NodePool) - Add conversion.NewRegistry() parameter to NewWebhookHandler - Remove unused apierrors and runtime imports Signed-off-by: Bryan Cox <brcox@redhat.com> Commit-Message-Assisted-by: Claude (via Claude Code)
1 parent 79a74f7 commit 8caf641

69 files changed

Lines changed: 59899 additions & 295 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go.mod

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,10 @@ require (
150150
github.com/PaesslerAG/gval v1.2.3 // indirect
151151
github.com/PaesslerAG/jsonpath v0.1.1 // indirect
152152
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
153-
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
154-
github.com/asaskevich/govalidator/v11 v11.0.2-0.20250122183457-e11347878e23 // indirect
155153
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.13 // indirect
156154
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.29 // indirect
157155
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.29 // indirect
158156
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.29 // indirect
159-
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect
160157
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.30 // indirect
161158
github.com/aws/aws-sdk-go-v2/service/eks v1.77.0 // indirect
162159
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.12 // indirect
@@ -307,7 +304,6 @@ require (
307304
kubevirt.io/controller-lifecycle-operator-sdk/api v0.2.4 // indirect
308305
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect
309306
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
310-
sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96 // indirect
311307
sigs.k8s.io/kustomize/api v0.21.1 // indirect
312308
sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect
313309
sigs.k8s.io/randfill v1.0.0 // indirect

go.sum

Lines changed: 112 additions & 110 deletions
Large diffs are not rendered by default.

hypershift-operator/controllers/hostedcluster/hostedcluster_webhook.go

Lines changed: 12 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ import (
99
"github.com/openshift/hypershift/support/supportedversion"
1010
hyperutil "github.com/openshift/hypershift/support/util"
1111

12-
apierrors "k8s.io/apimachinery/pkg/api/errors"
1312
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14-
"k8s.io/apimachinery/pkg/runtime"
1513
"k8s.io/apimachinery/pkg/runtime/schema"
1614
utilrand "k8s.io/apimachinery/pkg/util/rand"
1715

@@ -32,12 +30,7 @@ type nodePoolDefaulter struct {
3230
client client.Client
3331
}
3432

35-
func (defaulter *hostedClusterDefaulter) Default(ctx context.Context, obj runtime.Object) error {
36-
hcluster, ok := obj.(*hyperv1.HostedCluster)
37-
if !ok {
38-
return apierrors.NewBadRequest(fmt.Sprintf("expected a HostedCluster but got a %T", obj))
39-
}
40-
33+
func (defaulter *hostedClusterDefaulter) Default(ctx context.Context, hcluster *hyperv1.HostedCluster) error {
4134
if hcluster.Spec.Release.Image == "" {
4235
pullSpec, err := supportedversion.LookupLatestSupportedRelease(ctx, hcluster)
4336
if err != nil {
@@ -87,12 +80,7 @@ func (defaulter *hostedClusterDefaulter) Default(ctx context.Context, obj runtim
8780
return nil
8881
}
8982

90-
func (defaulter *nodePoolDefaulter) Default(ctx context.Context, obj runtime.Object) error {
91-
np, ok := obj.(*hyperv1.NodePool)
92-
if !ok {
93-
return apierrors.NewBadRequest(fmt.Sprintf("expected a NodePool but got a %T", obj))
94-
}
95-
83+
func (defaulter *nodePoolDefaulter) Default(ctx context.Context, np *hyperv1.NodePool) error {
9684
if np.Spec.Release.Image == "" {
9785
if np.Spec.ClusterName == "" {
9886
return fmt.Errorf("nodePool.Spec.ClusterName is a required field")
@@ -131,24 +119,21 @@ func (defaulter *nodePoolDefaulter) Default(ctx context.Context, obj runtime.Obj
131119

132120
// SetupWebhookWithManager sets up HostedCluster webhooks.
133121
func SetupWebhookWithManager(mgr ctrl.Manager, imageMetaDataProvider *hyperutil.RegistryClientImageMetadataProvider, logger logr.Logger) error {
134-
err := ctrl.NewWebhookManagedBy(mgr).
135-
For(&hyperv1.HostedCluster{}).
122+
err := ctrl.NewWebhookManagedBy(mgr, &hyperv1.HostedCluster{}).
136123
WithDefaulter(&hostedClusterDefaulter{}).
137124
WithValidator(&hostedClusterValidator{}).
138125
Complete()
139126
if err != nil {
140127
return fmt.Errorf("unable to register hostedcluster webhook: %w", err)
141128
}
142-
err = ctrl.NewWebhookManagedBy(mgr).
143-
For(&hyperv1.NodePool{}).
129+
err = ctrl.NewWebhookManagedBy(mgr, &hyperv1.NodePool{}).
144130
WithDefaulter(&nodePoolDefaulter{client: mgr.GetClient()}).
145131
WithValidator(newNodePoolValidator(logger)).
146132
Complete()
147133
if err != nil {
148134
return fmt.Errorf("unable to register nodepool webhook: %w", err)
149135
}
150-
err = ctrl.NewWebhookManagedBy(mgr).
151-
For(&hyperv1.HostedControlPlane{}).
136+
err = ctrl.NewWebhookManagedBy(mgr, &hyperv1.HostedControlPlane{}).
152137
Complete()
153138
if err != nil {
154139
return fmt.Errorf("unable to register hostedcontrolplane webhook: %w", err)
@@ -167,21 +152,14 @@ func SetupWebhookWithManager(mgr ctrl.Manager, imageMetaDataProvider *hyperutil.
167152
})
168153

169154
// Register conversion webhook handler for CRD version conversions (HyperShift and CAPI types)
170-
mgr.GetWebhookServer().Register("/convert", conversion.NewWebhookHandler(mgr.GetScheme()))
155+
mgr.GetWebhookServer().Register("/convert", conversion.NewWebhookHandler(mgr.GetScheme(), conversion.NewRegistry()))
171156

172157
return nil
173158
}
174159

175-
var _ admission.CustomValidator = (*hostedClusterValidator)(nil)
176-
177160
type hostedClusterValidator struct{}
178161

179-
func (v hostedClusterValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
180-
hc, ok := obj.(*hyperv1.HostedCluster)
181-
if !ok {
182-
return nil, fmt.Errorf("wrong type %T for validation, instead of HostedCluster", obj)
183-
}
184-
162+
func (v hostedClusterValidator) ValidateCreate(ctx context.Context, hc *hyperv1.HostedCluster) (admission.Warnings, error) {
185163
switch hc.Spec.Platform.Type {
186164
case hyperv1.KubevirtPlatform:
187165
return v.validateCreateKubevirtHostedCluster(ctx, hc)
@@ -190,17 +168,7 @@ func (v hostedClusterValidator) ValidateCreate(ctx context.Context, obj runtime.
190168
}
191169
}
192170

193-
func (v hostedClusterValidator) ValidateUpdate(ctx context.Context, oldHC, newHC runtime.Object) (admission.Warnings, error) {
194-
hc, ok := newHC.(*hyperv1.HostedCluster)
195-
if !ok {
196-
return nil, fmt.Errorf("wrong type %T for validation, instead of HostedCluster", newHC)
197-
}
198-
199-
hcOld, ok := oldHC.(*hyperv1.HostedCluster)
200-
if !ok {
201-
return nil, fmt.Errorf("wrong type %T for validation, instead of HostedCluster", oldHC)
202-
}
203-
171+
func (v hostedClusterValidator) ValidateUpdate(ctx context.Context, hcOld, hc *hyperv1.HostedCluster) (admission.Warnings, error) {
204172
switch hc.Spec.Platform.Type {
205173
case hyperv1.KubevirtPlatform:
206174
err := v.validateUpdateKubevirtHostedCluster(ctx, hcOld, hc)
@@ -211,7 +179,7 @@ func (v hostedClusterValidator) ValidateUpdate(ctx context.Context, oldHC, newHC
211179
return nil, nil
212180
}
213181

214-
func (v hostedClusterValidator) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
182+
func (v hostedClusterValidator) ValidateDelete(_ context.Context, _ *hyperv1.HostedCluster) (admission.Warnings, error) {
215183
return nil, nil
216184
}
217185

@@ -243,12 +211,7 @@ func newNodePoolValidator(logger logr.Logger) *nodePoolValidator {
243211
}
244212
}
245213

246-
func (v nodePoolValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
247-
np, ok := obj.(*hyperv1.NodePool)
248-
if !ok {
249-
return nil, fmt.Errorf("wrong type %T for validation, instead of NodePool", obj)
250-
}
251-
214+
func (v nodePoolValidator) ValidateCreate(ctx context.Context, np *hyperv1.NodePool) (admission.Warnings, error) {
252215
switch np.Spec.Platform.Type {
253216
case hyperv1.KubevirtPlatform:
254217
return v.validateCreateKubevirtNodePool(ctx, np)
@@ -257,17 +220,7 @@ func (v nodePoolValidator) ValidateCreate(ctx context.Context, obj runtime.Objec
257220
}
258221
}
259222

260-
func (v nodePoolValidator) ValidateUpdate(ctx context.Context, oldNP, newNP runtime.Object) (admission.Warnings, error) {
261-
npNew, ok := newNP.(*hyperv1.NodePool)
262-
if !ok {
263-
return nil, fmt.Errorf("wrong type %T for validation, instead of NodePool", newNP)
264-
}
265-
266-
npOld, ok := oldNP.(*hyperv1.NodePool)
267-
if !ok {
268-
return nil, fmt.Errorf("wrong type %T for validation, instead of NodePool", npOld)
269-
}
270-
223+
func (v nodePoolValidator) ValidateUpdate(ctx context.Context, npOld, npNew *hyperv1.NodePool) (admission.Warnings, error) {
271224
switch npNew.Spec.Platform.Type {
272225
case hyperv1.KubevirtPlatform:
273226
err := v.validateUpdateKubevirtNodePool(ctx, npOld, npNew)
@@ -279,7 +232,7 @@ func (v nodePoolValidator) ValidateUpdate(ctx context.Context, oldNP, newNP runt
279232
return nil, nil
280233
}
281234

282-
func (v nodePoolValidator) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) {
235+
func (v nodePoolValidator) ValidateDelete(_ context.Context, _ *hyperv1.NodePool) (admission.Warnings, error) {
283236
return nil, nil
284237
}
285238

0 commit comments

Comments
 (0)