func()

in oracle/controllers/backupcontroller/backup_controller.go [227:336]


func (r *BackupReconciler) reconcileBackupCreation(ctx context.Context, backup *v1alpha1.Backup, log logr.Logger) (ctrl.Result, error) {
	if v := r.BackupCtrl.ValidateBackupSpec(backup); !v {
		return ctrl.Result{}, r.BackupCtrl.UpdateStatus(backup)
	}

	state := ""
	backupReadyCond := k8s.FindCondition(backup.Status.Conditions, k8s.Ready)
	if backupReadyCond != nil {
		state = backupReadyCond.Reason
	}
	switch state {
	case "":
		backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionFalse, k8s.BackupPending, "Waiting for the instance to be ready.")
		backup.Status.Phase = commonv1alpha1.BackupPending
		log.Info("reconcileBackupCreation: ->BackupPending")
		return ctrl.Result{RequeueAfter: requeueInterval}, r.BackupCtrl.UpdateStatus(backup)

	case k8s.BackupPending:
		inst, err := r.instReady(ctx, backup.Namespace, backup.Spec.Instance)
		// ensure the inst is ready to create a backup
		if err != nil {
			msg := fmt.Sprintf("instance not ready: %v", err)
			r.Recorder.Event(backup, corev1.EventTypeWarning, k8s.BackupFailed, msg)
			backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionFalse, k8s.BackupFailed, msg)
			backup.Status.Phase = commonv1alpha1.BackupFailed
			log.Info("reconcileBackupCreation: BackupPending->BackupFailed")
			return ctrl.Result{}, r.BackupCtrl.UpdateStatus(backup)
		}
		// backup type is validated in validateBackupSpec
		b := r.OracleBackupFactory.newOracleBackup(r, backup, inst, log)
		if backup.Status.BackupID == "" || backup.Status.BackupTime == "" || backup.Status.StartTime == nil {
			backup.Status.BackupID = b.generateID()
			backup.Status.BackupTime = timeNow().Format("20060102150405")
			startTime := metav1.NewTime(timeNow())
			backup.Status.StartTime = &startTime
			log.Info("backup started at:", "StartTime", backup.Status.StartTime)
			// commit backup id and time
			return ctrl.Result{RequeueAfter: requeueInterval}, r.updateBackupStatus(ctx, backup, inst)
		}

		if err := r.addBackupMetadata(ctx, backup, &oracleBackupMetadata{
			incarnation:       inst.Status.CurrentDatabaseIncarnation,
			parentIncarnation: inst.Status.LastDatabaseIncarnation,
			databaseImage:     inst.Status.ActiveImages["service"],
		}); err != nil {
			return ctrl.Result{}, err
		}

		if err := b.create(ctx); err != nil {
			// default retry
			return ctrl.Result{}, err
		}
		backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionFalse, k8s.BackupInProgress, "Starting to create a backup.")
		log.Info("reconcileBackupCreation: BackupPending->BackupInProgress")
		return ctrl.Result{RequeueAfter: requeueInterval}, r.updateBackupStatus(ctx, backup, inst)

	case k8s.BackupInProgress:
		inst, err := r.BackupCtrl.GetInstance(backup.Spec.Instance, backup.Namespace)
		if err != nil {
			return ctrl.Result{}, err
		}
		// backup type is validated in validateBackupSpec
		b := r.OracleBackupFactory.newOracleBackup(r, backup, inst, log)
		done, err := b.status(ctx)
		if err != nil && strings.Contains(err.Error(), "code = NotFound") {
			// The backup was interrupted and the LRO is lost.
			backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionFalse, k8s.BackupFailed, "Backup interrupted")
			return ctrl.Result{}, r.updateBackupStatus(ctx, backup, inst)
		}

		if done {
			if err == nil {
				r.Recorder.Eventf(backup, corev1.EventTypeNormal, "BackupCompleted", "BackupId:%v, Elapsed time: %v", backup.Status.BackupID, k8s.ElapsedTimeFromLastTransitionTime(k8s.FindCondition(backup.Status.Conditions, k8s.Ready), time.Second))
				backupMetadata, err := b.metadata(ctx)
				if err != nil {
					return ctrl.Result{}, err
				}
				if err := r.addBackupMetadata(ctx, backup, backupMetadata); err != nil {
					return ctrl.Result{}, err
				}
				backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionTrue, k8s.BackupReady, "")
				duration := metav1.Duration{Duration: metav1.Now().Sub(backup.Status.StartTime.Time)}
				backup.Status.Duration = &duration
				backup.Status.GcsPath = controllers.GetBackupGcsPath(backup)
				log.Info("reconcileBackupCreation: BackupInProgress->BackupReady")
			} else {
				r.Recorder.Event(backup, corev1.EventTypeWarning, "BackupFailed", err.Error())
				backup.Status.Conditions = k8s.Upsert(backup.Status.Conditions, k8s.Ready, v1.ConditionFalse, k8s.BackupFailed, err.Error())
				log.Info("reconcileBackupCreation: BackupInProgress->BackupFailed")
			}
			log.Info("reconciling backup creation: DONE")

			return ctrl.Result{}, r.updateBackupStatus(ctx, backup, inst)
		}
		log.Info("reconciling backup creation: InProgress")
		return ctrl.Result{RequeueAfter: statusCheckInterval}, nil
	case k8s.BackupReady:
		// Add finalizer to clean backup data in case of deletion.
		if !controllerutil.ContainsFinalizer(backup, controllers.FinalizerName) {
			log.Info("Adding backup finalizer.")
			controllerutil.AddFinalizer(backup, controllers.FinalizerName)
			// Immediately return to update the object and do the rest of work in the next reconcile cycle.
			return ctrl.Result{}, r.Update(ctx, backup)
		}
		return ctrl.Result{}, nil
	default:
		log.Info("no action needed", "backupReady", backupReadyCond)
		return ctrl.Result{}, nil
	}
}