diff --git a/api/v1alpha1/drupalsite_types.go b/api/v1alpha1/drupalsite_types.go index 638b634489a6ed0235f496dd3ea5e507f9a66fcc..ae755f2327cbc028d2de691d0611736b0a8e3419 100644 --- a/api/v1alpha1/drupalsite_types.go +++ b/api/v1alpha1/drupalsite_types.go @@ -75,7 +75,7 @@ type Configuration struct { // TODO: support branches https://gitlab.cern.ch/drupal/paas/drupalsite-operator/-/issues/28 // QoSClass specifies the website's performance and availability requirements. The default value is "standard". - // +kubebuilder:validation:Enum:=critical;test;standard + // +kubebuilder:validation:Enum:=critical;eco;standard // +kubebuilder:default=standard // +optional QoSClass `json:"qosClass,omitempty"` @@ -211,6 +211,12 @@ func (drp DrupalSite) ConditionTrue(condition status.ConditionType) (update bool return init != nil && init.Status == v1.ConditionTrue } +// ConditionFalse reports if the condition is false +func (drp DrupalSite) ConditionFalse(condition status.ConditionType) (update bool) { + init := drp.Status.Conditions.GetCondition(condition) + return init != nil && init.Status == v1.ConditionFalse +} + // ConditionReasonSet reports if the condition Reason is not empty func (drp DrupalSite) ConditionReasonSet(condition status.ConditionType) (update bool) { init := drp.Status.Conditions.GetCondition(condition) diff --git a/config/crd/bases/drupal.webservices.cern.ch_drupalsites.yaml b/config/crd/bases/drupal.webservices.cern.ch_drupalsites.yaml index b4ab1ba0ce1c1bec5afd20d52cbfddb39c198809..2e9d0210a7c138a47f0824950aba238dc96333ed 100644 --- a/config/crd/bases/drupal.webservices.cern.ch_drupalsites.yaml +++ b/config/crd/bases/drupal.webservices.cern.ch_drupalsites.yaml @@ -82,7 +82,7 @@ spec: availability requirements. The default value is "standard". enum: - critical - - test + - eco - standard type: string webDAVPassword: diff --git a/controllers/drupalsite_controller.go b/controllers/drupalsite_controller.go index b518eeae0e5b88d628d4a22063956557a9dee286..21fcf1a1a62316afaa5e14c7f3cf2544bfb8d545 100644 --- a/controllers/drupalsite_controller.go +++ b/controllers/drupalsite_controller.go @@ -270,7 +270,11 @@ func (r *DrupalSiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) // Check if the site is installed or cloned and mark the condition if !drupalSite.ConditionTrue("Initialized") { - if r.isDrupalSiteInstalled(ctx, drupalSite) || r.isCloneJobCompleted(ctx, drupalSite) { + installed, err := r.isDrupalSiteInstalled(ctx, drupalSite) + if err != nil { + // Initialized? Unknown + update = setConditionStatus(drupalSite, "Initialized", true, err, true) || update + } else if installed { update = setInitialized(drupalSite) || update } else { update = setNotInitialized(drupalSite) || update @@ -429,19 +433,6 @@ func (r *DrupalSiteReconciler) Reconcile(ctx context.Context, req ctrl.Request) // business logic -// isInstallJobCompleted checks if the drush job is successfully completed -func (r *DrupalSiteReconciler) isInstallJobCompleted(ctx context.Context, d *webservicesv1a1.DrupalSite) bool { - found := &batchv1.Job{} - jobObject := &batchv1.Job{ObjectMeta: metav1.ObjectMeta{Name: "install-" + d.Name, Namespace: d.Namespace}} - err := r.Get(ctx, types.NamespacedName{Name: jobObject.Name, Namespace: jobObject.Namespace}, found) - if err == nil { - if found.Status.Succeeded != 0 { - return true - } - } - return false -} - // isCloneJobCompleted checks if the clone job is successfully completed func (r *DrupalSiteReconciler) isCloneJobCompleted(ctx context.Context, d *webservicesv1a1.DrupalSite) bool { cloneJob := &batchv1.Job{} @@ -467,14 +458,21 @@ func (r *DrupalSiteReconciler) isDrupalSiteReady(ctx context.Context, d *webserv } // isDrupalSiteInstalled checks if the drupal site is initialized by running drush status command in the PHP pod -func (r *DrupalSiteReconciler) isDrupalSiteInstalled(ctx context.Context, d *webservicesv1a1.DrupalSite) bool { +func (r *DrupalSiteReconciler) isDrupalSiteInstalled(ctx context.Context, d *webservicesv1a1.DrupalSite) (bool, reconcileError) { if r.isDrupalSiteReady(ctx, d) { - if _, err := r.execToServerPodErrOnStderr(ctx, d, "php-fpm", nil, checkIfSiteIsInstalled()...); err != nil { - return false + _, stderr, err := r.execToServerPod(ctx, d, "php-fpm", nil, checkIfSiteIsInstalled()...) + // Error running exec => condition unknown + if err != nil { + return true, newApplicationError(err, ErrClientK8s) } - return true + // The script executed and returned this error message + // TODO: check error code instead of message! + if stderr == "Drupal is not installed" { + return false, nil + } + return true, nil } - return false + return true, newApplicationError(fmt.Errorf("Can't check install status"), ErrTemporary) } // isDBODProvisioned checks if the DBOD has been provisioned by checking the status of DBOD custom resource diff --git a/controllers/drupalsite_resources.go b/controllers/drupalsite_resources.go index 78908e3abbb1bad7eaf11dca393c9204da3b9efe..9376679bd7246c02668c613f65a2d153501b0c31 100644 --- a/controllers/drupalsite_resources.go +++ b/controllers/drupalsite_resources.go @@ -247,13 +247,17 @@ func (r *DrupalSiteReconciler) ensureResources(drp *webservicesv1a1.DrupalSite, transientErrs = append(transientErrs, transientErr.Wrap("%v: for Nginx SVC")) } if r.isDBODProvisioned(ctx, drp) { - if drp.Spec.Configuration.CloneFrom == "" { - if transientErr := r.ensureResourceX(ctx, drp, "site_install_job", log); transientErr != nil { - transientErrs = append(transientErrs, transientErr.Wrap("%v: for site install Job")) - } - } else { - if transientErr := r.ensureResourceX(ctx, drp, "clone_job", log); transientErr != nil { - transientErrs = append(transientErrs, transientErr.Wrap("%v: for clone Job")) + // Important check to confirm that the site isn't initialized already, + // before creating an install/clone job! + if drp.ConditionFalse("Initialized") { + if drp.Spec.Configuration.CloneFrom == "" { + if transientErr := r.ensureResourceX(ctx, drp, "site_install_job", log); transientErr != nil { + transientErrs = append(transientErrs, transientErr.Wrap("%v: for site install Job")) + } + } else { + if transientErr := r.ensureResourceX(ctx, drp, "clone_job", log); transientErr != nil { + transientErrs = append(transientErrs, transientErr.Wrap("%v: for clone Job")) + } } } }