@@ -29,6 +29,7 @@ import (
2929 "k8s.io/apimachinery/pkg/labels"
3030 "k8s.io/apimachinery/pkg/runtime"
3131 "k8s.io/apimachinery/pkg/runtime/schema"
32+ "k8s.io/apimachinery/pkg/types"
3233 "k8s.io/klog/v2"
3334 "sigs.k8s.io/controller-runtime/pkg/client"
3435 workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1"
8384// selectResources selects the resources according to the placement resourceSelectors.
8485// It also generates an array of manifests obj based on the selected resources.
8586func (r * Reconciler ) selectResources (placement * fleetv1alpha1.ClusterResourcePlacement ) ([]workv1alpha1.Manifest , error ) {
86- selectedObjects , err := r .gatherSelectedResource (placement .GetName (), convertResourceSelector (placement .Spec .ResourceSelectors ))
87+ selectedObjects , err := r .gatherSelectedResource (types. NamespacedName { Name : placement .GetName ()} , convertResourceSelector (placement .Spec .ResourceSelectors ))
8788 if err != nil {
8889 return nil , err
8990 }
@@ -128,8 +129,7 @@ func convertResourceSelector(old []fleetv1alpha1.ClusterResourceSelector) []flee
128129}
129130
130131// gatherSelectedResource gets all the resources according to the resource selector.
131- // TODO: treat the RP selector differently to not allow RP to select cluster scoped resources
132- func (r * Reconciler ) gatherSelectedResource (placement string , selectors []fleetv1beta1.ClusterResourceSelector ) ([]* unstructured.Unstructured , error ) {
132+ func (r * Reconciler ) gatherSelectedResource (placementName types.NamespacedName , selectors []fleetv1beta1.ClusterResourceSelector ) ([]* unstructured.Unstructured , error ) {
133133 var resources []* unstructured.Unstructured
134134 var resourceMap = make (map [fleetv1beta1.ResourceIdentifier ]bool )
135135 for _ , selector := range selectors {
@@ -145,10 +145,10 @@ func (r *Reconciler) gatherSelectedResource(placement string, selectors []fleetv
145145 }
146146 var objs []runtime.Object
147147 var err error
148- if gvk == utils .NamespaceGVK {
149- objs , err = r .fetchNamespaceResources (selector , placement )
148+ if gvk == utils .NamespaceGVK && placementName . Namespace == "" {
149+ objs , err = r .fetchNamespaceResources (selector , placementName . Name )
150150 } else {
151- objs , err = r .fetchClusterScopedResources (selector , placement )
151+ objs , err = r .fetchResources (selector , placementName )
152152 }
153153 if err != nil {
154154 return nil , err
@@ -164,7 +164,7 @@ func (r *Reconciler) gatherSelectedResource(placement string, selectors []fleetv
164164 }
165165 if _ , exist := resourceMap [ri ]; exist {
166166 err = fmt .Errorf ("found duplicate resource %+v" , ri )
167- klog .ErrorS (err , "user selected one resource more than once" , "resource" , ri , "placement" , placement )
167+ klog .ErrorS (err , "User selected one resource more than once" , "resource" , ri , "placement" , placementName )
168168 return nil , controller .NewUserError (err )
169169 }
170170 resourceMap [ri ] = true
@@ -230,43 +230,64 @@ func buildApplyOrderMap() map[string]int {
230230 return ordering
231231}
232232
233- // fetchClusterScopedResources retrieves the objects based on the selector.
234- func (r * Reconciler ) fetchClusterScopedResources (selector fleetv1beta1.ClusterResourceSelector , placeName string ) ([]runtime.Object , error ) {
235- klog .V (2 ).InfoS ("start to fetch the cluster scoped resources by the selector" , "selector" , selector )
233+ // fetchResources retrieves the objects based on the selector.
234+ func (r * Reconciler ) fetchResources (selector fleetv1beta1.ClusterResourceSelector , placementName types. NamespacedName ) ([]runtime.Object , error ) {
235+ klog .V (2 ).InfoS ("Start to fetch resources by the selector" , "selector" , selector , "placement" , placementName )
236236 gk := schema.GroupKind {
237237 Group : selector .Group ,
238238 Kind : selector .Kind ,
239239 }
240240 restMapping , err := r .RestMapper .RESTMapping (gk , selector .Version )
241241 if err != nil {
242- return nil , controller .NewUserError (fmt .Errorf ("invalid placement %s, failed to get GVR of the selector: %w" , placeName , err ))
242+ return nil , controller .NewUserError (fmt .Errorf ("invalid placement %s, failed to get GVR of the selector: %w" , placementName , err ))
243243 }
244244 gvr := restMapping .Resource
245245 gvk := schema.GroupVersionKind {
246246 Group : selector .Group ,
247247 Version : selector .Version ,
248248 Kind : selector .Kind ,
249249 }
250- if ! r .InformerManager .IsClusterScopedResources (gvk ) {
251- return nil , controller .NewUserError (fmt .Errorf ("invalid placement %s: %+v is not a cluster scoped resource" , placeName , restMapping .Resource ))
250+
251+ isNamespacedResource := ! r .InformerManager .IsClusterScopedResources (gvk )
252+ if isNamespacedResource && placementName .Namespace == "" {
253+ // If it's a namespace-scoped resource but placement has no namespace, return error.
254+ err := fmt .Errorf ("invalid placement %s: cannot select namespace-scoped resource %v without a namespace" , placementName , gvr )
255+ klog .ErrorS (err , "Invalid resource selector" , "selector" , selector )
256+ return nil , controller .NewUserError (err )
257+ } else if ! isNamespacedResource && placementName .Namespace != "" {
258+ // If it's a cluster-scoped resource but placement has a namespace, return error.
259+ err := fmt .Errorf ("invalid placement %s: cannot select cluster-scoped resource %v with a namespace" , placementName , gvr )
260+ klog .ErrorS (err , "Invalid resource selector" , "selector" , selector )
261+ return nil , controller .NewUserError (err )
252262 }
263+
253264 if ! r .InformerManager .IsInformerSynced (gvr ) {
254- return nil , controller .NewExpectedBehaviorError (fmt .Errorf ("informer cache for %+v is not synced yet" , restMapping .Resource ))
265+ err := fmt .Errorf ("informer cache for %+v is not synced yet" , restMapping .Resource )
266+ klog .ErrorS (err , "Informer cache is not synced" , "gvr" , gvr , "placement" , placementName )
267+ return nil , controller .NewExpectedBehaviorError (err )
255268 }
256269
257270 lister := r .InformerManager .Lister (gvr )
271+
258272 // TODO: validator should enforce the mutual exclusiveness between the `name` and `labelSelector` fields
259273 if len (selector .Name ) != 0 {
260- obj , err := lister .Get (selector .Name )
274+ var obj runtime.Object
275+ var err error
276+
277+ if isNamespacedResource {
278+ obj , err = lister .ByNamespace (placementName .Namespace ).Get (selector .Name )
279+ } else {
280+ obj , err = lister .Get (selector .Name )
281+ }
282+
261283 if err != nil {
262- klog .ErrorS (err , "cannot get the resource" , "gvr" , gvr , "name" , selector .Name )
284+ klog .ErrorS (err , "Cannot get the resource" , "gvr" , gvr , "name" , selector .Name , "namespace" , placementName . Namespace )
263285 return nil , controller .NewAPIServerError (true , client .IgnoreNotFound (err ))
264286 }
265- uObj := obj .DeepCopyObject ().(* unstructured.Unstructured )
266- if uObj .GetDeletionTimestamp () != nil {
267- // skip a to be deleted namespace
268- klog .V (2 ).InfoS ("skip the deleting cluster scoped resources by the selector" ,
269- "selector" , selector , "placeName" , placeName , "resource name" , uObj .GetName ())
287+ if uObj := obj .DeepCopyObject ().(* unstructured.Unstructured ); uObj .GetDeletionTimestamp () != nil {
288+ // skip a to be deleted resource
289+ klog .V (2 ).InfoS ("Skip the deleting resource by the selector" ,
290+ "selector" , selector , "placement" , placementName , "resourceName" , uObj .GetName ())
270291 return []runtime.Object {}, nil
271292 }
272293 return []runtime.Object {obj }, nil
@@ -282,18 +303,26 @@ func (r *Reconciler) fetchClusterScopedResources(selector fleetv1beta1.ClusterRe
282303 return nil , controller .NewUnexpectedBehaviorError (fmt .Errorf ("cannot convert the label selector to a selector: %w" , err ))
283304 }
284305 }
306+
285307 var selectedObjs []runtime.Object
286- objects , err := lister .List (labelSelector )
308+ var objects []runtime.Object
309+
310+ if isNamespacedResource {
311+ objects , err = lister .ByNamespace (placementName .Namespace ).List (labelSelector )
312+ } else {
313+ objects , err = lister .List (labelSelector )
314+ }
287315 if err != nil {
288- return nil , controller .NewAPIServerError (true , fmt .Errorf ("cannot list all the objects: %w" , err ))
316+ klog .ErrorS (err , "Cannot list all the objects" , "gvr" , gvr , "labelSelector" , labelSelector , "placement" , placementName )
317+ return nil , controller .NewAPIServerError (true , err )
289318 }
319+
290320 // go ahead and claim all objects by adding a finalizer and insert the placement in its annotation
291321 for i := 0 ; i < len (objects ); i ++ {
292- uObj := objects [i ].DeepCopyObject ().(* unstructured.Unstructured )
293- if uObj .GetDeletionTimestamp () != nil {
294- // skip a to be deleted namespace
295- klog .V (2 ).InfoS ("skip the deleting cluster scoped resources by the selector" ,
296- "selector" , selector , "placeName" , placeName , "resource name" , uObj .GetName ())
322+ if uObj := objects [i ].DeepCopyObject ().(* unstructured.Unstructured ); uObj .GetDeletionTimestamp () != nil {
323+ // skip a to be deleted resource
324+ klog .V (2 ).InfoS ("skip the deleting resource by the selector" ,
325+ "selector" , selector , "placement" , placementName , "resourceName" , uObj .GetName ())
297326 continue
298327 }
299328 selectedObjs = append (selectedObjs , objects [i ])
@@ -330,7 +359,8 @@ func (r *Reconciler) fetchNamespaceResources(selector fleetv1beta1.ClusterResour
330359 }
331360 namespaces , err := r .InformerManager .Lister (utils .NamespaceGVR ).List (labelSelector )
332361 if err != nil {
333- return nil , controller .NewAPIServerError (true , fmt .Errorf ("cannot list all the namespaces given the label selector: %w" , err ))
362+ klog .ErrorS (err , "Cannot list all the namespaces by the label selector" , "labelSelector" , labelSelector , "placement" , placeName )
363+ return nil , controller .NewAPIServerError (true , err )
334364 }
335365
336366 for _ , namespace := range namespaces {
@@ -384,10 +414,17 @@ func (r *Reconciler) fetchAllResourcesInOneNamespace(namespaceName string, place
384414 lister := r .InformerManager .Lister (gvr )
385415 objs , err := lister .ByNamespace (namespaceName ).List (labels .Everything ())
386416 if err != nil {
387- return nil , controller .NewAPIServerError (true , fmt .Errorf ("cannot list all the objects of type %+v in namespace %s: %w" , gvr , namespaceName , err ))
417+ klog .ErrorS (err , "Cannot list all the objects in namespace" , "gvr" , gvr , "namespace" , namespaceName )
418+ return nil , controller .NewAPIServerError (true , err )
388419 }
389420 for _ , obj := range objs {
390421 uObj := obj .DeepCopyObject ().(* unstructured.Unstructured )
422+ if uObj .GetDeletionTimestamp () != nil {
423+ // skip a to be deleted resource
424+ klog .V (2 ).InfoS ("skip the deleting resource by the selector" ,
425+ "placeName" , placeName , "namespace" , namespaceName , "object" , klog .KObj (uObj ))
426+ continue
427+ }
391428 shouldInclude , err := utils .ShouldPropagateObj (r .InformerManager , uObj )
392429 if err != nil {
393430 klog .ErrorS (err , "cannot determine if we should propagate an object" , "object" , klog .KObj (uObj ))
@@ -520,8 +557,10 @@ func generateResourceContent(object *unstructured.Unstructured) (*fleetv1beta1.R
520557// It also returns the number of envelope configmaps so the CRP controller can have the right expectation of the number of work objects.
521558func (r * Reconciler ) selectResourcesForPlacement (placementObj fleetv1beta1.PlacementObj ) (int , []fleetv1beta1.ResourceContent , []fleetv1beta1.ResourceIdentifier , error ) {
522559 envelopeObjCount := 0
523- placementSpec := placementObj .GetPlacementSpec ()
524- selectedObjects , err := r .gatherSelectedResource (placementObj .GetName (), placementSpec .ResourceSelectors )
560+ selectedObjects , err := r .gatherSelectedResource (types.NamespacedName {
561+ Name : placementObj .GetName (),
562+ Namespace : placementObj .GetNamespace (),
563+ }, placementObj .GetPlacementSpec ().ResourceSelectors )
525564 if err != nil {
526565 return 0 , nil , nil , err
527566 }
0 commit comments