@@ -33,7 +33,10 @@ import (
3333 kcpcore "github.com/kcp-dev/kcp/sdk/apis/core"
3434 kcpdevcorev1alpha1 "github.com/kcp-dev/kcp/sdk/apis/core/v1alpha1"
3535
36+ corev1 "k8s.io/api/core/v1"
37+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3638 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
39+ "k8s.io/apimachinery/pkg/labels"
3740 "k8s.io/apimachinery/pkg/types"
3841 "k8s.io/utils/ptr"
3942 ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -165,6 +168,27 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
165168 return reconcile.Result {}, nil
166169 }
167170
171+ // if there is a namespace, get it if a namespace filter is also configured
172+ var namespace * corev1.Namespace
173+ if filter := r .pubRes .Spec .Filter ; filter != nil && filter .Namespace != nil && remoteObj .GetNamespace () != "" {
174+ namespace = & corev1.Namespace {}
175+ key := types.NamespacedName {Name : remoteObj .GetNamespace ()}
176+
177+ if err := r .vwClient .Get (wsCtx , key , namespace ); err != nil {
178+ return reconcile.Result {}, fmt .Errorf ("failed to retrieve remote object's namespace: %w" , err )
179+ }
180+ }
181+
182+ // apply filtering rules to scope down the number of objects we sync
183+ include , err := r .objectMatchesFilter (remoteObj , namespace )
184+ if err != nil {
185+ return reconcile.Result {}, fmt .Errorf ("failed to apply filtering rules: %w" , err )
186+ }
187+
188+ if ! include {
189+ return reconcile.Result {}, nil
190+ }
191+
168192 syncContext := sync .NewContext (ctx , wsCtx )
169193
170194 // if desired, fetch the cluster path as well (some downstream service providers might make use of it,
@@ -193,3 +217,34 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
193217
194218 return result , nil
195219}
220+
221+ func (r * Reconciler ) objectMatchesFilter (remoteObj * unstructured.Unstructured , namespace * corev1.Namespace ) (bool , error ) {
222+ if r .pubRes .Spec .Filter == nil {
223+ return true , nil
224+ }
225+
226+ objMatches , err := r .matchesFilter (remoteObj , r .pubRes .Spec .Filter .Resource )
227+ if err != nil || ! objMatches {
228+ return false , err
229+ }
230+
231+ nsMatches , err := r .matchesFilter (namespace , r .pubRes .Spec .Filter .Namespace )
232+ if err != nil || ! nsMatches {
233+ return false , err
234+ }
235+
236+ return true , nil
237+ }
238+
239+ func (r * Reconciler ) matchesFilter (obj metav1.Object , selector * metav1.LabelSelector ) (bool , error ) {
240+ if selector == nil {
241+ return true , nil
242+ }
243+
244+ s , err := metav1 .LabelSelectorAsSelector (selector )
245+ if err != nil {
246+ return false , err
247+ }
248+
249+ return s .Matches (labels .Set (obj .GetLabels ())), nil
250+ }
0 commit comments