in submarine-cloud-v3/controllers/submarine_controller.go [160:248]
func (r *SubmarineReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
r.Log.Info("Enter Reconcile", "req", req)
// Get the Submarine resource with the requested name/namespace
submarine := &submarineapacheorgv1.Submarine{}
err := r.Get(ctx, types.NamespacedName{Name: req.Name, Namespace: req.Namespace}, submarine)
if err != nil {
if errors.IsNotFound(err) {
// The Submarine resource may no longer exist, in which case we stop processing
r.Log.Error(nil, "Submarine no longer exists", "name", req.Name, "namespace", req.Namespace)
return ctrl.Result{}, nil
}
return ctrl.Result{}, err
}
// Submarine is in the terminating process, only used when in foreground cascading deletion, otherwise the submarine will be recreated
if !submarine.DeletionTimestamp.IsZero() {
return ctrl.Result{}, nil
}
submarineCopy := submarine.DeepCopy()
// Take action based on submarine state
// State machine for Submarine:
//+-----------------------------------------------------------------+
//| +---------+ +----------+ +----------+ |
//| | | | | | | |
//| | New +---------> Creating +----------> Running | |
//| | | | | | | |
//| +----+----+ +-----+----+ +-----+----+ |
//| | | | |
//| | | | |
//| | | | |
//| | | +-----v----+ |
//| | | | | |
//| +--------------------+---------------> Failed | |
//| | | |
//| +----------+ |
//+-----------------------------------------------------------------+
switch submarineCopy.Status.State {
case submarineapacheorgv1.NewState:
r.recordSubmarineEvent(submarineCopy)
if err := r.validateSubmarine(submarineCopy); err != nil {
submarineCopy.Status.State = submarineapacheorgv1.FailedState
submarineCopy.Status.ErrorMessage = err.Error()
r.recordSubmarineEvent(submarineCopy)
} else {
submarineCopy.Status.State = submarineapacheorgv1.CreatingState
r.recordSubmarineEvent(submarineCopy)
}
// If an event is performed in a failed state, we also need to process it
case submarineapacheorgv1.CreatingState, submarineapacheorgv1.FailedState:
if err := r.createSubmarine(ctx, submarineCopy); err != nil {
submarineCopy.Status.State = submarineapacheorgv1.FailedState
submarineCopy.Status.ErrorMessage = err.Error()
r.recordSubmarineEvent(submarineCopy)
}
ok, err := r.checkSubmarineDependentsReady(ctx, submarineCopy)
if err != nil {
submarineCopy.Status.State = submarineapacheorgv1.FailedState
submarineCopy.Status.ErrorMessage = err.Error()
r.recordSubmarineEvent(submarineCopy)
}
if ok {
submarineCopy.Status.State = submarineapacheorgv1.RunningState
submarineCopy.Status.ErrorMessage = ""
r.recordSubmarineEvent(submarineCopy)
}
case submarineapacheorgv1.RunningState:
if err := r.createSubmarine(ctx, submarineCopy); err != nil {
submarineCopy.Status.State = submarineapacheorgv1.FailedState
submarineCopy.Status.ErrorMessage = err.Error()
r.recordSubmarineEvent(submarineCopy)
}
}
// Update STATUS of Submarine
err = r.updateSubmarineStatus(ctx, submarine, submarineCopy)
if err != nil {
submarineCopy.Status.State = submarineapacheorgv1.FailedState
submarineCopy.Status.ErrorMessage = err.Error()
r.recordSubmarineEvent(submarineCopy)
}
// Re-run Reconcile regularly
result := ctrl.Result{}
result.RequeueAfter = time.Second * 30 // default resync period
return result, nil
}