From b193773469f1b24147529ca82ed4bdfd1bf97c9d Mon Sep 17 00:00:00 2001 From: Anatolii Bazko Date: Wed, 15 Jul 2020 16:20:44 +0300 Subject: [PATCH] Fix deployment Eclipse Che with single-host strategy (#341) * Fix deployment Eclipse Che with single-host strategy Signed-off-by: Anatoliy Bazko --- pkg/controller/che/che_controller.go | 248 ++-------------------- pkg/controller/che/che_controller_test.go | 28 +-- pkg/deploy/deployment_registry.go | 9 +- pkg/deploy/devfile_registry.go | 150 +++++++++++++ pkg/deploy/ingress.go | 37 ++-- pkg/deploy/plugin_registry.go | 152 +++++++++++++ pkg/deploy/registry_configmap.go | 105 --------- pkg/deploy/update.go | 11 + 8 files changed, 359 insertions(+), 381 deletions(-) create mode 100644 pkg/deploy/devfile_registry.go create mode 100644 pkg/deploy/plugin_registry.go delete mode 100644 pkg/deploy/registry_configmap.go diff --git a/pkg/controller/che/che_controller.go b/pkg/controller/che/che_controller.go index 054ae46d6..b162dd1bb 100644 --- a/pkg/controller/che/che_controller.go +++ b/pkg/controller/che/che_controller.go @@ -14,7 +14,6 @@ package che import ( "context" "fmt" - "reflect" "strconv" "time" @@ -862,244 +861,23 @@ func (r *ReconcileChe) Reconcile(request reconcile.Request) (reconcile.Result, e } } - // Create devfile registry resources unless an external registry is used - devfileRegistryURL := instance.Spec.Server.DevfileRegistryUrl - externalDevfileRegistry := instance.Spec.Server.ExternalDevfileRegistry - if !externalDevfileRegistry { - registryName := "devfile-registry" - host := "" - if !isOpenShift { - ingressStatus := deploy.SyncIngressToCluster(instance, registryName, registryName, 8080, clusterAPI) - if !tests { - if !ingressStatus.Continue { - logrus.Infof("Waiting on ingress '%s' to be ready", registryName) - if ingressStatus.Err != nil { - logrus.Error(ingressStatus.Err) - } - - return reconcile.Result{Requeue: ingressStatus.Requeue}, ingressStatus.Err - } - } - - host = ingressDomain - if ingressStrategy == "multi-host" { - host = registryName + "-" + instance.Namespace + "." + ingressDomain - } - } else { - routeStatus := deploy.SyncRouteToCluster(instance, registryName, registryName, 8080, clusterAPI) - if !tests { - if !routeStatus.Continue { - logrus.Infof("Waiting on route '%s' to be ready", registryName) - if routeStatus.Err != nil { - logrus.Error(routeStatus.Err) - } - - return reconcile.Result{Requeue: routeStatus.Requeue}, routeStatus.Err - } - } - - if !tests { - host = routeStatus.Route.Spec.Host - if len(host) < 1 { - cheRoute := r.GetEffectiveRoute(instance, routeStatus.Route.Name) - host = cheRoute.Spec.Host - } - } - } - guessedDevfileRegistryURL := protocol + "://" + host - if devfileRegistryURL == "" { - devfileRegistryURL = guessedDevfileRegistryURL - } - devFileRegistryConfigMap := &corev1.ConfigMap{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: "devfile-registry", Namespace: instance.Namespace}, devFileRegistryConfigMap) - if err != nil { - if errors.IsNotFound(err) { - devFileRegistryConfigMap = deploy.CreateDevfileRegistryConfigMap(instance, devfileRegistryURL) - err = controllerutil.SetControllerReference(instance, devFileRegistryConfigMap, r.scheme) - if err != nil { - logrus.Errorf("An error occurred: %v", err) - return reconcile.Result{}, err - } - logrus.Info("Creating devfile registry airgap configmap") - err = r.client.Create(context.TODO(), devFileRegistryConfigMap) - if err != nil { - logrus.Errorf("Error creating devfile registry configmap: %v", err) - return reconcile.Result{}, err - } - return reconcile.Result{Requeue: true}, nil - } else { - logrus.Errorf("Could not get devfile-registry ConfigMap: %v", err) - return reconcile.Result{}, err - } - } else { - newDevFileRegistryConfigMap := deploy.CreateDevfileRegistryConfigMap(instance, devfileRegistryURL) - if !reflect.DeepEqual(devFileRegistryConfigMap.Data, newDevFileRegistryConfigMap.Data) { - err = controllerutil.SetControllerReference(instance, devFileRegistryConfigMap, r.scheme) - if err != nil { - logrus.Errorf("An error occurred: %v", err) - return reconcile.Result{}, err - } - logrus.Info("Updating devfile-registry ConfigMap") - err = r.client.Update(context.TODO(), newDevFileRegistryConfigMap) - if err != nil { - logrus.Errorf("Error updating devfile-registry ConfigMap: %v", err) - return reconcile.Result{}, err - } - } - } - - // Create a new registry service - registryLabels := deploy.GetLabels(instance, registryName) - serviceStatus := deploy.SyncServiceToCluster(instance, registryName, []string{"http"}, []int32{8080}, registryLabels, clusterAPI) - if !tests { - if !serviceStatus.Continue { - logrus.Info("Waiting on service '" + registryName + "' to be ready") - if serviceStatus.Err != nil { - logrus.Error(serviceStatus.Err) - } - - return reconcile.Result{Requeue: serviceStatus.Requeue}, serviceStatus.Err - } - } - - // Deploy devfile registry - deploymentStatus := deploy.SyncDevfileRegistryDeploymentToCluster(instance, clusterAPI) - if !tests { - if !deploymentStatus.Continue { - logrus.Info("Waiting on deployment '" + registryName + "' to be ready") - if deploymentStatus.Err != nil { - logrus.Error(deploymentStatus.Err) - } - - return reconcile.Result{Requeue: deploymentStatus.Requeue}, deploymentStatus.Err - } - } - } - if devfileRegistryURL != instance.Status.DevfileRegistryURL { - instance.Status.DevfileRegistryURL = devfileRegistryURL - if err := r.UpdateCheCRStatus(instance, "status: Devfile Registry URL", devfileRegistryURL); err != nil { - instance, _ = r.GetCR(request) - return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 1}, err - } - } - - pluginRegistryURL := instance.Spec.Server.PluginRegistryUrl - // Create Plugin registry resources unless an external registry is used - externalPluginRegistry := instance.Spec.Server.ExternalPluginRegistry - if !externalPluginRegistry { - if instance.IsAirGapMode() { - pluginRegistryConfigMap := &corev1.ConfigMap{} - err = r.client.Get(context.TODO(), types.NamespacedName{Name: "plugin-registry", Namespace: instance.Namespace}, pluginRegistryConfigMap) + provisioned, err := deploy.SyncDevfileRegistryToCluster(instance, clusterAPI) + if !tests { + if !provisioned { if err != nil { - if errors.IsNotFound(err) { - pluginRegistryConfigMap = deploy.CreatePluginRegistryConfigMap(instance) - err = controllerutil.SetControllerReference(instance, pluginRegistryConfigMap, r.scheme) - if err != nil { - logrus.Errorf("An error occurred: %v", err) - return reconcile.Result{}, err - } - logrus.Info("Creating plugin registry airgap configmap") - err = r.client.Create(context.TODO(), pluginRegistryConfigMap) - if err != nil { - logrus.Errorf("Error creating plugin registry configmap: %v", err) - return reconcile.Result{}, err - } - return reconcile.Result{Requeue: true}, nil - } else { - logrus.Errorf("Could not get plugin-registry ConfigMap: %v", err) - return reconcile.Result{}, err - } - } else { - pluginRegistryConfigMap = deploy.CreatePluginRegistryConfigMap(instance) - err = controllerutil.SetControllerReference(instance, pluginRegistryConfigMap, r.scheme) - if err != nil { - logrus.Errorf("An error occurred: %v", err) - return reconcile.Result{}, err - } - logrus.Info("Updating plugin-registry ConfigMap") - err = r.client.Update(context.TODO(), pluginRegistryConfigMap) - if err != nil { - logrus.Errorf("Error updating plugin-registry ConfigMap: %v", err) - return reconcile.Result{}, err - } - } - } - - registryName := "plugin-registry" - host := "" - if !isOpenShift { - ingressStatus := deploy.SyncIngressToCluster(instance, registryName, registryName, 8080, clusterAPI) - if !tests { - if !ingressStatus.Continue { - logrus.Infof("Waiting on ingress '%s' to be ready", registryName) - if ingressStatus.Err != nil { - logrus.Error(ingressStatus.Err) - } - - return reconcile.Result{Requeue: ingressStatus.Requeue}, ingressStatus.Err - } - } - - host = ingressDomain - if ingressStrategy == "multi-host" { - host = registryName + "-" + instance.Namespace + "." + ingressDomain - } - } else { - routeStatus := deploy.SyncRouteToCluster(instance, registryName, registryName, 8080, clusterAPI) - if !tests { - if !routeStatus.Continue { - logrus.Infof("Waiting on route '%s' to be ready", registryName) - if routeStatus.Err != nil { - logrus.Error(routeStatus.Err) - } - - return reconcile.Result{Requeue: routeStatus.Requeue}, routeStatus.Err - } - } - - if !tests { - host = routeStatus.Route.Spec.Host - } - } - - guessedPluginRegistryURL := protocol + "://" + host - guessedPluginRegistryURL += "/v3" - if pluginRegistryURL == "" { - pluginRegistryURL = guessedPluginRegistryURL - } - - // Create a new registry service - registryLabels := deploy.GetLabels(instance, registryName) - serviceStatus := deploy.SyncServiceToCluster(instance, registryName, []string{"http"}, []int32{8080}, registryLabels, clusterAPI) - if !tests { - if !serviceStatus.Continue { - logrus.Info("Waiting on service '" + registryName + "' to be ready") - if serviceStatus.Err != nil { - logrus.Error(serviceStatus.Err) - } - - return reconcile.Result{Requeue: serviceStatus.Requeue}, serviceStatus.Err - } - } - - // Deploy plugin registry - deploymentStatus := deploy.SyncPluginRegistryDeploymentToCluster(instance, clusterAPI) - if !tests { - if !deploymentStatus.Continue { - logrus.Info("Waiting on deployment '" + registryName + "' to be ready") - if deploymentStatus.Err != nil { - logrus.Error(deploymentStatus.Err) - } - - return reconcile.Result{Requeue: deploymentStatus.Requeue}, deploymentStatus.Err + logrus.Errorf("Error provisioning '%s' to cluster: %v", deploy.DevfileRegistry, err) } + return reconcile.Result{Requeue: true}, err } } - if pluginRegistryURL != instance.Status.PluginRegistryURL { - instance.Status.PluginRegistryURL = pluginRegistryURL - if err := r.UpdateCheCRStatus(instance, "status: Plugin Registry URL", pluginRegistryURL); err != nil { - instance, _ = r.GetCR(request) - return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 1}, err + + provisioned, err = deploy.SyncPluginRegistryToCluster(instance, clusterAPI) + if !tests { + if !provisioned { + if err != nil { + logrus.Errorf("Error provisioning '%s' to cluster: %v", deploy.PluginRegistry, err) + } + return reconcile.Result{Requeue: true}, err } } diff --git a/pkg/controller/che/che_controller_test.go b/pkg/controller/che/che_controller_test.go index ad6b03102..1f62fbab3 100644 --- a/pkg/controller/che/che_controller_test.go +++ b/pkg/controller/che/che_controller_test.go @@ -140,7 +140,7 @@ func TestCheController(t *testing.T) { Namespace: namespace, }, } - res, err := r.Reconcile(req) + _, err := r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } @@ -151,22 +151,6 @@ func TestCheController(t *testing.T) { t.Errorf("ConfigMap %s not found: %s", devfilecm.Name, err) } - // Check the result of reconciliation to make sure it has the desired state. - if !res.Requeue { - t.Error("Reconcile did not requeue request as expected") - } - - // reconcile again - res, err = r.Reconcile(req) - if err != nil { - t.Fatalf("reconcile: (%v)", err) - } - - // Check the result of reconciliation to make sure it has the desired state. - if res.Requeue { - t.Error("Reconcile did not requeue request as expected") - } - // update CR and make sure Che configmap has been updated cheCR.Spec.Server.TlsSupport = true if err := cl.Update(context.TODO(), cheCR); err != nil { @@ -174,7 +158,7 @@ func TestCheController(t *testing.T) { } // reconcile again - res, err = r.Reconcile(req) + _, err = r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } @@ -188,7 +172,7 @@ func TestCheController(t *testing.T) { customCm := &corev1.ConfigMap{} // Reconcile to delete legacy custom configmap - res, err = r.Reconcile(req) + _, err = r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } @@ -221,7 +205,7 @@ func TestCheController(t *testing.T) { if err := cl.Update(context.TODO(), cheCR); err != nil { t.Error("Failed to update CheCluster custom resource") } - res, err = r.Reconcile(req) + _, err = r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } @@ -267,7 +251,7 @@ func TestCheController(t *testing.T) { postgresDeployment := &appsv1.Deployment{} err = r.client.Get(context.TODO(), types.NamespacedName{Name: "postgres", Namespace: cheCR.Namespace}, postgresDeployment) err = r.client.Delete(context.TODO(), postgresDeployment) - res, err = r.Reconcile(req) + _, err = r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } @@ -290,7 +274,7 @@ func TestCheController(t *testing.T) { if err = r.client.Delete(context.TODO(), pvc); err != nil { t.Fatalf("Failed to delete PVC %s: %s", pvc.Name, err) } - res, err = r.Reconcile(req) + _, err = r.Reconcile(req) if err != nil { t.Fatalf("reconcile: (%v)", err) } diff --git a/pkg/deploy/deployment_registry.go b/pkg/deploy/deployment_registry.go index ac19b1742..34ffcf617 100644 --- a/pkg/deploy/deployment_registry.go +++ b/pkg/deploy/deployment_registry.go @@ -22,11 +22,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" ) -const ( - PluginRegistryDeploymentName = "plugin-registry" - DevfileRegistryDeploymentName = "devfile-registry" -) - func SyncPluginRegistryDeploymentToCluster(checluster *orgv1.CheCluster, clusterAPI ClusterAPI) DeploymentProvisioningStatus { registryType := "plugin" registryImage := util.GetValue(checluster.Spec.Server.PluginRegistryImage, DefaultPluginRegistryImage(checluster)) @@ -36,7 +31,7 @@ func SyncPluginRegistryDeploymentToCluster(checluster *orgv1.CheCluster, cluster probePath := "/v3/plugins/" pluginImagesEnv := util.GetEnvByRegExp("^.*plugin_registry_image.*$") - clusterDeployment, err := getClusterDeployment(PluginRegistryDeploymentName, checluster.Namespace, clusterAPI.Client) + clusterDeployment, err := getClusterDeployment(PluginRegistry, checluster.Namespace, clusterAPI.Client) if err != nil { return DeploymentProvisioningStatus{ ProvisioningStatus: ProvisioningStatus{Err: err}, @@ -72,7 +67,7 @@ func SyncDevfileRegistryDeploymentToCluster(checluster *orgv1.CheCluster, cluste probePath := "/devfiles/" devfileImagesEnv := util.GetEnvByRegExp("^.*devfile_registry_image.*$") - clusterDeployment, err := getClusterDeployment(DevfileRegistryDeploymentName, checluster.Namespace, clusterAPI.Client) + clusterDeployment, err := getClusterDeployment(DevfileRegistry, checluster.Namespace, clusterAPI.Client) if err != nil { return DeploymentProvisioningStatus{ ProvisioningStatus: ProvisioningStatus{Err: err}, diff --git a/pkg/deploy/devfile_registry.go b/pkg/deploy/devfile_registry.go new file mode 100644 index 000000000..1da838306 --- /dev/null +++ b/pkg/deploy/devfile_registry.go @@ -0,0 +1,150 @@ +// +// 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 deploy + +import ( + "encoding/json" + "fmt" + + orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" + "github.com/eclipse/che-operator/pkg/util" + "github.com/sirupsen/logrus" +) + +type DevFileRegistryConfigMap struct { + CheDevfileImagesRegistryURL string `json:"CHE_DEVFILE_IMAGES_REGISTRY_URL"` + CheDevfileImagesRegistryOrganization string `json:"CHE_DEVFILE_IMAGES_REGISTRY_ORGANIZATION"` + CheDevfileRegistryURL string `json:"CHE_DEVFILE_REGISTRY_URL"` +} + +const ( + DevfileRegistry = "devfile-registry" +) + +/** + * Create devfile registry resources unless an external registry is used. + */ +func SyncDevfileRegistryToCluster(checluster *orgv1.CheCluster, clusterAPI ClusterAPI) (bool, error) { + devfileRegistryURL := checluster.Spec.Server.DevfileRegistryUrl + if !checluster.Spec.Server.ExternalDevfileRegistry { + var host string + if !util.IsOpenShift { + ingressStatus := SyncIngressToCluster(checluster, DevfileRegistry, DevfileRegistry, 8080, clusterAPI) + if !util.IsTestMode() { + if !ingressStatus.Continue { + logrus.Infof("Waiting on ingress '%s' to be ready", DevfileRegistry) + if ingressStatus.Err != nil { + logrus.Error(ingressStatus.Err) + } + return false, ingressStatus.Err + } + } + + if checluster.Spec.K8s.IngressStrategy == "multi-host" { + host = DevfileRegistry + "-" + checluster.Namespace + "." + checluster.Spec.K8s.IngressDomain + } else { + host = checluster.Spec.K8s.IngressDomain + "/" + DevfileRegistry + } + } else { + routeStatus := SyncRouteToCluster(checluster, DevfileRegistry, DevfileRegistry, 8080, clusterAPI) + if !util.IsTestMode() { + if !routeStatus.Continue { + logrus.Infof("Waiting on route '%s' to be ready", DevfileRegistry) + if routeStatus.Err != nil { + logrus.Error(routeStatus.Err) + } + + return false, routeStatus.Err + } + } + + if !util.IsTestMode() { + host = routeStatus.Route.Spec.Host + } + } + + if devfileRegistryURL == "" { + if checluster.Spec.Server.TlsSupport { + devfileRegistryURL = "https://" + host + } else { + devfileRegistryURL = "http://" + host + } + } + + configMapData := getDevfileRegistryConfigMapData(checluster, devfileRegistryURL) + configMapSpec, err := GetSpecConfigMap(checluster, DevfileRegistry, configMapData, clusterAPI) + if err != nil { + return false, err + } + + configMap, err := SyncConfigMapToCluster(checluster, configMapSpec, clusterAPI) + if configMap == nil { + return false, err + } + + // Create a new registry service + registryLabels := GetLabels(checluster, DevfileRegistry) + serviceStatus := SyncServiceToCluster(checluster, DevfileRegistry, []string{"http"}, []int32{8080}, registryLabels, clusterAPI) + if !util.IsTestMode() { + if !serviceStatus.Continue { + logrus.Info("Waiting on service '" + DevfileRegistry + "' to be ready") + if serviceStatus.Err != nil { + logrus.Error(serviceStatus.Err) + } + + return false, serviceStatus.Err + } + } + + // Deploy devfile registry + deploymentStatus := SyncDevfileRegistryDeploymentToCluster(checluster, clusterAPI) + if !util.IsTestMode() { + if !deploymentStatus.Continue { + logrus.Info("Waiting on deployment '" + DevfileRegistry + "' to be ready") + if deploymentStatus.Err != nil { + logrus.Error(deploymentStatus.Err) + } + + return false, deploymentStatus.Err + } + } + } + + if devfileRegistryURL != checluster.Status.DevfileRegistryURL { + checluster.Status.DevfileRegistryURL = devfileRegistryURL + if err := UpdateCheCRStatus(checluster, "status: Devfile Registry URL", devfileRegistryURL, clusterAPI); err != nil { + return false, err + } + } + + return true, nil +} + +func getDevfileRegistryConfigMapData(cr *orgv1.CheCluster, endpoint string) map[string]string { + devfileRegistryEnv := make(map[string]string) + data := &DevFileRegistryConfigMap{ + CheDevfileImagesRegistryURL: cr.Spec.Server.AirGapContainerRegistryHostname, + CheDevfileImagesRegistryOrganization: cr.Spec.Server.AirGapContainerRegistryOrganization, + CheDevfileRegistryURL: endpoint, + } + + out, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + } + + err = json.Unmarshal(out, &devfileRegistryEnv) + if err != nil { + fmt.Println(err) + } + return devfileRegistryEnv +} diff --git a/pkg/deploy/ingress.go b/pkg/deploy/ingress.go index 49cd494bc..53edba32c 100644 --- a/pkg/deploy/ingress.go +++ b/pkg/deploy/ingress.go @@ -129,32 +129,45 @@ func getSpecIngress(checluster *orgv1.CheCluster, name string, serviceName strin } } - host := "" path := "/" - if name == "keycloak" && ingressStrategy != "multi-host" { - path = "/auth" + if ingressStrategy != "multi-host" { + switch name { + case "keycloak": + path = "/auth" + case DevfileRegistry: + path = "/" + DevfileRegistry + "/(.*)" + case PluginRegistry: + path = "/" + PluginRegistry + "/(.*)" + } } + + host := "" if ingressStrategy == "multi-host" { host = name + "-" + checluster.Namespace + "." + ingressDomain } else if ingressStrategy == "single-host" { host = ingressDomain } + annotations := map[string]string{ + "kubernetes.io/ingress.class": ingressClass, + "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", + "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", + "nginx.ingress.kubernetes.io/ssl-redirect": tls, + } + if ingressStrategy != "multi-host" && (name == DevfileRegistry || name == PluginRegistry) { + annotations["nginx.ingress.kubernetes.io/rewrite-target"] = "/$1" + } + ingress := &v1beta1.Ingress{ TypeMeta: metav1.TypeMeta{ Kind: "Ingress", APIVersion: v1beta1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: checluster.Namespace, - Labels: labels, - Annotations: map[string]string{ - "kubernetes.io/ingress.class": ingressClass, - "nginx.ingress.kubernetes.io/proxy-read-timeout": "3600", - "nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600", - "nginx.ingress.kubernetes.io/ssl-redirect": tls, - }, + Name: name, + Namespace: checluster.Namespace, + Labels: labels, + Annotations: annotations, }, Spec: v1beta1.IngressSpec{ Rules: []v1beta1.IngressRule{ diff --git a/pkg/deploy/plugin_registry.go b/pkg/deploy/plugin_registry.go new file mode 100644 index 000000000..74bd563c7 --- /dev/null +++ b/pkg/deploy/plugin_registry.go @@ -0,0 +1,152 @@ +// +// 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 deploy + +import ( + "encoding/json" + "fmt" + + "github.com/eclipse/che-operator/pkg/util" + "github.com/sirupsen/logrus" + + orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" +) + +type PluginRegistryConfigMap struct { + CheSidecarContainersRegistryURL string `json:"CHE_SIDECAR_CONTAINERS_REGISTRY_URL"` + CheSidecarContainersRegistryOrganization string `json:"CHE_SIDECAR_CONTAINERS_REGISTRY_ORGANIZATION"` +} + +const ( + PluginRegistry = "plugin-registry" +) + +/** + * Create plugin registry resources unless an external registry is used. + */ +func SyncPluginRegistryToCluster(checluster *orgv1.CheCluster, clusterAPI ClusterAPI) (bool, error) { + pluginRegistryURL := checluster.Spec.Server.PluginRegistryUrl + if !checluster.Spec.Server.ExternalPluginRegistry { + var host string + if !util.IsOpenShift { + ingressStatus := SyncIngressToCluster(checluster, PluginRegistry, PluginRegistry, 8080, clusterAPI) + if !util.IsTestMode() { + if !ingressStatus.Continue { + logrus.Infof("Waiting on ingress '%s' to be ready", PluginRegistry) + if ingressStatus.Err != nil { + logrus.Error(ingressStatus.Err) + } + return false, ingressStatus.Err + } + } + + if checluster.Spec.K8s.IngressStrategy == "multi-host" { + host = PluginRegistry + "-" + checluster.Namespace + "." + checluster.Spec.K8s.IngressDomain + } else { + host = checluster.Spec.K8s.IngressDomain + "/" + PluginRegistry + } + } else { + routeStatus := SyncRouteToCluster(checluster, PluginRegistry, PluginRegistry, 8080, clusterAPI) + if !util.IsTestMode() { + if !routeStatus.Continue { + logrus.Infof("Waiting on route '%s' to be ready", PluginRegistry) + if routeStatus.Err != nil { + logrus.Error(routeStatus.Err) + } + + return false, routeStatus.Err + } + } + + if !util.IsTestMode() { + host = routeStatus.Route.Spec.Host + } + } + + if pluginRegistryURL == "" { + if checluster.Spec.Server.TlsSupport { + pluginRegistryURL = "https://" + host + "/v3" + } else { + pluginRegistryURL = "http://" + host + "/v3" + } + } + + if checluster.IsAirGapMode() { + configMapData := getPluginRegistryConfigMapData(checluster) + configMapSpec, err := GetSpecConfigMap(checluster, PluginRegistry, configMapData, clusterAPI) + if err != nil { + return false, err + } + + configMap, err := SyncConfigMapToCluster(checluster, configMapSpec, clusterAPI) + if configMap == nil { + return false, err + } + } + + // Create a new registry service + registryLabels := GetLabels(checluster, PluginRegistry) + serviceStatus := SyncServiceToCluster(checluster, PluginRegistry, []string{"http"}, []int32{8080}, registryLabels, clusterAPI) + if !util.IsTestMode() { + if !serviceStatus.Continue { + logrus.Info("Waiting on service '" + PluginRegistry + "' to be ready") + if serviceStatus.Err != nil { + logrus.Error(serviceStatus.Err) + } + + return false, serviceStatus.Err + } + } + + // Deploy plugin registry + deploymentStatus := SyncPluginRegistryDeploymentToCluster(checluster, clusterAPI) + if !util.IsTestMode() { + if !deploymentStatus.Continue { + logrus.Info("Waiting on deployment '" + PluginRegistry + "' to be ready") + if deploymentStatus.Err != nil { + logrus.Error(deploymentStatus.Err) + } + + return false, deploymentStatus.Err + } + } + } + + if pluginRegistryURL != checluster.Status.PluginRegistryURL { + checluster.Status.PluginRegistryURL = pluginRegistryURL + if err := UpdateCheCRStatus(checluster, "status: Plugin Registry URL", pluginRegistryURL, clusterAPI); err != nil { + return false, err + } + } + + return true, nil +} + +func getPluginRegistryConfigMapData(cr *orgv1.CheCluster) map[string]string { + pluginRegistryEnv := make(map[string]string) + data := &PluginRegistryConfigMap{ + CheSidecarContainersRegistryURL: cr.Spec.Server.AirGapContainerRegistryHostname, + CheSidecarContainersRegistryOrganization: cr.Spec.Server.AirGapContainerRegistryOrganization, + } + + out, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + } + + err = json.Unmarshal(out, &pluginRegistryEnv) + if err != nil { + fmt.Println(err) + } + + return pluginRegistryEnv +} diff --git a/pkg/deploy/registry_configmap.go b/pkg/deploy/registry_configmap.go deleted file mode 100644 index 5c137b485..000000000 --- a/pkg/deploy/registry_configmap.go +++ /dev/null @@ -1,105 +0,0 @@ -// -// 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 deploy - -import ( - "encoding/json" - "fmt" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - orgv1 "github.com/eclipse/che-operator/pkg/apis/org/v1" -) - -type DevFileRegistryConfigMap struct { - CheDevfileImagesRegistryURL string `json:"CHE_DEVFILE_IMAGES_REGISTRY_URL"` - CheDevfileImagesRegistryOrganization string `json:"CHE_DEVFILE_IMAGES_REGISTRY_ORGANIZATION"` - CheDevfileRegistryURL string `json:"CHE_DEVFILE_REGISTRY_URL"` -} - -type PluginRegistryConfigMap struct { - CheSidecarContainersRegistryURL string `json:"CHE_SIDECAR_CONTAINERS_REGISTRY_URL"` - CheSidecarContainersRegistryOrganization string `json:"CHE_SIDECAR_CONTAINERS_REGISTRY_ORGANIZATION"` -} - -func CreateDevfileRegistryConfigMap(cr *orgv1.CheCluster, endpoint string) *corev1.ConfigMap { - labels := GetLabels(cr, DefaultCheFlavor(cr)) - return &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "devfile-registry", - Namespace: cr.Namespace, - Labels: labels, - }, - Data: GetDevfileRegistryConfigMapData(cr, endpoint), - } -} - -func CreatePluginRegistryConfigMap(cr *orgv1.CheCluster) *corev1.ConfigMap { - labels := GetLabels(cr, DefaultCheFlavor(cr)) - return &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "plugin-registry", - Namespace: cr.Namespace, - Labels: labels, - }, - Data: GetPluginRegistryConfigMapData(cr), - } -} - -func GetDevfileRegistryConfigMapData(cr *orgv1.CheCluster, endpoint string) map[string]string { - devfileRegistryEnv := make(map[string]string) - data := &DevFileRegistryConfigMap{ - CheDevfileImagesRegistryURL: cr.Spec.Server.AirGapContainerRegistryHostname, - CheDevfileImagesRegistryOrganization: cr.Spec.Server.AirGapContainerRegistryOrganization, - CheDevfileRegistryURL: endpoint, - } - - out, err := json.Marshal(data) - if err != nil { - fmt.Println(err) - } - - err = json.Unmarshal(out, &devfileRegistryEnv) - if err != nil { - fmt.Println(err) - } - return devfileRegistryEnv -} - -func GetPluginRegistryConfigMapData(cr *orgv1.CheCluster) map[string]string { - pluginRegistryEnv := make(map[string]string) - data := &PluginRegistryConfigMap{ - CheSidecarContainersRegistryURL: cr.Spec.Server.AirGapContainerRegistryHostname, - CheSidecarContainersRegistryOrganization: cr.Spec.Server.AirGapContainerRegistryOrganization, - } - - out, err := json.Marshal(data) - if err != nil { - fmt.Println(err) - } - - err = json.Unmarshal(out, &pluginRegistryEnv) - if err != nil { - fmt.Println(err) - } - - return pluginRegistryEnv -} diff --git a/pkg/deploy/update.go b/pkg/deploy/update.go index e8dbbfb4a..94cb4c841 100644 --- a/pkg/deploy/update.go +++ b/pkg/deploy/update.go @@ -28,3 +28,14 @@ func UpdateCheCRSpec(instance *orgv1.CheCluster, updatedField string, value stri logrus.Infof("Custom resource %s updated", instance.Name) return nil } + +func UpdateCheCRStatus(instance *orgv1.CheCluster, updatedField string, value string, clusterAPI ClusterAPI) (err error) { + logrus.Infof("Updating %s CR with %s: %s", instance.Name, updatedField, value) + err = clusterAPI.Client.Status().Update(context.TODO(), instance) + if err != nil { + logrus.Errorf("Failed to update %s CR. Fetching the latest CR version: %s", instance.Name, err) + return err + } + logrus.Infof("Custom resource %s updated", instance.Name) + return nil +}