diff --git a/controllers/drupalsite_controller_test.go b/controllers/drupalsite_controller_test.go index 98258e1d7674d5f562a85d4dbc42289ef3b1a472..85b2eefa1d166a67f3b2f8fa51fbe5284c070e97 100644 --- a/controllers/drupalsite_controller_test.go +++ b/controllers/drupalsite_controller_test.go @@ -495,17 +495,17 @@ var _ = Describe("DrupalSite controller", func() { return k8sClient.Get(ctx, key, &cr) }, timeout, interval).Should(Succeed()) - By("Adding label to namespace") + By("Adding user-project label to namespace") Eventually(func() error { k8sClient.Get(ctx, types.NamespacedName{Name: key.Namespace}, &namespace) namespace.Labels = map[string]string{"okd.cern.ch/user-project": "true"} return k8sClient.Update(ctx, &namespace) }, timeout, interval).Should(Succeed()) - By("Adding annotations to namespace") + By("Adding blocked label to namespace") Eventually(func() error { k8sClient.Get(ctx, types.NamespacedName{Name: key.Namespace}, &namespace) - namespace.Annotations = map[string]string{"blocked.webservices.cern.ch/blocked-timestamp": "2021-08-11T10:20:00+00:00", "blocked.webservices.cern.ch/reason": "Blocked due to security reason"} + namespace.Labels["okd.cern.ch/project-blocked"] = "true" return k8sClient.Update(ctx, &namespace) }, timeout, interval).Should(Succeed()) @@ -516,11 +516,10 @@ var _ = Describe("DrupalSite controller", func() { return *deploy.Spec.Replicas == 0 }, timeout, interval).Should(BeTrue()) - By("Removing annotations to namespace") + By("Removing blocked label from namespace") Eventually(func() error { k8sClient.Get(ctx, types.NamespacedName{Name: key.Namespace}, &namespace) - delete(namespace.Annotations, "blocked.webservices.cern.ch/blocked-timestamp") - delete(namespace.Annotations, "blocked.webservices.cern.ch/reason") + delete(namespace.Labels, "okd.cern.ch/project-blocked") return k8sClient.Update(ctx, &namespace) }, timeout, interval).Should(Succeed()) diff --git a/controllers/reconciler_common.go b/controllers/reconciler_common.go index eac4c371de2528ebbefe7369e87e37e5c145c65f..b37a272155fea3e00ddc7d5708ce14ac4ad832db 100644 --- a/controllers/reconciler_common.go +++ b/controllers/reconciler_common.go @@ -59,6 +59,8 @@ type DeploymentConfig struct { drupalLogsResources corev1.ResourceRequirements } +const projectBlockedLabel = "okd.cern.ch/project-blocked" + func setReady(drp *webservicesv1a1.DrupalSite) (update bool) { return drp.Status.Conditions.SetCondition(status.Condition{ Type: "Ready", @@ -455,21 +457,28 @@ func backupListUpdateNeeded(veleroBackupsList []velerov1.Backup, statusBackupsLi // expectedDeploymentReplicas calculates expected replicas of deployment func expectedDeploymentReplicas(currentnamespace *corev1.Namespace, qosClass webservicesv1a1.QoSClass) (int32, error) { - _, isBlockedTimestampAnnotationSet := currentnamespace.Annotations["blocked.webservices.cern.ch/blocked-timestamp"] - _, isBlockedReasonAnnotationSet := currentnamespace.Annotations["blocked.webservices.cern.ch/reason"] - blocked := isBlockedTimestampAnnotationSet && isBlockedReasonAnnotationSet - notBlocked := !isBlockedTimestampAnnotationSet && !isBlockedReasonAnnotationSet - switch { - case !blocked && !notBlocked: - return 0, fmt.Errorf("both annotations blocked.webservices.cern.ch/blocked-timestamp and blocked.webservices.cern.ch/reason should be added/removed to block/unblock") - case blocked: + // websites in blocked projects should be scaled to zero replicas + // this causes HAProxy routers to return "503 Application not available" + if projectBlocked(*currentnamespace) { return 0, nil - default: - if qosClass == webservicesv1a1.QoSCritical { - return 3, nil - } - return 1, nil } + + // websites with "critical" QoS should be scaled to three replicas, + // so they have one pod per availability zone + if qosClass == webservicesv1a1.QoSCritical { + return 3, nil + } + + // regular websites should have a single replica + return 1, nil +} + +func projectBlocked(namespace corev1.Namespace) bool { + value, found := namespace.ObjectMeta.Labels[projectBlockedLabel] + if found && value == "true" { + return true + } + return false } // containerExists checks if a container exists on the deployment