Skip to content

Commit 728589a

Browse files
authored
feat: Feast Namespaces registry for client ConfigMaps availability (#5599)
* Feast Namespaces registery for client ConfigMaps listing Remove the registry entry for deleted feature store instance Signed-off-by: jyejare <[email protected]> * Dynamic controller namespace Signed-off-by: jyejare <[email protected]> * Non namespace handling Signed-off-by: jyejare <[email protected]> --------- Signed-off-by: jyejare <[email protected]>
1 parent 51c16b1 commit 728589a

File tree

7 files changed

+1019
-0
lines changed

7 files changed

+1019
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Feast Namespace Registry
2+
3+
## Overview
4+
5+
The Feast Namespace Registry is a feature that automatically creates and maintains a centralized ConfigMap containing information about all Feast feature store instances deployed by the operator. This enables dashboard applications and other tools to discover and connect to Feast instances across different namespaces.
6+
7+
## Implementation Details
8+
9+
1. **ConfigMap Creation**: The operator creates a ConfigMap in the appropriate namespace:
10+
- **OpenShift AI**: `redhat-ods-applications` namespace (or DSCi configured namespace)
11+
- **Kubernetes**: `feast-operator-system` namespace
12+
13+
2. **Access Control**: A RoleBinding is created to allow `system:authenticated` users to read the ConfigMap
14+
15+
3. **Automatic Registration & Cleanup**: When a new feature store instance is created, it automatically registers its namespace and client configuration in the ConfigMap. When deleted, it automatically removes its entry from the ConfigMap
16+
17+
4. **Data Structure**: The ConfigMap contains a JSON structure with namespace names as keys and lists of client configuration names as values
18+
19+
### ConfigMap Structure
20+
21+
The namespace registry ConfigMap (`feast-configs-registry`) contains the following data:
22+
23+
```json
24+
{
25+
"namespaces": {
26+
"namespace-1": ["client-config-1", "client-config-2"],
27+
"namespace-2": ["client-config-3"]
28+
}
29+
}
30+
```
31+
32+
### Usage
33+
34+
The namespace registry is automatically deployed when any Feast feature store instance is created. No additional configuration is required.
35+
36+
#### For External Applications
37+
38+
External applications can discover Feast instances by:
39+
40+
1. Reading the ConfigMap from the appropriate namespace:
41+
```bash
42+
# For OpenShift
43+
kubectl get configmap feast-configs-registry -n redhat-ods-applications -o jsonpath='{.data.namespaces}'
44+
45+
# For Kubernetes
46+
kubectl get configmap feast-configs-registry -n feast-operator-system -o jsonpath='{.data.namespaces}'
47+
```
48+
49+
### Lifecycle Management
50+
51+
The namespace registry automatically manages the lifecycle of feature store instances:
52+
53+
1. **Creation**: When a feature store is deployed, it registers itself in the ConfigMap
54+
2. **Updates**: If a feature store is updated, its entry remains in the ConfigMap
55+
3. **Deletion**: When a feature store is deleted, its entry is automatically removed from the ConfigMap
56+
4. **Namespace Cleanup**: If all feature stores in a namespace are deleted, the namespace entry is also removed
57+
58+

infra/feast-operator/internal/controller/featurestore_controller.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ func (r *FeatureStoreReconciler) Reconcile(ctx context.Context, req ctrl.Request
7878
if apierrors.IsNotFound(err) {
7979
// CR deleted since request queued, child objects getting GC'd, no requeue
8080
logger.V(1).Info("FeatureStore CR not found, has been deleted")
81+
// Clean up namespace registry entry even if the CR is not found
82+
if err := r.cleanupNamespaceRegistry(ctx, &feastdevv1alpha1.FeatureStore{
83+
ObjectMeta: metav1.ObjectMeta{
84+
Name: req.NamespacedName.Name,
85+
Namespace: req.NamespacedName.Namespace,
86+
},
87+
}); err != nil {
88+
logger.Error(err, "Failed to clean up namespace registry entry for deleted FeatureStore")
89+
// Don't return error here as the CR is already deleted
90+
}
8191
return ctrl.Result{}, nil
8292
}
8393
// error fetching FeatureStore instance, requeue and try again
@@ -86,6 +96,16 @@ func (r *FeatureStoreReconciler) Reconcile(ctx context.Context, req ctrl.Request
8696
}
8797
currentStatus := cr.Status.DeepCopy()
8898

99+
// Handle deletion - clean up namespace registry entry
100+
if cr.DeletionTimestamp != nil {
101+
logger.Info("FeatureStore is being deleted, cleaning up namespace registry entry")
102+
if err := r.cleanupNamespaceRegistry(ctx, cr); err != nil {
103+
logger.Error(err, "Failed to clean up namespace registry entry")
104+
return ctrl.Result{}, err
105+
}
106+
return ctrl.Result{}, nil
107+
}
108+
89109
result, recErr = r.deployFeast(ctx, cr)
90110
if cr.DeletionTimestamp == nil && !reflect.DeepEqual(currentStatus, cr.Status) {
91111
if err = r.Client.Status().Update(ctx, cr); err != nil {
@@ -102,6 +122,22 @@ func (r *FeatureStoreReconciler) Reconcile(ctx context.Context, req ctrl.Request
102122
}
103123
}
104124

125+
// Add to namespace registry if deployment was successful and not being deleted
126+
if recErr == nil && cr.DeletionTimestamp == nil {
127+
feast := services.FeastServices{
128+
Handler: feasthandler.FeastHandler{
129+
Client: r.Client,
130+
Context: ctx,
131+
FeatureStore: cr,
132+
Scheme: r.Scheme,
133+
},
134+
}
135+
if err := feast.AddToNamespaceRegistry(); err != nil {
136+
logger.Error(err, "Failed to add FeatureStore to namespace registry")
137+
// Don't return error here as the FeatureStore is already deployed successfully
138+
}
139+
}
140+
105141
return result, recErr
106142
}
107143

@@ -201,6 +237,20 @@ func (r *FeatureStoreReconciler) SetupWithManager(mgr ctrl.Manager) error {
201237

202238
}
203239

240+
// cleanupNamespaceRegistry removes the feature store instance from the namespace registry
241+
func (r *FeatureStoreReconciler) cleanupNamespaceRegistry(ctx context.Context, cr *feastdevv1alpha1.FeatureStore) error {
242+
feast := services.FeastServices{
243+
Handler: feasthandler.FeastHandler{
244+
Client: r.Client,
245+
Context: ctx,
246+
FeatureStore: cr,
247+
Scheme: r.Scheme,
248+
},
249+
}
250+
251+
return feast.RemoveFromNamespaceRegistry()
252+
}
253+
204254
// if a remotely referenced FeatureStore is changed, reconcile any FeatureStores that reference it.
205255
func (r *FeatureStoreReconciler) mapFeastRefsToFeastRequests(ctx context.Context, object client.Object) []reconcile.Request {
206256
logger := log.FromContext(ctx)

0 commit comments

Comments
 (0)