func()

in oracle/controllers/instancecontroller/instance_controller_standby.go [55:293]


func (r *InstanceReconciler) standbyStateMachine(ctx context.Context, inst *v1alpha1.Instance, log logr.Logger) (ctrl.Result, error) {
	log.Info("Running standby DR state machine")
	// Our initial state is equivalent to StandbyVerifyFailed. See state machine.
	state := k8s.StandbyDRVerifyFailed
	if standbyCond := k8s.FindCondition(inst.Status.Conditions, k8s.StandbyDRReady); standbyCond != nil {
		state = standbyCond.Reason
	}

	switch state {
	case k8s.StandbyDRVerifyFailed:
		externalErrMsgs, err := r.verifySettings(ctx, inst)
		if err != nil {
			log.Error(err, "verify settings failed")
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRVerifyFailed,
				"validate replication settings failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		if len(externalErrMsgs) > 0 {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRVerifyFailed,
				"validate replication settings failed", externalErrMsgs...)
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRVerifyCompleted,
			"validate replication settings completed")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRVerifyCompleted:
		inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRCreateInProgress,
			"create standby instance in progress")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRCreateInProgress:
		if inst.Spec.ReplicationSettings == nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateInProgress,
				replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
			return ctrl.Result{}, nil
		}
		inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
		operationId := lroOperationID(createStandby, inst)
		credentialReq, err := toCredentialReq(inst.Spec.ReplicationSettings.PrimaryUser)
		if err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateInProgress,
				"create standby instance failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		operation, err := controllers.CreateStandby(ctx, r, r.DatabaseClientFactory, inst.Namespace, inst.Name, controllers.CreateStandbyRequest{
			PrimaryHost:         inst.Spec.ReplicationSettings.PrimaryHost,
			PrimaryPort:         inst.Spec.ReplicationSettings.PrimaryPort,
			PrimaryService:      inst.Spec.ReplicationSettings.PrimaryServiceName,
			PrimaryUser:         inst.Spec.ReplicationSettings.PrimaryUser.Name,
			PrimaryCredential:   credentialReq,
			BackupGcsPath:       inst.Spec.ReplicationSettings.BackupURI,
			StandbyDbDomain:     inst.Spec.DBDomain,
			StandbyDbUniqueName: inst.Spec.DBUniqueName,
			StandbyLogDiskSize:  findLogDiskSize(inst),
			LroInput:            &controllers.LROInput{OperationId: operationId},
		})
		if err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateFailed,
				"create standby instance failed", internalErrToMsg(err))
			return ctrl.Result{}, nil
		}
		if operation.GetError() != nil {
			controllers.DeleteLROOperation(ctx, r.DatabaseClientFactory, r, operationId, inst.Namespace, inst.Name)
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateFailed,
				"create standby instance failed", operation.GetError().GetMessage())
			return ctrl.Result{}, nil
		} else if !operation.Done {
			log.Info("create standby still in progress")
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateInProgress,
				"create standby instance in progress")
			return ctrl.Result{RequeueAfter: StandbyReconcileInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRCreateCompleted,
			"create standby instance completed")
		return ctrl.Result{}, nil

	case k8s.StandbyDRCreateFailed:
		return ctrl.Result{}, nil

	case k8s.StandbyDRCreateCompleted:
		if inst.Spec.ReplicationSettings == nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRCreateCompleted,
				replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
			return ctrl.Result{}, nil
		}
		inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings
		if err := r.reconcileDataGuard(ctx, inst); err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRSetUpDataGuardFailed,
				"set up Data Guard failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRSetUpDataGuardCompleted,
			"set up Data Guard completed")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRSetUpDataGuardFailed:
		if inst.Spec.ReplicationSettings == nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRSetUpDataGuardFailed,
				replicationSettingsNilErr(inst.Status.CurrentReplicationSettings))
			return ctrl.Result{}, nil
		}
		inst.Status.CurrentReplicationSettings = inst.Spec.ReplicationSettings

		if err := r.reconcileDataGuard(ctx, inst); err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRSetUpDataGuardFailed,
				"set up Data Guard failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRSetUpDataGuardCompleted,
			"set up Data Guard completed")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRSetUpDataGuardCompleted:
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRDataGuardReplicationInProgress,
			"Data Guard data replication in progress")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRDataGuardReplicationInProgress:
		if inst.Spec.ReplicationSettings == nil {
			if err := r.reconcilePromoteStandby(ctx, inst, log); err != nil {
				r.updateStandbyDataReplicationStatus(ctx,
					inst, metav1.ConditionFalse,
					k8s.StandbyDRPromoteFailed,
					"promote standby failed", internalErrToMsg(err))
				return ctrl.Result{}, nil
			}
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRPromoteCompleted,
				"promote standby completed")
			return ctrl.Result{Requeue: true}, nil
		}
		if err := r.reconcileDataGuard(ctx, inst); err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRDataGuardReplicationInProgress,
				"Data Guard data replication in progress with errors", internalErrToMsg(err))
			r.updateDataGuardStatus(ctx, inst, standbyErrorRetryInterval, log)
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRDataGuardReplicationInProgress,
			"Data Guard data replication in progress")
		r.updateDataGuardStatus(ctx, inst, StandbyReconcileInterval, log)
		return ctrl.Result{RequeueAfter: StandbyReconcileInterval}, nil

	case k8s.StandbyDRPromoteFailed:
		if err := r.reconcilePromoteStandby(ctx, inst, log); err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRPromoteFailed,
				"promote standby failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionFalse,
			k8s.StandbyDRPromoteCompleted,
			"promote standby completed")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRPromoteCompleted, k8s.StandbyDRBootstrapFailed:
		inst.Status.CurrentReplicationSettings = nil
		inst.Status.DataGuardOutput = nil
		err := r.bootstrapStandby(ctx, inst)
		if err != nil {
			r.updateStandbyDataReplicationStatus(ctx,
				inst, metav1.ConditionFalse,
				k8s.StandbyDRBootstrapFailed,
				"bootstrap standby failed", internalErrToMsg(err))
			return ctrl.Result{RequeueAfter: standbyErrorRetryInterval}, nil
		}
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionTrue,
			k8s.StandbyDRBootstrapCompleted,
			"bootstrap standby completed")
		k8s.InstanceUpsertCondition(&inst.Status, k8s.Ready,
			metav1.ConditionTrue, k8s.CreateComplete,
			"bootstrap standby completed")
		k8s.InstanceUpsertCondition(&inst.Status, k8s.DatabaseInstanceReady,
			metav1.ConditionTrue, k8s.CreateComplete,
			"bootstrap standby completed")
		return ctrl.Result{Requeue: true}, nil

	case k8s.StandbyDRBootstrapCompleted:
		r.updateStandbyDataReplicationStatus(ctx,
			inst, metav1.ConditionTrue,
			k8s.StandbyDRBootstrapCompleted,
			"bootstrap standby completed")
		k8s.InstanceUpsertCondition(&inst.Status, k8s.Ready,
			metav1.ConditionTrue, k8s.CreateComplete,
			"bootstrap standby completed")
		k8s.InstanceUpsertCondition(&inst.Status, k8s.DatabaseInstanceReady,
			metav1.ConditionTrue, k8s.CreateComplete,
			"bootstrap standby completed")

		return ctrl.Result{Requeue: true}, nil

	default:
		log.Info("standbyStateMachine: no action needed, proceed with main reconciliation", "unknown state", state)
		return ctrl.Result{}, nil
	}
}