174 lines
5.1 KiB
Go
174 lines
5.1 KiB
Go
//
|
|
// Copyright (c) 2019-2023 Red Hat, Inc.
|
|
// This program and the accompanying materials are made
|
|
// available under the terms of the Eclipse Public License 2.0
|
|
// which is available at https://www.eclipse.org/legal/epl-2.0/
|
|
//
|
|
// SPDX-License-Identifier: EPL-2.0
|
|
//
|
|
// Contributors:
|
|
// Red Hat, Inc. - initial API and implementation
|
|
//
|
|
|
|
package server
|
|
|
|
import (
|
|
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
|
"github.com/eclipse-che/che-operator/pkg/common/chetypes"
|
|
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
|
defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults"
|
|
"github.com/eclipse-che/che-operator/pkg/deploy"
|
|
"github.com/sirupsen/logrus"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
|
)
|
|
|
|
const (
|
|
crb = ".crb."
|
|
cheCRBFinalizerSuffix = crb + constants.FinalizerSuffix
|
|
)
|
|
|
|
type CheServerReconciler struct {
|
|
deploy.Reconcilable
|
|
}
|
|
|
|
func NewCheServerReconciler() *CheServerReconciler {
|
|
return &CheServerReconciler{}
|
|
}
|
|
|
|
func (s *CheServerReconciler) Reconcile(ctx *chetypes.DeployContext) (reconcile.Result, bool, error) {
|
|
done, err := s.syncCheConfigMap(ctx)
|
|
if !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
// ensure configmap is created
|
|
// the version of the object is used in the deployment
|
|
exists, err := deploy.GetNamespacedObject(ctx, CheConfigMapName, &corev1.ConfigMap{})
|
|
if !exists {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
if done, err := deploy.SyncServiceAccountToCluster(ctx, constants.DefaultCheServiceAccountName); !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
if done, err := s.syncPermissions(ctx); !done {
|
|
return reconcile.Result{Requeue: true}, false, err
|
|
}
|
|
|
|
done, err = s.syncDeployment(ctx)
|
|
if !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
done, err = s.syncActiveChePhase(ctx)
|
|
if !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
done, err = s.syncCheVersion(ctx)
|
|
if !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
done, err = s.syncCheURL(ctx)
|
|
if !done {
|
|
return reconcile.Result{}, false, err
|
|
}
|
|
|
|
return reconcile.Result{}, true, nil
|
|
}
|
|
|
|
func (c *CheServerReconciler) Finalize(ctx *chetypes.DeployContext) bool {
|
|
return c.deletePermissions(ctx)
|
|
}
|
|
|
|
func (s *CheServerReconciler) syncCheConfigMap(ctx *chetypes.DeployContext) (bool, error) {
|
|
data, err := s.getCheConfigMapData(ctx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return deploy.SyncConfigMapDataToCluster(ctx, CheConfigMapName, data, getComponentName(ctx))
|
|
}
|
|
|
|
func (s *CheServerReconciler) syncActiveChePhase(ctx *chetypes.DeployContext) (bool, error) {
|
|
cheDeployment := &appsv1.Deployment{}
|
|
exists, err := deploy.GetNamespacedObject(ctx, getComponentName(ctx), cheDeployment)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if exists {
|
|
if cheDeployment.Status.AvailableReplicas == 0 {
|
|
if ctx.CheCluster.Status.ChePhase != chev2.ClusterPhaseInactive {
|
|
ctx.CheCluster.Status.ChePhase = chev2.ClusterPhaseInactive
|
|
err := deploy.UpdateCheCRStatus(ctx, "Phase", chev2.ClusterPhaseInactive)
|
|
return false, err
|
|
}
|
|
} else if cheDeployment.Status.Replicas != cheDeployment.Status.AvailableReplicas {
|
|
if ctx.CheCluster.Status.ChePhase != chev2.RollingUpdate {
|
|
ctx.CheCluster.Status.ChePhase = chev2.RollingUpdate
|
|
err := deploy.UpdateCheCRStatus(ctx, "Phase", chev2.RollingUpdate)
|
|
return false, err
|
|
}
|
|
} else {
|
|
if ctx.CheCluster.Status.ChePhase != chev2.ClusterPhaseActive {
|
|
ctx.CheCluster.Status.ChePhase = chev2.ClusterPhaseActive
|
|
err := deploy.UpdateCheCRStatus(ctx, "Phase", chev2.ClusterPhaseActive)
|
|
return err == nil, err
|
|
}
|
|
}
|
|
} else {
|
|
ctx.CheCluster.Status.ChePhase = chev2.ClusterPhaseInactive
|
|
err := deploy.UpdateCheCRStatus(ctx, "Phase", chev2.ClusterPhaseInactive)
|
|
return false, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (s *CheServerReconciler) getCRBFinalizerName(crbName string) string {
|
|
finalizer := crbName + cheCRBFinalizerSuffix
|
|
diff := len(finalizer) - 63
|
|
if diff > 0 {
|
|
return finalizer[:len(finalizer)-diff]
|
|
}
|
|
return finalizer
|
|
}
|
|
|
|
func (s *CheServerReconciler) syncDeployment(ctx *chetypes.DeployContext) (bool, error) {
|
|
spec, err := s.getDeploymentSpec(ctx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return deploy.SyncDeploymentSpecToCluster(ctx, spec, deploy.DefaultDeploymentDiffOpts)
|
|
}
|
|
|
|
func (s CheServerReconciler) syncCheVersion(ctx *chetypes.DeployContext) (bool, error) {
|
|
cheVersion := defaults.GetCheVersion()
|
|
if ctx.CheCluster.Status.CheVersion != cheVersion {
|
|
ctx.CheCluster.Status.CheVersion = cheVersion
|
|
err := deploy.UpdateCheCRStatus(ctx, "version", cheVersion)
|
|
return err == nil, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (s CheServerReconciler) syncCheURL(ctx *chetypes.DeployContext) (bool, error) {
|
|
var cheUrl = "https://" + ctx.CheHost
|
|
if ctx.CheCluster.Status.CheURL != cheUrl {
|
|
product := map[bool]string{true: "Red Hat OpenShift Dev Spaces", false: "Eclipse Che"}[defaults.GetCheFlavor() == "devspaces"]
|
|
logrus.Infof("%s is now available at: %s", product, cheUrl)
|
|
|
|
ctx.CheCluster.Status.CheURL = cheUrl
|
|
err := deploy.UpdateCheCRStatus(ctx, getComponentName(ctx)+" server URL", cheUrl)
|
|
return err == nil, err
|
|
}
|
|
|
|
return true, nil
|
|
}
|