Skip to content

Commit 316bb1d

Browse files
committed
actually implement support for resource filtering
On-behalf-of: @SAP [email protected]
1 parent 3682cfb commit 316bb1d

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

Diff for: internal/controller/apiexport/controller.go

+5
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ func (r *Reconciler) reconcile(ctx context.Context) error {
139139
for _, pubResource := range filteredPubResources {
140140
arsList.Insert(pubResource.Status.ResourceSchemaName)
141141

142+
// to evaluate the namespace filter, the agent needs to fetch the namespace
143+
if filter := pubResource.Spec.Filter; filter != nil && filter.Namespace != nil {
144+
claimedResources.Insert("namespaces")
145+
}
146+
142147
for _, rr := range pubResource.Spec.Related {
143148
resource, err := mapper.ResourceFor(schema.GroupVersionResource{
144149
Resource: rr.Kind,

Diff for: internal/controller/sync/controller.go

+55
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)