Skip to content

Commit

Permalink
Run dashboard as separate deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
sleshchenko committed Apr 5, 2021
1 parent 4b87fd3 commit 02a4b71
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 17 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,13 @@
"env": {
"MOCK_API": true,
"CHE_FLAVOR": "che"
},
}
},
{
"name": "Launch Main *.go File",
"type": "go",
"request": "launch",
"program": "${file}",
"program": "${file}"
},
{
"useApiV1": false,
Expand Down
2 changes: 1 addition & 1 deletion deploy/crds/org_v1_che_cr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ spec:
# All the endpoints whether backed by the ingress or gateway `route` always point to the subpaths on the same domain. Defaults to `native`.
singleHostExposureType: ''
metrics:
# Enables `metrics` the Che server endpoint.
# Enables `metrics` the Che server endpoint.
enable: true
devWorkspace:
# Deploys the DevWorkspace Operator in the cluster.
Expand Down
11 changes: 11 additions & 0 deletions pkg/controller/che/che_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

orgv1 "github.com/eclipse-che/che-operator/pkg/apis/org/v1"
"github.com/eclipse-che/che-operator/pkg/deploy"
"github.com/eclipse-che/che-operator/pkg/deploy/dashboard"
devworkspace "github.com/eclipse-che/che-operator/pkg/deploy/dev-workspace"
devfile_registry "github.com/eclipse-che/che-operator/pkg/deploy/devfile-registry"
"github.com/eclipse-che/che-operator/pkg/deploy/gateway"
Expand Down Expand Up @@ -938,6 +939,16 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e
}
}

provisioned, err = dashboard.SyncDashboardToCluster(deployContext, cheHost)
if !tests {
if !provisioned {
if err != nil {
logrus.Errorf("Error provisioning '%s' to cluster: %v", dashboard.Dashboard, err)
}
return reconcile.Result{Requeue: true}, err
}
}

// create Che ConfigMap which is synced with CR and is not supposed to be manually edited
// controller will reconcile this CM with CR spec
done, err = server.SyncCheConfigMapToCluster(deployContext)
Expand Down
60 changes: 60 additions & 0 deletions pkg/deploy/dashboard/dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// Copyright (c) 2012-2019 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 dashboard

import (
"github.com/eclipse-che/che-operator/pkg/deploy"
"github.com/eclipse-che/che-operator/pkg/deploy/expose"
"github.com/eclipse-che/che-operator/pkg/util"
"github.com/sirupsen/logrus"
)

const (
Dashboard = "dashboard"
)

/**
* Create dashboard resources.
*/
func SyncDashboardToCluster(deployContext *deploy.DeployContext, cheHost string) (done bool, err error) {
// Deploy plugin registry
success, err := SyncDashboardDeploymentToCluster(deployContext)
if !util.IsTestMode() {
if !success {
logrus.Info("Waiting on deployment '" + Dashboard + "' to be ready")
if err != nil {
logrus.Error(err)
}

return false, err
}
}

// Create a new registry service
dashboardComponent := getDashboardComponent(deployContext)
dashboardLabels := deploy.GetLabels(deployContext.CheCluster, dashboardComponent)
serviceStatus := deploy.SyncServiceToCluster(deployContext, dashboardComponent, []string{"http"}, []int32{8080}, dashboardLabels)
if !util.IsTestMode() {
if !serviceStatus.Continue {
logrus.Info("Waiting on service '" + Dashboard + "' to be ready")
if serviceStatus.Err != nil {
logrus.Error(serviceStatus.Err)
}

return false, serviceStatus.Err
}
}

_, done, err = expose.ExposeWithHost(deployContext, cheHost, dashboardComponent, cheHost, "/dashboard")

return done, err
}
197 changes: 197 additions & 0 deletions pkg/deploy/dashboard/deployment_dashboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
//
// Copyright (c) 2012-2019 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 dashboard

import (
"github.com/eclipse/che-operator/pkg/deploy"
"strconv"
"strings"

orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1"
"github.com/eclipse/che-operator/pkg/util"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

func SyncDashboardDeploymentToCluster(deployContext *deploy.DeployContext) (bool, error) {
component := getDashboardComponent(deployContext)
clusterDeployment, err := deploy.GetClusterDeployment(component, deployContext.CheCluster.Namespace, deployContext.ClusterAPI.Client)
if err != nil {
return false, err
}

specDeployment, err := getSpecDashboardDeployment(deployContext)
if err != nil {
return false, err
}

return deploy.SyncDeploymentToCluster(deployContext, specDeployment, clusterDeployment, nil, nil)
}

func getDashboardComponent(deployContext *deploy.DeployContext) string {
cheFlavor := deploy.DefaultCheFlavor(deployContext.CheCluster)
return cheFlavor + "-dashboard"
}

func getSpecDashboardDeployment(deployContext *deploy.DeployContext) (*appsv1.Deployment, error) {
isOpenShift, _, err := util.DetectOpenShift()
if err != nil {
return nil, err
}

terminationGracePeriodSeconds := int64(30)
cheFlavor := deploy.DefaultCheFlavor(deployContext.CheCluster)
dashboardComponent := getDashboardComponent(deployContext)
labels := deploy.GetLabels(deployContext.CheCluster, dashboardComponent)
memRequest := util.GetValue(deployContext.CheCluster.Spec.Server.ServerMemoryRequest, deploy.DefaultServerMemoryRequest)

memLimit := util.GetValue(deployContext.CheCluster.Spec.Server.ServerMemoryLimit, deploy.DefaultServerMemoryLimit)
dashboardImageAndTag := "quay.io/eclipse/che-dashboard:next"
pullPolicy := corev1.PullPolicy(util.GetValue(string(deployContext.CheCluster.Spec.Server.CheImagePullPolicy), deploy.DefaultPullPolicyFromDockerImage(dashboardImageAndTag)))

deployment := &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
APIVersion: "apps/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: dashboardComponent,
Namespace: deployContext.CheCluster.Namespace,
Labels: labels,
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{MatchLabels: labels},
Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: labels,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: cheFlavor,
ImagePullPolicy: pullPolicy,
Image: dashboardImageAndTag,
Ports: []corev1.ContainerPort{
{
Name: "http",
ContainerPort: 8080,
Protocol: "TCP",
},
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse(memRequest),
},
Limits: corev1.ResourceList{
corev1.ResourceMemory: resource.MustParse(memLimit),
},
},
},
},
RestartPolicy: "Always",
TerminationGracePeriodSeconds: &terminationGracePeriodSeconds,
},
},
},
}

// configure probes if debug isn't set
//deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = &corev1.Probe{
// Handler: corev1.Handler{
// HTTPGet: &corev1.HTTPGetAction{
// Path: "/api/system/state",
// Port: intstr.IntOrString{
// Type: intstr.Int,
// IntVal: int32(8080),
// },
// Scheme: corev1.URISchemeHTTP,
// },
// },
// // After POD start, the POD will be seen as ready after a minimum of 15 seconds and we expect it to be seen as ready until a maximum of 200 seconds
// // 200 s = InitialDelaySeconds + PeriodSeconds * (FailureThreshold - 1) + TimeoutSeconds
// InitialDelaySeconds: 25,
// FailureThreshold: 18,
// TimeoutSeconds: 5,
// PeriodSeconds: 10,
// SuccessThreshold: 1,
//}
//deployment.Spec.Template.Spec.Containers[0].LivenessProbe = &corev1.Probe{
// Handler: corev1.Handler{
// HTTPGet: &corev1.HTTPGetAction{
// Path: "/api/system/state",
// Port: intstr.IntOrString{
// Type: intstr.Int,
// IntVal: int32(8080),
// },
// Scheme: corev1.URISchemeHTTP,
// },
// },
// // After POD start, don't initiate liveness probe while the POD is still expected to be declared as ready by the readiness probe
// InitialDelaySeconds: 200,
// FailureThreshold: 3,
// TimeoutSeconds: 3,
// PeriodSeconds: 10,
// SuccessThreshold: 1,
//}

if !isOpenShift {
runAsUser, err := strconv.ParseInt(util.GetValue(deployContext.CheCluster.Spec.K8s.SecurityContextRunAsUser, deploy.DefaultSecurityContextRunAsUser), 10, 64)
if err != nil {
return nil, err
}
fsGroup, err := strconv.ParseInt(util.GetValue(deployContext.CheCluster.Spec.K8s.SecurityContextFsGroup, deploy.DefaultSecurityContextFsGroup), 10, 64)
if err != nil {
return nil, err
}
deployment.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
RunAsUser: &runAsUser,
FSGroup: &fsGroup,
}
}

if !util.IsTestMode() {
err = controllerutil.SetControllerReference(deployContext.CheCluster, deployment, deployContext.ClusterAPI.Scheme)
if err != nil {
return nil, err
}
}

return deployment, nil
}

// GetFullCheServerImageLink evaluate full cheImage link(with repo and tag)
// based on Checluster information and image defaults from env variables
func GetFullDashboardServerImageLink(checluster *orgv1.CheCluster) string {
if len(checluster.Spec.Server.CheImage) > 0 {
cheServerImageTag := util.GetValue(checluster.Spec.Server.CheImageTag, deploy.DefaultCheVersion())
return checluster.Spec.Server.CheImage + ":" + cheServerImageTag
}

defaultCheServerImage := deploy.DefaultCheServerImage(checluster)
if len(checluster.Spec.Server.CheImageTag) == 0 {
return defaultCheServerImage
}

// For back compatibility with version < 7.9.0:
// if cr.Spec.Server.CheImage is empty, but cr.Spec.Server.CheImageTag is not empty,
// parse from default Che image(value comes from env variable) "Che image repository"
// and return "Che image", like concatenation: "cheImageRepo:cheImageTag"
separator := map[bool]string{true: "@", false: ":"}[strings.Contains(defaultCheServerImage, "@")]
imageParts := strings.Split(defaultCheServerImage, separator)
return imageParts[0] + ":" + checluster.Spec.Server.CheImageTag
}
30 changes: 17 additions & 13 deletions pkg/deploy/expose/expose.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func Expose(
if !util.IsOpenShift {
if useGateway {
cfg := gateway.GetGatewayRouteConfig(deployContext, gatewayConfig, "/"+pathPrefix, 10, "http://"+endpointName+":8080", stripPrefix)
done, err := deploy.SyncConfigMapSpecToCluster(deployContext, &cfg)
clusterCfg, err := deploy.SyncConfigMapToCluster(deployContext, &cfg)
if !util.IsTestMode() {
if !done {
if err != nil {
Expand All @@ -70,17 +70,19 @@ func Expose(
return "", false, err
}
}
if _, err = deploy.DeleteNamespacedObject(deployContext, endpointName, &extentionsv1beta1.Ingress{}); err != nil {
if err := deploy.DeleteIngressIfExists(endpointName, deployContext); !util.IsTestMode() && err != nil {
logrus.Error(err)
}
} else {
done, err := deploy.SyncIngressToCluster(deployContext, endpointName, domain, endpointName, 8080, ingressCustomSettings, component)
if !done {
logrus.Infof("Waiting on ingress '%s' to be ready", endpointName)
if err != nil {
logrus.Error(err)
ingress, err := deploy.SyncIngressToCluster(deployContext, endpointName, domain, endpointName, 8080, ingressCustomSettings, component)
if !util.IsTestMode() {
if ingress == nil {
logrus.Infof("Waiting on ingress '%s' to be ready", endpointName)
if err != nil {
logrus.Error(err)
}
return "", false, err
}
return "", false, err
}
if err := gateway.DeleteGatewayRouteConfig(gatewayConfig, deployContext); !util.IsTestMode() && err != nil {
logrus.Error(err)
Expand All @@ -89,12 +91,14 @@ func Expose(
} else {
if useGateway {
cfg := gateway.GetGatewayRouteConfig(deployContext, gatewayConfig, "/"+pathPrefix, 10, "http://"+endpointName+":8080", stripPrefix)
done, err := deploy.SyncConfigMapSpecToCluster(deployContext, &cfg)
if !done {
if err != nil {
logrus.Error(err)
clusterCfg, err := deploy.SyncConfigMapToCluster(deployContext, &cfg)
if !util.IsTestMode() {
if clusterCfg == nil {
if err != nil {
logrus.Error(err)
}
return "", false, err
}
return "", false, err
}
if err := deploy.DeleteRouteIfExists(endpointName, deployContext); !util.IsTestMode() && err != nil {
logrus.Error(err)
Expand Down
4 changes: 4 additions & 0 deletions pkg/deploy/identity-provider/deployment_keycloak.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,10 @@ func GetSpecKeycloakDeployment(
corev1.ResourceCPU: util.GetResourceQuantity(
deployContext.CheCluster.Spec.Auth.IdentityProviderContainerResources.Limits.Cpu,
deploy.DefaultIdentityProviderCpuLimit),
// corev1.ResourceMemory: resource.MustParse("256Mi"),
//},
//Limits: corev1.ResourceList{
// corev1.ResourceMemory: resource.MustParse("512Mi"),
},
},
ReadinessProbe: &corev1.Probe{
Expand Down
1 change: 1 addition & 0 deletions pkg/deploy/postgres/deployment_postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ func GetSpecPostgresDeployment(deployContext *deploy.DeployContext, clusterDeplo
corev1.ResourceCPU: util.GetResourceQuantity(
deployContext.CheCluster.Spec.Database.ChePostgresContainerResources.Limits.Cpu,
deploy.DefaultPostgresCpuLimit),
//corev1.ResourceMemory: resource.MustParse("756Mi"),
},
},
VolumeMounts: []corev1.VolumeMount{
Expand Down
Loading

0 comments on commit 02a4b71

Please sign in to comment.