func()

in oracle/controllers/databasecontroller/database_controller.go [171:289]


func (r *DatabaseReconciler) ReconcileDatabaseCreation(ctx context.Context, req ctrl.Request, log logr.Logger) (ctrl.Result, error) {

	log.Info("reconciling database")

	var db v1alpha1.Database
	if err := r.Get(ctx, req.NamespacedName, &db); err != nil {
		return ctrl.Result{}, client.IgnoreNotFound(err)
	}

	if err := validateSpec(&db); err != nil {
		return ctrl.Result{}, r.handlePreflightCheckError(ctx, &db, err)
	}

	// Find an Instance resource that the Database belongs to.
	var inst v1alpha1.Instance
	if err := r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: db.Spec.Instance}, &inst); err != nil {
		return ctrl.Result{}, r.handlePreflightCheckError(ctx, &db, fmt.Errorf("failed to find instance %q for database %q", db.Spec.Instance, db.Name))
	}
	log.Info("using the following instance to create a new database(PDB)", "db.Spec.Instance", db.Spec.Instance, "inst", inst)

	DBDomain := controllers.GetDBDomain(&inst)

	// Find a pod running a database container.
	pods, err := r.findPod(ctx, req.Namespace, db.Spec.Instance)
	if err != nil {
		return ctrl.Result{}, r.handlePreflightCheckError(ctx, &db, fmt.Errorf("failed to find a pod"))
	}
	log.V(2).Info("found a pod", "pods", pods)

	if len(pods.Items) != 1 {
		return ctrl.Result{}, r.handlePreflightCheckError(ctx, &db, fmt.Errorf("expected 1 pod, found %d", len(pods.Items)))
	}

	// Find a database container within that pod.
	if _, err := findContainer(pods.Items[0], controllers.DatabaseContainerName); err != nil {
		log.Error(err, "reconciling database - failed to find a database container")
		return ctrl.Result{}, err
	}
	log.V(1).Info("a database container identified")

	// CDBName is specified in Instance specs
	cdbName := inst.Spec.CDBName
	istatus, err := CheckStatusInstanceFunc(ctx, r, r.DatabaseClientFactory, db.Spec.Instance, cdbName, inst.Namespace, "", DBDomain, log)
	if err != nil {
		log.Error(err, "preflight check failed", "check the database instance status", "failed")
		return ctrl.Result{}, err
	}

	if istatus != controllers.StatusReady {
		return ctrl.Result{}, r.handlePreflightCheckError(ctx, &db, fmt.Errorf("database instance doesn't appear to be ready yet"))
	}

	log.Info("preflight check: database instance is ready")

	// Confirm that an external LB is ready.
	lbSvc := &corev1.Service{}
	if err := r.Get(ctx, types.NamespacedName{Name: fmt.Sprintf(controllers.SvcName, db.Spec.Instance), Namespace: req.NamespacedName.Namespace}, lbSvc); err != nil {
		return ctrl.Result{}, err
	}

	if len(lbSvc.Status.LoadBalancer.Ingress) == 0 && !skipLBCheckForTest {
		return ctrl.Result{}, fmt.Errorf("preflight check: createDatabase: external LB is NOT ready")
	}
	log.Info("preflight check: createDatabase external LB service is ready", "svcName", lbSvc.Name)

	// Add finalizer to clean up the underlying PDB in case of deletion.
	if !controllerutil.ContainsFinalizer(&db, controllers.FinalizerName) {
		log.Info("adding a finalizer to the Database object.")
		controllerutil.AddFinalizer(&db, controllers.FinalizerName)
		if err := r.Update(ctx, &db); err != nil {
			return ctrl.Result{}, err
		}
	}

	alreadyExists, err := NewDatabase(ctx, r, &db, DBDomain, cdbName, log)
	if err != nil {
		return ctrl.Result{}, err
	}

	r.Recorder.Eventf(&db, corev1.EventTypeNormal, k8s.CreatedDatabase, fmt.Sprintf("Created new database %q", db.Spec.Name))
	db.Status.Phase = commonv1alpha1.DatabaseReady
	db.Status.Conditions = k8s.Upsert(db.Status.Conditions, k8s.Ready, v1.ConditionTrue, k8s.CreateComplete, "")
	if err := r.Status().Update(ctx, &db); err != nil {
		return ctrl.Result{}, err
	}

	if alreadyExists {
		if err := SyncUsers(ctx, r, &db, cdbName, log); err != nil {
			log.Error(err, "failed to sync database")
			return ctrl.Result{}, err
		}
		return ctrl.Result{}, nil
	}

	log.V(1).Info("[DEBUG] create users", "Database", db.Spec.Name, "Users/Privs", db.Spec.Users)
	if err := NewUsers(ctx, r, &db, DBDomain, cdbName, log); err != nil {
		return ctrl.Result{}, err
	}

	// check DB name against existing ones to decide whether this is a new DB
	if !util.Contains(inst.Status.DatabaseNames, db.Spec.Name) {
		log.Info("found a new DB", "dbName", db.Spec.Name)
		inst.Status.DatabaseNames = append(inst.Status.DatabaseNames, db.Spec.Name)
	} else {
		log.V(1).Info("not a new DB, skipping the update", "dbName", db.Spec.Name)
	}

	log.Info("instance status", "conditions", inst.Status.Conditions, "endpoint", inst.Status.Endpoint,
		"url", inst.Status.URL, "databases", inst.Status.DatabaseNames)

	if err := r.Status().Update(ctx, &inst); err != nil {
		log.Error(err, "failed to update an Instance status")
		return ctrl.Result{}, err
	}

	log.Info("reconciling database: DONE")

	return ctrl.Result{}, nil
}