Skip to content

Commit 06e62df

Browse files
committed
Merge branch 'group-dls-part-2' of github.com:langflow-ai/openrag into group-dls-part-2
2 parents a1a9496 + a018e21 commit 06e62df

2 files changed

Lines changed: 129 additions & 40 deletions

File tree

kubernetes/operator/internal/controller/openrag_controller.go

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ const (
3232
userSecretFinalizer = "openr.ag/user-secret-protection"
3333
specHashAnnotation = "openr.ag/spec-hash"
3434
immutableAnnotation = "openr.ag/immutable"
35+
36+
// Condition types
37+
conditionBackendReady = "BackendReady"
38+
39+
// Phase values
40+
phaseReconciled = "Reconciled"
41+
phaseRunning = "Running"
42+
phaseError = "Error"
3543
)
3644

3745
// OpenRAGReconciler reconciles an OpenRAG object.
@@ -123,46 +131,7 @@ func (r *OpenRAGReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
123131

124132
// Update status to success
125133
logger.Info("reconciled OpenRAG instance", "name", instance.Name, "targetNamespace", targetNS)
126-
return r.updateStatusSuccess(ctx, instance)
127-
}
128-
129-
// updateStatusSuccess updates the status to indicate successful reconciliation
130-
func (r *OpenRAGReconciler) updateStatusSuccess(ctx context.Context, instance *openragv1alpha1.OpenRAG) (ctrl.Result, error) {
131-
const successMsg = "All resources reconciled successfully"
132-
if instance.Status.Phase == "Running" &&
133-
instance.Status.Message == successMsg &&
134-
instance.Status.ObservedGeneration == instance.Generation {
135-
return ctrl.Result{}, nil
136-
}
137-
138-
instance.Status.Phase = "Running"
139-
instance.Status.Message = successMsg
140-
instance.Status.ObservedGeneration = instance.Generation
141-
if err := r.Status().Update(ctx, instance); err != nil {
142-
return ctrl.Result{}, fmt.Errorf("failed to update status: %w", err)
143-
}
144-
145-
return ctrl.Result{}, nil
146-
}
147-
148-
// updateStatusError updates the status to indicate reconciliation failure and schedules retry after 5 minutes
149-
func (r *OpenRAGReconciler) updateStatusError(ctx context.Context, instance *openragv1alpha1.OpenRAG, component string, reconcileErr error) (ctrl.Result, error) {
150-
logger := log.FromContext(ctx)
151-
152-
instance.Status.Phase = "Error"
153-
instance.Status.Message = fmt.Sprintf("Failed to reconcile %s: %s", component, reconcileErr.Error())
154-
instance.Status.ObservedGeneration = instance.Generation
155-
156-
if err := r.Status().Update(ctx, instance); err != nil {
157-
logger.Error(err, "failed to update status after error", "component", component, "reconcileError", reconcileErr.Error())
158-
// Return original error even if status update fails
159-
return ctrl.Result{}, reconcileErr
160-
}
161-
162-
logger.Error(reconcileErr, "reconciliation failed, will retry in 5 minutes", "component", component)
163-
164-
// Requeue after 5 minutes on failure
165-
return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil
134+
return r.updateStatusSuccess(ctx, instance, targetNS)
166135
}
167136

168137
func (r *OpenRAGReconciler) handleDeletion(ctx context.Context, o *openragv1alpha1.OpenRAG) error {
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package controller
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
openragv1alpha1 "github.com/langflow-ai/openrag-operator/api/v1alpha1"
9+
appsv1 "k8s.io/api/apps/v1"
10+
"k8s.io/apimachinery/pkg/api/errors"
11+
"k8s.io/apimachinery/pkg/api/meta"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
ctrl "sigs.k8s.io/controller-runtime"
14+
"sigs.k8s.io/controller-runtime/pkg/client"
15+
"sigs.k8s.io/controller-runtime/pkg/log"
16+
)
17+
18+
// updateStatusSuccess updates the status to indicate successful reconciliation
19+
// Phase is set to "Reconciled" initially, then updated to "Running" if backend pod is ready
20+
func (r *OpenRAGReconciler) updateStatusSuccess(ctx context.Context, instance *openragv1alpha1.OpenRAG, targetNS string) (ctrl.Result, error) {
21+
logger := log.FromContext(ctx)
22+
23+
// Update backend condition first
24+
backendConditionStatus, err := r.updateBackendCondition(ctx, instance, targetNS)
25+
if err != nil {
26+
logger.Error(err, "failed to update backend condition")
27+
// Continue anyway, don't fail reconciliation
28+
}
29+
30+
// Determine phase based on backend readiness
31+
phase := phaseReconciled
32+
message := "All resources reconciled successfully, waiting for backend pod to be ready"
33+
if backendConditionStatus == metav1.ConditionTrue {
34+
phase = phaseRunning
35+
message = "All resources reconciled successfully and backend is running"
36+
}
37+
38+
instance.Status.Phase = phase
39+
instance.Status.Message = message
40+
instance.Status.ObservedGeneration = instance.Generation
41+
42+
if err := r.Status().Update(ctx, instance); err != nil {
43+
return ctrl.Result{}, fmt.Errorf("failed to update status: %w", err)
44+
}
45+
46+
// Requeue after 1 minute to check backend pod status
47+
return ctrl.Result{RequeueAfter: 1 * time.Minute}, nil
48+
}
49+
50+
// updateStatusError updates the status to indicate reconciliation failure and schedules retry after 5 minutes
51+
func (r *OpenRAGReconciler) updateStatusError(ctx context.Context, instance *openragv1alpha1.OpenRAG, component string, reconcileErr error) (ctrl.Result, error) {
52+
logger := log.FromContext(ctx)
53+
54+
instance.Status.Phase = phaseError
55+
instance.Status.Message = fmt.Sprintf("Failed to reconcile %s: %s", component, reconcileErr.Error())
56+
instance.Status.ObservedGeneration = instance.Generation
57+
58+
if err := r.Status().Update(ctx, instance); err != nil {
59+
logger.Error(err, "failed to update status after error", "component", component, "reconcileError", reconcileErr.Error())
60+
// Return original error even if status update fails
61+
return ctrl.Result{}, reconcileErr
62+
}
63+
64+
logger.Error(reconcileErr, "reconciliation failed, will retry in 5 minutes", "component", component)
65+
66+
// Requeue after 5 minutes on failure
67+
return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil
68+
}
69+
70+
// updateBackendCondition checks the backend deployment pod status and updates the BackendReady condition
71+
func (r *OpenRAGReconciler) updateBackendCondition(ctx context.Context, instance *openragv1alpha1.OpenRAG, targetNS string) (metav1.ConditionStatus, error) {
72+
logger := log.FromContext(ctx)
73+
74+
deployment := &appsv1.Deployment{}
75+
err := r.Get(ctx, client.ObjectKey{
76+
Name: resourceName("be"),
77+
Namespace: targetNS,
78+
}, deployment)
79+
80+
if err != nil {
81+
if errors.IsNotFound(err) {
82+
// Backend deployment doesn't exist yet
83+
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
84+
Type: conditionBackendReady,
85+
Status: metav1.ConditionUnknown,
86+
Reason: "DeploymentNotFound",
87+
Message: "Backend deployment not found",
88+
ObservedGeneration: instance.Generation,
89+
})
90+
logger.Info("Backend deployment not found", "deployment", resourceName("be"))
91+
return metav1.ConditionUnknown, nil
92+
}
93+
return metav1.ConditionUnknown, fmt.Errorf("failed to get backend deployment: %w", err)
94+
}
95+
96+
reportedStatus := metav1.ConditionFalse
97+
// Check if backend pod is ready (single replica)
98+
if deployment.Status.ReadyReplicas > 0 && deployment.Status.ReadyReplicas == deployment.Status.Replicas {
99+
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
100+
Type: conditionBackendReady,
101+
Status: metav1.ConditionTrue,
102+
Reason: "PodRunning",
103+
Message: "Backend pod is running and ready",
104+
ObservedGeneration: instance.Generation,
105+
})
106+
reportedStatus = metav1.ConditionTrue
107+
logger.Info("Backend pod is ready", "readyReplicas", deployment.Status.ReadyReplicas)
108+
} else {
109+
meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{
110+
Type: conditionBackendReady,
111+
Status: metav1.ConditionFalse,
112+
Reason: "PodNotReady",
113+
Message: fmt.Sprintf("Backend pod not ready (ready: %d, desired: %d)", deployment.Status.ReadyReplicas, deployment.Status.Replicas),
114+
ObservedGeneration: instance.Generation,
115+
})
116+
logger.Info("Backend pod not ready", "readyReplicas", deployment.Status.ReadyReplicas, "desiredReplicas", deployment.Status.Replicas)
117+
}
118+
119+
return reportedStatus, nil
120+
}

0 commit comments

Comments
 (0)