diff --git a/api/v1/checluster_types.go b/api/v1/checluster_types.go index eee0db81a..53f413eb8 100644 --- a/api/v1/checluster_types.go +++ b/api/v1/checluster_types.go @@ -18,6 +18,8 @@ package v1 // - update `config/crd/bases/org_v1_checluster_crd.yaml` file; import ( + "strings" + chev1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/api/v1alpha1" v2alpha1 "github.com/eclipse-che/che-operator/api/v2alpha1" corev1 "k8s.io/api/core/v1" @@ -843,3 +845,7 @@ func (c *CheCluster) IsImagePullerSpecEmpty() bool { func (c *CheCluster) IsImagePullerImagesEmpty() bool { return len(c.Spec.ImagePuller.Spec.Images) == 0 } + +func (c *CheCluster) GetCheHost() string { + return strings.TrimPrefix(c.Status.CheURL, "https://") +} diff --git a/pkg/deploy/consolelink/consolelink.go b/pkg/deploy/consolelink/consolelink.go index ea78fd7d3..c33e3ed2d 100644 --- a/pkg/deploy/consolelink/consolelink.go +++ b/pkg/deploy/consolelink/consolelink.go @@ -74,7 +74,7 @@ func (c *ConsoleLinkReconciler) createConsoleLink(ctx *deploy.DeployContext) (bo } // consolelink is for this specific instance of Eclipse Che - if strings.Index(consoleLink.Spec.Link.Href, ctx.CheHost) != -1 { + if strings.Index(consoleLink.Spec.Link.Href, ctx.CheCluster.GetCheHost()) != -1 { err = deploy.AppendFinalizer(ctx, ConsoleLinkFinalizerName) return err == nil, err } @@ -96,12 +96,12 @@ func (c *ConsoleLinkReconciler) getConsoleLinkSpec(ctx *deploy.DeployContext) *c }, Spec: consolev1.ConsoleLinkSpec{ Link: consolev1.Link{ - Href: "https://" + ctx.CheHost, + Href: ctx.CheCluster.Status.CheURL, Text: deploy.DefaultConsoleLinkDisplayName()}, Location: consolev1.ApplicationMenu, ApplicationMenu: &consolev1.ApplicationMenuSpec{ Section: deploy.DefaultConsoleLinkSection(), - ImageURL: fmt.Sprintf("https://%s%s", ctx.CheHost, deploy.DefaultConsoleLinkImage()), + ImageURL: fmt.Sprintf("https://%s%s", ctx.CheCluster.GetCheHost(), deploy.DefaultConsoleLinkImage()), }, }, } diff --git a/pkg/deploy/consolelink/consolelink_test.go b/pkg/deploy/consolelink/consolelink_test.go index 760921255..7a90d1f34 100644 --- a/pkg/deploy/consolelink/consolelink_test.go +++ b/pkg/deploy/consolelink/consolelink_test.go @@ -31,7 +31,9 @@ func TestReconcileConsoleLink(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, - Spec: orgv1.CheClusterSpec{}, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, } util.IsOpenShift4 = true diff --git a/pkg/deploy/dashboard/dashboard.go b/pkg/deploy/dashboard/dashboard.go index f7ff6fc8a..0b6a2b124 100644 --- a/pkg/deploy/dashboard/dashboard.go +++ b/pkg/deploy/dashboard/dashboard.go @@ -55,7 +55,7 @@ func (d *DashboardReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Re } // Expose dashboard service with route or ingress - _, done, err = expose.ExposeWithHostPath(ctx, d.getComponentName(ctx), ctx.CheHost, + _, done, err = expose.ExposeWithHostPath(ctx, d.getComponentName(ctx), ctx.CheCluster.GetCheHost(), exposePath, d.createGatewayConfig(ctx), ) diff --git a/pkg/deploy/dashboard/dashboard_deployment_test.go b/pkg/deploy/dashboard/dashboard_deployment_test.go index 9092a7122..702165bc5 100644 --- a/pkg/deploy/dashboard/dashboard_deployment_test.go +++ b/pkg/deploy/dashboard/dashboard_deployment_test.go @@ -156,6 +156,9 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, }, { @@ -202,6 +205,9 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { Namespace: "eclipse-che", Name: "eclipse-che", }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, }, } diff --git a/pkg/deploy/dashboard/deployment_dashboard.go b/pkg/deploy/dashboard/deployment_dashboard.go index 18d78f5a8..47ba17666 100644 --- a/pkg/deploy/dashboard/deployment_dashboard.go +++ b/pkg/deploy/dashboard/deployment_dashboard.go @@ -52,10 +52,10 @@ func (d *DashboardReconciler) getDashboardDeploymentSpec(ctx *deploy.DeployConte // CHE_HOST is here for backward compatibility. Replaced with CHE_URL corev1.EnvVar{ Name: "CHE_HOST", - Value: "https://" + ctx.CheHost}, + Value: ctx.CheCluster.Status.CheURL}, corev1.EnvVar{ Name: "CHE_URL", - Value: "https://" + ctx.CheHost}, + Value: ctx.CheCluster.Status.CheURL}, corev1.EnvVar{ Name: "CHECLUSTER_CR_NAMESPACE", Value: ctx.CheCluster.Namespace}, diff --git a/pkg/deploy/data_types.go b/pkg/deploy/data_types.go index d85ece03c..f4ef11ea9 100644 --- a/pkg/deploy/data_types.go +++ b/pkg/deploy/data_types.go @@ -30,7 +30,6 @@ type DeployContext struct { ClusterAPI ClusterAPI Proxy *Proxy IsSelfSignedCertificate bool - CheHost string } type ClusterAPI struct { diff --git a/pkg/deploy/devfileregistry/devfileregistry_test.go b/pkg/deploy/devfileregistry/devfileregistry_test.go index bd113b407..34475c25f 100644 --- a/pkg/deploy/devfileregistry/devfileregistry_test.go +++ b/pkg/deploy/devfileregistry/devfileregistry_test.go @@ -69,6 +69,9 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { ExternalDevfileRegistry: false, }, }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedDevfileRegistryURL: "https://che-host/devfile-registry", }, @@ -92,6 +95,9 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { }, }, }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedDevfileRegistryURL: "https://che-host/devfile-registry", }, @@ -115,6 +121,9 @@ func TestShouldSetUpCorrectlyDevfileRegistryURL(t *testing.T) { }, }, }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedDevfileRegistryURL: "", }, diff --git a/pkg/deploy/expose/expose.go b/pkg/deploy/expose/expose.go index 019e49030..41d8c5f9e 100644 --- a/pkg/deploy/expose/expose.go +++ b/pkg/deploy/expose/expose.go @@ -88,5 +88,5 @@ func exposeWithGateway(deployContext *deploy.DeployContext, if path == "" { path = "/" + component } - return deployContext.CheHost + path, true, err + return deployContext.CheCluster.GetCheHost() + path, true, err } diff --git a/pkg/deploy/gateway/oauth_proxy.go b/pkg/deploy/gateway/oauth_proxy.go index a06718eec..dd2be8d3c 100644 --- a/pkg/deploy/gateway/oauth_proxy.go +++ b/pkg/deploy/gateway/oauth_proxy.go @@ -71,7 +71,7 @@ pass_access_token = true skip_provider_button = true %s `, GatewayServicePort, - ctx.CheHost, + ctx.CheCluster.GetCheHost(), ctx.CheCluster.Spec.Auth.OAuthClientName, ctx.CheCluster.Spec.Auth.OAuthSecret, GatewayServiceName, @@ -102,7 +102,7 @@ pass_authorization_header = true skip_provider_button = true %s `, GatewayServicePort, - ctx.CheHost, + ctx.CheCluster.GetCheHost(), ctx.CheCluster.Spec.Auth.IdentityProviderURL, ctx.CheCluster.Spec.Auth.OAuthClientName, ctx.CheCluster.Spec.Auth.OAuthSecret, diff --git a/pkg/deploy/identity-provider/identity_provider_reconciler.go b/pkg/deploy/identity-provider/identity_provider_reconciler.go index cc5166ec6..cf6368b3c 100644 --- a/pkg/deploy/identity-provider/identity_provider_reconciler.go +++ b/pkg/deploy/identity-provider/identity_provider_reconciler.go @@ -76,7 +76,7 @@ func syncNativeIdentityProviderItems(deployContext *deploy.DeployContext) (bool, } if util.IsOpenShift { - redirectURIs := []string{"https://" + deployContext.CheHost + "/oauth/callback"} + redirectURIs := []string{"https://" + deployContext.CheCluster.GetCheHost() + "/oauth/callback"} oAuthClient := getOAuthClientSpec(cr.Spec.Auth.OAuthClientName, cr.Spec.Auth.OAuthSecret, redirectURIs) done, err := deploy.Sync(deployContext, oAuthClient, oAuthClientDiffOpts) if !done { diff --git a/pkg/deploy/server/chehost_reconciler.go b/pkg/deploy/server/chehost_reconciler.go index 970dcb1c8..f5225a4e0 100644 --- a/pkg/deploy/server/chehost_reconciler.go +++ b/pkg/deploy/server/chehost_reconciler.go @@ -22,8 +22,6 @@ import ( type CheHostReconciler struct { deploy.Reconcilable - // CheHost that is set by k8s itself - defaultCheHost string } func NewCheHostReconciler() *CheHostReconciler { @@ -31,20 +29,17 @@ func NewCheHostReconciler() *CheHostReconciler { } func (s *CheHostReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Result, bool, error) { - if util.IsOpenShift && s.defaultCheHost == "" { - done, defaultCheHost, err := s.getDefaultCheHost(ctx) - if !done { - return reconcile.Result{}, false, err - } - s.defaultCheHost = defaultCheHost - } - done, err := s.syncCheService(ctx) if !done { return reconcile.Result{}, false, err } - done, err = s.exposeCheEndpoint(ctx) + cheHost, done, err := s.exposeCheEndpoint(ctx) + if !done { + return reconcile.Result{}, false, err + } + + done, err = s.updateCheURL(cheHost, ctx) if !done { return reconcile.Result{}, false, err } @@ -56,29 +51,6 @@ func (s *CheHostReconciler) Finalize(ctx *deploy.DeployContext) bool { return true } -func (s *CheHostReconciler) getDefaultCheHost(ctx *deploy.DeployContext) (bool, string, error) { - done, err := deploy.SyncRouteToCluster( - ctx, - getComponentName(ctx), - "", - "/", - gateway.GatewayServiceName, - 8080, - ctx.CheCluster.Spec.Server.CheServerRoute, - getComponentName(ctx)) - if !done { - return false, "", err - } - - route := &routev1.Route{} - exists, err := deploy.GetNamespacedObject(ctx, getComponentName(ctx), route) - if !exists { - return false, "", err - } - - return true, route.Spec.Host, nil -} - func (s *CheHostReconciler) syncCheService(ctx *deploy.DeployContext) (bool, error) { portName := []string{"http"} portNumber := []int32{8080} @@ -98,58 +70,58 @@ func (s *CheHostReconciler) syncCheService(ctx *deploy.DeployContext) (bool, err return deploy.Sync(ctx, spec, deploy.ServiceDefaultDiffOpts) } -func (s CheHostReconciler) exposeCheEndpoint(ctx *deploy.DeployContext) (bool, error) { - ctx.CheHost = ctx.CheCluster.Spec.Server.CheHost - +func (s CheHostReconciler) exposeCheEndpoint(ctx *deploy.DeployContext) (string, bool, error) { if !util.IsOpenShift { _, done, err := deploy.SyncIngressToCluster( ctx, getComponentName(ctx), - ctx.CheHost, + ctx.CheCluster.Spec.Server.CheHost, "", gateway.GatewayServiceName, 8080, ctx.CheCluster.Spec.Server.CheServerIngress, getComponentName(ctx)) if !done { - return false, err + return "", false, err } ingress := &networking.Ingress{} exists, err := deploy.GetNamespacedObject(ctx, getComponentName(ctx), ingress) if !exists { - return false, err + return "", false, err } - ctx.CheHost = ingress.Spec.Rules[0].Host - } else { - host2expose := ctx.CheHost - if host2expose == s.defaultCheHost { - // CheHost is not overridden. - // Let OpenShift set a hostname by itself since it requires a routes/custom-host permissions - host2expose = "" - } + return ingress.Spec.Rules[0].Host, true, nil + } - done, err := deploy.SyncRouteToCluster( - ctx, - getComponentName(ctx), - host2expose, - "/", - gateway.GatewayServiceName, - 8080, - ctx.CheCluster.Spec.Server.CheServerRoute, - getComponentName(ctx)) - if !done { - return false, err - } + done, err := deploy.SyncRouteToCluster( + ctx, + getComponentName(ctx), + ctx.CheCluster.Spec.Server.CheHost, + "/", + gateway.GatewayServiceName, + 8080, + ctx.CheCluster.Spec.Server.CheServerRoute, + getComponentName(ctx)) + if !done { + return "", false, err + } - route := &routev1.Route{} - exists, err := deploy.GetNamespacedObject(ctx, getComponentName(ctx), route) - if !exists { - return false, err - } + route := &routev1.Route{} + exists, err := deploy.GetNamespacedObject(ctx, getComponentName(ctx), route) + if !exists { + return "", false, err + } - ctx.CheHost = route.Spec.Host + return route.Spec.Host, true, nil +} + +func (s CheHostReconciler) updateCheURL(cheHost string, ctx *deploy.DeployContext) (bool, error) { + var cheUrl = "https://" + cheHost + if ctx.CheCluster.Status.CheURL != cheUrl { + ctx.CheCluster.Status.CheURL = cheUrl + err := deploy.UpdateCheCRStatus(ctx, getComponentName(ctx)+" server URL", cheUrl) + return err == nil, err } return true, nil diff --git a/pkg/deploy/server/chehost_reconciler_test.go b/pkg/deploy/server/chehost_reconciler_test.go index 56eeb11ab..d4cb04825 100644 --- a/pkg/deploy/server/chehost_reconciler_test.go +++ b/pkg/deploy/server/chehost_reconciler_test.go @@ -96,7 +96,7 @@ func TestConfiguringLabelsForRoutes(t *testing.T) { ctx := deploy.GetTestDeployContext(cheCluster, []runtime.Object{}) server := NewCheHostReconciler() - done, err := server.exposeCheEndpoint(ctx) + _, done, err := server.exposeCheEndpoint(ctx) assert.True(t, done) assert.Nil(t, err) @@ -105,3 +105,23 @@ func TestConfiguringLabelsForRoutes(t *testing.T) { assert.Nil(t, err) assert.Equal(t, route.ObjectMeta.Labels["route"], "one") } + +func TestCheHostReconciler(t *testing.T) { + util.IsOpenShift = true + + cheCluster := &orgv1.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + } + ctx := deploy.GetTestDeployContext(cheCluster, []runtime.Object{}) + + cheHostReconciler := NewCheHostReconciler() + _, done, err := cheHostReconciler.Reconcile(ctx) + assert.True(t, done) + assert.Nil(t, err) + assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: getComponentName(ctx), Namespace: "eclipse-che"}, &routev1.Route{})) + assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: deploy.CheServiceName, Namespace: "eclipse-che"}, &corev1.Service{})) + assert.NotEmpty(t, cheCluster.Status.CheURL) +} diff --git a/pkg/deploy/server/server_configmap.go b/pkg/deploy/server/server_configmap.go index 13b10cafd..7f74d03ef 100644 --- a/pkg/deploy/server/server_configmap.go +++ b/pkg/deploy/server/server_configmap.go @@ -161,7 +161,7 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch singleHostGatewayConfigMapLabels := labels.FormatLabels(util.GetMapValue(ctx.CheCluster.Spec.Server.SingleHostGatewayConfigMapLabels, deploy.DefaultSingleHostGatewayConfigMapLabels)) workspaceNamespaceDefault := deploy.GetWorkspaceNamespaceDefault(ctx.CheCluster) - cheAPI := "https://" + ctx.CheHost + "/api" + cheAPI := ctx.CheCluster.Status.CheURL + "/api" var pluginRegistryInternalURL, devfileRegistryInternalURL string // If there is a devfile registry deployed by operator @@ -175,13 +175,13 @@ func (s *CheServerReconciler) getCheConfigMapData(ctx *deploy.DeployContext) (ch cheInternalAPI := fmt.Sprintf("http://%s.%s.svc:8080/api", deploy.CheServiceName, ctx.CheCluster.Namespace) webSocketInternalEndpoint := fmt.Sprintf("ws://%s.%s.svc:8080/api/websocket", deploy.CheServiceName, ctx.CheCluster.Namespace) - webSocketEndpoint := "wss://" + ctx.CheHost + "/api/websocket" + webSocketEndpoint := "wss://" + ctx.CheCluster.GetCheHost() + "/api/websocket" cheWorkspaceServiceAccount := "NULL" cheUserClusterRoleNames := fmt.Sprintf("%s-cheworkspaces-clusterrole, %s-cheworkspaces-devworkspace-clusterrole", ctx.CheCluster.Namespace, ctx.CheCluster.Namespace) data := &CheConfigMap{ CheMultiUser: "true", - CheHost: ctx.CheHost, + CheHost: ctx.CheCluster.GetCheHost(), ChePort: "8080", CheApi: cheAPI, CheApiInternal: cheInternalAPI, diff --git a/pkg/deploy/server/server_configmap_test.go b/pkg/deploy/server/server_configmap_test.go index 5ed04b7d8..0d11d39eb 100644 --- a/pkg/deploy/server/server_configmap_test.go +++ b/pkg/deploy/server/server_configmap_test.go @@ -51,6 +51,9 @@ func TestNewCheConfigMap(t *testing.T) { }, }, }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedData: map[string]string{ "CHE_INFRA_OPENSHIFT_OAUTH__IDENTITY__PROVIDER": "openshift-v4", @@ -146,6 +149,9 @@ func TestConfigMap(t *testing.T) { Name: "eclipse-che", Namespace: "eclipse-che", }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedData: map[string]string{ "CHE_WEBSOCKET_ENDPOINT": "wss://che-host/api/websocket", @@ -170,6 +176,9 @@ func TestConfigMap(t *testing.T) { Name: "eclipse-che", Namespace: "eclipse-che", }, + Status: orgv1.CheClusterStatus{ + CheURL: "https://che-host", + }, }, expectedData: map[string]string{ "CHE_WEBSOCKET_ENDPOINT": "wss://che-host/api/websocket", diff --git a/pkg/deploy/server/server_reconciler.go b/pkg/deploy/server/server_reconciler.go index aa60326ac..438223e1c 100644 --- a/pkg/deploy/server/server_reconciler.go +++ b/pkg/deploy/server/server_reconciler.go @@ -58,11 +58,6 @@ func (s *CheServerReconciler) Reconcile(ctx *deploy.DeployContext) (reconcile.Re return reconcile.Result{}, false, err } - done, err = s.updateCheURL(ctx) - if !done { - return reconcile.Result{}, false, err - } - done, err = s.updateAvailabilityStatus(ctx) if !done { return reconcile.Result{}, false, err @@ -80,17 +75,6 @@ func (s *CheServerReconciler) Finalize(ctx *deploy.DeployContext) bool { return true } -func (s CheServerReconciler) updateCheURL(ctx *deploy.DeployContext) (bool, error) { - var cheUrl = "https://" + ctx.CheHost - if ctx.CheCluster.Status.CheURL != cheUrl { - ctx.CheCluster.Status.CheURL = cheUrl - err := deploy.UpdateCheCRStatus(ctx, getComponentName(ctx)+" server URL", cheUrl) - return err == nil, err - } - - return true, nil -} - func (s *CheServerReconciler) syncCheConfigMap(ctx *deploy.DeployContext) (bool, error) { data, err := s.getCheConfigMapData(ctx) if err != nil { diff --git a/pkg/deploy/server/server_reconciler_test.go b/pkg/deploy/server/server_reconciler_test.go index 7eff4234d..6d42e3022 100644 --- a/pkg/deploy/server/server_reconciler_test.go +++ b/pkg/deploy/server/server_reconciler_test.go @@ -42,7 +42,7 @@ func TestReconcile(t *testing.T) { ctx := deploy.GetTestDeployContext(cheCluster, []runtime.Object{}) chehost := NewCheHostReconciler() - done, err := chehost.exposeCheEndpoint(ctx) + _, done, err := chehost.exposeCheEndpoint(ctx) assert.True(t, done) assert.Nil(t, err) @@ -54,7 +54,6 @@ func TestReconcile(t *testing.T) { assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: getComponentName(ctx), Namespace: "eclipse-che"}, &routev1.Route{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: CheConfigMapName, Namespace: "eclipse-che"}, &corev1.ConfigMap{})) assert.True(t, util.IsObjectExists(ctx.ClusterAPI.Client, types.NamespacedName{Name: getComponentName(ctx), Namespace: "eclipse-che"}, &appsv1.Deployment{})) - assert.NotEmpty(t, cheCluster.Status.CheURL) assert.NotEmpty(t, cheCluster.Status.CheClusterRunning) assert.NotEmpty(t, cheCluster.Status.CheVersion) } diff --git a/pkg/deploy/test_util.go b/pkg/deploy/test_util.go index 7c3a8ef7f..ef7b552f2 100644 --- a/pkg/deploy/test_util.go +++ b/pkg/deploy/test_util.go @@ -43,6 +43,9 @@ func GetTestDeployContext(cheCluster *orgv1.CheCluster, initObjs []runtime.Objec APIVersion: "org.eclipse.che/v1", Kind: "CheCluster", }, + Status: orgv1.CheClusterStatus{ + CheURL: "che-host", + }, } } @@ -72,7 +75,6 @@ func GetTestDeployContext(cheCluster *orgv1.CheCluster, initObjs []runtime.Objec Scheme: scheme, DiscoveryClient: fakeDiscovery, }, - CheHost: "che-host", - Proxy: &Proxy{}, + Proxy: &Proxy{}, } } diff --git a/pkg/deploy/tls/tls_utils.go b/pkg/deploy/tls/tls_utils.go index 4bdc4e98a..591501c41 100644 --- a/pkg/deploy/tls/tls_utils.go +++ b/pkg/deploy/tls/tls_utils.go @@ -365,8 +365,8 @@ func K8sHandleCheTLSSecrets(ctx *deploy.DeployContext) (reconcile.Result, error) } domains := ctx.CheCluster.Spec.K8s.IngressDomain + ",*." + ctx.CheCluster.Spec.K8s.IngressDomain - if ctx.CheHost != "" && !strings.Contains(ctx.CheHost, ctx.CheCluster.Spec.K8s.IngressDomain) && ctx.CheCluster.Spec.Server.CheHostTLSSecret == "" { - domains += "," + ctx.CheHost + if ctx.CheCluster.GetCheHost() != "" && !strings.Contains(ctx.CheCluster.GetCheHost(), ctx.CheCluster.Spec.K8s.IngressDomain) && ctx.CheCluster.Spec.Server.CheHostTLSSecret == "" { + domains += "," + ctx.CheCluster.GetCheHost() } labels := ""