@@ -19,18 +19,21 @@ import (
1919 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2020 logf "sigs.k8s.io/controller-runtime/pkg/log"
2121 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
22+ mccontext "sigs.k8s.io/multicluster-runtime/pkg/context"
23+ mcmanager "sigs.k8s.io/multicluster-runtime/pkg/manager"
2224)
2325
2426var noteLog = logf .Log .WithName ("note-resource" )
2527
26- func SetupNoteWebhooksWithManager (mgr ctrl.Manager ) error {
28+ func SetupNoteWebhooksWithManager (mgr ctrl.Manager , mcMgr mcmanager. Manager ) error {
2729 noteLog .Info ("Setting up notes.miloapis.com note webhooks" )
2830 return ctrl .NewWebhookManagedBy (mgr ).
2931 For (& notesv1alpha1.Note {}).
3032 WithDefaulter (& NoteMutator {
31- Client : mgr .GetClient (),
32- Scheme : mgr .GetScheme (),
33- RESTMapper : mgr .GetRESTMapper (),
33+ Client : mgr .GetClient (),
34+ Scheme : mgr .GetScheme (),
35+ RESTMapper : mgr .GetRESTMapper (),
36+ ClusterManager : mcMgr ,
3437 }).
3538 WithValidator (& NoteValidator {
3639 Client : mgr .GetClient (),
@@ -41,9 +44,10 @@ func SetupNoteWebhooksWithManager(mgr ctrl.Manager) error {
4144// +kubebuilder:webhook:path=/mutate-notes-miloapis-com-v1alpha1-note,mutating=true,failurePolicy=fail,sideEffects=None,groups=notes.miloapis.com,resources=notes,verbs=create,versions=v1alpha1,name=mnote.notes.miloapis.com,admissionReviewVersions={v1,v1beta1},serviceName=milo-controller-manager,servicePort=9443,serviceNamespace=milo-system
4245
4346type NoteMutator struct {
44- Client client.Client
45- Scheme * runtime.Scheme
46- RESTMapper meta.RESTMapper
47+ Client client.Client
48+ Scheme * runtime.Scheme
49+ RESTMapper meta.RESTMapper
50+ ClusterManager mcmanager.Manager
4751}
4852
4953var _ admission.CustomDefaulter = & NoteMutator {}
@@ -70,7 +74,6 @@ func (m *NoteMutator) Default(ctx context.Context, obj runtime.Object) error {
7074 }
7175
7276 // Set owner reference to the subject resource for automatic garbage collection
73- // This is critical for the Note to be garbage collected when the subject is deleted
7477 if err := m .setSubjectOwnerReference (ctx , note ); err != nil {
7578 noteLog .Error (err , "Failed to set owner reference to subject" , "note" , note .Name )
7679 return errors .NewInternalError (fmt .Errorf ("failed to set owner reference to subject: %w" , err ))
@@ -79,14 +82,15 @@ func (m *NoteMutator) Default(ctx context.Context, obj runtime.Object) error {
7982 return nil
8083}
8184
82- // setSubjectOwnerReference sets the owner reference to the subject resource if it's in the same namespace
85+ // setSubjectOwnerReference sets the owner reference to the subject resource if it's in the same namespace.
86+ // The cluster context is expected to be injected by the ClusterAwareServer wrapper.
8387func (m * NoteMutator ) setSubjectOwnerReference (ctx context.Context , note * notesv1alpha1.Note ) error {
8488 // Only set owner reference if the subject is in the same namespace
8589 if note .Spec .SubjectRef .Namespace == "" || note .Spec .SubjectRef .Namespace != note .Namespace {
8690 return nil
8791 }
8892
89- // Resolve the GVK using REST mapper to discover the correct API version
93+ // Resolve the GVK using REST mapper
9094 groupKind := schema.GroupKind {
9195 Group : note .Spec .SubjectRef .APIGroup ,
9296 Kind : note .Spec .SubjectRef .Kind ,
@@ -97,25 +101,35 @@ func (m *NoteMutator) setSubjectOwnerReference(ctx context.Context, note *notesv
97101 return fmt .Errorf ("failed to get REST mapping for %s: %w" , groupKind , err )
98102 }
99103
100- subject := & unstructured.Unstructured {}
101- subject .SetGroupVersionKind (mapping .GroupVersionKind )
102-
103- if err := m .Client .Get (ctx , types.NamespacedName {
104+ key := types.NamespacedName {
104105 Name : note .Spec .SubjectRef .Name ,
105106 Namespace : note .Spec .SubjectRef .Namespace ,
106- }, subject ); err != nil {
107+ }
108+
109+ // Determine which client to use based on cluster context (injected by ClusterAwareServer)
110+ subjectClient := m .Client
111+
112+ if m .ClusterManager != nil {
113+ if clusterName , ok := mccontext .ClusterFrom (ctx ); ok && clusterName != "" {
114+ cluster , err := m .ClusterManager .GetCluster (ctx , clusterName )
115+ if err != nil {
116+ return fmt .Errorf ("failed to get project control plane %s: %w" , clusterName , err )
117+ }
118+ subjectClient = cluster .GetClient ()
119+ noteLog .V (1 ).Info ("Using project control plane client" , "cluster" , clusterName )
120+ }
121+ }
122+
123+ subject := & unstructured.Unstructured {}
124+ subject .SetGroupVersionKind (mapping .GroupVersionKind )
125+ if err := subjectClient .Get (ctx , key , subject ); err != nil {
107126 if errors .IsNotFound (err ) {
108127 return fmt .Errorf ("subject resource not found: %w" , err )
109128 }
110129 return fmt .Errorf ("failed to get subject resource: %w" , err )
111130 }
112131
113- // Set owner reference
114- if err := controllerutil .SetOwnerReference (subject , note , m .Scheme ); err != nil {
115- return fmt .Errorf ("failed to set owner reference: %w" , err )
116- }
117-
118- return nil
132+ return controllerutil .SetOwnerReference (subject , note , m .Scheme )
119133}
120134
121135// +kubebuilder:webhook:path=/validate-notes-miloapis-com-v1alpha1-note,mutating=false,failurePolicy=fail,sideEffects=None,groups=notes.miloapis.com,resources=notes,verbs=create;update,versions=v1alpha1,name=vnote.notes.miloapis.com,admissionReviewVersions={v1,v1beta1},serviceName=milo-controller-manager,servicePort=9443,serviceNamespace=milo-system
0 commit comments