Skip to content

Commit 5c83ffd

Browse files
committed
feat: wip
1 parent bbb67ea commit 5c83ffd

File tree

2 files changed

+170
-4
lines changed

2 files changed

+170
-4
lines changed

api/postgresql/v1alpha1/postgresqlbackup_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const (
5252
// PostgresqlBackupStatus defines the observed state of PostgresqlBackup.
5353
type PostgresqlBackupStatus struct {
5454
// Current phase of the operator
55-
Phase BackupProviderStatusPhase `json:"phase,omitempty"`
55+
Phase BackupStatusPhase `json:"phase,omitempty"`
5656
// Human-readable message indicating details about current operator phase or error.
5757
// +optional
5858
Message string `json:"message,omitempty"`

internal/controller/postgresql/postgresqlbackup_controller.go

Lines changed: 169 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,21 @@ package postgresql
1818

1919
import (
2020
"context"
21+
"reflect"
2122
"time"
2223

2324
"github.com/go-logr/logr"
2425
"github.com/prometheus/client_golang/prometheus"
26+
"k8s.io/apimachinery/pkg/api/errors"
2527
"k8s.io/apimachinery/pkg/runtime"
2628
"k8s.io/client-go/tools/record"
2729
"sigs.k8s.io/controller-runtime/pkg/client"
30+
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
2831

2932
ctrl "sigs.k8s.io/controller-runtime"
30-
logf "sigs.k8s.io/controller-runtime/pkg/log"
3133

3234
postgresqlv1alpha1 "github.com/easymile/postgresql-operator/api/postgresql/v1alpha1"
35+
"github.com/easymile/postgresql-operator/internal/controller/config"
3336
)
3437

3538
// PostgresqlBackupReconciler reconciles a PostgresqlBackup object.
@@ -57,9 +60,172 @@ type PostgresqlBackupReconciler struct {
5760
// For more details, check Reconcile and its Result here:
5861
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.21.0/pkg/reconcile
5962
func (r *PostgresqlBackupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
60-
_ = logf.FromContext(ctx)
63+
// Issue with this logger: controller and controllerKind are incorrect
64+
// Build another logger from upper to fix this.
65+
// reqLogger := log.FromContext(ctx)
66+
reqLogger := r.Log.WithValues("Request.Namespace", req.Namespace, "Request.Name", req.Name)
67+
reqLogger.Info("Reconciling PostgresqlBackup")
6168

62-
// TODO(user): your logic here
69+
// Fetch the PostgresqlDatabase instance
70+
instance := &postgresqlv1alpha1.PostgresqlBackup{}
71+
72+
err := r.Get(ctx, req.NamespacedName, instance)
73+
if err != nil {
74+
if errors.IsNotFound(err) {
75+
// Request object not found, could have been deleted after reconcile request.
76+
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
77+
// Return and don't requeue
78+
return ctrl.Result{}, nil
79+
}
80+
// Error reading the object - requeue the request.
81+
return ctrl.Result{}, err
82+
}
83+
84+
// Original patch
85+
originalPatch := client.MergeFrom(instance.DeepCopy())
86+
87+
// Create timeout in ctx
88+
timeoutCtx, cancel := context.WithTimeout(ctx, r.ReconcileTimeout)
89+
// Defer cancel
90+
defer cancel()
91+
92+
// Init result
93+
var res ctrl.Result
94+
95+
errC := make(chan error, 1)
96+
97+
// Create wrapping function
98+
cb := func() {
99+
a, err := r.mainReconcile(timeoutCtx, reqLogger, instance, originalPatch)
100+
// Save result
101+
res = a
102+
// Send error
103+
errC <- err
104+
}
105+
106+
// Start wrapped function
107+
go cb()
108+
109+
// Run or timeout
110+
select {
111+
case <-timeoutCtx.Done():
112+
// ? Note: Here use primary context otherwise update to set error will be aborted
113+
return r.manageError(ctx, reqLogger, instance, originalPatch, timeoutCtx.Err())
114+
case err := <-errC:
115+
return res, err
116+
}
117+
}
118+
119+
func (r *PostgresqlBackupReconciler) mainReconcile(
120+
ctx context.Context,
121+
reqLogger logr.Logger,
122+
instance *postgresqlv1alpha1.PostgresqlBackup,
123+
originalPatch client.Patch,
124+
) (ctrl.Result, error) {
125+
// Deletion case
126+
if !instance.GetDeletionTimestamp().IsZero() {
127+
// Deletion in progress detected
128+
// TODO wait for children
129+
130+
// Remove finalizer
131+
controllerutil.RemoveFinalizer(instance, config.Finalizer)
132+
// Update CR
133+
err := r.Update(ctx, instance)
134+
if err != nil {
135+
return r.manageError(ctx, reqLogger, instance, originalPatch, err)
136+
}
137+
// Stop reconcile
138+
return ctrl.Result{}, nil
139+
}
140+
141+
// Creation case
142+
143+
// Add finalizer, owners and default values
144+
updated, err := r.updateInstance(ctx, instance)
145+
// Check error
146+
if err != nil {
147+
return r.manageError(ctx, reqLogger, instance, originalPatch, err)
148+
}
149+
// Check if it has been updated in order to stop this reconcile loop here for the moment
150+
if updated {
151+
return ctrl.Result{}, nil
152+
}
153+
154+
// Success
155+
return r.manageSuccess(ctx, reqLogger, instance, originalPatch)
156+
}
157+
158+
func (r *PostgresqlBackupReconciler) updateInstance(
159+
ctx context.Context,
160+
instance *postgresqlv1alpha1.PostgresqlBackup,
161+
) (bool, error) {
162+
// Deep copy
163+
oCopy := instance.DeepCopy()
164+
165+
// Add finalizer
166+
controllerutil.AddFinalizer(instance, config.Finalizer)
167+
168+
// Check if update is needed
169+
if !reflect.DeepEqual(oCopy.ObjectMeta, instance.ObjectMeta) {
170+
return true, r.Update(ctx, instance)
171+
}
172+
173+
return false, nil
174+
}
175+
176+
func (r *PostgresqlBackupReconciler) manageError(
177+
ctx context.Context,
178+
logger logr.Logger,
179+
instance *postgresqlv1alpha1.PostgresqlBackup,
180+
originalPatch client.Patch,
181+
issue error,
182+
) (ctrl.Result, error) {
183+
logger.Error(issue, "issue raised in reconcile")
184+
// Add kubernetes event
185+
r.Recorder.Event(instance, "Warning", "ProcessingError", issue.Error())
186+
187+
// Update status
188+
instance.Status.Message = issue.Error()
189+
instance.Status.Ready = false
190+
instance.Status.Phase = postgresqlv1alpha1.BackupErrorPhase
191+
192+
// Increase fail counter
193+
r.ControllerRuntimeDetailedErrorTotal.WithLabelValues(r.ControllerName, instance.Namespace, instance.Name).Inc()
194+
195+
// Patch status
196+
err := r.Status().Patch(ctx, instance, originalPatch)
197+
if err != nil {
198+
logger.Error(err, "unable to update status")
199+
}
200+
201+
// Return error
202+
return ctrl.Result{}, issue
203+
}
204+
205+
func (r *PostgresqlBackupReconciler) manageSuccess(
206+
ctx context.Context,
207+
logger logr.Logger,
208+
instance *postgresqlv1alpha1.PostgresqlBackup,
209+
originalPatch client.Patch,
210+
) (ctrl.Result, error) {
211+
// Update status
212+
instance.Status.Message = ""
213+
instance.Status.Ready = true
214+
instance.Status.Phase = postgresqlv1alpha1.BackupValidPhase
215+
216+
// Patch status
217+
err := r.Status().Patch(ctx, instance, originalPatch)
218+
if err != nil {
219+
// Increase fail counter
220+
r.ControllerRuntimeDetailedErrorTotal.WithLabelValues(r.ControllerName, instance.Namespace, instance.Name).Inc()
221+
222+
logger.Error(err, "unable to update status")
223+
224+
// Return error
225+
return ctrl.Result{}, err
226+
}
227+
228+
logger.Info("Reconcile done")
63229

64230
return ctrl.Result{}, nil
65231
}

0 commit comments

Comments
 (0)