From 3c2bbe5a8f4428e7eddc0d5f5864a8bc87b8c886 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Wed, 14 Feb 2018 09:06:35 +0200 Subject: [PATCH 01/12] k8s-infra: add host/path-based ingress strategies Signed-off-by: Guy Daich --- .../modules/che-kubernetes-helm/readme.md | 12 + .../templates/configmap.yaml | 7 + .../templates/deployment.yaml | 5 + .../kubernetes/KubernetesInfraModule.java | 13 + .../provision/server/ServersConverter.java | 11 +- .../server/ExternalServerExposerStrategy.java | 27 +++ ...ExternalServerExposerStrategyProvider.java | 49 ++++ .../server/ExternalServerIngressBuilder.java | 125 ++++++++++ .../IngressHostExternalServerExposer.java | 101 ++++++++ .../IngressPathExternalServerExposer.java | 95 ++++++++ .../server/KubernetesServerExposer.java | 145 ++--------- .../IngressHostExternalServerExposerTest.java | 226 ++++++++++++++++++ .../IngressPathExternalServerExposerTest.java | 218 +++++++++++++++++ .../server/KubernetesServerExposerTest.java | 42 +--- 14 files changed, 916 insertions(+), 160 deletions(-) create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java create mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java create mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java diff --git a/dockerfiles/init/modules/che-kubernetes-helm/readme.md b/dockerfiles/init/modules/che-kubernetes-helm/readme.md index 4e39d067061..c19f1873c2e 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/readme.md +++ b/dockerfiles/init/modules/che-kubernetes-helm/readme.md @@ -34,6 +34,18 @@ The context of the commands below is the directory in which this readme file res ```bash helm upgrade --install --namespace --set cheDomain= --set cheImage= ./ ``` + +- Local Host-Based (wildcard DNS) installation: + ```bash + helm upgrade --install --namespace che --set cheDomain=che..xip.io ./ + ``` + master url: http://master.che..xip.io +- Local Path-Based installation: + ```bash + helm upgrade --install --namespace che --set cheDomain= --set isHostBased=false ./ + ``` + master url: http:// + ## Deleting a Deployment You can delete a deployment using the following command: ``` bash diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml index 28c2d600294..49b21cdf870 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml @@ -44,3 +44,10 @@ data: {{- else }} CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- end }} +{{- if .Values.isHostBased }} + CHE_INFRA_KUBERNETES_SERVER_STRATEGY: "host" +{{- else }} + CHE_INFRA_KUBERNETES_SERVER_STRATEGY: "path" +{{- end }} + + diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml index 09394b0a4d7..cedbf1de406 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml @@ -166,6 +166,11 @@ spec: configMapKeyRef: key: CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON name: che + - name: CHE_INFRA_KUBERNETES_SERVER_STRATEGY + valueFrom: + configMapKeyRef: + key: CHE_INFRA_KUBERNETES_SERVER_STRATEGY + name: che image: {{ .Values.cheImage }} imagePullPolicy: {{ .Values.cheImagePullPolicy }} livenessProbe: diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java index 596077ada51..4c0a002d53f 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java @@ -12,6 +12,8 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.CommonPVCStrategy.COMMON_STRATEGY; import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.UniqueWorkspacePVCStrategy.UNIQUE_STRATEGY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressHostExternalServerExposer.HOST_STRATEGY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressPathExternalServerExposer.PATH_STRATEGY; import com.google.inject.AbstractModule; import com.google.inject.TypeLiteral; @@ -36,7 +38,11 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.KubernetesCheApiEnvVarProvider; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.LogsRootEnvVariableProvider; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategyProvider; import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressAnnotationsProvider; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressHostExternalServerExposer; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressPathExternalServerExposer; /** @author Sergii Leshchenko */ public class KubernetesInfraModule extends AbstractModule { @@ -65,6 +71,13 @@ protected void configure() { volumesStrategies.addBinding(UNIQUE_STRATEGY).to(UniqueWorkspacePVCStrategy.class); bind(WorkspaceVolumesStrategy.class).toProvider(WorkspaceVolumeStrategyProvider.class); + MapBinder ingressStrategies = + MapBinder.newMapBinder(binder(), String.class, ExternalServerExposerStrategy.class); + ingressStrategies.addBinding(HOST_STRATEGY).to(IngressHostExternalServerExposer.class); + ingressStrategies.addBinding(PATH_STRATEGY).to(IngressPathExternalServerExposer.class); + bind(ExternalServerExposerStrategy.class) + .toProvider(ExternalServerExposerStrategyProvider.class); + Multibinder envVarProviders = Multibinder.newSetBinder(binder(), EnvVarProvider.class); envVarProviders.addBinding().to(LogsRootEnvVariableProvider.class); diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/server/ServersConverter.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/server/ServersConverter.java index 511dccf4686..c41f87907b5 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/server/ServersConverter.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/server/ServersConverter.java @@ -15,7 +15,6 @@ import io.fabric8.kubernetes.api.model.PodSpec; import java.util.Map; import javax.inject.Inject; -import javax.inject.Named; import javax.inject.Singleton; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; @@ -24,6 +23,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.Names; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer; /** @@ -38,12 +38,11 @@ @Singleton public class ServersConverter implements ConfigurationProvisioner { - private final Map ingressAnnotations; + private final ExternalServerExposerStrategy externalServerExposerStrategy; @Inject - public ServersConverter( - @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations) { - this.ingressAnnotations = ingressAnnotations; + public ServersConverter(ExternalServerExposerStrategy externalServerExposerStrategy) { + this.externalServerExposerStrategy = externalServerExposerStrategy; } @Override @@ -58,7 +57,7 @@ public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) if (!machineConfig.getServers().isEmpty()) { KubernetesServerExposer kubernetesServerExposer = new KubernetesServerExposer<>( - ingressAnnotations, machineName, podConfig, containerConfig, k8sEnv); + externalServerExposerStrategy, machineName, podConfig, containerConfig, k8sEnv); kubernetesServerExposer.expose(machineConfig.getServers()); } } diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java new file mode 100644 index 00000000000..0317b56ec33 --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import io.fabric8.kubernetes.api.model.ServicePort; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; + +/** @author Guy Daich */ +public interface ExternalServerExposerStrategy { + + void exposeExternalServers( + KubernetesEnvironment k8sEnv, + String machineName, + String serviceName, + Map portToServicePort, + Map externalServers); +} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java new file mode 100644 index 00000000000..ab8343d4559 --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.lang.String.format; + +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +/** + * Provides implementation of {@link ExternalServerExposerStrategy} for configured value. + * + * @author Guy Daich + */ +@Singleton +public class ExternalServerExposerStrategyProvider + implements Provider { + + private final ExternalServerExposerStrategy externalServerExposerStrategy; + + @Inject + public ExternalServerExposerStrategyProvider( + @Named("che.infra.kubernetes.server.strategy") String strategy, + Map strategies) { + final ExternalServerExposerStrategy externalServerExposerStrategy = strategies.get(strategy); + if (externalServerExposerStrategy != null) { + this.externalServerExposerStrategy = externalServerExposerStrategy; + } else { + throw new IllegalArgumentException( + format("Unsupported Ingress strategy '%s' configured", strategy)); + } + } + + @Override + public ExternalServerExposerStrategy get() { + return externalServerExposerStrategy; + } +} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java new file mode 100644 index 00000000000..3e83d58b907 --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static com.google.common.base.Strings.isNullOrEmpty; + +import io.fabric8.kubernetes.api.model.IntOrString; +import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; +import io.fabric8.kubernetes.api.model.extensions.HTTPIngressPath; +import io.fabric8.kubernetes.api.model.extensions.HTTPIngressPathBuilder; +import io.fabric8.kubernetes.api.model.extensions.HTTPIngressRuleValue; +import io.fabric8.kubernetes.api.model.extensions.HTTPIngressRuleValueBuilder; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import io.fabric8.kubernetes.api.model.extensions.IngressBackend; +import io.fabric8.kubernetes.api.model.extensions.IngressBackendBuilder; +import io.fabric8.kubernetes.api.model.extensions.IngressRule; +import io.fabric8.kubernetes.api.model.extensions.IngressRuleBuilder; +import io.fabric8.kubernetes.api.model.extensions.IngressSpec; +import io.fabric8.kubernetes.api.model.extensions.IngressSpecBuilder; +import java.util.HashMap; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; + +/** @author Guy Daich */ +public class ExternalServerIngressBuilder { + + private String host; + private String path; + private String name; + private String serviceName; + private IntOrString servicePort; + private Map serversConfigs; + private String machineName; + private Map annotations; + + public ExternalServerIngressBuilder withHost(String host) { + this.host = host; + return this; + } + + public ExternalServerIngressBuilder withPath(String path) { + this.path = path; + return this; + } + + public ExternalServerIngressBuilder withName(String name) { + this.name = name; + return this; + } + + public ExternalServerIngressBuilder withServiceName(String serviceName) { + this.serviceName = serviceName; + return this; + } + + public ExternalServerIngressBuilder withAnnotations(Map annotations) { + this.annotations = annotations; + return this; + } + + public ExternalServerIngressBuilder withServicePort(String targetPortName) { + this.servicePort = new IntOrString(targetPortName); + return this; + } + + public ExternalServerIngressBuilder withServers( + Map serversConfigs) { + this.serversConfigs = serversConfigs; + return this; + } + + public ExternalServerIngressBuilder withMachineName(String machineName) { + this.machineName = machineName; + return this; + } + + public Ingress build() { + + IngressBackend ingressBackend = + new IngressBackendBuilder() + .withServiceName(serviceName) + .withNewServicePort(servicePort.getStrVal()) + .build(); + + HTTPIngressPathBuilder httpIngressPathBuilder = + new HTTPIngressPathBuilder().withBackend(ingressBackend); + + if (!isNullOrEmpty(path)) { + httpIngressPathBuilder.withPath(path); + } + + HTTPIngressPath httpIngressPath = httpIngressPathBuilder.build(); + + HTTPIngressRuleValue httpIngressRuleValue = + new HTTPIngressRuleValueBuilder().withPaths(httpIngressPath).build(); + IngressRuleBuilder ingressRuleBuilder = new IngressRuleBuilder().withHttp(httpIngressRuleValue); + + if (!isNullOrEmpty(host)) { + ingressRuleBuilder.withHost(host); + } + + IngressRule ingressRule = ingressRuleBuilder.build(); + + IngressSpec ingressSpec = new IngressSpecBuilder().withRules(ingressRule).build(); + + Map ingressAnnotations = new HashMap<>(annotations); + ingressAnnotations.putAll( + Annotations.newSerializer().servers(serversConfigs).machineName(machineName).annotations()); + + return new io.fabric8.kubernetes.api.model.extensions.IngressBuilder() + .withSpec(ingressSpec) + .withMetadata( + new ObjectMetaBuilder().withName(name).withAnnotations(ingressAnnotations).build()) + .build(); + } +} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java new file mode 100644 index 00000000000..1aa774ca81a --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.lang.Integer.parseInt; +import static java.util.stream.Collectors.toMap; + +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides a host-based strategy for exposing service ports outside the cluster using Ingress + * + *

This strategy uses different Ingress host entries
+ * Each external server is exposed with a unique subdomain of CHE_DOMAIN. + * + * @author Sergii Leshchenko + * @author Guy Daich + */ +public class IngressHostExternalServerExposer implements ExternalServerExposerStrategy { + + public static final String HOST_STRATEGY = "host"; + private final String domain; + private final Map ingressAnnotations; + private static final Logger LOG = LoggerFactory.getLogger(IngressHostExternalServerExposer.class); + + @Inject + public IngressHostExternalServerExposer( + @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations, + @Named("che.domain") String domain) { + if (ingressAnnotations == null) { + LOG.warn( + "Ingresses annotations are absent. Make sure that workspace ingresses don't need " + + "to be configured according to ingress controller."); + } + this.ingressAnnotations = ingressAnnotations; + this.domain = domain; + } + + @Override + public void exposeExternalServers( + KubernetesEnvironment k8sEnv, + String machineName, + String serviceName, + Map portToServicePort, + Map externalServers) { + + for (ServicePort servicePort : portToServicePort.values()) { + int port = servicePort.getTargetPort().getIntVal(); + + Map ingressesServers = + externalServers + .entrySet() + .stream() + .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + Ingress ingress = + new ExternalServerIngressBuilder() + .withHost(generateExternalServerIngressHostname(serviceName, servicePort)) + .withPath(generateExternalServerIngressPath()) + .withName(generateExternalServerIngressName(serviceName, servicePort)) + .withMachineName(machineName) + .withServiceName(serviceName) + .withAnnotations(ingressAnnotations) + .withServicePort(servicePort.getName()) + .withServers(ingressesServers) + .build(); + + k8sEnv.getIngresses().put(ingress.getMetadata().getName(), ingress); + } + } + + private String generateExternalServerIngressPath() { + return "/"; + } + + private String generateExternalServerIngressName(String serviceName, ServicePort servicePort) { + return serviceName + '-' + servicePort.getName(); + } + + private String generateExternalServerIngressHostname( + String serviceName, ServicePort servicePort) { + return serviceName + "-" + servicePort.getName() + "." + domain; + } +} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java new file mode 100644 index 00000000000..4ed8eb96857 --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.lang.Integer.parseInt; +import static java.util.stream.Collectors.toMap; + +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides a path-based strategy for exposing service ports outside the cluster using Ingress + * + *

This strategy uses different Ingress path entries
+ * Each external server is exposed with a unique path prefix. + * + *

This strategy imposes limitation on user-developed applications.
+ * It should only be used for local development with a single IP adress + * + * @author Sergii Leshchenko + * @author Guy Daich + */ +public class IngressPathExternalServerExposer implements ExternalServerExposerStrategy { + + public static final String PATH_STRATEGY = "path"; + private final Map ingressAnnotations; + private static final Logger LOG = LoggerFactory.getLogger(IngressPathExternalServerExposer.class); + + @Inject + public IngressPathExternalServerExposer( + @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations) { + if (ingressAnnotations == null) { + LOG.warn( + "Ingresses annotations are absent. Make sure that workspace ingresses don't need " + + "to be configured according to ingress controller."); + } + this.ingressAnnotations = ingressAnnotations; + } + + @Override + public void exposeExternalServers( + KubernetesEnvironment k8sEnv, + String machineName, + String serviceName, + Map portToServicePort, + Map externalServers) { + + for (ServicePort servicePort : portToServicePort.values()) { + int port = servicePort.getTargetPort().getIntVal(); + + Map ingressesServers = + externalServers + .entrySet() + .stream() + .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + Ingress ingress = + new ExternalServerIngressBuilder() + .withPath(generateExternalServerIngressPath(serviceName, servicePort)) + .withName(generateExternalServerIngressName(serviceName, servicePort)) + .withMachineName(machineName) + .withServiceName(serviceName) + .withAnnotations(ingressAnnotations) + .withServicePort(servicePort.getName()) + .withServers(ingressesServers) + .build(); + + k8sEnv.getIngresses().put(ingress.getMetadata().getName(), ingress); + } + } + + private String generateExternalServerIngressName(String serviceName, ServicePort servicePort) { + return serviceName + '-' + servicePort.getName(); + } + + private String generateExternalServerIngressPath(String serviceName, ServicePort servicePort) { + return "/" + serviceName + "/" + servicePort.getName(); + } +} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java index 3db5001ef4a..0a49a1bf2ac 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java @@ -11,7 +11,6 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.server; import static java.lang.Integer.parseInt; -import static java.util.stream.Collectors.toMap; import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.INTERNAL_SERVER_ATTRIBUTE; import static org.eclipse.che.commons.lang.NameGenerator.generate; import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.CHE_ORIGINAL_NAME_LABEL; @@ -19,23 +18,11 @@ import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.ContainerPort; import io.fabric8.kubernetes.api.model.ContainerPortBuilder; -import io.fabric8.kubernetes.api.model.IntOrString; -import io.fabric8.kubernetes.api.model.ObjectMetaBuilder; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServicePort; import io.fabric8.kubernetes.api.model.ServicePortBuilder; -import io.fabric8.kubernetes.api.model.extensions.HTTPIngressPath; -import io.fabric8.kubernetes.api.model.extensions.HTTPIngressPathBuilder; -import io.fabric8.kubernetes.api.model.extensions.HTTPIngressRuleValue; -import io.fabric8.kubernetes.api.model.extensions.HTTPIngressRuleValueBuilder; import io.fabric8.kubernetes.api.model.extensions.Ingress; -import io.fabric8.kubernetes.api.model.extensions.IngressBackend; -import io.fabric8.kubernetes.api.model.extensions.IngressBackendBuilder; -import io.fabric8.kubernetes.api.model.extensions.IngressRule; -import io.fabric8.kubernetes.api.model.extensions.IngressRuleBuilder; -import io.fabric8.kubernetes.api.model.extensions.IngressSpec; -import io.fabric8.kubernetes.api.model.extensions.IngressSpecBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -45,7 +32,6 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import javax.inject.Named; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; @@ -99,9 +85,11 @@ * protocol: TCP ---->> Pod.spec.ports[0].protocol * * - * Then corresponding ingress expose one of the service's port: + * Then, a server exposer strategy is used to expose one of the service's ports, to outside of the + * cluster. Currently, Host-Based and Path-Based Ingresses can be used to expose service ports. * *

+ *   Path-Based Ingress exposing service's port:
  * Ingress
  * ...
  * spec:
@@ -114,6 +102,21 @@
  *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
  * 
* + *
+ *   Host-Based Ingress exposing service's port:
+ * Ingress
+ * ...
+ * spec:
+ *   rules:
+ *     - host: service123-webapp.che-domain   ---->> Service.metadata.name + - + Service.spec.ports[0].name
+ *     - http:
+ *         paths:
+ *           - path: /
+ *             backend:
+ *               serviceName: service123      ---->> Service.metadata.name
+ *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
+ * 
+ * *

For accessing publicly accessible server user will use ingress host or its load balancer IP. * For accessing workspace-wide accessible server user will use service name. Information about * servers that are exposed by ingress and/or service are stored in annotations of a ingress or @@ -130,24 +133,19 @@ public class KubernetesServerExposer { public static final int SERVER_UNIQUE_PART_SIZE = 8; public static final String SERVER_PREFIX = "server"; - private final Map ingressAnnotations; + private final ExternalServerExposerStrategy kubernetesExternalServerExposerStrategy; protected final String machineName; protected final Container container; protected final Pod pod; protected final T kubernetesEnvironment; public KubernetesServerExposer( - @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations, + ExternalServerExposerStrategy kubernetesExternalServerExposerStrategy, String machineName, Pod pod, Container container, T kubernetesEnvironment) { - if (ingressAnnotations == null) { - LOG.warn( - "Ingresses annotations are absent. Make sure that workspace ingresses don't need " - + "to be configured according to ingress controller."); - } - this.ingressAnnotations = ingressAnnotations; + this.kubernetesExternalServerExposerStrategy = kubernetesExternalServerExposerStrategy; this.machineName = machineName; this.pod = pod; this.container = container; @@ -190,35 +188,8 @@ public void expose(Map servers) { String serviceName = service.getMetadata().getName(); kubernetesEnvironment.getServices().put(serviceName, service); - exposeExternalServers(serviceName, portToServicePort, externalServers); - } - - protected void exposeExternalServers( - String serviceName, - Map portToServicePort, - Map externalServers) { - for (ServicePort servicePort : portToServicePort.values()) { - int port = servicePort.getTargetPort().getIntVal(); - - Map ingressesServers = - externalServers - .entrySet() - .stream() - .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) - .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); - - Ingress ingress = - new IngressBuilder() - .withName(serviceName + '-' + servicePort.getName()) - .withMachineName(machineName) - .withServiceName(serviceName) - .withAnnotations(ingressAnnotations) - .withServicePort(servicePort.getName()) - .withServers(ingressesServers) - .build(); - - kubernetesEnvironment.getIngresses().put(ingress.getMetadata().getName(), ingress); - } + kubernetesExternalServerExposerStrategy.exposeExternalServers( + kubernetesEnvironment, machineName, serviceName, portToServicePort, externalServers); } private Map exposePort(Collection serverConfig) { @@ -309,74 +280,4 @@ public ServiceBuilder withMachineName(String machineName) { return this; } } - - private static class IngressBuilder { - private String name; - private String serviceName; - private IntOrString servicePort; - private Map serversConfigs; - private String machineName; - private Map annotations; - - private IngressBuilder withName(String name) { - this.name = name; - return this; - } - - private IngressBuilder withServiceName(String serviceName) { - this.serviceName = serviceName; - return this; - } - - private IngressBuilder withAnnotations(Map annotations) { - this.annotations = annotations; - return this; - } - - private IngressBuilder withServicePort(String targetPortName) { - this.servicePort = new IntOrString(targetPortName); - return this; - } - - private IngressBuilder withServers(Map serversConfigs) { - this.serversConfigs = serversConfigs; - return this; - } - - public IngressBuilder withMachineName(String machineName) { - this.machineName = machineName; - return this; - } - - private Ingress build() { - - IngressBackend ingressBackend = - new IngressBackendBuilder() - .withServiceName(serviceName) - .withNewServicePort(servicePort.getStrVal()) - .build(); - - String serverPath = "/" + serviceName + "/" + servicePort.getStrVal(); - HTTPIngressPath httpIngressPath = - new HTTPIngressPathBuilder().withPath(serverPath).withBackend(ingressBackend).build(); - - HTTPIngressRuleValue httpIngressRuleValue = - new HTTPIngressRuleValueBuilder().withPaths(httpIngressPath).build(); - IngressRule ingressRule = new IngressRuleBuilder().withHttp(httpIngressRuleValue).build(); - IngressSpec ingressSpec = new IngressSpecBuilder().withRules(ingressRule).build(); - - Map ingressAnnotations = new HashMap<>(annotations); - ingressAnnotations.putAll( - Annotations.newSerializer() - .servers(serversConfigs) - .machineName(machineName) - .annotations()); - - return new io.fabric8.kubernetes.api.model.extensions.IngressBuilder() - .withSpec(ingressSpec) - .withMetadata( - new ObjectMetaBuilder().withName(name).withAnnotations(ingressAnnotations).build()) - .build(); - } - } } diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java new file mode 100644 index 00000000000..fdb9e737588 --- /dev/null +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_PREFIX; +import static org.testng.Assert.assertEquals; + +import com.google.common.collect.ImmutableMap; +import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.ContainerBuilder; +import io.fabric8.kubernetes.api.model.IntOrString; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.ServicePortBuilder; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import io.fabric8.kubernetes.api.model.extensions.IngressBackend; +import io.fabric8.kubernetes.api.model.extensions.IngressRule; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** @author Guy Daich */ +public class IngressHostExternalServerExposerTest { + + private static final Map ATTRIBUTES_MAP = singletonMap("key", "value"); + public static final String MACHINE_NAME = "pod/main"; + public static final String SERVICE_NAME = SERVER_PREFIX + "12345678" + "-" + MACHINE_NAME; + public static final String DOMAIN = "che.com"; + + private IngressHostExternalServerExposer hostExternalServerExposer; + private KubernetesEnvironment kubernetesEnvironment; + private Container container; + + @BeforeMethod + public void setUp() throws Exception { + container = new ContainerBuilder().withName("main").build(); + Pod pod = + new PodBuilder() + .withNewMetadata() + .withName("pod") + .endMetadata() + .withNewSpec() + .withContainers(container) + .endSpec() + .build(); + + kubernetesEnvironment = + KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build(); + hostExternalServerExposer = new IngressHostExternalServerExposer(emptyMap(), DOMAIN); + } + + @Test + public void shouldCreateIngressForServer() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + IntOrString targetPort = new IntOrString(8080); + ServicePort servicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(targetPort) + .build(); + Map portToServicePort = ImmutableMap.of("8080/tcp", servicePort); + Map serversToExpose = ImmutableMap.of("http-server", httpServerConfig); + + // when + hostExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + @Test + public void shouldCreateIngressForServerWhenTwoServersHasTheSamePort() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + ServerConfigImpl wsServerConfig = + new ServerConfigImpl("8080/tcp", "ws", "/connect", ATTRIBUTES_MAP); + IntOrString targetPort = new IntOrString(8080); + + ServicePort servicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(targetPort) + .build(); + Map portToServicePort = ImmutableMap.of("8080/tcp", servicePort); + + Map serversToExpose = + ImmutableMap.of( + "http-server", httpServerConfig, + "ws-server", wsServerConfig); + + // when + hostExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertEquals(kubernetesEnvironment.getIngresses().size(), 1); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "ws-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + @Test + public void shouldCreateIngressesForServerWhenTwoServersHasDifferentPorts() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + ServerConfigImpl wsServerConfig = + new ServerConfigImpl("8081/tcp", "ws", "/connect", ATTRIBUTES_MAP); + IntOrString httpTargetPort = new IntOrString(8080); + IntOrString wsTargetPort = new IntOrString(8081); + ServicePort httpServicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(httpTargetPort) + .build(); + ServicePort wsServicePort = + new ServicePortBuilder() + .withName("server-8081") + .withPort(8081) + .withProtocol("TCP") + .withTargetPort(wsTargetPort) + .build(); + Map portToServicePort = + ImmutableMap.of("8080/tcp", httpServicePort, "8081/tcp", wsServicePort); + + Map serversToExpose = + ImmutableMap.of( + "http-server", httpServerConfig, + "ws-server", wsServerConfig); + + // when + hostExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertEquals(kubernetesEnvironment.getIngresses().size(), 2); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + httpServicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "ws-server", + "tcp", + 8081, + wsServicePort, + new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + private void assertThatExternalServerIsExposed( + String machineName, + String serviceName, + String serverNameRegex, + String portProtocol, + Integer port, + ServicePort servicePort, + ServerConfigImpl expected) { + + // ensure that required ingress is created + Ingress ingress = kubernetesEnvironment.getIngresses().get(serviceName + "-server-" + port); + IngressRule ingressRule = ingress.getSpec().getRules().get(0); + assertEquals(ingressRule.getHost(), serviceName + "-" + servicePort.getName() + "." + DOMAIN); + assertEquals(ingressRule.getHttp().getPaths().get(0).getPath(), "/"); + IngressBackend backend = ingressRule.getHttp().getPaths().get(0).getBackend(); + assertEquals(backend.getServiceName(), serviceName); + assertEquals(backend.getServicePort().getStrVal(), servicePort.getName()); + + Annotations.Deserializer ingressAnnotations = + Annotations.newDeserializer(ingress.getMetadata().getAnnotations()); + Map servers = ingressAnnotations.servers(); + ServerConfig serverConfig = servers.get(serverNameRegex); + assertEquals(serverConfig, expected); + + assertEquals(ingressAnnotations.machineName(), machineName); + } +} diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java new file mode 100644 index 00000000000..9b52698d6d2 --- /dev/null +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_PREFIX; +import static org.testng.Assert.*; + +import com.google.common.collect.ImmutableMap; +import io.fabric8.kubernetes.api.model.Container; +import io.fabric8.kubernetes.api.model.ContainerBuilder; +import io.fabric8.kubernetes.api.model.IntOrString; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.kubernetes.api.model.PodBuilder; +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.ServicePortBuilder; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import io.fabric8.kubernetes.api.model.extensions.IngressBackend; +import io.fabric8.kubernetes.api.model.extensions.IngressRule; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** @author Guy Daich */ +public class IngressPathExternalServerExposerTest { + + private static final Map ATTRIBUTES_MAP = singletonMap("key", "value"); + public static final String MACHINE_NAME = "pod/main"; + public static final String SERVICE_NAME = SERVER_PREFIX + "12345678" + "-" + MACHINE_NAME; + + private IngressPathExternalServerExposer pathExternalServerExposer; + private KubernetesEnvironment kubernetesEnvironment; + private Container container; + + @BeforeMethod + public void setUp() throws Exception { + container = new ContainerBuilder().withName("main").build(); + Pod pod = + new PodBuilder() + .withNewMetadata() + .withName("pod") + .endMetadata() + .withNewSpec() + .withContainers(container) + .endSpec() + .build(); + + kubernetesEnvironment = + KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build(); + pathExternalServerExposer = new IngressPathExternalServerExposer(emptyMap()); + } + + @Test + public void shouldCreateIngressForServer() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + ServicePort servicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(new IntOrString(8080)) + .build(); + Map portToServicePort = ImmutableMap.of("8080/tcp", servicePort); + Map serversToExpose = ImmutableMap.of("http-server", httpServerConfig); + + // when + pathExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + @Test + public void shouldCreateIngressForServerWhenTwoServersHasTheSamePort() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + ServerConfigImpl wsServerConfig = + new ServerConfigImpl("8080/tcp", "ws", "/connect", ATTRIBUTES_MAP); + ServicePort servicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(new IntOrString(8080)) + .build(); + Map portToServicePort = ImmutableMap.of("8080/tcp", servicePort); + + Map serversToExpose = + ImmutableMap.of( + "http-server", httpServerConfig, + "ws-server", wsServerConfig); + + // when + pathExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertEquals(kubernetesEnvironment.getIngresses().size(), 1); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "ws-server", + "tcp", + 8080, + servicePort, + new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + @Test + public void shouldCreateIngressesForServerWhenTwoServersHasDifferentPorts() { + // given + ServerConfigImpl httpServerConfig = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + ServerConfigImpl wsServerConfig = + new ServerConfigImpl("8081/tcp", "ws", "/connect", ATTRIBUTES_MAP); + ServicePort httpServicePort = + new ServicePortBuilder() + .withName("server-8080") + .withPort(8080) + .withProtocol("TCP") + .withTargetPort(new IntOrString(8080)) + .build(); + ServicePort wsServicePort = + new ServicePortBuilder() + .withName("server-8081") + .withPort(8081) + .withProtocol("TCP") + .withTargetPort(new IntOrString(8081)) + .build(); + Map portToServicePort = + ImmutableMap.of("8080/tcp", httpServicePort, "8081/tcp", wsServicePort); + + Map serversToExpose = + ImmutableMap.of( + "http-server", httpServerConfig, + "ws-server", wsServerConfig); + + // when + pathExternalServerExposer.exposeExternalServers( + kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose); + + // then + assertEquals(kubernetesEnvironment.getIngresses().size(), 2); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "http-server", + "tcp", + 8080, + httpServicePort, + new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); + assertThatExternalServerIsExposed( + MACHINE_NAME, + SERVICE_NAME, + "ws-server", + "tcp", + 8081, + wsServicePort, + new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); + } + + private void assertThatExternalServerIsExposed( + String machineName, + String serviceName, + String serverNameRegex, + String portProtocol, + Integer port, + ServicePort servicePort, + ServerConfigImpl expected) { + + // ensure that required ingress is created + Ingress ingress = kubernetesEnvironment.getIngresses().get(serviceName + "-server-" + port); + IngressRule ingressRule = ingress.getSpec().getRules().get(0); + IngressBackend backend = ingressRule.getHttp().getPaths().get(0).getBackend(); + assertEquals(backend.getServiceName(), serviceName); + assertEquals(backend.getServicePort().getStrVal(), servicePort.getName()); + + Annotations.Deserializer ingressAnnotations = + Annotations.newDeserializer(ingress.getMetadata().getAnnotations()); + Map servers = ingressAnnotations.servers(); + ServerConfig serverConfig = servers.get(serverNameRegex); + assertEquals(serverConfig, expected); + + assertEquals(ingressAnnotations.machineName(), machineName); + } +} diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java index 3912962f5d3..3d8ab71c312 100644 --- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposerTest.java @@ -10,7 +10,6 @@ */ package org.eclipse.che.workspace.infrastructure.kubernetes.server; -import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; import static org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer.SERVER_PREFIX; @@ -27,9 +26,6 @@ import io.fabric8.kubernetes.api.model.PodBuilder; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServicePort; -import io.fabric8.kubernetes.api.model.extensions.Ingress; -import io.fabric8.kubernetes.api.model.extensions.IngressBackend; -import io.fabric8.kubernetes.api.model.extensions.IngressRule; import java.util.ArrayList; import java.util.Map; import java.util.Map.Entry; @@ -39,6 +35,7 @@ import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.mockito.Mock; import org.mockito.testng.MockitoTestNGListener; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Listeners; @@ -52,6 +49,7 @@ @Listeners(MockitoTestNGListener.class) public class KubernetesServerExposerTest { + @Mock private ExternalServerExposerStrategy externalServerExposerStrategy; private static final Map ATTRIBUTES_MAP = singletonMap("key", "value"); private static final Map INTERNAL_SERVER_ATTRIBUTE_MAP = singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, Boolean.TRUE.toString()); @@ -81,11 +79,11 @@ public void setUp() throws Exception { KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build(); this.serverExposer = new KubernetesServerExposer<>( - emptyMap(), MACHINE_NAME, pod, container, kubernetesEnvironment); + externalServerExposerStrategy, MACHINE_NAME, pod, container, kubernetesEnvironment); } @Test - public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { + public void shouldExposeContainerPortAndCreateServiceForServer() { // given ServerConfigImpl httpServerConfig = new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); @@ -105,8 +103,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { } @Test - public void - shouldExposeContainerPortAndCreateServiceAndIngressForServerWhenTwoServersHasTheSamePort() { + public void shouldExposeContainerPortAndCreateServiceAndForServerWhenTwoServersHasTheSamePort() { // given ServerConfigImpl httpServerConfig = new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); @@ -122,7 +119,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { // then assertEquals(kubernetesEnvironment.getServices().size(), 1); - assertEquals(kubernetesEnvironment.getIngresses().size(), 1); + assertThatExternalServerIsExposed( MACHINE_NAME, "http-server", @@ -138,8 +135,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { } @Test - public void - shouldExposeContainerPortsAndCreateServiceAndIngressesForServerWhenTwoServersHasDifferentPorts() { + public void shouldExposeContainerPortsAndCreateServiceForServerWhenTwoServersHasDifferentPorts() { // given ServerConfigImpl httpServerConfig = new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); @@ -155,7 +151,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { // then assertEquals(kubernetesEnvironment.getServices().size(), 1); - assertEquals(kubernetesEnvironment.getIngresses().size(), 2); + assertThatExternalServerIsExposed( MACHINE_NAME, "http-server", @@ -172,7 +168,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { @Test public void - shouldExposeTcpContainerPortsAndCreateServiceAndIngressForServerWhenProtocolIsMissedInPort() { + shouldExposeTcpContainerPortsAndCreateServiceAndForServerWhenProtocolIsMissedInPort() { // given ServerConfigImpl httpServerConfig = new ServerConfigImpl("8080", "http", "/api", ATTRIBUTES_MAP); @@ -184,7 +180,7 @@ public void shouldExposeContainerPortAndCreateServiceAndIngressForServer() { // then assertEquals(kubernetesEnvironment.getServices().size(), 1); - assertEquals(kubernetesEnvironment.getIngresses().size(), 1); + assertThatExternalServerIsExposed( MACHINE_NAME, "http-server", @@ -341,24 +337,6 @@ private void assertThatExternalServerIsExposed( Annotations.Deserializer serviceAnnotations = Annotations.newDeserializer(service.getMetadata().getAnnotations()); assertEquals(serviceAnnotations.machineName(), machineName); - - // ensure that required ingress is created - Ingress ingress = - kubernetesEnvironment - .getIngresses() - .get(service.getMetadata().getName() + "-server-" + port); - IngressRule ingressRule = ingress.getSpec().getRules().get(0); - IngressBackend backend = ingressRule.getHttp().getPaths().get(0).getBackend(); - assertEquals(backend.getServiceName(), service.getMetadata().getName()); - assertEquals(backend.getServicePort().getStrVal(), servicePort.getName()); - - Annotations.Deserializer ingressAnnotations = - Annotations.newDeserializer(ingress.getMetadata().getAnnotations()); - Map servers = ingressAnnotations.servers(); - ServerConfig serverConfig = servers.get(serverNameRegex); - assertEquals(serverConfig, expected); - - assertEquals(ingressAnnotations.machineName(), machineName); } private void assertThatInternalServerIsExposed( From cf4faba15f96db91a154e28dabddaa1726991a86 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Sun, 18 Feb 2018 18:15:22 +0200 Subject: [PATCH 02/12] Adapt OS infra to use external server exposer Signed-off-by: Guy Daich --- .../modules/che-kubernetes-helm/readme.md | 4 +- .../server/ExternalServerExposerStrategy.java | 6 +- .../IngressHostExternalServerExposer.java | 3 +- .../IngressPathExternalServerExposer.java | 3 +- .../server/KubernetesServerExposer.java | 15 ++- .../openshift/OpenShiftInfraModule.java | 4 + .../provision/OpenShiftServersConverter.java | 12 +- .../OpenShiftExternalServerExposer.java | 117 ++++++++++++++++++ .../server/OpenShiftServerExposer.java | 97 ++------------- .../openshift/OpenShiftServerExposerTest.java | 6 +- 10 files changed, 167 insertions(+), 100 deletions(-) create mode 100644 infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java diff --git a/dockerfiles/init/modules/che-kubernetes-helm/readme.md b/dockerfiles/init/modules/che-kubernetes-helm/readme.md index c19f1873c2e..440b692758e 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/readme.md +++ b/dockerfiles/init/modules/che-kubernetes-helm/readme.md @@ -39,12 +39,12 @@ The context of the commands below is the directory in which this readme file res ```bash helm upgrade --install --namespace che --set cheDomain=che..xip.io ./ ``` - master url: http://master.che..xip.io + master url: ``http://master.che..xip.io`` - Local Path-Based installation: ```bash helm upgrade --install --namespace che --set cheDomain= --set isHostBased=false ./ ``` - master url: http:// + master url: ``http://`` ## Deleting a Deployment You can delete a deployment using the following command: diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java index 0317b56ec33..4a5597d5e04 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java @@ -16,10 +16,10 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; /** @author Guy Daich */ -public interface ExternalServerExposerStrategy { +public interface ExternalServerExposerStrategy { - void exposeExternalServers( - KubernetesEnvironment k8sEnv, + public void exposeExternalServers( + T k8sEnv, String machineName, String serviceName, Map portToServicePort, diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java index 1aa774ca81a..28cf52b5981 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java @@ -32,7 +32,8 @@ * @author Sergii Leshchenko * @author Guy Daich */ -public class IngressHostExternalServerExposer implements ExternalServerExposerStrategy { +public class IngressHostExternalServerExposer + implements ExternalServerExposerStrategy { public static final String HOST_STRATEGY = "host"; private final String domain; diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java index 4ed8eb96857..400c865bae0 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java @@ -35,7 +35,8 @@ * @author Sergii Leshchenko * @author Guy Daich */ -public class IngressPathExternalServerExposer implements ExternalServerExposerStrategy { +public class IngressPathExternalServerExposer + implements ExternalServerExposerStrategy { public static final String PATH_STRATEGY = "path"; private final Map ingressAnnotations; diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java index 0a49a1bf2ac..49bfbdebbbb 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java @@ -133,7 +133,7 @@ public class KubernetesServerExposer { public static final int SERVER_UNIQUE_PART_SIZE = 8; public static final String SERVER_PREFIX = "server"; - private final ExternalServerExposerStrategy kubernetesExternalServerExposerStrategy; + protected final ExternalServerExposerStrategy kubernetesExternalServerExposerStrategy; protected final String machineName; protected final Container container; protected final Pod pod; @@ -187,9 +187,7 @@ public void expose(Map servers) { String serviceName = service.getMetadata().getName(); kubernetesEnvironment.getServices().put(serviceName, service); - - kubernetesExternalServerExposerStrategy.exposeExternalServers( - kubernetesEnvironment, machineName, serviceName, portToServicePort, externalServers); + exposeExternalServers(serviceName, portToServicePort, externalServers); } private Map exposePort(Collection serverConfig) { @@ -229,6 +227,15 @@ private Map exposePort(Collection s return exposedPorts; } + protected void exposeExternalServers( + String serviceName, + Map portToServicePort, + Map externalServers) { + + kubernetesExternalServerExposerStrategy.exposeExternalServers( + kubernetesEnvironment, machineName, serviceName, portToServicePort, externalServers); + } + private static class ServiceBuilder { private String name; private String machineName; diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java index f23bb0d20a6..7955fcc8582 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java @@ -32,10 +32,12 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.KubernetesCheApiEnvVarProvider; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.LogsRootEnvVariableProvider; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironmentFactory; import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProjectFactory; import org.eclipse.che.workspace.infrastructure.openshift.project.RemoveProjectOnWorkspaceRemove; +import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftExternalServerExposer; /** @author Sergii Leshchenko */ public class OpenShiftInfraModule extends AbstractModule { @@ -66,6 +68,8 @@ protected void configure() { volumesStrategies.addBinding(UNIQUE_STRATEGY).to(UniqueWorkspacePVCStrategy.class); bind(WorkspaceVolumesStrategy.class).toProvider(WorkspaceVolumeStrategyProvider.class); + bind(ExternalServerExposerStrategy.class).to(OpenShiftExternalServerExposer.class); + Multibinder envVarProviders = Multibinder.newSetBinder(binder(), EnvVarProvider.class); envVarProviders.addBinding().to(LogsRootEnvVariableProvider.class); diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java index a57203c6e15..e92dc89a523 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java @@ -14,6 +14,7 @@ import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.PodSpec; import java.util.Map; +import javax.inject.Inject; import javax.inject.Singleton; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; @@ -21,6 +22,7 @@ import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig; import org.eclipse.che.workspace.infrastructure.kubernetes.Names; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer; @@ -36,6 +38,13 @@ @Singleton public class OpenShiftServersConverter implements ConfigurationProvisioner { + ExternalServerExposerStrategy openshiftExternalServerExposer; + + @Inject + public OpenShiftServersConverter(ExternalServerExposerStrategy externalServerExposerStrategy) { + this.openshiftExternalServerExposer = externalServerExposerStrategy; + } + @Override public void provision(OpenShiftEnvironment osEnv, RuntimeIdentity identity) throws InfrastructureException { @@ -47,7 +56,8 @@ public void provision(OpenShiftEnvironment osEnv, RuntimeIdentity identity) InternalMachineConfig machineConfig = osEnv.getMachines().get(machineName); if (!machineConfig.getServers().isEmpty()) { OpenShiftServerExposer openShiftServerExposer = - new OpenShiftServerExposer(machineName, podConfig, containerConfig, osEnv); + new OpenShiftServerExposer( + openshiftExternalServerExposer, machineName, podConfig, containerConfig, osEnv); openShiftServerExposer.expose(machineConfig.getServers()); } } diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java new file mode 100644 index 00000000000..8bf6d0b72c3 --- /dev/null +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.openshift.server; + +import static java.lang.Integer.parseInt; +import static java.util.stream.Collectors.toMap; + +import io.fabric8.kubernetes.api.model.IntOrString; +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.openshift.api.model.Route; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; +import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; + +/** + * @author Sergii Leshchenko + * @author Alexander Garagatyi + */ +public class OpenShiftExternalServerExposer + implements ExternalServerExposerStrategy { + + @Override + public void exposeExternalServers( + OpenShiftEnvironment openShiftEnvironment, + String machineName, + String serviceName, + Map portToServicePort, + Map externalServers) { + for (ServicePort servicePort : portToServicePort.values()) { + int port = servicePort.getTargetPort().getIntVal(); + Map routesServers = + externalServers + .entrySet() + .stream() + .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + Route route = + new RouteBuilder() + .withName(serviceName + '-' + servicePort.getName()) + .withMachineName(machineName) + .withTargetPort(servicePort.getName()) + .withServers(routesServers) + .withTo(serviceName) + .build(); + openShiftEnvironment.getRoutes().put(route.getMetadata().getName(), route); + } + } + + private static class RouteBuilder { + + private String name; + private String serviceName; + private IntOrString targetPort; + private Map serversConfigs; + private String machineName; + + private RouteBuilder withName(String name) { + this.name = name; + return this; + } + + private RouteBuilder withTo(String serviceName) { + this.serviceName = serviceName; + return this; + } + + private RouteBuilder withTargetPort(String targetPortName) { + this.targetPort = new IntOrString(targetPortName); + return this; + } + + private RouteBuilder withServers(Map serversConfigs) { + this.serversConfigs = serversConfigs; + return this; + } + + public RouteBuilder withMachineName(String machineName) { + this.machineName = machineName; + return this; + } + + private Route build() { + io.fabric8.openshift.api.model.RouteBuilder builder = + new io.fabric8.openshift.api.model.RouteBuilder(); + + return builder + .withNewMetadata() + .withName(name.replace("/", "-")) + .withAnnotations( + Annotations.newSerializer() + .servers(serversConfigs) + .machineName(machineName) + .annotations()) + .endMetadata() + .withNewSpec() + .withNewTo() + .withName(serviceName) + .endTo() + .withNewPort() + .withTargetPort(targetPort) + .endPort() + .endSpec() + .build(); + } + } +} diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java index da017de0e40..3b83ede1dab 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java @@ -10,19 +10,15 @@ */ package org.eclipse.che.workspace.infrastructure.openshift.server; -import static java.lang.Integer.parseInt; -import static java.util.stream.Collectors.toMap; - import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.IntOrString; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServicePort; import io.fabric8.openshift.api.model.Route; -import java.util.Collections; import java.util.Map; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; @@ -91,12 +87,14 @@ */ public class OpenShiftServerExposer extends KubernetesServerExposer { - private final OpenShiftEnvironment openShiftEnvironment; - public OpenShiftServerExposer( - String machineName, Pod pod, Container container, OpenShiftEnvironment openShiftEnvironment) { - super(Collections.emptyMap(), machineName, pod, container, openShiftEnvironment); - this.openShiftEnvironment = openShiftEnvironment; + ExternalServerExposerStrategy OpenshiftExternalServerExposerStrategy, + String machineName, + Pod pod, + Container container, + OpenShiftEnvironment kubernetesEnvironment) { + super( + OpenshiftExternalServerExposerStrategy, machineName, pod, container, kubernetesEnvironment); } @Override @@ -104,82 +102,7 @@ protected void exposeExternalServers( String serviceName, Map portToServicePort, Map externalServers) { - for (ServicePort servicePort : portToServicePort.values()) { - int port = servicePort.getTargetPort().getIntVal(); - Map routesServers = - externalServers - .entrySet() - .stream() - .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) - .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); - - Route route = - new RouteBuilder() - .withName(serviceName + '-' + servicePort.getName()) - .withMachineName(machineName) - .withTargetPort(servicePort.getName()) - .withServers(routesServers) - .withTo(serviceName) - .build(); - openShiftEnvironment.getRoutes().put(route.getMetadata().getName(), route); - } - } - - private static class RouteBuilder { - - private String name; - private String serviceName; - private IntOrString targetPort; - private Map serversConfigs; - private String machineName; - - private RouteBuilder withName(String name) { - this.name = name; - return this; - } - - private RouteBuilder withTo(String serviceName) { - this.serviceName = serviceName; - return this; - } - - private RouteBuilder withTargetPort(String targetPortName) { - this.targetPort = new IntOrString(targetPortName); - return this; - } - - private RouteBuilder withServers(Map serversConfigs) { - this.serversConfigs = serversConfigs; - return this; - } - - public RouteBuilder withMachineName(String machineName) { - this.machineName = machineName; - return this; - } - - private Route build() { - io.fabric8.openshift.api.model.RouteBuilder builder = - new io.fabric8.openshift.api.model.RouteBuilder(); - - return builder - .withNewMetadata() - .withName(name.replace("/", "-")) - .withAnnotations( - Annotations.newSerializer() - .servers(serversConfigs) - .machineName(machineName) - .annotations()) - .endMetadata() - .withNewSpec() - .withNewTo() - .withName(serviceName) - .endTo() - .withNewPort() - .withTargetPort(targetPort) - .endPort() - .endSpec() - .build(); - } + kubernetesExternalServerExposerStrategy.exposeExternalServers( + kubernetesEnvironment, machineName, serviceName, portToServicePort, externalServers); } } diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java index 395a93a9466..2c98d1f1e0e 100644 --- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java +++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java @@ -37,6 +37,7 @@ import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; +import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftExternalServerExposer; import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -59,6 +60,7 @@ public class OpenShiftServerExposerTest { private OpenShiftServerExposer serverExposer; private OpenShiftEnvironment openShiftEnvironment; private Container container; + private OpenShiftExternalServerExposer openShiftExternalServerExposer; @BeforeMethod public void setUp() throws Exception { @@ -75,8 +77,10 @@ public void setUp() throws Exception { openShiftEnvironment = OpenShiftEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build(); + openShiftExternalServerExposer = new OpenShiftExternalServerExposer(); this.serverExposer = - new OpenShiftServerExposer(MACHINE_NAME, pod, container, openShiftEnvironment); + new OpenShiftServerExposer( + openShiftExternalServerExposer, MACHINE_NAME, pod, container, openShiftEnvironment); } @Test From 3ceebee944c9e3068911a54be25eb7a4ef978a9b Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Tue, 20 Feb 2018 13:31:33 +0200 Subject: [PATCH 03/12] reuse k8s ServersConverter in OS infra --- .../templates/configmap.yaml | 4 +- .../templates/deployment.yaml | 4 +- .../server/ExternalServerExposerStrategy.java | 17 ++- ...ExternalServerExposerStrategyProvider.java | 2 +- .../server/ExternalServerIngressBuilder.java | 5 + .../IngressHostExternalServerExposer.java | 15 ++ .../IngressPathExternalServerExposer.java | 16 ++- .../server/KubernetesServerExposer.java | 29 ---- .../ExternalServerIngressBuilderTest.java | 132 ++++++++++++++++++ .../OpenShiftEnvironmentProvisioner.java | 10 +- .../provision/OpenShiftServersConverter.java | 66 --------- .../OpenShiftExternalServerExposer.java | 60 ++++++++ .../server/OpenShiftServerExposer.java | 15 +- .../OpenShiftEnvironmentProvisionerTest.java | 4 +- 14 files changed, 257 insertions(+), 122 deletions(-) create mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilderTest.java delete mode 100644 infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml index 49b21cdf870..4423ac2e70d 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml @@ -45,9 +45,9 @@ data: CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- end }} {{- if .Values.isHostBased }} - CHE_INFRA_KUBERNETES_SERVER_STRATEGY: "host" + CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "host" {{- else }} - CHE_INFRA_KUBERNETES_SERVER_STRATEGY: "path" + CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "path" {{- end }} diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml index cedbf1de406..b498d79ed80 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml @@ -166,10 +166,10 @@ spec: configMapKeyRef: key: CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON name: che - - name: CHE_INFRA_KUBERNETES_SERVER_STRATEGY + - name: CHE_INFRA_KUBERNETES_SERVER__STRATEGY valueFrom: configMapKeyRef: - key: CHE_INFRA_KUBERNETES_SERVER_STRATEGY + key: CHE_INFRA_KUBERNETES_SERVER__STRATEGY name: che image: {{ .Values.cheImage }} imagePullPolicy: {{ .Values.cheImagePullPolicy }} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java index 4a5597d5e04..6e068771ca4 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategy.java @@ -15,9 +15,24 @@ import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; -/** @author Guy Daich */ +/** + * Defines a basic set of operations for exposing external servers. + * + * @author Guy Daich + */ public interface ExternalServerExposerStrategy { + /** + * Exposes service ports on given service externally (outside kubernetes cluster). Each exposed + * service port is associated with a specific Server configuration. Server configuration should be + * encoded in the exposing object's annotations, to be used by {@link KubernetesServerResolver}. + * + * @param k8sEnv Kubernetes environment + * @param machineName machine containing servers + * @param serviceName service associated with machine, mapping all machine server ports + * @param portToServicePort specific service ports to be exposed externally + * @param externalServers server configs of servers to be exposed externally + */ public void exposeExternalServers( T k8sEnv, String machineName, diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java index ab8343d4559..854394af3cf 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerExposerStrategyProvider.java @@ -31,7 +31,7 @@ public class ExternalServerExposerStrategyProvider @Inject public ExternalServerExposerStrategyProvider( - @Named("che.infra.kubernetes.server.strategy") String strategy, + @Named("che.infra.kubernetes.server_strategy") String strategy, Map strategies) { final ExternalServerExposerStrategy externalServerExposerStrategy = strategies.get(strategy); if (externalServerExposerStrategy != null) { diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java index 3e83d58b907..d38fe1a8366 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilder.java @@ -31,6 +31,11 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; /** @author Guy Daich */ + +/** + * helper class for builder ingresses. Creates an ingress with a single rule, based on hostname, + * http path. Ingress maps path to a specific service and service port. + */ public class ExternalServerIngressBuilder { private String host; diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java index 28cf52b5981..39440f57b75 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java @@ -29,6 +29,21 @@ *

This strategy uses different Ingress host entries
* Each external server is exposed with a unique subdomain of CHE_DOMAIN. * + *

+ *   Host-Based Ingress exposing service's port:
+ * Ingress
+ * ...
+ * spec:
+ *   rules:
+ *     - host: service123-webapp.che-domain   ---->> Service.metadata.name + - + Service.spec.ports[0].name + . + CHE_DOMAIN
+ *     - http:
+ *         paths:
+ *           - path: /
+ *             backend:
+ *               serviceName: service123      ---->> Service.metadata.name
+ *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
+ * 
+ * * @author Sergii Leshchenko * @author Guy Daich */ diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java index 400c865bae0..6e6c15fa76d 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java @@ -30,7 +30,21 @@ * Each external server is exposed with a unique path prefix. * *

This strategy imposes limitation on user-developed applications.
- * It should only be used for local development with a single IP adress + * It should only be used for local development with a single IP address + * + *

+ *   Path-Based Ingress exposing service's port:
+ * Ingress
+ * ...
+ * spec:
+ *   rules:
+ *     - http:
+ *         paths:
+ *           - path: service123/webapp        ---->> Service.metadata.name + / + Service.spec.ports[0].name
+ *             backend:
+ *               serviceName: service123      ---->> Service.metadata.name
+ *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
+ * 
* * @author Sergii Leshchenko * @author Guy Daich diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java index 49bfbdebbbb..878afe7d1f6 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/KubernetesServerExposer.java @@ -88,35 +88,6 @@ * Then, a server exposer strategy is used to expose one of the service's ports, to outside of the * cluster. Currently, Host-Based and Path-Based Ingresses can be used to expose service ports. * - *
- *   Path-Based Ingress exposing service's port:
- * Ingress
- * ...
- * spec:
- *   rules:
- *     - http:
- *         paths:
- *           - path: service123/webapp        ---->> Service.metadata.name + / + Service.spec.ports[0].name
- *             backend:
- *               serviceName: service123      ---->> Service.metadata.name
- *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
- * 
- * - *
- *   Host-Based Ingress exposing service's port:
- * Ingress
- * ...
- * spec:
- *   rules:
- *     - host: service123-webapp.che-domain   ---->> Service.metadata.name + - + Service.spec.ports[0].name
- *     - http:
- *         paths:
- *           - path: /
- *             backend:
- *               serviceName: service123      ---->> Service.metadata.name
- *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
- * 
- * *

For accessing publicly accessible server user will use ingress host or its load balancer IP. * For accessing workspace-wide accessible server user will use service name. Information about * servers that are exposed by ingress and/or service are stored in annotations of a ingress or diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilderTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilderTest.java new file mode 100644 index 00000000000..08929b39eb3 --- /dev/null +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/ExternalServerIngressBuilderTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.util.Collections.singletonMap; +import static org.testng.Assert.*; + +import com.google.common.collect.ImmutableMap; +import io.fabric8.kubernetes.api.model.extensions.HTTPIngressPath; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import java.util.Map; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +/** @author Guy Daich */ +public class ExternalServerIngressBuilderTest { + + private static final Map ATTRIBUTES_MAP = singletonMap("key", "value"); + private static final ServerConfig SERVER_CONFIG = + new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); + Map SERVERS = ImmutableMap.of("http-server", SERVER_CONFIG); + private static final Map ANNOTATIONS = + singletonMap("annotation-key", "annotation-value"); + private static final String MACHINE_NAME = "machine"; + private static final String NAME = "IngressName"; + private static final String SERVICE_NAME = "ServiceName"; + private static final String SERVICE_PORT = "server-port"; + + ExternalServerIngressBuilder externalServerIngressBuilder; + + @BeforeMethod + public void setUp() throws Exception { + this.externalServerIngressBuilder = new ExternalServerIngressBuilder(); + } + + @Test + public void shouldCreateIngress() { + // given + final String path = "/path/to/server"; + final String host = "host-to-server"; + + // when + Ingress ingress = + externalServerIngressBuilder + .withPath(path) + .withHost(host) + .withAnnotations(ANNOTATIONS) + .withMachineName(MACHINE_NAME) + .withName(NAME) + .withServers(SERVERS) + .withServiceName(SERVICE_NAME) + .withServicePort(SERVICE_PORT) + .build(); + + // then + AssertIngressSpec(path, host, ingress); + } + + @Test + public void shouldCreateIngressWithNoPath() { + // given + final String host = "host-to-server"; + + // when + Ingress ingress = + externalServerIngressBuilder + .withHost(host) + .withAnnotations(ANNOTATIONS) + .withMachineName(MACHINE_NAME) + .withName(NAME) + .withServers(SERVERS) + .withServiceName(SERVICE_NAME) + .withServicePort(SERVICE_PORT) + .build(); + + // then + AssertIngressSpec(null, host, ingress); + } + + @Test + public void shouldCreateIngressWithNoHost() { + // given + final String path = "/path/to/server"; + + // when + Ingress ingress = + externalServerIngressBuilder + .withPath(path) + .withAnnotations(ANNOTATIONS) + .withMachineName(MACHINE_NAME) + .withName(NAME) + .withServers(SERVERS) + .withServiceName(SERVICE_NAME) + .withServicePort(SERVICE_PORT) + .build(); + + // then + AssertIngressSpec(path, null, ingress); + } + + private void AssertIngressSpec(String path, String host, Ingress ingress) { + assertEquals(ingress.getSpec().getRules().get(0).getHost(), host); + HTTPIngressPath httpIngressPath = + ingress.getSpec().getRules().get(0).getHttp().getPaths().get(0); + assertEquals(httpIngressPath.getPath(), path); + assertEquals(httpIngressPath.getBackend().getServiceName(), SERVICE_NAME); + assertEquals(httpIngressPath.getBackend().getServicePort().getStrVal(), SERVICE_PORT); + + assertEquals(ingress.getMetadata().getName(), NAME); + assertTrue(ingress.getMetadata().getAnnotations().containsKey("annotation-key")); + assertEquals(ingress.getMetadata().getAnnotations().get("annotation-key"), "annotation-value"); + + Annotations.Deserializer ingressAnnotations = + Annotations.newDeserializer(ingress.getMetadata().getAnnotations()); + Map servers = ingressAnnotations.servers(); + ServerConfig serverConfig = servers.get("http-server"); + assertEquals(serverConfig, SERVER_CONFIG); + + assertEquals(ingressAnnotations.machineName(), MACHINE_NAME); + } +} diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisioner.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisioner.java index 1f503442a83..6533c4ea6ac 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisioner.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisioner.java @@ -22,8 +22,8 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.EnvVarsConverter; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.limits.ram.RamLimitProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.restartpolicy.RestartPolicyRewriter; +import org.eclipse.che.workspace.infrastructure.kubernetes.provision.server.ServersConverter; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; -import org.eclipse.che.workspace.infrastructure.openshift.provision.OpenShiftServersConverter; import org.eclipse.che.workspace.infrastructure.openshift.provision.OpenShiftUniqueNamesProvisioner; import org.eclipse.che.workspace.infrastructure.openshift.provision.RouteTlsProvisioner; @@ -41,7 +41,7 @@ public class OpenShiftEnvironmentProvisioner { private final WorkspaceVolumesStrategy volumesStrategy; private final UniqueNamesProvisioner uniqueNamesProvisioner; private final RouteTlsProvisioner routeTlsProvisioner; - private final OpenShiftServersConverter openShiftServersConverter; + private final ServersConverter serversConverter; private final EnvVarsConverter envVarsConverter; private final RestartPolicyRewriter restartPolicyRewriter; private final RamLimitProvisioner ramLimitProvisioner; @@ -53,7 +53,7 @@ public OpenShiftEnvironmentProvisioner( @Named("che.infra.kubernetes.pvc.enabled") boolean pvcEnabled, OpenShiftUniqueNamesProvisioner uniqueNamesProvisioner, RouteTlsProvisioner routeTlsProvisioner, - OpenShiftServersConverter openShiftServersConverter, + ServersConverter serversConverter, EnvVarsConverter envVarsConverter, RestartPolicyRewriter restartPolicyRewriter, WorkspaceVolumesStrategy volumesStrategy, @@ -64,7 +64,7 @@ public OpenShiftEnvironmentProvisioner( this.volumesStrategy = volumesStrategy; this.uniqueNamesProvisioner = uniqueNamesProvisioner; this.routeTlsProvisioner = routeTlsProvisioner; - this.openShiftServersConverter = openShiftServersConverter; + this.serversConverter = serversConverter; this.envVarsConverter = envVarsConverter; this.restartPolicyRewriter = restartPolicyRewriter; this.ramLimitProvisioner = ramLimitProvisioner; @@ -81,7 +81,7 @@ public void provision(OpenShiftEnvironment osEnv, RuntimeIdentity identity) } // 2 stage - converting Che model env to OpenShift env - openShiftServersConverter.provision(osEnv, identity); + serversConverter.provision(osEnv, identity); envVarsConverter.provision(osEnv, identity); if (pvcEnabled) { volumesStrategy.provision(osEnv, identity); diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java deleted file mode 100644 index e92dc89a523..00000000000 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/OpenShiftServersConverter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.workspace.infrastructure.openshift.provision; - -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.PodSpec; -import java.util.Map; -import javax.inject.Inject; -import javax.inject.Singleton; -import org.eclipse.che.api.core.model.workspace.config.ServerConfig; -import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; -import org.eclipse.che.api.workspace.server.spi.InfrastructureException; -import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig; -import org.eclipse.che.workspace.infrastructure.kubernetes.Names; -import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ConfigurationProvisioner; -import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; -import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; -import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer; - -/** - * Converts {@link ServerConfig} to OpenShift related objects to add a server into OpenShift - * runtime. - * - *

Adds OpenShift objects by calling {@link OpenShiftServerExposer#expose(Map)} on each machine - * with servers. - * - * @author Alexander Garagatyi - */ -@Singleton -public class OpenShiftServersConverter implements ConfigurationProvisioner { - - ExternalServerExposerStrategy openshiftExternalServerExposer; - - @Inject - public OpenShiftServersConverter(ExternalServerExposerStrategy externalServerExposerStrategy) { - this.openshiftExternalServerExposer = externalServerExposerStrategy; - } - - @Override - public void provision(OpenShiftEnvironment osEnv, RuntimeIdentity identity) - throws InfrastructureException { - - for (Pod podConfig : osEnv.getPods().values()) { - final PodSpec podSpec = podConfig.getSpec(); - for (Container containerConfig : podSpec.getContainers()) { - String machineName = Names.machineName(podConfig, containerConfig); - InternalMachineConfig machineConfig = osEnv.getMachines().get(machineName); - if (!machineConfig.getServers().isEmpty()) { - OpenShiftServerExposer openShiftServerExposer = - new OpenShiftServerExposer( - openshiftExternalServerExposer, machineName, podConfig, containerConfig, osEnv); - openShiftServerExposer.expose(machineConfig.getServers()); - } - } - } - } -} diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java index 8bf6d0b72c3..2bdf9577ad4 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftExternalServerExposer.java @@ -14,6 +14,7 @@ import static java.util.stream.Collectors.toMap; import io.fabric8.kubernetes.api.model.IntOrString; +import io.fabric8.kubernetes.api.model.Service; import io.fabric8.kubernetes.api.model.ServicePort; import io.fabric8.openshift.api.model.Route; import java.util.Map; @@ -23,8 +24,67 @@ import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; /** + * Helps to modify {@link OpenShiftEnvironment} to make servers that are configured by {@link + * ServerConfig} publicly or workspace-wide accessible. + * + *

To make server accessible it is needed to make sure that container port is declared, create + * {@link Service}. To make it also publicly accessible it is needed to create corresponding {@link + * Route} for exposing this port. + * + *

Created services and routes will have serialized servers which are exposed by the + * corresponding object and machine name to which these servers belongs to. + * + *

Container, service and route are linked in the following way: + * + *

+ * Pod
+ * metadata:
+ *   labels:
+ *     type: web-app
+ * spec:
+ *   containers:
+ *   ...
+ *   - ports:
+ *     - containerPort: 8080
+ *       name: web-app
+ *       protocol: TCP
+ *   ...
+ * 
+ * + * Then services expose containers ports in the following way: + * + *
+ * Service
+ * metadata:
+ *   name: service123
+ * spec:
+ *   selector:                        ---->> Pod.metadata.labels
+ *     type: web-app
+ *   ports:
+ *     - name: web-app
+ *       port: 8080
+ *       targetPort: [8080|web-app]   ---->> Pod.spec.ports[0].[containerPort|name]
+ *       protocol: TCP                ---->> Pod.spec.ports[0].protocol
+ * 
+ * + * Then corresponding route expose one of the service's port: + * + *
+ * Route
+ * ...
+ * spec:
+ *   to:
+ *     name: dev-machine              ---->> Service.metadata.name
+ *     targetPort: [8080|web-app]     ---->> Service.spec.ports[0].[port|name]
+ * 
+ * + *

For accessing publicly accessible server user will use route host. For accessing + * workspace-wide accessible server user will use service name. Information about servers that are + * exposed by route and/or service are stored in annotations of a route or service. + * * @author Sergii Leshchenko * @author Alexander Garagatyi + * @see Annotations */ public class OpenShiftExternalServerExposer implements ExternalServerExposerStrategy { diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java index 3b83ede1dab..ee2d4199a10 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java @@ -13,9 +13,7 @@ import io.fabric8.kubernetes.api.model.Container; import io.fabric8.kubernetes.api.model.Pod; import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServicePort; import io.fabric8.openshift.api.model.Route; -import java.util.Map; import org.eclipse.che.api.core.model.workspace.config.ServerConfig; import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; @@ -88,21 +86,12 @@ public class OpenShiftServerExposer extends KubernetesServerExposer { public OpenShiftServerExposer( - ExternalServerExposerStrategy OpenshiftExternalServerExposerStrategy, + ExternalServerExposerStrategy openshiftExternalServerExposerStrategy, String machineName, Pod pod, Container container, OpenShiftEnvironment kubernetesEnvironment) { super( - OpenshiftExternalServerExposerStrategy, machineName, pod, container, kubernetesEnvironment); - } - - @Override - protected void exposeExternalServers( - String serviceName, - Map portToServicePort, - Map externalServers) { - kubernetesExternalServerExposerStrategy.exposeExternalServers( - kubernetesEnvironment, machineName, serviceName, portToServicePort, externalServers); + openshiftExternalServerExposerStrategy, machineName, pod, container, kubernetesEnvironment); } } diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisionerTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisionerTest.java index 20ab71b96ea..d97ecb19279 100644 --- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisionerTest.java +++ b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftEnvironmentProvisionerTest.java @@ -20,8 +20,8 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.EnvVarsConverter; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.limits.ram.RamLimitProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.restartpolicy.RestartPolicyRewriter; +import org.eclipse.che.workspace.infrastructure.kubernetes.provision.server.ServersConverter; import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; -import org.eclipse.che.workspace.infrastructure.openshift.provision.OpenShiftServersConverter; import org.eclipse.che.workspace.infrastructure.openshift.provision.OpenShiftUniqueNamesProvisioner; import org.eclipse.che.workspace.infrastructure.openshift.provision.RouteTlsProvisioner; import org.mockito.InOrder; @@ -46,7 +46,7 @@ public class OpenShiftEnvironmentProvisionerTest { @Mock private RuntimeIdentity runtimeIdentity; @Mock private RouteTlsProvisioner tlsRouteProvisioner; @Mock private EnvVarsConverter envVarsProvisioner; - @Mock private OpenShiftServersConverter serversProvisioner; + @Mock private ServersConverter serversProvisioner; @Mock private RestartPolicyRewriter restartPolicyRewriter; @Mock private RamLimitProvisioner ramLimitProvisioner; @Mock private LogsVolumeMachineProvisioner logsVolumeMachineProvisioner; From d451c140605c4ec025ce4fa63db1cf8336cccdb7 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Mon, 26 Feb 2018 20:14:20 +0200 Subject: [PATCH 04/12] begin tls for path-based k8s infra Signed-off-by: Guy Daich --- dockerfiles/init/modules/che-kubernetes-helm/readme.md | 6 ++++++ .../che-kubernetes-helm/templates/certificate.yaml | 8 ++++---- .../che-kubernetes-helm/templates/configmap.yaml | 10 ++++++++++ .../che-kubernetes-helm/templates/deployment.yaml | 10 ++++++++++ .../modules/che-kubernetes-helm/templates/ingress.yaml | 10 ++++------ .../init/modules/che-kubernetes-helm/values.yaml | 4 ++-- .../provision/ExternalServerIngressTlsProvisioner.java | 8 ++++++++ 7 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java diff --git a/dockerfiles/init/modules/che-kubernetes-helm/readme.md b/dockerfiles/init/modules/che-kubernetes-helm/readme.md index 440b692758e..e415cab38b6 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/readme.md +++ b/dockerfiles/init/modules/che-kubernetes-helm/readme.md @@ -45,7 +45,13 @@ The context of the commands below is the directory in which this readme file res helm upgrade --install --namespace che --set cheDomain= --set isHostBased=false ./ ``` master url: ``http://`` + +- TLS (only path based): + ``` + helm install --name stable/cert-manager + helm upgrade --install che --namespace che --set global.cheDomain=che..xip.io --set global.tlsEnabled=true --set global.isHostBased=false ./ + ``` ## Deleting a Deployment You can delete a deployment using the following command: ``` bash diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml index dc93da99cc4..de2bdf286c1 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml @@ -4,16 +4,16 @@ kind: Certificate metadata: name: che-host-cert spec: - secretName: che-tls + secretName: {{ .Values.tlsSecretName }} issuerRef: name: letsencrypt - commonName: {{ .Values.cheDomain }} + commonName: {{ template "cheHost" . }} dnsNames: - - {{ .Values.cheDomain }} + - {{ template "cheHost" . }} acme: config: - http01: ingressClass: nginx domains: - - {{ .Values.cheDomain }} + - {{ template "cheHost" . }} {{- end }} diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml index 4423ac2e70d..4ff68ec4f32 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml @@ -24,7 +24,17 @@ data: CHE_INFRA_KUBERNETES_OAUTH__TOKEN: "" CHE_INFRA_KUBERNETES_PASSWORD: "" CHE_INFRA_KUBERNETES_USERNAME: "" +{{- if .Values.isHostBased }} CHE_INFRA_KUBERNETES_NAMESPACE: "" +{{- else }} + CHE_INFRA_KUBERNETES_NAMESPACE: "che" +{{- end }} +{{- if .Values.tlsEnabled }} + CHE_INFRA_KUBERNETES_TLS__ENABLED: "true" +{{- else }} + CHE_INFRA_KUBERNETES_TLS__ENABLED: "false" +{{- end }} + CHE_INFRA_KUBERNETES_TLS__SECRET: {{ .Values.tlsSecretName }} CHE_INFRA_KUBERNETES_TRUST__CERTS: "false" CHE_INFRA_KUBERNETES_PVC_STRATEGY: "common" CHE_INFRA_KUBERNETES_PVC_PRECREATE__SUBPATHS: "false" diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml index b498d79ed80..0f8a0e22c48 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml @@ -116,6 +116,16 @@ spec: configMapKeyRef: key: CHE_INFRA_KUBERNETES_USERNAME name: che + - name: CHE_INFRA_KUBERNETES_TLS__ENABLED + valueFrom: + configMapKeyRef: + key: CHE_INFRA_KUBERNETES_TLS__ENABLED + name: che + - name: CHE_INFRA_KUBERNETES_TLS__SECRET + valueFrom: + configMapKeyRef: + key: CHE_INFRA_KUBERNETES_TLS__SECRET + name: che - name: CHE_INFRA_KUBERNETES_NAMESPACE valueFrom: configMapKeyRef: diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml index fb7ce7abfd2..f777a6df5c9 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml @@ -17,15 +17,13 @@ spec: tls: - hosts: - {{ template "cheHost" . }} - secretName: che-tls + secretName: {{ .Values.tlsSecretName }} {{- end }} rules: - - http: + - host: {{ template "cheHost" . }} + http: paths: - backend: serviceName: che-host servicePort: 8080 - path: / -{{- if .Values.isHostBased }} - host: {{ template "cheHost" . }} -{{- end }} + path: / \ No newline at end of file diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml index 14c2370f4bb..513e31a2c84 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml @@ -1,7 +1,7 @@ cheDomain: 192.168.99.100.nip.io isHostBased: true tlsEnabled: false - +tlsSecretName: che-tls # the following section is for secure registries. when uncommented, a pull secret will be created #registry: # host: my-secure-private-registry.com @@ -9,4 +9,4 @@ tlsEnabled: false # password: myPass cheImage: eclipse/che-server:nightly -cheImagePullPolicy: Always +cheImagePullPolicy: Always \ No newline at end of file diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java new file mode 100644 index 00000000000..f45c1fb90d7 --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java @@ -0,0 +1,8 @@ +package org.eclipse.che.workspace.infrastructure.kubernetes.provision; + +/** + * Created by I313632 on 26/02/2018. + */ +public class ExternalServerIngressTlsProvisioner { + +} From d28892f149e68e896e8624b4907fd4429f7b9834 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Tue, 27 Feb 2018 15:28:35 +0200 Subject: [PATCH 05/12] continue k8s tls support Signed-off-by: Guy Daich --- .../webapp/WEB-INF/classes/che/che.properties | 2 +- .../templates/configmap.yaml | 4 +- .../templates/ingress.yaml | 2 +- .../openshift/files/scripts/che-config | 2 +- .../KubernetesEnvironmentProvisioner.java | 7 +- .../ExternalServerIngressTlsProvisioner.java | 86 ++++++++++++++++++- .../KubernetesEnvironmentProvisionerTest.java | 9 +- ...ternalServerIngressTlsProvisionerTest.java | 48 +++++++++++ .../provision/RouteTlsProvisioner.java | 2 +- 9 files changed, 152 insertions(+), 10 deletions(-) create mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java diff --git a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties index c76703f5cab..6a40c72bfb8 100644 --- a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties +++ b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties @@ -425,7 +425,7 @@ che.infra.kubernetes.pod.security_context.fs_group=NULL che.infra.openshift.project= # Create routes with Transport Layer Security (TLS) enabled -che.infra.openshift.tls_enabled=false +che.infra.kubernetes.tls_enabled=false # Single port mode wildcard domain host & port. nip.io is used by default diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml index 4ff68ec4f32..dafc31303e6 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml @@ -50,9 +50,9 @@ data: JAVA_OPTS: "-XX:MaxRAMFraction=2 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true -Xms20m " CHE_WORKSPACE_AUTO_START: "false" {{- if .Values.tlsEnabled }} - CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "true","kubernetes.io/tls-acme": "true","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' + CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "true","kubernetes.io/tls-acme": "true","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- else }} - CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' + CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- end }} {{- if .Values.isHostBased }} CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "host" diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml index f777a6df5c9..3046cc1eceb 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml @@ -3,7 +3,7 @@ kind: Ingress metadata: name: che-ingress annotations: - nginx.ingress.kubernetes.io/rewrite-target: / + #nginx.ingress.kubernetes.io/rewrite-target: "/" kubernetes.io/ingress.class: "nginx" {{- if .Values.tlsEnabled }} kubernetes.io/tls-acme: "true" diff --git a/dockerfiles/init/modules/openshift/files/scripts/che-config b/dockerfiles/init/modules/openshift/files/scripts/che-config index d5b23f80a2a..abd8e6eecfb 100644 --- a/dockerfiles/init/modules/openshift/files/scripts/che-config +++ b/dockerfiles/init/modules/openshift/files/scripts/che-config @@ -14,7 +14,7 @@ CHE_INFRA_KUBERNETES_PASSWORD: ${CHE_INFRA_KUBERNETES_PASSWORD} CHE_INFRA_OPENSHIFT_PROJECT: ${CHE_INFRA_OPENSHIFT_PROJECT} CHE_INFRA_KUBERNETES_PVC_STRATEGY: ${CHE_INFRA_KUBERNETES_PVC_STRATEGY} CHE_INFRA_KUBERNETES_PVC_PRECREATE__SUBPATHS: ${CHE_INFRA_KUBERNETES_PVC_PRECREATE__SUBPATHS} -CHE_INFRA_OPENSHIFT_TLS__ENABLED: ${ENABLE_SSL} +CHE_INFRA_KUBERNETES_TLS__ENABLED: ${ENABLE_SSL} CHE_INFRA_KUBERNETES_TRUST__CERTS: "false" CHE_INFRA_KUBERNETES_USERNAME: ${CHE_INFRA_KUBERNETES_USERNAME} CHE_KEYCLOAK_AUTH__SERVER__URL: ${CHE_KEYCLOAK_AUTH__SERVER__URL} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java index 66d42c48d63..543c509ae68 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java @@ -17,6 +17,7 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; +import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ExternalServerIngressTlsProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.InstallerServersPortProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.LogsVolumeMachineProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.SecurityContextProvisioner; @@ -46,6 +47,7 @@ public class KubernetesEnvironmentProvisioner { private final InstallerServersPortProvisioner installerServersPortProvisioner; private final LogsVolumeMachineProvisioner logsVolumeMachineProvisioner; private final SecurityContextProvisioner securityContextProvisioner; + private final ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner; @Inject public KubernetesEnvironmentProvisioner( @@ -58,7 +60,8 @@ public KubernetesEnvironmentProvisioner( RamLimitProvisioner ramLimitProvisioner, InstallerServersPortProvisioner installerServersPortProvisioner, LogsVolumeMachineProvisioner logsVolumeMachineProvisioner, - SecurityContextProvisioner securityContextProvisioner) { + SecurityContextProvisioner securityContextProvisioner, + ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner) { this.pvcEnabled = pvcEnabled; this.volumesStrategy = volumesStrategy; this.uniqueNamesProvisioner = uniqueNamesProvisioner; @@ -69,6 +72,7 @@ public KubernetesEnvironmentProvisioner( this.installerServersPortProvisioner = installerServersPortProvisioner; this.logsVolumeMachineProvisioner = logsVolumeMachineProvisioner; this.securityContextProvisioner = securityContextProvisioner; + this.externalServerIngressTlsProvisioner = externalServerIngressTlsProvisioner; } public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) @@ -90,6 +94,7 @@ public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) restartPolicyRewriter.provision(k8sEnv, identity); uniqueNamesProvisioner.provision(k8sEnv, identity); ramLimitProvisioner.provision(k8sEnv, identity); + externalServerIngressTlsProvisioner.provision(k8sEnv, identity); securityContextProvisioner.provision(k8sEnv, identity); } } diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java index f45c1fb90d7..088d0407a20 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java @@ -1,8 +1,90 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ package org.eclipse.che.workspace.infrastructure.kubernetes.provision; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import io.fabric8.kubernetes.api.model.extensions.IngressTLS; +import io.fabric8.kubernetes.api.model.extensions.IngressTLSBuilder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; +import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; +import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; +import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; + /** - * Created by I313632 on 26/02/2018. + * Enables Transport Layer Security (TLS) for external server ingresses + * + * @author Guy Daich */ -public class ExternalServerIngressTlsProvisioner { +public class ExternalServerIngressTlsProvisioner + implements ConfigurationProvisioner { + + protected final boolean isTlsEnabled; + protected final String tlsSecret; + protected final String cheHost; + + @Inject + public ExternalServerIngressTlsProvisioner( + @Named("che.infra.kubernetes.tls_enabled") boolean isTlsEnabled, + @Named("che.infra.kubernetes.tls_secret") String tlsSecret, + @Named("che.host") String cheHost) { + this.isTlsEnabled = isTlsEnabled; + this.cheHost = cheHost; + this.tlsSecret = tlsSecret; + } + + @Override + public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) + throws KubernetesInfrastructureException { + if (!isTlsEnabled) { + return; + } + + Collection ingresses = k8sEnv.getIngresses().values(); + for (Ingress ingress : ingresses) { + useSecureProtocolForServers(ingress); + enableTLS(ingress); + } + } + + private void enableTLS(Ingress ingress) { + IngressTLS ingressTLS = + new IngressTLSBuilder().withHosts(cheHost).withSecretName(tlsSecret).build(); + List ingressTLSList = new ArrayList<>(Arrays.asList(ingressTLS)); + ingress.getSpec().setTls(ingressTLSList); + } + + private void useSecureProtocolForServers(final Ingress ingress) { + Map servers = + Annotations.newDeserializer(ingress.getMetadata().getAnnotations()).servers(); + + servers.values().forEach(s -> s.setProtocol(getSecureProtocol(s.getProtocol()))); + + Map annotations = Annotations.newSerializer().servers(servers).annotations(); + + ingress.getMetadata().getAnnotations().putAll(annotations); + } + private String getSecureProtocol(final String protocol) { + if ("ws".equals(protocol)) { + return "wss"; + } else if ("http".equals(protocol)) { + return "https"; + } else return protocol; + } } diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java index 2e91492862f..1e07583c855 100644 --- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java @@ -16,6 +16,7 @@ import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; +import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ExternalServerIngressTlsProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.InstallerServersPortProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.LogsVolumeMachineProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.SecurityContextProvisioner; @@ -50,6 +51,7 @@ public class KubernetesEnvironmentProvisionerTest { @Mock private RamLimitProvisioner ramLimitProvisioner; @Mock private LogsVolumeMachineProvisioner logsVolumeMachineProvisioner; @Mock private SecurityContextProvisioner securityContextProvisioner; + @Mock private ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner; private KubernetesEnvironmentProvisioner osInfraProvisioner; @@ -68,7 +70,8 @@ public void setUp() { ramLimitProvisioner, installerServersPortProvisioner, logsVolumeMachineProvisioner, - securityContextProvisioner); + securityContextProvisioner, + externalServerIngressTlsProvisioner); provisionOrder = inOrder( installerServersPortProvisioner, @@ -79,6 +82,7 @@ public void setUp() { envVarsProvisioner, restartPolicyRewriter, ramLimitProvisioner, + externalServerIngressTlsProvisioner, securityContextProvisioner); } @@ -96,6 +100,9 @@ public void performsOrderedProvisioning() throws Exception { provisionOrder.verify(restartPolicyRewriter).provision(eq(k8sEnv), eq(runtimeIdentity)); provisionOrder.verify(uniqueNamesProvisioner).provision(eq(k8sEnv), eq(runtimeIdentity)); provisionOrder.verify(ramLimitProvisioner).provision(eq(k8sEnv), eq(runtimeIdentity)); + provisionOrder + .verify(externalServerIngressTlsProvisioner) + .provision(eq(k8sEnv), eq(runtimeIdentity)); provisionOrder.verify(securityContextProvisioner).provision(eq(k8sEnv), eq(runtimeIdentity)); provisionOrder.verifyNoMoreInteractions(); } diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java new file mode 100644 index 00000000000..a68620f1400 --- /dev/null +++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.provision; + +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.mockito.Mock; +import org.mockito.testng.MockitoTestNGListener; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +/** + * Tests {@link ExternalServerIngressTlsProvisioner}. + * + * @author Ilya Buziuk + * @author Sergii Leshchenko + * @author Guy Daich + */ +@Listeners(MockitoTestNGListener.class) +public class ExternalServerIngressTlsProvisionerTest { + + @Mock private KubernetesEnvironment k8sEnv; + @Mock private RuntimeIdentity runtimeIdentity; + + @Test + public void doNothingWhenTlsDisabled() throws Exception { + // given + ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner = + new ExternalServerIngressTlsProvisioner(false, "", ""); + + // when + externalServerIngressTlsProvisioner.provision(k8sEnv, runtimeIdentity); + + // then + verify(k8sEnv, never()).getIngresses(); + } +} diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/RouteTlsProvisioner.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/RouteTlsProvisioner.java index 9653dccc416..dc319d5108a 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/RouteTlsProvisioner.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/provision/RouteTlsProvisioner.java @@ -39,7 +39,7 @@ public class RouteTlsProvisioner implements ConfigurationProvisioner Date: Tue, 6 Mar 2018 13:58:45 +0200 Subject: [PATCH 06/12] Add single-host strategy, cert-manager support Signed-off-by: Guy Daich --- .../templates/staging-cert-issuer.yaml | 17 --- ...aultHostIngressExternalServerExposer.java} | 0 ...ultiHostIngressExternalServerExposer.java} | 0 ...ingleHostIngressExternalServerExposer.java | 111 ++++++++++++++++++ 4 files changed, 111 insertions(+), 17 deletions(-) delete mode 100644 dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml rename infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/{IngressPathExternalServerExposer.java => DefaultHostIngressExternalServerExposer.java} (100%) rename infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/{IngressHostExternalServerExposer.java => MultiHostIngressExternalServerExposer.java} (100%) create mode 100644 infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml deleted file mode 100644 index 82dfd66f730..00000000000 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# {{- if .Values.tlsEnabled }} -# apiVersion: certmanager.k8s.io/v1alpha1 -# kind: Issuer -# metadata: -# name: letsencrypt-staging -# spec: -# acme: -# # The ACME server URL -# server: https://acme-staging.api.letsencrypt.org/directory -# # Email address used for ACME registration -# email: eyal.barlev@sap.com -# # Name of a secret used to store the ACME account private key -# privateKeySecretRef: -# name: letsencrypt-staging -# # Enable the HTTP-01 challenge provider -# http01: {} -# {{- end }} diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java similarity index 100% rename from infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposer.java rename to infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java similarity index 100% rename from infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposer.java rename to infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java new file mode 100644 index 00000000000..04ffd3c43ea --- /dev/null +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2012-2018 Red Hat, Inc. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + */ +package org.eclipse.che.workspace.infrastructure.kubernetes.server; + +import static java.lang.Integer.parseInt; +import static java.util.stream.Collectors.toMap; + +import io.fabric8.kubernetes.api.model.ServicePort; +import io.fabric8.kubernetes.api.model.extensions.Ingress; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Named; +import org.eclipse.che.api.core.model.workspace.config.ServerConfig; +import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provides a path-based strategy for exposing service ports outside the cluster using Ingress + * Ingresses will be created without an explicit host (defaulting to *). + * + *

This strategy uses different Ingress path entries
+ * Each external server is exposed with a unique path prefix. + * + *

This strategy imposes limitation on user-developed applications.
+ * It should only be used for local development with a single IP address + * + *

+ *   Path-Based Ingress exposing service's port:
+ * Ingress
+ * ...
+ * spec:
+ *   rules:
+ *     - http:
+ *         paths:
+ *           - path: service123/webapp        ---->> Service.metadata.name + / + Service.spec.ports[0].name
+ *             backend:
+ *               serviceName: service123      ---->> Service.metadata.name
+ *               servicePort: [8080|web-app]  ---->> Service.spec.ports[0].[port|name]
+ * 
+ * + * @author Sergii Leshchenko + * @author Guy Daich + */ +public class DefaultHostIngressExternalServerExposer + implements ExternalServerExposerStrategy { + + public static final String DEFAULT_HOST_STRATEGY = "default-host"; + private final Map ingressAnnotations; + private static final Logger LOG = LoggerFactory.getLogger(DefaultHostIngressExternalServerExposer.class); + + @Inject + public DefaultHostIngressExternalServerExposer( + @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations) { + if (ingressAnnotations == null) { + LOG.warn( + "Ingresses annotations are absent. Make sure that workspace ingresses don't need " + + "to be configured according to ingress controller."); + } + this.ingressAnnotations = ingressAnnotations; + } + + @Override + public void exposeExternalServers( + KubernetesEnvironment k8sEnv, + String machineName, + String serviceName, + Map portToServicePort, + Map externalServers) { + + for (ServicePort servicePort : portToServicePort.values()) { + int port = servicePort.getTargetPort().getIntVal(); + + Map ingressesServers = + externalServers + .entrySet() + .stream() + .filter(e -> parseInt(e.getValue().getPort().split("/")[0]) == port) + .collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + + Ingress ingress = + new ExternalServerIngressBuilder() + .withPath(generateExternalServerIngressPath(serviceName, servicePort)) + .withName(generateExternalServerIngressName(serviceName, servicePort)) + .withMachineName(machineName) + .withServiceName(serviceName) + .withAnnotations(ingressAnnotations) + .withServicePort(servicePort.getName()) + .withServers(ingressesServers) + .build(); + + k8sEnv.getIngresses().put(ingress.getMetadata().getName(), ingress); + } + } + + private String generateExternalServerIngressName(String serviceName, ServicePort servicePort) { + return serviceName + '-' + servicePort.getName(); + } + + private String generateExternalServerIngressPath(String serviceName, ServicePort servicePort) { + return "/" + serviceName + "/" + servicePort.getName(); + } +} From c2db0f56cdbdbf9b3201b127af9956acf5f99e22 Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Tue, 6 Mar 2018 19:27:59 +0200 Subject: [PATCH 07/12] fix charts, add single-host strategy, add TLS test Signed-off-by: Guy Daich --- .../modules/che-kubernetes-helm/readme.md | 62 ++++++++-- .../templates/_hostHelper.tpl | 8 +- .../templates/cert-issuer.yaml | 8 +- .../templates/certificate.yaml | 6 +- .../templates/configmap.yaml | 32 +++--- .../templates/deployment.yaml | 10 +- .../templates/ingress.yaml | 23 ++-- .../modules/che-kubernetes-helm/values.yaml | 21 +++- .../KubernetesEnvironmentProvisioner.java | 6 +- .../kubernetes/KubernetesInfraModule.java | 21 +++- ...sioner.java => IngressTlsProvisioner.java} | 13 +-- ...faultHostIngressExternalServerExposer.java | 10 +- ...MultiHostIngressExternalServerExposer.java | 11 +- ...ingleHostIngressExternalServerExposer.java | 21 ++-- .../KubernetesEnvironmentProvisionerTest.java | 4 +- ...ternalServerIngressTlsProvisionerTest.java | 48 -------- .../provision/IngressTlsProvisionerTest.java | 106 ++++++++++++++++++ ...HostIngressExternalServerExposerTest.java} | 12 +- ...HostIngressExternalServerExposerTest.java} | 12 +- 19 files changed, 281 insertions(+), 153 deletions(-) rename infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/{ExternalServerIngressTlsProvisioner.java => IngressTlsProvisioner.java} (89%) delete mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java create mode 100644 infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisionerTest.java rename infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/{IngressPathExternalServerExposerTest.java => DefaultHostIngressExternalServerExposerTest.java} (95%) rename infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/{IngressHostExternalServerExposerTest.java => MultiHostIngressExternalServerExposerTest.java} (95%) diff --git a/dockerfiles/init/modules/che-kubernetes-helm/readme.md b/dockerfiles/init/modules/che-kubernetes-helm/readme.md index e415cab38b6..785bc9e4455 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/readme.md +++ b/dockerfiles/init/modules/che-kubernetes-helm/readme.md @@ -17,7 +17,7 @@ In production, you should specify a hostname (see [here](https://github.com/eclipse/che/issues/8694) why). In case you don't have a hostname (e.g. during development), and would still want to use a host-based configuration, you can use services such as nip.io or xip.io. -In case you're specifying a hostname, simply pass it as the value of the `cheDomain` parameter below. +In case you're specifying a hostname, simply pass it as the value of the `ingressDomain` parameter below. If you must use an ip address (e.g. your corporate policy prevents you from using nip.io), you would also have to set `isHostBased` to `false`. @@ -32,26 +32,64 @@ The context of the commands below is the directory in which this readme file res - Or, you can override default values during installation, using the `--set` flag: ```bash - helm upgrade --install --namespace --set cheDomain= --set cheImage= ./ + helm upgrade --install --namespace --set global.ingressDomain= --set cheImage= ./ ``` -- Local Host-Based (wildcard DNS) installation: +#### Deployment Options + +##### Routing + +- No Hostname + +All Ingress specs are created without a host attribute (defaults to *). + ```bash - helm upgrade --install --namespace che --set cheDomain=che..xip.io ./ + helm upgrade --install --namespace che --set global.ingressDomain= --set global.serverStrategy=default-host ./ + Master: http:/// + Workspace servers: http:/// + Keycloak: http:///auth/ ``` - master url: ``http://master.che..xip.io`` -- Local Path-Based installation: +- Single Host + +All Ingress specs are created with the same host. Path based routing. +Can be used in conjunction with cert-manager for TLS, with a single certificate. +Useful for development and testing in cloud environments. + ```bash - helm upgrade --install --namespace che --set cheDomain= --set isHostBased=false ./ + helm upgrade --install --namespace --set global.ingressDomain=.xip.io --set global.serverStrategy=single-host ./ + Master: http://che..xip.io/ + Workspaces servers: http://che..xip.io/ + Keycloak: http://che..xip.io/auth/ ``` - master url: ``http://`` -- TLS (only path based): - +- Multiple Hosts +helm upgrade --install che --namespace che --set global.ingressDomain=che.192.168.99.100.xip.io --set global.serverStrategy=multi-host --set cheImage=guydaich/che-server:tls ./ +All Ingress specs are created with a unique host. +Host based routing. + + ```bash + helm upgrade --install --namespace --set global.ingressDomain=.xip.io --set global.serverStrategy=multi-host ./ + Master: http://master..xip.io + Workspaces: http://..xip.io + Keycloak: http://keycloak..xip.io/ ``` + +##### TLS + +- Cert-Manager + +Currently, limited to Single Host routing. + +helm upgrade --install che --namespace che --set global.ingressDomain= --set global.serverStrategy=single-host --set global.cheNamespace=che --set global.tls.enabled=true --set global.tls.useStaging=false --set cheImage=guydaich/che-server:tls ./ + + ```bash helm install --name stable/cert-manager - helm upgrade --install che --namespace che --set global.cheDomain=che..xip.io --set global.tlsEnabled=true --set global.isHostBased=false ./ - ``` + helm upgrade --install che --namespace che --set global.ingressDomain= --set global.tls.enabled=true --set global.serverStrategy=single-host ./ + Master: https://che.domain/ + Workspaces servers: https://che.domain/ + Keycloak: https://che.domain/auth/ + ``` + ## Deleting a Deployment You can delete a deployment using the following command: ``` bash diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl b/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl index ce8ef5bb40c..e5d0b2063c7 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl @@ -1,7 +1,9 @@ {{- define "cheHost" }} -{{- if .Values.isHostBased }} -{{- printf "master.%s" .Values.cheDomain }} +{{- if eq .Values.global.serverStrategy "default-host" }} +{{- printf "%s" .Values.global.ingressDomain }} +{{- else if eq .Values.global.serverStrategy "single-host" }} +{{- printf "che.%s" .Values.global.ingressDomain }} {{- else }} -{{- printf "%s" .Values.cheDomain }} +{{- printf "master.%s" .Values.global.ingressDomain }} {{- end }} {{- end }} diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml index 17b1f44cd81..7c62a17f8fd 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml @@ -1,4 +1,5 @@ -{{- if .Values.tlsEnabled }} +{{- if and .Values.global.tls }} +{{- if and .Values.global.tls.enabled .Values.global.tls.useCertManager }} apiVersion: certmanager.k8s.io/v1alpha1 kind: Issuer metadata: @@ -6,7 +7,11 @@ metadata: spec: acme: # The ACME server URL +{{- if .Values.global.tls.useStaging }} + server: https://acme-staging.api.letsencrypt.org/directory +{{- else }} server: https://acme-v01.api.letsencrypt.org/directory +{{- end }} # Email address used for ACME registration email: eyal.barlev@sap.com # Name of a secret used to store the ACME account private key @@ -15,3 +20,4 @@ spec: # Enable the HTTP-01 challenge provider http01: {} {{- end }} +{{- end }} \ No newline at end of file diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml index de2bdf286c1..08cbc1d2193 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml @@ -1,10 +1,11 @@ -{{- if .Values.tlsEnabled }} +{{- if and .Values.global.tls }} +{{- if and .Values.global.tls.enabled .Values.global.tls.useCertManager }} apiVersion: certmanager.k8s.io/v1alpha1 kind: Certificate metadata: name: che-host-cert spec: - secretName: {{ .Values.tlsSecretName }} + secretName: {{ .Values.global.tls.secretName }} issuerRef: name: letsencrypt commonName: {{ template "cheHost" . }} @@ -17,3 +18,4 @@ spec: domains: - {{ template "cheHost" . }} {{- end }} +{{- end }} \ No newline at end of file diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml index dafc31303e6..cc00cfd075b 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml @@ -5,10 +5,9 @@ metadata: app: che name: che data: - CHE_DOMAIN: {{ .Values.cheDomain }} CHE_HOST: {{ template "cheHost" . }} CHE_PORT: "8080" -{{- if .Values.tlsEnabled }} +{{- if and .Values.global.tls .Values.global.tls.enabled }} CHE_API: https://{{ template "cheHost" . }}/api CHE_WEBSOCKET_ENDPOINT: wss://{{ template "cheHost" . }}/api/websocket CHE_INFRA_KUBERNETES_BOOTSTRAPPER_BINARY__URL: https://{{ template "cheHost" . }}/agent-binaries/linux_amd64/bootstrapper/bootstrapper @@ -18,23 +17,21 @@ data: CHE_INFRA_KUBERNETES_BOOTSTRAPPER_BINARY__URL: http://{{ template "cheHost" . }}/agent-binaries/linux_amd64/bootstrapper/bootstrapper {{- end }} CHE_DEBUG_SERVER: "true" - CHE_INFRASTRUCTURE_ACTIVE: kubernetes + CHE_INFRASTRUCTURE_ACTIVE: "kubernetes" + CHE_INFRA_KUBERNETES_INGRESS_DOMAIN: {{ .Values.global.ingressDomain }} CHE_INFRA_KUBERNETES_MACHINE__START__TIMEOUT__MIN: "5" CHE_INFRA_KUBERNETES_MASTER__URL: "" CHE_INFRA_KUBERNETES_OAUTH__TOKEN: "" CHE_INFRA_KUBERNETES_PASSWORD: "" CHE_INFRA_KUBERNETES_USERNAME: "" -{{- if .Values.isHostBased }} - CHE_INFRA_KUBERNETES_NAMESPACE: "" -{{- else }} - CHE_INFRA_KUBERNETES_NAMESPACE: "che" -{{- end }} -{{- if .Values.tlsEnabled }} - CHE_INFRA_KUBERNETES_TLS__ENABLED: "true" + CHE_INFRA_KUBERNETES_NAMESPACE: {{ .Values.global.cheNamespace }} +{{- if and .Values.global.tls .Values.global.tls.enabled }} + CHE_INFRA_KUBERNETES_TLS__ENABLED: {{ .Values.global.tls.enabled }} + CHE_INFRA_KUBERNETES_TLS__SECRET: {{ .Values.global.tls.secretName }} {{- else }} CHE_INFRA_KUBERNETES_TLS__ENABLED: "false" + CHE_INFRA_KUBERNETES_TLS__SECRET: "" {{- end }} - CHE_INFRA_KUBERNETES_TLS__SECRET: {{ .Values.tlsSecretName }} CHE_INFRA_KUBERNETES_TRUST__CERTS: "false" CHE_INFRA_KUBERNETES_PVC_STRATEGY: "common" CHE_INFRA_KUBERNETES_PVC_PRECREATE__SUBPATHS: "false" @@ -49,15 +46,12 @@ data: CHE_PREDEFINED_STACKS_RELOAD__ON__START: "false" JAVA_OPTS: "-XX:MaxRAMFraction=2 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Dsun.zip.disableMemoryMapping=true -Xms20m " CHE_WORKSPACE_AUTO_START: "false" -{{- if .Values.tlsEnabled }} - CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "true","kubernetes.io/tls-acme": "true","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' +{{- if .Values.global.tls.enabled }} + CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "kubernetes.io/tls-acme": "true", "{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/rewrite-target": "/","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect": "true","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-connect-timeout": "3600","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- else }} - CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "nginx.ingress.kubernetes.io/rewrite-target": "/","nginx.ingress.kubernetes.io/ssl-redirect": "false","nginx.ingress.kubernetes.io/proxy-connect-timeout": "3600","nginx.ingress.kubernetes.io/proxy-read-timeout": "3600"}' -{{- end }} -{{- if .Values.isHostBased }} - CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "host" -{{- else }} - CHE_INFRA_KUBERNETES_SERVER__STRATEGY: "path" + CHE_INFRA_KUBERNETES_INGRESS_ANNOTATIONS__JSON: '{"kubernetes.io/ingress.class": "nginx", "{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/rewrite-target": "/","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect": "false","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-connect-timeout": "3600","{{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-read-timeout": "3600"}' {{- end }} + CHE_INFRA_KUBERNETES_SERVER__STRATEGY: {{ .Values.global.serverStrategy }} + diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml index 0f8a0e22c48..85cb4cb7a3e 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/deployment.yaml @@ -21,11 +21,6 @@ spec: spec: containers: - env: - - name: CHE_DOMAIN - valueFrom: - configMapKeyRef: - key: CHE_DOMAIN - name: che - name: CHE_HOST valueFrom: configMapKeyRef: @@ -56,6 +51,11 @@ spec: configMapKeyRef: key: CHE_INFRASTRUCTURE_ACTIVE name: che + - name: CHE_INFRA_KUBERNETES_INGRESS_DOMAIN + valueFrom: + configMapKeyRef: + key: CHE_INFRA_KUBERNETES_INGRESS_DOMAIN + name: che - name: CHE_INFRA_KUBERNETES_BOOTSTRAPPER_BINARY__URL valueFrom: configMapKeyRef: diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml index 3046cc1eceb..daf6b8d7ef6 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml @@ -3,27 +3,30 @@ kind: Ingress metadata: name: che-ingress annotations: - #nginx.ingress.kubernetes.io/rewrite-target: "/" kubernetes.io/ingress.class: "nginx" -{{- if .Values.tlsEnabled }} + {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-read-timeout: "3600" + {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-connect-timeout: "3600" +{{- if and .Values.global.tls .Values.global.tls.enabled .Values.global.tls.useCertManager }} kubernetes.io/tls-acme: "true" {{- else }} - nginx.ingress.kubernetes.io/ssl-redirect: "false" + {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect: "false" {{- end }} - ingress.kubernetes.io/proxy-read-timeout: "3600" - ingress.kubernetes.io/proxy-connect-timeout: "3600" spec: -{{- if .Values.tlsEnabled }} +{{- if .Values.global.tls.enabled }} tls: - hosts: - {{ template "cheHost" . }} - secretName: {{ .Values.tlsSecretName }} + secretName: che-tls {{- end }} rules: +{{- if ne .Values.global.serverStrategy "default-host" }} - host: {{ template "cheHost" . }} http: +{{- else }} + - http: +{{- end }} paths: - - backend: + - path: / + backend: serviceName: che-host - servicePort: 8080 - path: / \ No newline at end of file + servicePort: 8080 \ No newline at end of file diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml index 513e31a2c84..955ac9b07f7 100644 --- a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml +++ b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml @@ -1,12 +1,23 @@ -cheDomain: 192.168.99.100.nip.io -isHostBased: true -tlsEnabled: false -tlsSecretName: che-tls # the following section is for secure registries. when uncommented, a pull secret will be created #registry: # host: my-secure-private-registry.com +# host: my-secure-private-registry.com # username: myUser # password: myPass cheImage: eclipse/che-server:nightly -cheImagePullPolicy: Always \ No newline at end of file +cheImagePullPolicy: Always + +global: + cheNamespace: "" + multiuser: false + ingressDomain: 192.168.99.100.xip.io + # See --annotations-prefix flag (https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/cli-arguments.md) + ingressAnnotationsPrefix: "nginx." + # options: default-host, single-host, multi-host + serverStrategy: multi-host + tls: + enabled: false + useCertManager: true + useStaging: true + secretName: che-tls diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java index 543c509ae68..e6101e020c3 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisioner.java @@ -17,7 +17,7 @@ import org.eclipse.che.api.workspace.server.spi.InfrastructureException; import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment; import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; -import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ExternalServerIngressTlsProvisioner; +import org.eclipse.che.workspace.infrastructure.kubernetes.provision.IngressTlsProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.InstallerServersPortProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.LogsVolumeMachineProvisioner; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.SecurityContextProvisioner; @@ -47,7 +47,7 @@ public class KubernetesEnvironmentProvisioner { private final InstallerServersPortProvisioner installerServersPortProvisioner; private final LogsVolumeMachineProvisioner logsVolumeMachineProvisioner; private final SecurityContextProvisioner securityContextProvisioner; - private final ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner; + private final IngressTlsProvisioner externalServerIngressTlsProvisioner; @Inject public KubernetesEnvironmentProvisioner( @@ -61,7 +61,7 @@ public KubernetesEnvironmentProvisioner( InstallerServersPortProvisioner installerServersPortProvisioner, LogsVolumeMachineProvisioner logsVolumeMachineProvisioner, SecurityContextProvisioner securityContextProvisioner, - ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner) { + IngressTlsProvisioner externalServerIngressTlsProvisioner) { this.pvcEnabled = pvcEnabled; this.volumesStrategy = volumesStrategy; this.uniqueNamesProvisioner = uniqueNamesProvisioner; diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java index 4c0a002d53f..93db3b0a91f 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java @@ -12,8 +12,9 @@ import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.CommonPVCStrategy.COMMON_STRATEGY; import static org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.UniqueWorkspacePVCStrategy.UNIQUE_STRATEGY; -import static org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressHostExternalServerExposer.HOST_STRATEGY; -import static org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressPathExternalServerExposer.PATH_STRATEGY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.DefaultHostIngressExternalServerExposer.DEFAULT_HOST_STRATEGY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.MultiHostIngressExternalServerExposer.MULTI_HOST_STRATEGY; +import static org.eclipse.che.workspace.infrastructure.kubernetes.server.SingleHostIngressExternalServerExposer.SINGLE_HOST_STRATEGY; import com.google.inject.AbstractModule; import com.google.inject.TypeLiteral; @@ -38,11 +39,12 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.KubernetesCheApiEnvVarProvider; import org.eclipse.che.workspace.infrastructure.kubernetes.provision.env.LogsRootEnvVariableProvider; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.DefaultHostIngressExternalServerExposer; import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy; import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategyProvider; import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressAnnotationsProvider; -import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressHostExternalServerExposer; -import org.eclipse.che.workspace.infrastructure.kubernetes.server.IngressPathExternalServerExposer; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.MultiHostIngressExternalServerExposer; +import org.eclipse.che.workspace.infrastructure.kubernetes.server.SingleHostIngressExternalServerExposer; /** @author Sergii Leshchenko */ public class KubernetesInfraModule extends AbstractModule { @@ -73,8 +75,15 @@ protected void configure() { MapBinder ingressStrategies = MapBinder.newMapBinder(binder(), String.class, ExternalServerExposerStrategy.class); - ingressStrategies.addBinding(HOST_STRATEGY).to(IngressHostExternalServerExposer.class); - ingressStrategies.addBinding(PATH_STRATEGY).to(IngressPathExternalServerExposer.class); + ingressStrategies + .addBinding(MULTI_HOST_STRATEGY) + .to(MultiHostIngressExternalServerExposer.class); + ingressStrategies + .addBinding(SINGLE_HOST_STRATEGY) + .to(SingleHostIngressExternalServerExposer.class); + ingressStrategies + .addBinding(DEFAULT_HOST_STRATEGY) + .to(DefaultHostIngressExternalServerExposer.class); bind(ExternalServerExposerStrategy.class) .toProvider(ExternalServerExposerStrategyProvider.class); diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java similarity index 89% rename from infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java rename to infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java index 088d0407a20..4a78e254999 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisioner.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java @@ -31,20 +31,16 @@ * * @author Guy Daich */ -public class ExternalServerIngressTlsProvisioner - implements ConfigurationProvisioner { +public class IngressTlsProvisioner implements ConfigurationProvisioner { protected final boolean isTlsEnabled; protected final String tlsSecret; - protected final String cheHost; @Inject - public ExternalServerIngressTlsProvisioner( + public IngressTlsProvisioner( @Named("che.infra.kubernetes.tls_enabled") boolean isTlsEnabled, - @Named("che.infra.kubernetes.tls_secret") String tlsSecret, - @Named("che.host") String cheHost) { + @Named("che.infra.kubernetes.tls_secret") String tlsSecret) { this.isTlsEnabled = isTlsEnabled; - this.cheHost = cheHost; this.tlsSecret = tlsSecret; } @@ -63,8 +59,9 @@ public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity) } private void enableTLS(Ingress ingress) { + String host = ingress.getSpec().getRules().get(0).getHost(); IngressTLS ingressTLS = - new IngressTLSBuilder().withHosts(cheHost).withSecretName(tlsSecret).build(); + new IngressTLSBuilder().withHosts(host).withSecretName(tlsSecret).build(); List ingressTLSList = new ArrayList<>(Arrays.asList(ingressTLS)); ingress.getSpec().setTls(ingressTLSList); } diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java index 6e6c15fa76d..e7c07be8b96 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposer.java @@ -25,6 +25,7 @@ /** * Provides a path-based strategy for exposing service ports outside the cluster using Ingress + * Ingresses will be created without an explicit host (defaulting to *). * *

This strategy uses different Ingress path entries
* Each external server is exposed with a unique path prefix. @@ -49,15 +50,16 @@ * @author Sergii Leshchenko * @author Guy Daich */ -public class IngressPathExternalServerExposer +public class DefaultHostIngressExternalServerExposer implements ExternalServerExposerStrategy { - public static final String PATH_STRATEGY = "path"; + public static final String DEFAULT_HOST_STRATEGY = "default-host"; private final Map ingressAnnotations; - private static final Logger LOG = LoggerFactory.getLogger(IngressPathExternalServerExposer.class); + private static final Logger LOG = + LoggerFactory.getLogger(DefaultHostIngressExternalServerExposer.class); @Inject - public IngressPathExternalServerExposer( + public DefaultHostIngressExternalServerExposer( @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations) { if (ingressAnnotations == null) { LOG.warn( diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java index 39440f57b75..380f4cf9a6b 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposer.java @@ -47,18 +47,19 @@ * @author Sergii Leshchenko * @author Guy Daich */ -public class IngressHostExternalServerExposer +public class MultiHostIngressExternalServerExposer implements ExternalServerExposerStrategy { - public static final String HOST_STRATEGY = "host"; + public static final String MULTI_HOST_STRATEGY = "multi-host"; private final String domain; private final Map ingressAnnotations; - private static final Logger LOG = LoggerFactory.getLogger(IngressHostExternalServerExposer.class); + private static final Logger LOG = + LoggerFactory.getLogger(MultiHostIngressExternalServerExposer.class); @Inject - public IngressHostExternalServerExposer( + public MultiHostIngressExternalServerExposer( @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations, - @Named("che.domain") String domain) { + @Named("che.infra.kubernetes.ingress.domain") String domain) { if (ingressAnnotations == null) { LOG.warn( "Ingresses annotations are absent. Make sure that workspace ingresses don't need " diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java index 04ffd3c43ea..1ce9832d718 100644 --- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java +++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/SingleHostIngressExternalServerExposer.java @@ -25,13 +25,12 @@ /** * Provides a path-based strategy for exposing service ports outside the cluster using Ingress - * Ingresses will be created without an explicit host (defaulting to *). + * Ingresses will be created with a common host name for all workspaces. * *

This strategy uses different Ingress path entries
* Each external server is exposed with a unique path prefix. * *

This strategy imposes limitation on user-developed applications.
- * It should only be used for local development with a single IP address * *

  *   Path-Based Ingress exposing service's port:
@@ -39,7 +38,8 @@
  * ...
  * spec:
  *   rules:
- *     - http:
+ *     - host: CHE_HOST
+ *       http:
  *         paths:
  *           - path: service123/webapp        ---->> Service.metadata.name + / + Service.spec.ports[0].name
  *             backend:
@@ -50,22 +50,26 @@
  * @author Sergii Leshchenko
  * @author Guy Daich
  */
-public class DefaultHostIngressExternalServerExposer
+public class SingleHostIngressExternalServerExposer
     implements ExternalServerExposerStrategy {
 
-  public static final String DEFAULT_HOST_STRATEGY = "default-host";
+  public static final String SINGLE_HOST_STRATEGY = "single-host";
   private final Map ingressAnnotations;
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultHostIngressExternalServerExposer.class);
+  private final String cheHost;
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SingleHostIngressExternalServerExposer.class);
 
   @Inject
-  public DefaultHostIngressExternalServerExposer(
-      @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations) {
+  public SingleHostIngressExternalServerExposer(
+      @Named("infra.kubernetes.ingress.annotations") Map ingressAnnotations,
+      @Named("che.host") String cheHost) {
     if (ingressAnnotations == null) {
       LOG.warn(
           "Ingresses annotations are absent. Make sure that workspace ingresses don't need "
               + "to be configured according to ingress controller.");
     }
     this.ingressAnnotations = ingressAnnotations;
+    this.cheHost = cheHost;
   }
 
   @Override
@@ -88,6 +92,7 @@ public void exposeExternalServers(
 
       Ingress ingress =
           new ExternalServerIngressBuilder()
+              .withHost(cheHost)
               .withPath(generateExternalServerIngressPath(serviceName, servicePort))
               .withName(generateExternalServerIngressName(serviceName, servicePort))
               .withMachineName(machineName)
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java
index 1e07583c855..e121f36d942 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesEnvironmentProvisionerTest.java
@@ -16,7 +16,7 @@
 import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
 import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
 import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.pvc.WorkspaceVolumesStrategy;
-import org.eclipse.che.workspace.infrastructure.kubernetes.provision.ExternalServerIngressTlsProvisioner;
+import org.eclipse.che.workspace.infrastructure.kubernetes.provision.IngressTlsProvisioner;
 import org.eclipse.che.workspace.infrastructure.kubernetes.provision.InstallerServersPortProvisioner;
 import org.eclipse.che.workspace.infrastructure.kubernetes.provision.LogsVolumeMachineProvisioner;
 import org.eclipse.che.workspace.infrastructure.kubernetes.provision.SecurityContextProvisioner;
@@ -51,7 +51,7 @@ public class KubernetesEnvironmentProvisionerTest {
   @Mock private RamLimitProvisioner ramLimitProvisioner;
   @Mock private LogsVolumeMachineProvisioner logsVolumeMachineProvisioner;
   @Mock private SecurityContextProvisioner securityContextProvisioner;
-  @Mock private ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner;
+  @Mock private IngressTlsProvisioner externalServerIngressTlsProvisioner;
 
   private KubernetesEnvironmentProvisioner osInfraProvisioner;
 
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java
deleted file mode 100644
index a68620f1400..00000000000
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/ExternalServerIngressTlsProvisionerTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2012-2018 Red Hat, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Red Hat, Inc. - initial API and implementation
- */
-package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
-
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
-import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
-import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
-import org.mockito.Mock;
-import org.mockito.testng.MockitoTestNGListener;
-import org.testng.annotations.Listeners;
-import org.testng.annotations.Test;
-
-/**
- * Tests {@link ExternalServerIngressTlsProvisioner}.
- *
- * @author Ilya Buziuk
- * @author Sergii Leshchenko
- * @author Guy Daich
- */
-@Listeners(MockitoTestNGListener.class)
-public class ExternalServerIngressTlsProvisionerTest {
-
-  @Mock private KubernetesEnvironment k8sEnv;
-  @Mock private RuntimeIdentity runtimeIdentity;
-
-  @Test
-  public void doNothingWhenTlsDisabled() throws Exception {
-    // given
-    ExternalServerIngressTlsProvisioner externalServerIngressTlsProvisioner =
-        new ExternalServerIngressTlsProvisioner(false, "", "");
-
-    // when
-    externalServerIngressTlsProvisioner.provision(k8sEnv, runtimeIdentity);
-
-    // then
-    verify(k8sEnv, never()).getIngresses();
-  }
-}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisionerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisionerTest.java
new file mode 100644
index 00000000000..7874406c391
--- /dev/null
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisionerTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertEquals;
+
+import com.google.common.collect.ImmutableMap;
+import io.fabric8.kubernetes.api.model.extensions.Ingress;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
+import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations;
+import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
+import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerIngressBuilder;
+import org.mockito.Mock;
+import org.mockito.testng.MockitoTestNGListener;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/**
+ * Tests {@link IngressTlsProvisioner}.
+ *
+ * @author Ilya Buziuk
+ * @author Sergii Leshchenko
+ * @author Guy Daich
+ */
+@Listeners(MockitoTestNGListener.class)
+public class IngressTlsProvisionerTest {
+
+  @Mock private KubernetesEnvironment k8sEnv;
+  @Mock private RuntimeIdentity runtimeIdentity;
+
+  @Test
+  public void doNothingWhenTlsDisabled() throws Exception {
+    // given
+    IngressTlsProvisioner ingressTlsProvisioner = new IngressTlsProvisioner(false, "");
+
+    // when
+    ingressTlsProvisioner.provision(k8sEnv, runtimeIdentity);
+
+    // then
+    verify(k8sEnv, never()).getIngresses();
+  }
+
+  @Test
+  public void provisionTlsForRoutes() throws Exception {
+    // given
+    IngressTlsProvisioner ingressTlsProvisioner = new IngressTlsProvisioner(true, "");
+
+    Map attributesMap = singletonMap("key", "value");
+    ServerConfigImpl httpServer = new ServerConfigImpl("8080/tpc", "http", "/api", emptyMap());
+    ServerConfigImpl wsServer = new ServerConfigImpl("8080/tpc", "ws", "/ws", emptyMap());
+    Map servers =
+        ImmutableMap.of("http-server", httpServer, "ws-server", wsServer);
+    Map annotations = singletonMap("annotation-key", "annotation-value");
+    String machine = "machine";
+    String name = "IngressName";
+    String serviceName = "ServiceName";
+    String servicePort = "server-port";
+    String host = "server-host";
+
+    final Map ingresses = new HashMap<>();
+
+    ExternalServerIngressBuilder externalServerIngressBuilder = new ExternalServerIngressBuilder();
+    Ingress ingress =
+        externalServerIngressBuilder
+            .withHost(host)
+            .withAnnotations(annotations)
+            .withMachineName(machine)
+            .withName(name)
+            .withServers(servers)
+            .withServiceName(serviceName)
+            .withServicePort(servicePort)
+            .build();
+    ingresses.put("ingress", ingress);
+    when(k8sEnv.getIngresses()).thenReturn(ingresses);
+
+    // when
+    ingressTlsProvisioner.provision(k8sEnv, runtimeIdentity);
+
+    // then
+    assertEquals(ingress.getSpec().getTls().size(), 1);
+    assertEquals(ingress.getSpec().getTls().get(0).getHosts().size(), 1);
+    assertEquals(ingress.getSpec().getTls().get(0).getHosts().get(0), host);
+
+    Map ingressServers =
+        Annotations.newDeserializer(ingress.getMetadata().getAnnotations()).servers();
+    assertEquals(ingressServers.get("http-server").getProtocol(), "https");
+    assertEquals(ingressServers.get("ws-server").getProtocol(), "wss");
+  }
+}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposerTest.java
similarity index 95%
rename from infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java
rename to infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposerTest.java
index 9b52698d6d2..eb7d4c3b00c 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressPathExternalServerExposerTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/DefaultHostIngressExternalServerExposerTest.java
@@ -35,13 +35,13 @@
 import org.testng.annotations.Test;
 
 /** @author Guy Daich */
-public class IngressPathExternalServerExposerTest {
+public class DefaultHostIngressExternalServerExposerTest {
 
   private static final Map ATTRIBUTES_MAP = singletonMap("key", "value");
   public static final String MACHINE_NAME = "pod/main";
   public static final String SERVICE_NAME = SERVER_PREFIX + "12345678" + "-" + MACHINE_NAME;
 
-  private IngressPathExternalServerExposer pathExternalServerExposer;
+  private DefaultHostIngressExternalServerExposer externalServerExposer;
   private KubernetesEnvironment kubernetesEnvironment;
   private Container container;
 
@@ -60,7 +60,7 @@ public void setUp() throws Exception {
 
     kubernetesEnvironment =
         KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build();
-    pathExternalServerExposer = new IngressPathExternalServerExposer(emptyMap());
+    externalServerExposer = new DefaultHostIngressExternalServerExposer(emptyMap());
   }
 
   @Test
@@ -79,7 +79,7 @@ public void shouldCreateIngressForServer() {
     Map serversToExpose = ImmutableMap.of("http-server", httpServerConfig);
 
     // when
-    pathExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then
@@ -115,7 +115,7 @@ public void shouldCreateIngressForServerWhenTwoServersHasTheSamePort() {
             "ws-server", wsServerConfig);
 
     // when
-    pathExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then
@@ -168,7 +168,7 @@ public void shouldCreateIngressesForServerWhenTwoServersHasDifferentPorts() {
             "ws-server", wsServerConfig);
 
     // when
-    pathExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposerTest.java
similarity index 95%
rename from infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java
rename to infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposerTest.java
index fdb9e737588..a3ab6507bef 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/IngressHostExternalServerExposerTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/server/MultiHostIngressExternalServerExposerTest.java
@@ -35,14 +35,14 @@
 import org.testng.annotations.Test;
 
 /** @author Guy Daich */
-public class IngressHostExternalServerExposerTest {
+public class MultiHostIngressExternalServerExposerTest {
 
   private static final Map ATTRIBUTES_MAP = singletonMap("key", "value");
   public static final String MACHINE_NAME = "pod/main";
   public static final String SERVICE_NAME = SERVER_PREFIX + "12345678" + "-" + MACHINE_NAME;
   public static final String DOMAIN = "che.com";
 
-  private IngressHostExternalServerExposer hostExternalServerExposer;
+  private MultiHostIngressExternalServerExposer externalServerExposer;
   private KubernetesEnvironment kubernetesEnvironment;
   private Container container;
 
@@ -61,7 +61,7 @@ public void setUp() throws Exception {
 
     kubernetesEnvironment =
         KubernetesEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build();
-    hostExternalServerExposer = new IngressHostExternalServerExposer(emptyMap(), DOMAIN);
+    externalServerExposer = new MultiHostIngressExternalServerExposer(emptyMap(), DOMAIN);
   }
 
   @Test
@@ -81,7 +81,7 @@ public void shouldCreateIngressForServer() {
     Map serversToExpose = ImmutableMap.of("http-server", httpServerConfig);
 
     // when
-    hostExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then
@@ -119,7 +119,7 @@ public void shouldCreateIngressForServerWhenTwoServersHasTheSamePort() {
             "ws-server", wsServerConfig);
 
     // when
-    hostExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then
@@ -174,7 +174,7 @@ public void shouldCreateIngressesForServerWhenTwoServersHasDifferentPorts() {
             "ws-server", wsServerConfig);
 
     // when
-    hostExternalServerExposer.exposeExternalServers(
+    externalServerExposer.exposeExternalServers(
         kubernetesEnvironment, MACHINE_NAME, SERVICE_NAME, portToServicePort, serversToExpose);
 
     // then

From cfeb1e61186d586b24ba337136a0344c165eba15 Mon Sep 17 00:00:00 2001
From: Eyal Barlev 
Date: Tue, 6 Mar 2018 17:57:06 +0200
Subject: [PATCH 08/12] TLS: changed cert-manager certficiate issuer to be
 ClusterIssuer

Signed-off-by: Eyal Barlev 
---
 .../modules/che-kubernetes-helm/templates/cert-issuer.yaml  | 2 +-
 .../modules/che-kubernetes-helm/templates/certificate.yaml  | 6 ++++++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml
index 7c62a17f8fd..68e4e80f751 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/cert-issuer.yaml
@@ -1,7 +1,7 @@
 {{- if and .Values.global.tls }}
 {{- if and .Values.global.tls.enabled .Values.global.tls.useCertManager }}
 apiVersion: certmanager.k8s.io/v1alpha1
-kind: Issuer
+kind: ClusterIssuer
 metadata:
   name: letsencrypt
 spec:
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
index 08cbc1d2193..ff1aec8722d 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
@@ -1,3 +1,8 @@
+# Certificates can be created automatically using cert-manager's ingress-shim:
+#   https://github.com/jetstack/cert-manager/blob/master/docs/user-guides/ingress-shim.md
+# This would simplify issuing identical certificates for workspaces residing in their own namespaces (see CHE_INFRA_KUBERNETES_NAMESPACE environment variable).
+# However, this issue prevents us from using ingress-shim in conjuction with the rewrite-rule ingress annotation:
+#   https://github.com/jetstack/cert-manager/issues/286
 {{- if and .Values.global.tls }}
 {{- if and .Values.global.tls.enabled .Values.global.tls.useCertManager }}
 apiVersion: certmanager.k8s.io/v1alpha1
@@ -8,6 +13,7 @@ spec:
   secretName: {{ .Values.global.tls.secretName }}
   issuerRef:
     name: letsencrypt
+    kind: ClusterIssuer
   commonName: {{ template "cheHost" . }}
   dnsNames:
       - {{ template "cheHost" . }}

From 7d6eb968aa3f49e5e88ee3fbb65f01f8d2dc6059 Mon Sep 17 00:00:00 2001
From: Guy Daich 
Date: Thu, 8 Mar 2018 10:26:38 +0200
Subject: [PATCH 09/12] add resolved values.yaml

Signed-off-by: Guy Daich 
---
 dockerfiles/init/modules/che-kubernetes-helm/values.yaml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml
index 955ac9b07f7..4c7ca78a76a 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/values.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/values.yaml
@@ -1,7 +1,6 @@
 # the following section is for secure registries. when uncommented, a pull secret will be created
 #registry:
 #  host: my-secure-private-registry.com
-#  host: my-secure-private-registry.com
 #  username: myUser
 #  password: myPass
 

From e25ddf10ceb7f072613040e9f75ed197d3b178e6 Mon Sep 17 00:00:00 2001
From: Guy Daich 
Date: Sat, 10 Mar 2018 18:53:13 +0200
Subject: [PATCH 10/12] Adapt to k8s Multiuser

* Add sample values files
* Fix merge issues

Signed-off-by: Guy Daich 
---
 .../che-keycloak/templates/deployment.yaml    |  3 +
 .../che-keycloak/templates/ingress.yaml       | 16 +++--
 .../che-postgres/templates/deployment.yaml    |  1 +
 .../modules/che-kubernetes-helm/readme.md     | 69 ++++++-------------
 .../templates/_hostHelper.tpl                 |  4 +-
 .../templates/_keycloakAuthUrlHelper.tpl      | 32 +++++----
 .../templates/_keycloakHostHelper.tpl         | 10 +--
 .../templates/certificate.yaml                | 35 ----------
 .../templates/configmap.yaml                  |  2 +-
 .../templates/ingress.yaml                    |  7 +-
 .../templates/staging-cert-issuer.yaml        | 24 -------
 .../values/default-host.yaml                  | 11 +++
 .../values/multi-user.yaml                    | 10 +++
 .../che-kubernetes-helm/values/tls.yaml       | 18 +++++
 .../provision/IngressTlsProvisioner.java      | 22 ++++--
 15 files changed, 126 insertions(+), 138 deletions(-)
 delete mode 100644 dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
 delete mode 100644 dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml
 create mode 100644 dockerfiles/init/modules/che-kubernetes-helm/values/default-host.yaml
 create mode 100644 dockerfiles/init/modules/che-kubernetes-helm/values/multi-user.yaml
 create mode 100644 dockerfiles/init/modules/che-kubernetes-helm/values/tls.yaml

diff --git a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/deployment.yaml
index 6bafdd82216..dd70f84b111 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/deployment.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/deployment.yaml
@@ -46,6 +46,9 @@ spec:
         - name: CHE_HOST
           value: {{ template "cheHost" . }}
         image: {{ .Values.image }}
+        securityContext:
+          runAsUser: 0
+          fsGroup: 0
         imagePullPolicy: Always
         name: keycloak
         livenessProbe:
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/ingress.yaml b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/ingress.yaml
index 6041ab57d57..04a953cf45e 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/ingress.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-keycloak/templates/ingress.yaml
@@ -14,27 +14,33 @@ metadata:
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-read-timeout: "3600"
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-connect-timeout: "3600"
 {{- if .Values.global.tlsEnabled }}
+    {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect: "true"
     kubernetes.io/tls-acme: "true"
 {{- else }}
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect: "false"
 {{- end }}
 spec:
-{{- if .Values.global.tlsEnabled }}
+{{- if .Values.global.tls.enabled }}
   tls:
   - hosts:
     - {{ template "keycloakHost" . }}
     secretName: keycloak-tls
 {{- end }}
   rules:
-{{- if .Values.global.isHostBased }}
+{{- if eq .Values.global.serverStrategy "default-host" }}
+  - http:
+      paths:
+      - path: /auth/
+{{- else if eq .Values.global.serverStrategy "single-host" }}
   - host: {{ template "keycloakHost" . }}
     http:
       paths:
-      - path: /
+      - path: /auth/
 {{- else }}
-  - http:
+  - host: {{ template "keycloakHost" . }}
+    http:
       paths:
-      - path: /auth/
+      - path: /
 {{- end }}
         backend:
           serviceName: keycloak
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-postgres/templates/deployment.yaml b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-postgres/templates/deployment.yaml
index 5014f0391f0..5befe009e91 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/charts/che-postgres/templates/deployment.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/charts/che-postgres/templates/deployment.yaml
@@ -36,6 +36,7 @@ spec:
         image: {{ .Values.image }}
         securityContext:
           runAsUser: 26
+          fsGroup: 26
         imagePullPolicy: Always
         name: postgres
         livenessProbe:
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/readme.md b/dockerfiles/init/modules/che-kubernetes-helm/readme.md
index 7b0a8d1d2f3..8fdb86cd073 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/readme.md
+++ b/dockerfiles/init/modules/che-kubernetes-helm/readme.md
@@ -41,68 +41,43 @@ The context of the commands below is the directory in which this readme file res
 Only Che will be deployed.
 
   ```bash
-  helm upgrade --install  --namespace  --set global.ingressDomain= ./
+  helm upgrade --install  --namespace  --set global.ingressDomain= ./
   ```
   
 ##### Multi User 
 Che, KeyCloak and Postgres will be deployed.
 
   ```bash
-  helm upgrade --install  --namespace  --set global.multiuser=true --set global.ingressDomain= ./
+  helm upgrade --install  --namespace  -f ./values/multi-user.yaml --set global.ingressDomain= ./
   ```
 
-##### Routing
-
-- No Hostname 
-
-All Ingress specs are created without a host attribute (defaults to *).   
-
-  ```bash
-  helm upgrade --install  --namespace che --set global.ingressDomain=  --set global.serverStrategy=default-host ./
-      Master: http:///
-      Workspace servers: http:///
-      Keycloak: http:///auth/
-  ```
-- Single Host
-
-All Ingress specs are created with the same host. Path based routing.
-Can be used in conjunction with cert-manager for TLS, with a single certificate.
-Useful for development and testing in cloud environments.
-
+#### Default Host
+All Ingress specs are created without a host attribute (defaults to *).
+Path based routing to all components.
+Multi User configuration is enabled. 
+ 
   ```bash
-  helm upgrade --install  --namespace  --set global.ingressDomain=.xip.io --set global.serverStrategy=single-host ./
-    Master: http://che..xip.io/
-    Workspaces servers: http://che..xip.io/
-    Keycloak: http://che..xip.io/auth/
+  helm upgrade --install  --namespace  -f ./values/default-host.yaml --set global.ingressDomain= ./
   ```
+ 
+* Master: `http:///`
+* Keycloak:  `http:///auth/`
+* Workspaces servers: `http:///`
 
-- Multiple Hosts
-helm upgrade --install che --namespace che --set global.ingressDomain=che.192.168.99.100.xip.io --set global.serverStrategy=multi-host --set cheImage=guydaich/che-server:tls ./
-All Ingress specs are created with a unique host. 
-Host based routing. 
+#### TLS-enabled
+Cert-Manager is used to issue LetsEncrypt certificates.
+To avoid rate-limit issues, we use a single hostname for all ingresses.
+Path based routing to all components.
+Multi User configuration is enabled. 
 
   ```bash
-  helm upgrade --install  --namespace  --set global.ingressDomain=.xip.io --set global.serverStrategy=multi-host ./
-    Master: http://master..xip.io
-    Workspaces: http://..xip.io
-    Keycloak: http://keycloak..xip.io/
+  helm install --name  stable/cert-manager
+  helm upgrade --install  --namespace  -f ./values/tls.yaml --set global.ingressDomain= ./
   ```
 
-##### TLS
-
-- Cert-Manager
-
-Currently, limited to Single Host routing.   
-
-helm upgrade --install che --namespace che --set global.ingressDomain= --set global.serverStrategy=single-host --set global.cheNamespace=che --set global.tls.enabled=true --set global.tls.useStaging=false --set cheImage=guydaich/che-server:tls ./
-
-  ```bash
-  helm install --name  stable/cert-manager
-  helm upgrade --install che --namespace che --set global.ingressDomain= --set global.tls.enabled=true --set global.serverStrategy=single-host ./
-    Master: https://che.domain/
-    Workspaces servers: https://che.domain/
-    Keycloak: https://che.domain/auth/
-  ```    
+* Master: `https://che-.your-domain/`
+* Keycloak:  `https://che-.your-domain/auth/`
+* Workspaces servers: `https://.your-domain/`
 
 ## Deleting a Deployment
 You can delete a deployment using the following command:
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl b/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl
index e5d0b2063c7..cfaf5b0a60d 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/_hostHelper.tpl
@@ -2,8 +2,8 @@
 {{- if eq .Values.global.serverStrategy "default-host" }}
 {{- printf "%s" .Values.global.ingressDomain }}
 {{- else if eq .Values.global.serverStrategy "single-host" }}
-{{- printf "che.%s" .Values.global.ingressDomain }}
+{{- printf "che-%s.%s" .Release.Namespace .Values.global.ingressDomain }}
 {{- else }}
-{{- printf "master.%s" .Values.global.ingressDomain }}
+{{- printf "che-%s.%s" .Release.Namespace .Values.global.ingressDomain }}
 {{- end }}
 {{- end }}
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakAuthUrlHelper.tpl b/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakAuthUrlHelper.tpl
index db73ece70a7..0f2206045b1 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakAuthUrlHelper.tpl
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakAuthUrlHelper.tpl
@@ -1,15 +1,21 @@
 {{- define "keycloakAuthUrl" }}
-{{- if .Values.global.isHostBased }}
-{{- if .Values.global.tlsEnabled }}
-{{- printf "https://keycloak.%s/auth" .Values.global.cheDomain }}
-{{- else }}
-{{- printf "http://keycloak.%s/auth" .Values.global.cheDomain }}
-{{- end }}
-{{- else }}
-{{- if .Values.global.tlsEnabled }}
-{{- printf "https://%s/auth" .Values.global.cheDomain }}
-{{- else }}
-{{- printf "http://%s/auth" .Values.global.cheDomain }}
-{{- end }}
-{{- end }}
+  {{- if eq .Values.global.serverStrategy "default-host" }}
+    {{- if .Values.global.tls.enabled }}
+      {{- printf "https://%s/auth" .Values.global.ingressDomain }}
+    {{- else }}
+      {{- printf "http://%s/auth" .Values.global.ingressDomain }}
+    {{- end }}
+  {{- else if eq .Values.global.serverStrategy "single-host" }}
+    {{- if .Values.global.tls.enabled }}
+      {{- printf "https://che-%s.%s/auth" .Release.Namespace .Values.global.ingressDomain }}
+    {{- else }}
+      {{- printf "http:/che-%s./%s/auth" .Release.Namespace .Values.global.ingressDomain }}
+    {{- end }}
+  {{- else }}
+    {{- if .Values.global.tls.enabled }}
+      {{- printf "https://keycloak-%s.%s/auth" .Release.Namespace .Values.global.ingressDomain }}
+    {{- else }}
+      {{- printf "http://keycloak-%s.%s/auth" .Release.Namespace .Values.global.ingressDomain }}
+    {{- end }}
+  {{- end }}
 {{- end }}
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakHostHelper.tpl b/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakHostHelper.tpl
index 71e0654db1d..6e21748c2d4 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakHostHelper.tpl
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/_keycloakHostHelper.tpl
@@ -1,7 +1,9 @@
 {{- define "keycloakHost" }}
-{{- if .Values.global.isHostBased }}
-{{- printf "keycloak.%s" .Values.global.cheDomain }}
+{{- if eq .Values.global.serverStrategy "default-host" }}
+{{- printf "%s" .Values.global.ingressDomain }}
+{{- else if eq .Values.global.serverStrategy "single-host" }}
+{{- printf "che-%s.%s" .Release.Namespace .Values.global.ingressDomain }}
 {{- else }}
-{{- printf "%s" .Values.global.cheDomain }}
-{{- end }}
+{{- printf "keycloak-%s.%s" .Release.Namespace .Values.global.ingressDomain }}
 {{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
deleted file mode 100644
index 7cefb3f0f1a..00000000000
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/certificate.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2012-2017 Red Hat, Inc
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-
-# Certificates can be created automatically using cert-manager's ingress-shim:
-#   https://github.com/jetstack/cert-manager/blob/master/docs/user-guides/ingress-shim.md
-# This would simplify issuing identical certificates for workspaces residing in their own namespaces (see CHE_INFRA_KUBERNETES_NAMESPACE environment variable).
-# However, this issue prevents us from using ingress-shim in conjuction with the rewrite-rule ingress annotation:
-#   https://github.com/jetstack/cert-manager/issues/286
-{{- if and .Values.global.tls }}
-{{- if and .Values.global.tls.enabled .Values.global.tls.useCertManager }}
-apiVersion: certmanager.k8s.io/v1alpha1
-kind: Certificate
-metadata:
-  name: che-host-cert
-spec:
-  secretName: {{ .Values.global.tls.secretName }}
-  issuerRef:
-    name: letsencrypt
-    kind: ClusterIssuer
-  commonName: {{ template "cheHost" . }}
-  dnsNames:
-      - {{ template "cheHost" . }}
-  acme:
-    config:
-    - http01:
-        ingressClass: nginx
-      domains:
-      - {{ template "cheHost" . }}
-{{- end }}
-      - {{ .Values.global.cheDomain }}
-{{- end }}
\ No newline at end of file
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml
index 170e763b025..0f1500f5334 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/configmap.yaml
@@ -38,7 +38,7 @@ data:
 {{- end }}
   CHE_INFRA_KUBERNETES_NAMESPACE: {{ .Values.global.cheNamespace }}
 {{- if and .Values.global.tls .Values.global.tls.enabled }}
-  CHE_INFRA_KUBERNETES_TLS__ENABLED: {{ .Values.global.tls.enabled }}
+  CHE_INFRA_KUBERNETES_TLS__ENABLED: {{ .Values.global.tls.enabled | quote}}
   CHE_INFRA_KUBERNETES_TLS__SECRET: {{ .Values.global.tls.secretName }}
 {{- else }}
   CHE_INFRA_KUBERNETES_TLS__ENABLED: "false"
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml
index dd756bfb1ff..5f744f5c121 100644
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml
+++ b/dockerfiles/init/modules/che-kubernetes-helm/templates/ingress.yaml
@@ -13,11 +13,14 @@ metadata:
     kubernetes.io/ingress.class: "nginx"
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-read-timeout: "3600"
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/proxy-connect-timeout: "3600"
-{{- if and .Values.global.tls .Values.global.tls.enabled .Values.global.tls.useCertManager }}
-    kubernetes.io/tls-acme: "true"
+{{- if and .Values.global.tls .Values.global.tls.enabled }}
+    {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect: "true"
 {{- else }}
     {{ .Values.global.ingressAnnotationsPrefix }}ingress.kubernetes.io/ssl-redirect: "false"
 {{- end }}
+{{- if and .Values.global.tls .Values.global.tls.enabled .Values.global.tls.useCertManager }}
+    certmanager.k8s.io/cluster-issuer: "letsencrypt"
+{{- end }}
 spec:
 {{- if .Values.global.tls.enabled }}
   tls:
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml b/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml
deleted file mode 100644
index b8a7bcf34df..00000000000
--- a/dockerfiles/init/modules/che-kubernetes-helm/templates/staging-cert-issuer.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (c) 2012-2017 Red Hat, Inc
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-
-# {{- if .Values.global.tlsEnabled }}
-# apiVersion: certmanager.k8s.io/v1alpha1
-# kind: Issuer
-# metadata:
-#   name: letsencrypt-staging
-# spec:
-#   acme:
-#     # The ACME server URL
-#     server: https://acme-staging.api.letsencrypt.org/directory
-#     # Email address used for ACME registration
-#     email: eyal.barlev@sap.com
-#     # Name of a secret used to store the ACME account private key
-#     privateKeySecretRef:
-#       name: letsencrypt-staging
-#     # Enable the HTTP-01 challenge provider
-#     http01: {}
-# {{- end }}
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values/default-host.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values/default-host.yaml
new file mode 100644
index 00000000000..4fd514e9654
--- /dev/null
+++ b/dockerfiles/init/modules/che-kubernetes-helm/values/default-host.yaml
@@ -0,0 +1,11 @@
+# Copyright (c) 2012-2017 Red Hat, Inc
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+
+global:
+  multiuser: true
+  ingressDomain: 192.168.99.100
+  serverStrategy: default-host
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values/multi-user.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values/multi-user.yaml
new file mode 100644
index 00000000000..96e87bcbecc
--- /dev/null
+++ b/dockerfiles/init/modules/che-kubernetes-helm/values/multi-user.yaml
@@ -0,0 +1,10 @@
+# Copyright (c) 2012-2017 Red Hat, Inc
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+
+global:
+  multiuser: true
+
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values/tls.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values/tls.yaml
new file mode 100644
index 00000000000..143035bc073
--- /dev/null
+++ b/dockerfiles/init/modules/che-kubernetes-helm/values/tls.yaml
@@ -0,0 +1,18 @@
+# Copyright (c) 2012-2017 Red Hat, Inc
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+
+# Currently, TLS support is enabled only for single-host deployments
+
+global:
+  multiuser: true
+  ingressDomain: 
+  serverStrategy: single-host
+  tls:
+    enabled: true
+    useCertManager: true
+    useStaging: false
+    secretName: che-tls
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java
index 4a78e254999..5a9eadfbb57 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/provision/IngressTlsProvisioner.java
@@ -10,6 +10,8 @@
  */
 package org.eclipse.che.workspace.infrastructure.kubernetes.provision;
 
+import static com.google.common.base.Strings.isNullOrEmpty;
+
 import io.fabric8.kubernetes.api.model.extensions.Ingress;
 import io.fabric8.kubernetes.api.model.extensions.IngressTLS;
 import io.fabric8.kubernetes.api.model.extensions.IngressTLSBuilder;
@@ -34,14 +36,14 @@
 public class IngressTlsProvisioner implements ConfigurationProvisioner {
 
   protected final boolean isTlsEnabled;
-  protected final String tlsSecret;
+  protected final String tlsSecretName;
 
   @Inject
   public IngressTlsProvisioner(
       @Named("che.infra.kubernetes.tls_enabled") boolean isTlsEnabled,
-      @Named("che.infra.kubernetes.tls_secret") String tlsSecret) {
+      @Named("che.infra.kubernetes.tls_secret") String tlsSecretName) {
     this.isTlsEnabled = isTlsEnabled;
-    this.tlsSecret = tlsSecret;
+    this.tlsSecretName = tlsSecretName;
   }
 
   @Override
@@ -60,8 +62,18 @@ public void provision(KubernetesEnvironment k8sEnv, RuntimeIdentity identity)
 
   private void enableTLS(Ingress ingress) {
     String host = ingress.getSpec().getRules().get(0).getHost();
-    IngressTLS ingressTLS =
-        new IngressTLSBuilder().withHosts(host).withSecretName(tlsSecret).build();
+
+    IngressTLSBuilder ingressTLSBuilder =
+        new IngressTLSBuilder().withHosts(host).withSecretName(tlsSecretName);
+
+    // according to ingress tls spec, secret name is optional
+    // when working in single-host mode, nginx controller wil reuse the che-master secret
+    // https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/api/extensions/v1beta1/types.go
+    if (!isNullOrEmpty(tlsSecretName)) {
+      ingressTLSBuilder.withSecretName(tlsSecretName);
+    }
+
+    IngressTLS ingressTLS = ingressTLSBuilder.build();
     List ingressTLSList = new ArrayList<>(Arrays.asList(ingressTLS));
     ingress.getSpec().setTls(ingressTLSList);
   }

From b5fe1edcae123c2521fc1de98405675522a58c97 Mon Sep 17 00:00:00 2001
From: Guy Daich 
Date: Mon, 12 Mar 2018 20:20:57 +0200
Subject: [PATCH 11/12] Cleanup OpenShift Infra

* rename TLS default value in che.env
* remove openshift server exposer (consolidated with k8s)

Signed-off-by: Guy Daich 
---
 dockerfiles/init/manifests/che.env            |   7 +-
 .../modules/che-kubernetes-helm/kubeconfig    |  23 +
 .../che-kubernetes-helm/values-gardener.yaml  |  19 +
 .../openshift/files/scripts/deploy_che.sh     |   8 +-
 .../openshift/files/scripts/kubeconfig        |  68 +++
 dockerfiles/init/modules/openshift/kubeconfig |  46 ++
 .../server/OpenShiftServerExposer.java        |  97 ----
 .../server/OpenShiftServerResolver.java       |   2 +-
 .../openshift/OpenShiftServerExposerTest.java | 421 ------------------
 9 files changed, 165 insertions(+), 526 deletions(-)
 create mode 100644 dockerfiles/init/modules/che-kubernetes-helm/kubeconfig
 create mode 100644 dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml
 create mode 100644 dockerfiles/init/modules/openshift/files/scripts/kubeconfig
 create mode 100644 dockerfiles/init/modules/openshift/kubeconfig
 delete mode 100644 infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java
 delete mode 100644 infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java

diff --git a/dockerfiles/init/manifests/che.env b/dockerfiles/init/manifests/che.env
index 818d41e169d..b5ef08e5012 100644
--- a/dockerfiles/init/manifests/che.env
+++ b/dockerfiles/init/manifests/che.env
@@ -433,6 +433,10 @@ CHE_SINGLE_PORT=false
 #####                              Kubernetes Infrastructure                       #####
 #####                                                                              #####
 #
+
+# Create routes with Transport Layer Security (TLS) enabled
+CHE_INFRA_KUBERNETES_TLS_ENABLED=false
+
 #Configuration of Kubernetes client that Infra will use
 #CHE_INFRA_KUBERNETES_MASTER__URL=
 #CHE_INFRA_KUBERNETES_USERNAME=
@@ -511,9 +515,6 @@ CHE_SINGLE_PORT=false
 # If not set, every workspace will be created in a new project, where project name = workspace id
 #CHE_INFRA_OPENSHIFT_PROJECT=
 
-# Create routes with Transport Layer Security (TLS) enabled
-CHE_INFRA_OPENSHIFT_TLS_ENABLED=false
-
 
 ########################################################################################
 #####                                                                              #####
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig b/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig
new file mode 100644
index 00000000000..d8ba6a5028b
--- /dev/null
+++ b/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig
@@ -0,0 +1,23 @@
+---
+apiVersion: v1
+kind: Config
+current-context: shoot-garden-devx-che-che-6-dev
+clusters:
+- name: shoot-garden-devx-che-che-6-dev
+  cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMxekNDQWIrZ0F3SUJBZ0lRVTBYU3VFOGRvcC95OC9meEowRUoyekFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1CNFhEVEU0TURJeU9EQTRORFl4TWxvWERUSTRNREl5T0RBNApORFl4TWxvd0ZURVRNQkVHQTFVRUF4TUthM1ZpWlhKdVpYUmxjekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBT1AzVnFyM2NYbXdYMWtKZ2ozdUUyZ3haSk95dFNtNFRrbEY5UEVOaTVIK243eG4KODVoRFhYSzkyaHpjcjlmTnQvOG1XcjBlRWFYR0hId0t6b1dwQWh1K1l6d1NQSnZLZ2lTQzlOQkVrdndiQnZpegorZjhJOWtQZy9DVDRidXRnMjFRY2I0aTlvTWlVQ3RYQkZhem05QUJDWTJ1NFVZT2FRN0xBeDBzUGtkSXlURHJLCnI5SDNDNk82eTJhYzF4Vk5VWUZtK0JHT01IRzR2cWp0M3g3dDF6Q0JyR2RxQ2VpOHMzWTVwdFVUUmlqUmI0RkkKeW4vZ3piUFhLVWltRDJuMjF1K1k4VHMyUk51QUdjQjRWZElGcjlJNFFxR3kxc3BHNFppQllmNlI2bmVwTlRXawp3V1BlT1E0SlgxMDdsd3c3cEFKQU9SY0xXRDBJNWhINFVHMWNNZjhDQXdFQUFhTWpNQ0V3RGdZRFZSMFBBUUgvCkJBUURBZ0dtTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUkzeGk0Rk8KZnNjcERrZklGVmNSbWFNa3B1N08yZVo5TXQxTlk0MWxGOWF5cTQ2TE5DbU54SEFoY2ZDZU41UDZ4UEwvb05GLwo3MC9Bb2REbXVobFZpOFFmWS9Cb3RZQU90V3hxRFhPazR0cy9JQ1Z4b1VtNEJBVUR4UmlpakxRWmJ5ZURZYkd6CnJjUE8rUXhsQ2VodHhOczFqSjVYc1FiNzRDYUR3d2o1dmxFSGw2c2RGSlloek9raVh6Vlk0UDhRcGJvZG9IWUIKcTk2dWQrUEdDK1d6YXpqZ1czVFh4NitxSmhjMzlJeitBb2tRem90TWRuOG02K2RWSmp4dFBhaEdaY1dCcUs3TAprdkxhOTBiUzhNaFhYcEU3TEYzQlAyemtacGNuTDJkdis2aEU0TS9EZjNyTFFGQlJ6eUhtS2Z5STk5S3IvNFhnClhWR0p5aVV4YjFMckJUMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    server: https://api.che-6-dev.devx-che.k8s.sapcloud.io
+contexts:
+- name: shoot-garden-devx-che-che-6-dev
+  context:
+    cluster: shoot-garden-devx-che-che-6-dev
+    user: shoot-garden-devx-che-che-6-dev
+users:
+- name: shoot-garden-devx-che-che-6-dev
+  user:
+    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBRENDQWVpZ0F3SUJBZ0lSQUxUMjRmOEdMNmRFNk1nRzQwRUJOUk13RFFZSktvWklodmNOQVFFTEJRQXcKRlRFVE1CRUdBMVVFQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T0RBeU1qZ3dPRFEyTVRoYUZ3MHlPREF5TWpndwpPRFEyTVRoYU1Dc3hGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1SQXdEZ1lEVlFRREV3ZHJkV0psClkyWm5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW1ubVhnblFpbUh3azFkQ1AKaHJjQUF4bG9Yb2psWnUxVEttdjJ3OUpXemthb2J6ZGNmRGVTZDZsS3JXRG5GQy91dTBTWVp1UzRnQTVOWmRDSgpoY3RTbDlxNVFJc3UvYVYxeCs0WENMYVAxR0hvQkM1QnpWQnJNUEdLN0p3SlRhTTk1YzMrOWVCeUc3RDUwL2tUCi91QWFlbWhMVjV5WmU0YlBwYmhUYld6K2p3QW5mZ2M1UlFGNmRIN29nSGRvcUJpMGgyMCs4eUw5Nnhyb1FRdTgKbzJ4SU9nWWdpK0puVTJkSzJLWGo5N3NCVnpxWG80QjRJMk9JU3pBcmRuL29ucitQdzJpSlV2SklDQ3REbnF4ZgphckNwTnloeG5zeUNhM3pnSXY0OGxrZTdSSWlJVnVBd1o1K29TMUhoSS8vUUkzMHRJYnZOaDRXdkRPRVRlUmc2ClEvUFpad0lEQVFBQm96VXdNekFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBUk94aHQ1cFhrd2JWSVA0QgpOSzcxeUZpeWZxRVhOcEEyT1V1TUNMMDhWZ1p5TWpsU0M5NFV4K3prV3k1N2lHZHNzb1c1NkZseXYyT285aE91CmN2bE1vRmQrajdLdU42d1VONmVWQU81MW1oRUdvMkpJcVZSdVVhQWh2TUxqM0NCTnZyTzJVTVdhSmc1ZERLSnoKWlQydTZzbk1uNnlaeDNUQStiSjJVVkxBZDNiTEo4L21kQUFyUjlwdkxQbUJ4V3pFa2NPNUFkRDFLZDNtd2U0cwpqK3FVbjZTWnlnUnQ4Vk1VbC9henNlaG9QUUh3TThlWnpCTW45dGR4d1o3dzFsSjNFNzFEWlA3R0dTL3YzTTVLCmZjUlJaQ2tEUm1hcTJGbUJ3SzZJVW82WnRYNmR3Qk1ON3JQZUswQmNJbUU3TU1aaVRCcFE0bFlSRnZpREZSSWgKV01reDN3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBbW5tWGduUWltSHdrMWRDUGhyY0FBeGxvWG9qbFp1MVRLbXYydzlKV3prYW9iemRjCmZEZVNkNmxLcldEbkZDL3V1MFNZWnVTNGdBNU5aZENKaGN0U2w5cTVRSXN1L2FWMXgrNFhDTGFQMUdIb0JDNUIKelZCck1QR0s3SndKVGFNOTVjMys5ZUJ5RzdENTAva1QvdUFhZW1oTFY1eVplNGJQcGJoVGJXeitqd0FuZmdjNQpSUUY2ZEg3b2dIZG9xQmkwaDIwKzh5TDk2eHJvUVF1OG8yeElPZ1lnaStKblUyZEsyS1hqOTdzQlZ6cVhvNEI0CkkyT0lTekFyZG4vb25yK1B3MmlKVXZKSUNDdERucXhmYXJDcE55aHhuc3lDYTN6Z0l2NDhsa2U3UklpSVZ1QXcKWjUrb1MxSGhJLy9RSTMwdElidk5oNFd2RE9FVGVSZzZRL1BaWndJREFRQUJBb0lCQUJCZGQxYWp0UktRZkZxRwppTjROdnh1VThvQ3BZaHhBWWtJcFEvQkU5VnRQRXdNTlMyZ0JmeXZjTElRbnN2TnBqSkljVjBUM1VEQ0kwMXhJCjluak5MSWZYN1M1UVVIOGdxMVN0L1pTM3VvOFdmRDBOSlgxNTJwRkoxWnp4ZnU3UnIzb01FOG02cUh3VWlMTVQKUFRJUVRkM1A5TU5vWEw1QWJ2a3dpTzRiMFBBWE92TFZ5bVdSVlhIQ0xzRDU3ZEFFT1dhQ3hpWGFSQ0h0UlF1awpUVkRLNi96RXFuUTI0MXVmS2dtQTE3QTViSzBZUDRwWVZXM1RoU3Z4bkZWQVM1bGVaaVJrTGpTeERXdzZrdnI0CmllVjZ6Q05PVUU4S2huRFhUZEZqRzRIRktsQSthRnQ0WXRQT24yWjFqTTlwRllZbVBnMmpYbmljRDA5d05IcVoKMkswcnh0RUNnWUVBd3J6UlFQeEhhMnNwcXpYa2paWlh3VGRyMWFwMXhKNUJTVTJscVF1a1FWNXJIbHhRdHlNNQovRmJpeFo4TGlIRE94ZDdUWHVpYVhvSE15SEtoTEl2c2R4ZUx6K3dwV2orMTFsYXhZM0FncmRPMSs2a3hWVE1EClY3TjgrckJiWW5iRGt0RE5BS1kxcWZnbXFVV2puREF3cFV0aG5mTVJVcDRFdFp4L0Z2NTFNbzhDZ1lFQXl4STYKUFFsYXRVbVR3VC9JTGhIS0N0aXVydzhSWGlvdEJwQTg3ZWdVUDZiUmJFVWdYRWxONEg1OEs1NGx3cC9Ra1BaKwpreWlKUThPYmZzamFLd2hqMWZEOEZIcXZvWExFNEt0ZUJzZ1BQWDdjN0dvOHhIUm1qbjV3MFFuWks2aGtTOWhGCmQvRnc5RjNUbWVsczhmRUZnaUJwY2xyenVBRUFTRjlvS1hjYmQ2a0NnWUJIY1JQbm5tWHBMNkJTMG11dDBla1IKMW00Mkxkb1VydVpPcVRETVNwd1E2ejJySHJ6eDR2ZUQ3ckExUmZycUxGQi9ZUmIwYTZzdVhyb3RFM2l6cWdXdgpUekVZcjVBZ0x0MWI2K1FhRWVtN083ODR1MEtBK2owUXNLVjZKcmJ2OFpnZ1JYL2Y3Qm9sNkFidTlNQm9MWG03Ck9tTnVtZHpTRFd5MjM5bjBLcGYrV3dLQmdBYk1XMnJEcjJlMlNONEZWcHhFT0RGWXc3QlVuczQ2Tnp1ckJIOHEKYjlNWnNKVWhVMDREbmpuUHdqUnJuUFFCQ2Fod3VCZ1JHVmROYXgwNWVDUk1xWnIxOEZwM0tQNE1xNDZoN2dubwpGS3FJWHJrRGJYbGVORGk4L3VYZ29JYVhvcFB2YjVQdVgwdXZBSEI4b2dzUGVKRzhxQXNPQkc2NmlkbmlaOGhMCmxuM1JBb0dBUmVuQU1uUEpzUmUrQVJjazhwQ0lnN0JnRmM1bnQrYzBReXBnWTcxUjB2RElwMWNoTys3dWZDUFYKN3hKekRBVXlkTDBoMmxHUFRlcTZ2T0c3bzlFa2kvaW1XSUdjN0ZoSmRzRnVvNGlvVE9GbmZDNTV0bGtLWHpQbwoxaFIyRUNHZ1AzSFFjSHY2KzRnc0Q1QmNUVVR2eXA4R1BJdWlQdCsweUVqK1JhbDhVWGs9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
+- name: shoot-garden-devx-che-che-6-dev-basic-auth
+  user:
+    username: admin
+    password: mpPPLP7RqKw4Accn5oYTXfcOAvGlhAsu
\ No newline at end of file
diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml
new file mode 100644
index 00000000000..26ce84d344f
--- /dev/null
+++ b/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml
@@ -0,0 +1,19 @@
+#  helm upgrade --install che --namespace che -f ./values-gardener.yaml  ./
+
+cheImage: guydaich/che-server:routing
+cheImagePullPolicy: Always
+cheKeycloakClientId: "che-public"
+cheKeycloakRealm: "che"
+
+global:
+  cheNamespace: ""
+  multiuser: false
+  ingressDomain: ingress.che-6-dev.devx-che.k8s.sapcloud.io
+  ingressAnnotationsPrefix: ""
+  serverStrategy: single-host
+  tls:
+    enabled: true
+    useCertManager: true
+    useStaging: true
+    secretName: che-tls
+
diff --git a/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh b/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh
index df56e9478b1..95782cb7ecf 100755
--- a/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh
+++ b/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh
@@ -177,7 +177,7 @@ if [ "${OPENSHIFT_FLAVOR}" == "minishift" ]; then
   DEFAULT_CHE_DEBUG_SERVER="true"
   DEFAULT_OC_SKIP_TLS="true"
   DEFAULT_CHE_APPLY_RESOURCE_QUOTAS="false"
-  DEFAULT_IMAGE_PULL_POLICY="IfNotPresent"
+  DEFAULT_IMAGE_PULL_POLICY="Always"
   DEFAULT_ENABLE_SSL="false"
   DEFAULT_CHE_LOG_LEVEL="INFO"
   DEFAULT_CHE_PREDEFINED_STACKS_RELOAD="false"
@@ -221,14 +221,14 @@ fi
 CHE_OPENSHIFT_PROJECT=${CHE_OPENSHIFT_PROJECT:-${DEFAULT_CHE_OPENSHIFT_PROJECT}}
 DEFAULT_COMMAND="deploy"
 DEFAULT_CHE_MULTIUSER="false"
-DEFAULT_CHE_IMAGE_REPO="docker.io/eclipse/che-server"
-DEFAULT_CHE_IMAGE_TAG="nightly"
+DEFAULT_CHE_IMAGE_REPO="docker.io/guydaich/che-server"
+DEFAULT_CHE_IMAGE_TAG="routing"
 DEFAULT_CHE_KEYCLOAK_OSO_ENDPOINT="https://sso.openshift.io/auth/realms/fabric8/broker/openshift-v3/token"
 DEFAULT_KEYCLOAK_GITHUB_ENDPOINT="https://sso.openshift.io/auth/realms/fabric8/broker/github/token"
 DEFAULT_CHE_KEYCLOAK_ADMIN_REQUIRE_UPDATE_PASSWORD="true"
 
 COMMAND=${COMMAND:-${DEFAULT_COMMAND}}
-WAIT_FOR_CHE=${WAIT_FOR_CHE:-"false"}
+WAIT_FOR_CHE=${WAIT_FOR_CHE:-"true"}
 CHE_MULTIUSER=${CHE_MULTIUSER:-${DEFAULT_CHE_MULTIUSER}}
 if [ "${CHE_MULTIUSER}" == "true" ]; then
   CHE_DEDICATED_KEYCLOAK=${CHE_DEDICATED_KEYCLOAK:-"true"}
diff --git a/dockerfiles/init/modules/openshift/files/scripts/kubeconfig b/dockerfiles/init/modules/openshift/files/scripts/kubeconfig
new file mode 100644
index 00000000000..f873cccc469
--- /dev/null
+++ b/dockerfiles/init/modules/openshift/files/scripts/kubeconfig
@@ -0,0 +1,68 @@
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMVdoY05Nak13TXpFeApNVGMxTnpJMldqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE56YzBORFl3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNWbDZjZnVBQkNLVEJUeEJKcURJZloKWEI2c2VNc05sUGJGTEZHUm9mcGczMElOWXZUeUJJcU9CZ281YjlTR2s0TWZORVNVdHNZQVc1SFdlK0drcHI1cQpyQjRxejRGTnA2MzZvSS9MTTNtZVJaV0JDWCtIemtUYytCODNYU2EzUnMrSDJ3NnFUL3pvRjdCaGVmWWpGeElHCklNQ2xuT1p3Q2t3Q0FsRDI1U3MxMzZrRVRzNVBMVWxHS3c2dVdZbTlHK2VWWjJaMHhoMmh0a0VLZ2Jud09PZXQKYXAxN3ZFSnBncFg4WTAvSXp0YTJlVEdrenNob29YOW1wR1R1c3hRNU9RMU1mVUtyc1pjZThsL1dJS2pIcGZBKwpkcUU2WEx1NncvVW10NXN0bmdxVDVkTi9vQVFQZjluWTBkR1pXOXY2T2dMSzhHUlRFN1JNYmlqczBXZlRJY25wCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQXRLWVp0VzVvZlZ3cnIvcU9BdlZ2WDFyeEtPRmd2SWg4aGVZTnVlNis5OWpMYQpDNDJtOTM4SkRTS1dya3hoNzd4eHNiSm90Q1NyVTQzbW1JcnBkUldrUTY5SE16cUhFTml3Q25mOE1QMkRscDVECjhoZGhic2FGemhSc21rRFVMNFp2VldURDJ3SmZSRitxd1lXSHEybUduNkxwdHU3Smd5WUdIcjBZaHovRGJTa1kKR21hdHJQQWRaUjBzSnM3UnZDT001c3R1eGl5QmluVC96QU9oMElwVlNZMEFhSUNUU25sOEVrNlFveTJjbmhRVQpjTGQ3Z01ZcDFNL3JNQUZTRSs5OVB6c3dObUhnMVFkdS9na1ZNWS9ZWmZBRE9QM3JhODdHeFBlcFIzOGwyVVhJCmVBcDJFcmJhNXdjaHQ2NHorZSsyNjh2VHZaWUJ5OFU4YTU2a3RtUTMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    server: https://127.0.0.1:8443
+  name: 127-0-0-1:8443
+- cluster:
+    insecure-skip-tls-verify: true
+    server: https://192.168.99.103:8443
+  name: 192-168-99-103:8443
+- cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMVdoY05Nak13TXpFeApNVGMxTnpJMldqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE56YzBORFl3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNWbDZjZnVBQkNLVEJUeEJKcURJZloKWEI2c2VNc05sUGJGTEZHUm9mcGczMElOWXZUeUJJcU9CZ281YjlTR2s0TWZORVNVdHNZQVc1SFdlK0drcHI1cQpyQjRxejRGTnA2MzZvSS9MTTNtZVJaV0JDWCtIemtUYytCODNYU2EzUnMrSDJ3NnFUL3pvRjdCaGVmWWpGeElHCklNQ2xuT1p3Q2t3Q0FsRDI1U3MxMzZrRVRzNVBMVWxHS3c2dVdZbTlHK2VWWjJaMHhoMmh0a0VLZ2Jud09PZXQKYXAxN3ZFSnBncFg4WTAvSXp0YTJlVEdrenNob29YOW1wR1R1c3hRNU9RMU1mVUtyc1pjZThsL1dJS2pIcGZBKwpkcUU2WEx1NncvVW10NXN0bmdxVDVkTi9vQVFQZjluWTBkR1pXOXY2T2dMSzhHUlRFN1JNYmlqczBXZlRJY25wCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQXRLWVp0VzVvZlZ3cnIvcU9BdlZ2WDFyeEtPRmd2SWg4aGVZTnVlNis5OWpMYQpDNDJtOTM4SkRTS1dya3hoNzd4eHNiSm90Q1NyVTQzbW1JcnBkUldrUTY5SE16cUhFTml3Q25mOE1QMkRscDVECjhoZGhic2FGemhSc21rRFVMNFp2VldURDJ3SmZSRitxd1lXSHEybUduNkxwdHU3Smd5WUdIcjBZaHovRGJTa1kKR21hdHJQQWRaUjBzSnM3UnZDT001c3R1eGl5QmluVC96QU9oMElwVlNZMEFhSUNUU25sOEVrNlFveTJjbmhRVQpjTGQ3Z01ZcDFNL3JNQUZTRSs5OVB6c3dObUhnMVFkdS9na1ZNWS9ZWmZBRE9QM3JhODdHeFBlcFIzOGwyVVhJCmVBcDJFcmJhNXdjaHQ2NHorZSsyNjh2VHZaWUJ5OFU4YTU2a3RtUTMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    server: https://192.168.99.104:8443
+  name: 192-168-99-104:8443
+contexts:
+- context:
+    cluster: 192-168-99-104:8443
+    user: developer/192-168-99-104:8443
+  name: /192-168-99-104:8443/developer
+- context:
+    cluster: 127-0-0-1:8443
+    namespace: default
+    user: system:admin/127-0-0-1:8443
+  name: default/127-0-0-1:8443/system:admin
+- context:
+    cluster: 192-168-99-104:8443
+    namespace: default
+    user: system:admin/127-0-0-1:8443
+  name: default/192-168-99-104:8443/system:admin
+- context:
+    cluster: 192-168-99-103:8443
+    namespace: eclipse-che
+    user: developer/192-168-99-103:8443
+  name: eclipse-che/192-168-99-103:8443/developer
+- context:
+    cluster: 192-168-99-104:8443
+    namespace: eclipse-che
+    user: developer/192-168-99-104:8443
+  name: eclipse-che/192-168-99-104:8443/developer
+- context:
+    cluster: 192-168-99-104:8443
+    namespace: myproject
+    user: developer/192-168-99-104:8443
+  name: minishift
+- context:
+    cluster: 192-168-99-103:8443
+    namespace: myproject
+    user: developer/192-168-99-103:8443
+  name: myproject/192-168-99-103:8443/developer
+- context:
+    cluster: 192-168-99-104:8443
+    namespace: myproject
+    user: developer/192-168-99-104:8443
+  name: myproject/192-168-99-104:8443/developer
+current-context: eclipse-che/192-168-99-104:8443/developer
+kind: Config
+preferences: {}
+users:
+- name: developer/192-168-99-103:8443
+  user:
+    token: jfcILwn25kx0SJjpbBL6jbjRv8n8BvXhwQjsLabHp5M
+- name: developer/192-168-99-104:8443
+  user:
+    token: k0kpNdAtnH6hjA7AEf5Y58rWkVk2kYizcC_lLmadazM
+- name: system:admin/127-0-0-1:8443
+  user:
+    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQnpBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMldoY05NakF3TXpFeApNVGMxTnpJM1dqQTNNUjR3SEFZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNSbGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQUtWdmFZN3RXak0vQzR5TnVtakRwTUZkT1hKbzFRWUkrQ1Bpc090T1JKRVZWcndXdmMyTysyMDJYUDFDR2FmegpuQjVjeXgwOHVwUlFRZ1FnazZvOWVBVG9zY3dEUXl1WDBwRkg2Ymxxc3JUdGg1dS9mWVRGeWs1ZUFVNzVzcklCCjV2Ti9HVGpKS0hpYmVYSG5hb0s1dE0vMm1TVmhIUzNieHpDRS8yemR6ZHJkRHBPc214MFc1clNnbjM5M2NQTzUKd3lvNkNPT3I5V1pXNjRtcVRPdnNxaHRQMmNXK29CdXUvdnMyNVVPQzFSbjBwdG5mVmE5VklLR2s3OHdCUmduaAp2VzZ1SmxDUXBUQ2l3VkJTaXM1Y2tJWDUwbkZBNWpKd3pHMncvaFRiaFMvOXI2bnI0eThRRUt4QXFTdVg2OGhsCmt5TlFEMXBPVVVmTExEeHk4cWRuTDY4Q0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBQ2dmSWtlWXhLS2FvZFZsTGc4cEUzQ2FiMnhGaDRDMGt4TWJ5KzgxVFRCYmJCVngxVHR0NGtBRjNDUVFOZERUCkE5NXdPbmJFVzgzRVl6Tis0c2ZGditFekpET1F4aG1ybE04SjdNU2JPTjBoaU92aW1lTUEwUkxudEhTNFpQdzMKOHA5OE15OTJiZFRWaTJQZkEvbGoyeWMyaHIwaFZMQ3V6dkJjdFBJaEVNamo5ZWxubE9LK3ZRRzNHUzhldldCMQowdCtjd093WDZIQWFSQitVUnlDNTBLOGJRME9HVXM1aTNRNkUwTTBySmttaC9VN0xjWm5VdCtkaVVZbzZLempZCmkyS0s2S1J6L2QrMnVoQktsTm5wZjNndDlSMjJwZi9JaDYvdGhiTUZzOG5WWmcyUGgrNk1nQ3RUallwbndDdHoKdHZOS2FIaURNK0xHM2JQWit0OGJqYW89Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBcFc5cGp1MWFNejhMakkyNmFNT2t3VjA1Y21qVkJnajRJK0t3NjA1RWtSVld2QmE5CnpZNzdiVFpjL1VJWnAvT2NIbHpMSFR5NmxGQkNCQ0NUcWoxNEJPaXh6QU5ESzVmU2tVZnB1V3F5dE8ySG03OTkKaE1YS1RsNEJUdm15c2dIbTgzOFpPTWtvZUp0NWNlZHFncm0wei9hWkpXRWRMZHZITUlUL2JOM04ydDBPazZ5YgpIUmJtdEtDZmYzZHc4N25ES2pvSTQ2djFabGJyaWFwTTYreXFHMC9aeGI2Z0c2NysremJsUTRMVkdmU20yZDlWCnIxVWdvYVR2ekFGR0NlRzlicTRtVUpDbE1LTEJVRktLemx5UWhmblNjVURtTW5ETWJiRCtGTnVGTC8ydnFldmoKTHhBUXJFQ3BLNWZyeUdXVEkxQVBXazVSUjhzc1BITHlwMmN2cndJREFRQUJBb0lCQVFDRUcvOVFxc3dnSmxWagpyWDVSMFFKTmc5T3ZRSFgwdHM3cFlVcms3WUNsMTBPSE9pWGg5QzlsM0ViUDI2dy9TYk8vTDF6b0FTb0I3RUY3CnFFUWphNmpmU3E5SStzWDJGdXlKSmNOSVZTTldobVNIaEppSW9hWlhoSXhJOCsrMlpQeDRNR1FFeSthc3dZTnUKNlYxTi9WeWR3aEEwSUdRN3pjazRQc3oycy8yQ3EwSEJiYmZjRThSd2xESHRaU1lhVUtjQWh0THpNbEpVb0gzeQpiZWNBcnU0b050K0pIQ01aWHRUanB6aFZ5MW41Z3h1Yjcrd29DM2ZaRXFqK3JLNzh1VnNtN0pqejFEWmxpZzUxCi9zS0ZsVDZWSDgzbTQ0Qlkwa0c3SFZpMlFsSTQ1MU9LOHQ3THpDQjY3c2l0UFdSMi9kdkI2YWZ2Q0hnQzk4aWIKTUZqNlpneDVBb0dCQU1ScEZXdXUwWjh2VUlrSDRsaHJ5d2Q3M2RTV2l0NnBnMXV4T1Z6cW5WMVlKWERuOTE3MQoyci9RUXFlRm84WXB6UUR1eXkyWnA4ZCtWcCtSR05vWjYzdlNpUW1jRmJFMkw4ZlhzaThNeWxmZHhEckl2SmFhCm1sbXphcWNSTFJBa0NpbGRvcHI4YmpzSmFwVTl5Q0EvMStQMlo0SlNDR1oyamxxWjVtN0t2V0hGQW9HQkFOZWcKaGh0L3BiUkpzajFKNEJEKzVzY2tJcDBVRjZBK25ycnVSZC85L2wxa21nK1E1alBQbGhWZk5JazBLbUU1ZzJUSgpjUllIc3VwU1gveDlZc1ZsclAyMWNnTlVrMUpiZkZvRUI2NHVwUGhKaEQwbGNnWnNiQThQYVh5VUlSTHd2Si9ZClpLK1JaRlRleVRTRmRhb2ZSVTlYVFROU2t2SEtZcS9DMFpwTHdXYmpBb0dCQUl1N2V3cldIN29SYmtsZSs1QU8KZUM0RjJLYml4ejlyOTlFbS8zbDBUS3BaQ0tJUDFiU1FVcVUrSS8yTW5SeGhKc0R3SWtwNTA1eWc3RDJ2ZTYvRwoydnFIcVFqV0s3U2NxVmVTdytpblA5bE5JOHJ5ZndEaVVzZFlWcHN2SkJFa29yb1ZMSmI0MmU5VVhxaDRnTVU0CnhuNGZFanJyNDZBSjNuTGtwTVRUcGZKRkFvR0FjYXZ4SnN2N0dma0QycVY0VnQxWjRiK2Q4N3JrM1poRmEzd3oKSCtzeFRpQzd5dHJ6VUhydHZ1U0t1STNralk2WlF1ZWpFeDhKNWRkNVBJMEpKZEQ5Q2w2OTlSMS84Sm5FQzF3MgpoRStZcmo5clZDVEtZTEtGb01iYU1FK1N3LzVmSWRFYyt5VWxoRXhTTzdyamxjU1ljRVF3c1k2bFlvdnp6SDVpCnF2bW13a3NDZ1lFQW4xUjAydVFpVW52S2xCT3BIS3J1ajJnUGNFbGZEcWgrUllrT2xtWVQybnJDL29ZQjVRb2wKSmFQQTc2N0hnMjVpdXNjY3MzaXR2dUZRSmxqam5DYWNCNS9NNDd3S09GUWFCSmZ1WWFKVUt5NmNyRWFLQUxOUwpJVzBtWHhZOWxRdnZ3OEY3d3dKcUZLclkyZjVPc3RjdkFjL0JLZXY0UnJVZCtwbktheVFoWjNrPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
diff --git a/dockerfiles/init/modules/openshift/kubeconfig b/dockerfiles/init/modules/openshift/kubeconfig
new file mode 100644
index 00000000000..2ce3e00a866
--- /dev/null
+++ b/dockerfiles/init/modules/openshift/kubeconfig
@@ -0,0 +1,46 @@
+apiVersion: v1
+clusters:
+- cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMFdoY05Nak13TXpFeApNVFF6TURRMVdqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE5qVXdORFV3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUREODFCVU9GUzkxeStIcUR2ODB3ZHAKWUNuNERRaDRrcXRjMkJlWTJmeEhKbU1PUzlPZGpGbUhDQWxvNk1TL0ZlNllHT1pXUWY5eVpmeENZZkJFSUIvdApLZG1nUXRUbFBZOUZlVXN3NDlORG5nNWxCUVNVS1REa2tXWTlTRWNaRUUwT3dzTnpaSndncDNSWDBSRzNNVHM2CkR3aGNTNFB5bEEzVWQ0ekhaSmhjZFZtMHVtallyRW8reFJyUXN3eGpvWmt3dVdycXMycWcyV1p6Q0ZyazVGbGMKN2FrTEVVT0N2SEZQTUtmZ1g5cXJtam9qVnZhaEZqS0pZYldJZVRKNlZOeUo1ZC9MUWR3ZHdjZXdsSHpHYWpiaQpIcG53bm13ZHp3MUdVRWM2ZTBha0xJQjBNc2wwY3BlcFZCNG41RHNENnl5eVJqekFQR0FXdXliakZJUUVaa3pwCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQjU3WFhMSlVhSTF4SFFTKytXSHNjNHZvRVhya3hIMk8yNm43UGFOc2NTQ1BKMApRNm5JbjZkemVscG5iQmI5NXJlUUxSRTJoV2d5dEx5Nm15VGVGL3lTSkxua3JNMjE4YmlFZHhCbStZTFJZdHhUCjVKcVU3QnZRbjV2RWxiSzlCVU5NdHgyY1lSQWNaT2d1N0R5eTlNQmtlRzBSMHV5R3laWXBlaE9FR2QyOCtSNGsKR2V3OThCMjV5Q20rVE55bkR1TGc3MmVIVVNKdlRTcDhPeXlEci9qbUNZazMwSWFSZkx3MElvUjEvNXoyd3FNbQo1MmRBaEJud01YdWVON1drUkpaMS85QmZKV3hlYzF2STlhNVNlek1sRnUxa1FneW5YTCtGZFk3WGJOT05YN1FDCitDNmZuS09qTVhnbTdueUY4dXVZd2EyWDcveVdWOFlweE5aU3lQWDMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    server: https://127.0.0.1:8443
+  name: 127-0-0-1:8443
+- cluster:
+    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMFdoY05Nak13TXpFeApNVFF6TURRMVdqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE5qVXdORFV3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUREODFCVU9GUzkxeStIcUR2ODB3ZHAKWUNuNERRaDRrcXRjMkJlWTJmeEhKbU1PUzlPZGpGbUhDQWxvNk1TL0ZlNllHT1pXUWY5eVpmeENZZkJFSUIvdApLZG1nUXRUbFBZOUZlVXN3NDlORG5nNWxCUVNVS1REa2tXWTlTRWNaRUUwT3dzTnpaSndncDNSWDBSRzNNVHM2CkR3aGNTNFB5bEEzVWQ0ekhaSmhjZFZtMHVtallyRW8reFJyUXN3eGpvWmt3dVdycXMycWcyV1p6Q0ZyazVGbGMKN2FrTEVVT0N2SEZQTUtmZ1g5cXJtam9qVnZhaEZqS0pZYldJZVRKNlZOeUo1ZC9MUWR3ZHdjZXdsSHpHYWpiaQpIcG53bm13ZHp3MUdVRWM2ZTBha0xJQjBNc2wwY3BlcFZCNG41RHNENnl5eVJqekFQR0FXdXliakZJUUVaa3pwCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQjU3WFhMSlVhSTF4SFFTKytXSHNjNHZvRVhya3hIMk8yNm43UGFOc2NTQ1BKMApRNm5JbjZkemVscG5iQmI5NXJlUUxSRTJoV2d5dEx5Nm15VGVGL3lTSkxua3JNMjE4YmlFZHhCbStZTFJZdHhUCjVKcVU3QnZRbjV2RWxiSzlCVU5NdHgyY1lSQWNaT2d1N0R5eTlNQmtlRzBSMHV5R3laWXBlaE9FR2QyOCtSNGsKR2V3OThCMjV5Q20rVE55bkR1TGc3MmVIVVNKdlRTcDhPeXlEci9qbUNZazMwSWFSZkx3MElvUjEvNXoyd3FNbQo1MmRBaEJud01YdWVON1drUkpaMS85QmZKV3hlYzF2STlhNVNlek1sRnUxa1FneW5YTCtGZFk3WGJOT05YN1FDCitDNmZuS09qTVhnbTdueUY4dXVZd2EyWDcveVdWOFlweE5aU3lQWDMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
+    server: https://192.168.99.103:8443
+  name: 192-168-99-103:8443
+contexts:
+- context:
+    cluster: 192-168-99-103:8443
+    user: developer/192-168-99-103:8443
+  name: /192-168-99-103:8443/developer
+- context:
+    cluster: 127-0-0-1:8443
+    namespace: default
+    user: system:admin/127-0-0-1:8443
+  name: default/127-0-0-1:8443/system:admin
+- context:
+    cluster: 192-168-99-103:8443
+    namespace: default
+    user: system:admin/127-0-0-1:8443
+  name: default/192-168-99-103:8443/system:admin
+- context:
+    cluster: 192-168-99-103:8443
+    namespace: myproject
+    user: developer/192-168-99-103:8443
+  name: minishift
+- context:
+    cluster: 192-168-99-103:8443
+    namespace: myproject
+    user: developer/192-168-99-103:8443
+  name: myproject/192-168-99-103:8443/developer
+current-context: minishift
+kind: Config
+preferences: {}
+users:
+- name: developer/192-168-99-103:8443
+  user:
+    token: _-QRfnZ0lSQVS4wUExp4yNMnlr5D6LHL8yE73Zjlm2Y
+- name: system:admin/127-0-0-1:8443
+  user:
+    client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQ0RBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMVdoY05NakF3TXpFeApNVFF6TURRMldqQTNNUjR3SEFZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNSbGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQUw5S25zWE04T2g5TlA5eWNyRDFnVGxTVkdCZ212bzAvYnZTQ1RXeXJxbU4xNGE5YnR6UUU2SWNZWTRtT0FBagoveFJNWjRHclBJSGpET2Z0MjhmMisvemtQZk15Q09tS3dvRTRtNFRtSCtBNnFHNDBua29JeGc4bXpFUlRNSzg4Cmtzd1ZPcmMzOXJXalVhbVIwT1ZwSDh1WTd6dmNueC9GcU54YlJBbU9TN3BoMU1UWXd6VmMvUWpiUkRCZGViYjIKV3VUS0hKSzM1bzZZSnVkUE5NUUpXeStaVmpMRUJXU1EraUc4SVFKSTd6T0lmQ2F6OXh5cEN2VHBicjZaV0NJRwpPV0wvSzV2NG80Nmk5Q3BDazA1Z2N6S0JiWVRZVkRvY3ZPV3ZZN2Vmbnhva3hZMENDZm9tM216NDBZOWRVT3BYCnJ6Zk1Zd0R0MHEySkltSmNhOWtKOFRVQ0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBR2RsdWNWSFN3Uk9Dem13cmlza0hkWVhnczBVRWFSRWZZYTNET0RVeXJuR1hIMlVEVnVNSHM4REJ6Wnd1QTdOCkt6T1BFaFR4WFZ3SFdwWEtKME5VQXpaSkNhT2tZMmF3cGFNbkhnZHJMcWtXOStMTmRERk80SE10N08rNWVwbzMKTHBSK0puQmpkZFBUQTdFL3pFQm9sOUhmczZvM3BGMUVuZ2lVcWR3Y3hlUmR5SllwR21zTkNPSzBtcUFFUStsbgpvb050Z2J0TFdWNDJWR2F6OVhkaTk4SHZRcDJ6bWF1d3BjL3UweHlsdWNZQ0U4ZFY1Rk1UWU84UXZmUkdjTDJGCnJNMU9STm5GN3ZocGNjaSttRU52RzRKVGtHWnVEUVVCdVI4dXYvVE9uNDBEdVVLYm0rN2ltR1RsUVhCcU9henAKaHl3NE9EalVlV0tUR2ZtemQxeHdJVDQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
+    client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdjBxZXhjenc2SDAwLzNKeXNQV0JPVkpVWUdDYStqVDl1OUlKTmJLdXFZM1hocjF1CjNOQVRvaHhoamlZNEFDUC9GRXhuZ2FzOGdlTU01KzNieC9iNy9PUTk4eklJNllyQ2dUaWJoT1lmNERxb2JqU2UKU2dqR0R5Yk1SRk13cnp5U3pCVTZ0emYydGFOUnFaSFE1V2tmeTVqdk85eWZIOFdvM0Z0RUNZNUx1bUhVeE5qRApOVno5Q050RU1GMTV0dlphNU1vY2tyZm1qcGdtNTA4MHhBbGJMNWxXTXNRRlpKRDZJYndoQWtqdk00aDhKclAzCkhLa0s5T2x1dnBsWUlnWTVZdjhybS9pampxTDBLa0tUVG1Cek1vRnRoTmhVT2h5ODVhOWp0NStmR2lURmpRSUoKK2liZWJQalJqMTFRNmxldk44eGpBTzNTcllraVlseHIyUW54TlFJREFRQUJBb0lCQVFDSWE1MERqMzZYTHdQbQowU1grRVhmUSsyZjFPN0FLbEZRSDZHaHRCVHNPN0hzeU9sS2Y0enk5TmVSVXplak9JTjIvQ2lZZkVaR2JSK05pClcvMkxoQlo5YWdETU9YaWxwVEhGbWlzL0FpYmxjSy9CdUlEU1o2Tm9GdEZDUU5uTmZ6TnBuQkk5ckFtanpBOW4KRVBpYlF2ZEw2WXRqYzVsL3ZTVUowWVNhRkFMcHJiT2E1QzVWT2x6T09yd0oxTlp3NFM0ZW1YME1aNW55R2lNNQp0Z1F1Q3JlU2ZoMlNTNjJLejhzTSs0Q01ZUU44V1ZJTGpHNWZ2THV3anJ4ak1hdzhyemNxRlNXNlBtbGdBMFlHCnE3QTFIUnY2UmJWRWNBN1VuMzdFK3VxTDRpZEhRUHJyUW9SM1lTUG5RZEx5b0t1Mk9KOXpqbjZsdzI4a2d0VXAKY1BOQVdSdUJBb0dCQU5iUjdlTVFoUis3Ni9uclV3QnpiSEpZYm9OaWZZQWM0ODVkNGNKSlVWaHhmcXg5L1ZNdQp3Z3dUUkUvYlhaNmxRV0orTUtpL1RVYUpVVzF3U0N0QzN6UDE4Y0ljR3hyYWdSejBhcy9wekF6K0hDTEFjR3dRCk1welZVV3B5MmVQa2NXL0R0M3BjKzFwNDNRdk1xVm01b0ZVNUczeC8yWTJiYXQ4dURMRThnMnVGQW9HQkFPUDIKRFR2VHIrYk9VckVDdEp3QXJ6RlNTZ2R0QzRNZ0NXOC9LSzlyZ2o5TElDRUM2TGptbkE2ZTI5TXJHR2VtMkR5VwpoZEN1UUxPTjBGblBKNkNWaEo1c1JkelZibi9abFN2ZVVRUU4wb1JyeTVRV0N6djVhcGdhVGdFZVo3NmtUdjAvCnpWYnB2dERvZEVZMmM4ZTluUS9sZkEzTUdLMzVIcWlmRGFLemdhWHhBb0dBYktRT290OGY5RVNkdXU4QU15SXMKbmtlSzNIZGE4UWVyVGhxOHFmMWFYbGhIc0FTbnNRSGNzUzZ0UlpXemF5QTRTUTk0bkY3alBlRUVoVXhiczBWRwpqSWk5azJXVGI2bEIwdHJwaWV5N2ZYYWwxQTF1emJnRFlMMmhSeXgrZFhwNnhBTS9MMnNHMDJKOHFCTUJNcGRtCk5yT0M2eHZkY25nL1BFK1ZxNnptNmVFQ2dZQTJ6OXpTdTgyWnc1WmlkWElUNko0M1Q3LzVGU0VsZ0RpRWhUMDEKSUxhS25YZTJPRXJZMnFvL1liY2RpVWt1OHhFZlVGb1FtVFY1ZHVuWURsVks2V2lmNXd6TlVveGxOVjRHMUVmSwpuOEEwa3U2NlJxcWcyeEhrVEw3Z3lmekwvQm42RHJOQzZLVTIrZzJyTEVDZWtGc0pqWFpNb3Z4MEtHaFV4eG15Ck8xTTdJUUtCZ1FDb1ZnQldlUXAyUUFTZTRlSk11cEF2RXFOTXd2QjdjcFQ4M2dtdUJyWVFMeDA1dFBwMjk3S1MKY2U4cUZTUU13M0o5MHRzOVpkeGZrcE8rWXk1OTVqNVZsYWxDY1dnbE8yeVFkc3VCYjhId0thclJHN2k2b3JLdQp1aE9vc3hHL3M4UmJUVlBzSlRkdE9zN2I0elBXSFVpcTUyNDhHUSt2a3FxZUdBZitiUENMY0E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java
deleted file mode 100644
index ee2d4199a10..00000000000
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerExposer.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2012-2018 Red Hat, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *   Red Hat, Inc. - initial API and implementation
- */
-package org.eclipse.che.workspace.infrastructure.openshift.server;
-
-import io.fabric8.kubernetes.api.model.Container;
-import io.fabric8.kubernetes.api.model.Pod;
-import io.fabric8.kubernetes.api.model.Service;
-import io.fabric8.openshift.api.model.Route;
-import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
-import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations;
-import org.eclipse.che.workspace.infrastructure.kubernetes.server.ExternalServerExposerStrategy;
-import org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServerExposer;
-import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
-
-/**
- * Helps to modify {@link OpenShiftEnvironment} to make servers that are configured by {@link
- * ServerConfig} publicly or workspace-wide accessible.
- *
- * 

To make server accessible it is needed to make sure that container port is declared, create - * {@link Service}. To make it also publicly accessible it is needed to create corresponding {@link - * Route} for exposing this port. - * - *

Created services and routes will have serialized servers which are exposed by the - * corresponding object and machine name to which these servers belongs to. - * - *

Container, service and route are linked in the following way: - * - *

- * Pod
- * metadata:
- *   labels:
- *     type: web-app
- * spec:
- *   containers:
- *   ...
- *   - ports:
- *     - containerPort: 8080
- *       name: web-app
- *       protocol: TCP
- *   ...
- * 
- * - * Then services expose containers ports in the following way: - * - *
- * Service
- * metadata:
- *   name: service123
- * spec:
- *   selector:                        ---->> Pod.metadata.labels
- *     type: web-app
- *   ports:
- *     - name: web-app
- *       port: 8080
- *       targetPort: [8080|web-app]   ---->> Pod.spec.ports[0].[containerPort|name]
- *       protocol: TCP                ---->> Pod.spec.ports[0].protocol
- * 
- * - * Then corresponding route expose one of the service's port: - * - *
- * Route
- * ...
- * spec:
- *   to:
- *     name: dev-machine              ---->> Service.metadata.name
- *     targetPort: [8080|web-app]     ---->> Service.spec.ports[0].[port|name]
- * 
- * - *

For accessing publicly accessible server user will use route host. For accessing - * workspace-wide accessible server user will use service name. Information about servers that are - * exposed by route and/or service are stored in annotations of a route or service. - * - * @author Sergii Leshchenko - * @author Alexander Garagatyi - * @see Annotations - */ -public class OpenShiftServerExposer extends KubernetesServerExposer { - - public OpenShiftServerExposer( - ExternalServerExposerStrategy openshiftExternalServerExposerStrategy, - String machineName, - Pod pod, - Container container, - OpenShiftEnvironment kubernetesEnvironment) { - super( - openshiftExternalServerExposerStrategy, machineName, pod, container, kubernetesEnvironment); - } -} diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerResolver.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerResolver.java index d0604a6ffb5..5a4b3fce51a 100644 --- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerResolver.java +++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/server/OpenShiftServerResolver.java @@ -30,7 +30,7 @@ * * @author Sergii Leshchenko * @author Alexander Garagatyi - * @see OpenShiftServerExposer + * @see OpenShiftExternalServerExposer * @see Annotations */ public class OpenShiftServerResolver extends KubernetesServerResolver { diff --git a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java b/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java deleted file mode 100644 index 2c98d1f1e0e..00000000000 --- a/infrastructures/openshift/src/test/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftServerExposerTest.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2012-2018 Red Hat, Inc. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.che.workspace.infrastructure.openshift; - -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; -import static org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer.SERVER_PREFIX; -import static org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer.SERVER_UNIQUE_PART_SIZE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import com.google.common.collect.ImmutableMap; -import io.fabric8.kubernetes.api.model.Container; -import io.fabric8.kubernetes.api.model.ContainerBuilder; -import io.fabric8.kubernetes.api.model.ContainerPortBuilder; -import io.fabric8.kubernetes.api.model.Pod; -import io.fabric8.kubernetes.api.model.PodBuilder; -import io.fabric8.kubernetes.api.model.Service; -import io.fabric8.kubernetes.api.model.ServicePort; -import io.fabric8.openshift.api.model.Route; -import java.util.ArrayList; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.regex.Pattern; -import org.eclipse.che.api.core.model.workspace.config.ServerConfig; -import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl; -import org.eclipse.che.workspace.infrastructure.kubernetes.Annotations; -import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment; -import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftExternalServerExposer; -import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposer; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -/** - * Test for {@link OpenShiftServerExposer}. - * - * @author Sergii Leshchenko - */ -public class OpenShiftServerExposerTest { - - private static final Map ATTRIBUTES_MAP = singletonMap("key", "value"); - private static final Map INTERNAL_SERVER_ATTRIBUTE_MAP = - singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, Boolean.TRUE.toString()); - - private static final Pattern SERVER_PREFIX_REGEX = - Pattern.compile('^' + SERVER_PREFIX + "[A-z0-9]{" + SERVER_UNIQUE_PART_SIZE + "}-pod-main$"); - public static final String MACHINE_NAME = "pod/main"; - - private OpenShiftServerExposer serverExposer; - private OpenShiftEnvironment openShiftEnvironment; - private Container container; - private OpenShiftExternalServerExposer openShiftExternalServerExposer; - - @BeforeMethod - public void setUp() throws Exception { - container = new ContainerBuilder().withName("main").build(); - Pod pod = - new PodBuilder() - .withNewMetadata() - .withName("pod") - .endMetadata() - .withNewSpec() - .withContainers(container) - .endSpec() - .build(); - - openShiftEnvironment = - OpenShiftEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build(); - openShiftExternalServerExposer = new OpenShiftExternalServerExposer(); - this.serverExposer = - new OpenShiftServerExposer( - openShiftExternalServerExposer, MACHINE_NAME, pod, container, openShiftEnvironment); - } - - @Test - public void shouldExposeContainerPortAndCreateServiceAndRouteForServer() { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of("http-server", httpServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertThatExternalServerIsExposed( - MACHINE_NAME, - "http-server", - "tcp", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void - shouldExposeContainerPortAndCreateServiceAndRouteForServerWhenTwoServersHasTheSamePort() { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); - ServerConfigImpl wsServerConfig = - new ServerConfigImpl("8080/tcp", "ws", "/connect", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of( - "http-server", httpServerConfig, - "ws-server", wsServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertEquals(openShiftEnvironment.getServices().size(), 1); - assertEquals(openShiftEnvironment.getRoutes().size(), 1); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "http-server", - "tcp", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "ws-server", - "tcp", - 8080, - new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void - shouldExposeContainerPortsAndCreateServiceAndRoutesForServerWhenTwoServersHasDifferentPorts() { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); - ServerConfigImpl wsServerConfig = - new ServerConfigImpl("8081/tcp", "ws", "/connect", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of( - "http-server", httpServerConfig, - "ws-server", wsServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertEquals(openShiftEnvironment.getServices().size(), 1); - assertEquals(openShiftEnvironment.getRoutes().size(), 2); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "http-server", - "tcp", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "ws-server", - "tcp", - 8081, - new ServerConfigImpl(wsServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void - shouldExposeTcpContainerPortsAndCreateServiceAndRouteForServerWhenProtocolIsMissedInPort() { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080", "http", "/api", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of("http-server", httpServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertEquals(openShiftEnvironment.getServices().size(), 1); - assertEquals(openShiftEnvironment.getRoutes().size(), 1); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "http-server", - "TCP", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void shouldNotAddAdditionalContainerPortWhenItIsAlreadyExposed() { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of("http-server", httpServerConfig); - container.setPorts( - singletonList( - new ContainerPortBuilder() - .withName("port-8080") - .withContainerPort(8080) - .withProtocol("TCP") - .build())); - - // when - serverExposer.expose(serversToExpose); - - // then - assertThatExternalServerIsExposed( - MACHINE_NAME, - "http-server", - "tcp", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void shouldAddAdditionalContainerPortWhenThereIsTheSameButWithDifferentProtocol() { - // given - ServerConfigImpl udpServerConfig = - new ServerConfigImpl("8080/udp", "udp", "/api", ATTRIBUTES_MAP); - Map serversToExpose = ImmutableMap.of("server", udpServerConfig); - container.setPorts( - new ArrayList<>( - singletonList( - new ContainerPortBuilder() - .withName("port-8080") - .withContainerPort(8080) - .withProtocol("TCP") - .build()))); - - // when - serverExposer.expose(serversToExpose); - - // then - assertEquals(container.getPorts().size(), 2); - assertEquals(container.getPorts().get(1).getContainerPort(), new Integer(8080)); - assertEquals(container.getPorts().get(1).getProtocol(), "UDP"); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "server", - "udp", - 8080, - new ServerConfigImpl(udpServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - @Test - public void shouldExposeContainerPortAndCreateServiceForInternalServer() throws Exception { - // given - ServerConfigImpl httpServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", INTERNAL_SERVER_ATTRIBUTE_MAP); - Map serversToExpose = - ImmutableMap.of("http-server", httpServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertThatInternalServerIsExposed( - MACHINE_NAME, - "http-server", - "tcp", - 8080, - new ServerConfigImpl(httpServerConfig).withAttributes(INTERNAL_SERVER_ATTRIBUTE_MAP)); - } - - @Test - public void shouldExposeInternalAndExternalServers() throws Exception { - // given - ServerConfigImpl internalServerConfig = - new ServerConfigImpl("8080/tcp", "http", "/api", INTERNAL_SERVER_ATTRIBUTE_MAP); - ServerConfigImpl externalServerConfig = - new ServerConfigImpl("9090/tcp", "http", "/api", ATTRIBUTES_MAP); - Map serversToExpose = - ImmutableMap.of("int-server", internalServerConfig, "ext-server", externalServerConfig); - - // when - serverExposer.expose(serversToExpose); - - // then - assertThatInternalServerIsExposed( - MACHINE_NAME, - "int-server", - "tcp", - 8080, - new ServerConfigImpl(internalServerConfig).withAttributes(INTERNAL_SERVER_ATTRIBUTE_MAP)); - assertThatExternalServerIsExposed( - MACHINE_NAME, - "ext-server", - "tcp", - 9090, - new ServerConfigImpl(externalServerConfig).withAttributes(ATTRIBUTES_MAP)); - } - - private void assertThatExternalServerIsExposed( - String machineName, - String serverNameRegex, - String portProtocol, - Integer port, - ServerConfigImpl expected) { - // then - assertTrue( - container - .getPorts() - .stream() - .anyMatch( - p -> - p.getContainerPort().equals(port) - && p.getProtocol().equals(portProtocol.toUpperCase()))); - // ensure that service is created - - Service service = null; - for (Entry entry : openShiftEnvironment.getServices().entrySet()) { - if (SERVER_PREFIX_REGEX.matcher(entry.getKey()).matches()) { - service = entry.getValue(); - break; - } - } - assertNotNull(service); - - // ensure that required service port is exposed - Optional servicePortOpt = - service - .getSpec() - .getPorts() - .stream() - .filter(p -> p.getTargetPort().getIntVal().equals(port)) - .findAny(); - assertTrue(servicePortOpt.isPresent()); - ServicePort servicePort = servicePortOpt.get(); - assertEquals(servicePort.getTargetPort().getIntVal(), port); - assertEquals(servicePort.getPort(), port); - assertEquals(servicePort.getName(), SERVER_PREFIX + "-" + port); - - Annotations.Deserializer serviceAnnotations = - Annotations.newDeserializer(service.getMetadata().getAnnotations()); - assertEquals(serviceAnnotations.machineName(), machineName); - - // ensure that required route is created - Route route = - openShiftEnvironment.getRoutes().get(service.getMetadata().getName() + "-server-" + port); - assertEquals(route.getSpec().getTo().getName(), service.getMetadata().getName()); - assertEquals(route.getSpec().getPort().getTargetPort().getStrVal(), servicePort.getName()); - - Annotations.Deserializer routeAnnotations = - Annotations.newDeserializer(route.getMetadata().getAnnotations()); - Map servers = routeAnnotations.servers(); - ServerConfig serverConfig = servers.get(serverNameRegex); - assertEquals(serverConfig, expected); - - assertEquals(routeAnnotations.machineName(), machineName); - } - - private void assertThatInternalServerIsExposed( - String machineName, - String serverNameRegex, - String portProtocol, - Integer port, - ServerConfigImpl expected) { - // then - assertTrue( - container - .getPorts() - .stream() - .anyMatch( - p -> - p.getContainerPort().equals(port) - && p.getProtocol().equals(portProtocol.toUpperCase()))); - // ensure that service is created - - Service service = null; - for (Entry entry : openShiftEnvironment.getServices().entrySet()) { - if (SERVER_PREFIX_REGEX.matcher(entry.getKey()).matches()) { - service = entry.getValue(); - break; - } - } - assertNotNull(service); - - // ensure that required service port is exposed - Optional servicePortOpt = - service - .getSpec() - .getPorts() - .stream() - .filter(p -> p.getTargetPort().getIntVal().equals(port)) - .findAny(); - assertTrue(servicePortOpt.isPresent()); - ServicePort servicePort = servicePortOpt.get(); - assertEquals(servicePort.getTargetPort().getIntVal(), port); - assertEquals(servicePort.getPort(), port); - assertEquals(servicePort.getName(), SERVER_PREFIX + "-" + port); - - Annotations.Deserializer serviceAnnotations = - Annotations.newDeserializer(service.getMetadata().getAnnotations()); - assertEquals(serviceAnnotations.machineName(), machineName); - - Map servers = serviceAnnotations.servers(); - ServerConfig serverConfig = servers.get(serverNameRegex); - assertEquals(serverConfig, expected); - - // ensure that required route is created - Route route = - openShiftEnvironment.getRoutes().get(service.getMetadata().getName() + "-server-" + port); - assertEquals(route.getSpec().getTo().getName(), service.getMetadata().getName()); - assertEquals(route.getSpec().getPort().getTargetPort().getStrVal(), servicePort.getName()); - - Annotations.Deserializer routeAnnotations = - Annotations.newDeserializer(route.getMetadata().getAnnotations()); - Map routeServers = routeAnnotations.servers(); - ServerConfig routeServerConfig = routeServers.get(serverNameRegex); - assertNull(routeServerConfig); - - assertEquals(routeAnnotations.machineName(), machineName); - } -} From b5b28321419bdb07bc10ac1a6ebbd98ccfaec30c Mon Sep 17 00:00:00 2001 From: Guy Daich Date: Tue, 13 Mar 2018 07:47:03 +0200 Subject: [PATCH 12/12] remove uintended automation changes Signed-off-by: Guy Daich --- .../modules/che-kubernetes-helm/kubeconfig | 23 ------- .../che-kubernetes-helm/values-gardener.yaml | 19 ------ .../openshift/files/scripts/deploy_che.sh | 8 +-- .../openshift/files/scripts/kubeconfig | 68 ------------------- dockerfiles/init/modules/openshift/kubeconfig | 46 ------------- 5 files changed, 4 insertions(+), 160 deletions(-) delete mode 100644 dockerfiles/init/modules/che-kubernetes-helm/kubeconfig delete mode 100644 dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml delete mode 100644 dockerfiles/init/modules/openshift/files/scripts/kubeconfig delete mode 100644 dockerfiles/init/modules/openshift/kubeconfig diff --git a/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig b/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig deleted file mode 100644 index d8ba6a5028b..00000000000 --- a/dockerfiles/init/modules/che-kubernetes-helm/kubeconfig +++ /dev/null @@ -1,23 +0,0 @@ ---- -apiVersion: v1 -kind: Config -current-context: shoot-garden-devx-che-che-6-dev -clusters: -- name: shoot-garden-devx-che-che-6-dev - cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMxekNDQWIrZ0F3SUJBZ0lRVTBYU3VFOGRvcC95OC9meEowRUoyekFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1CNFhEVEU0TURJeU9EQTRORFl4TWxvWERUSTRNREl5T0RBNApORFl4TWxvd0ZURVRNQkVHQTFVRUF4TUthM1ZpWlhKdVpYUmxjekNDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFECmdnRVBBRENDQVFvQ2dnRUJBT1AzVnFyM2NYbXdYMWtKZ2ozdUUyZ3haSk95dFNtNFRrbEY5UEVOaTVIK243eG4KODVoRFhYSzkyaHpjcjlmTnQvOG1XcjBlRWFYR0hId0t6b1dwQWh1K1l6d1NQSnZLZ2lTQzlOQkVrdndiQnZpegorZjhJOWtQZy9DVDRidXRnMjFRY2I0aTlvTWlVQ3RYQkZhem05QUJDWTJ1NFVZT2FRN0xBeDBzUGtkSXlURHJLCnI5SDNDNk82eTJhYzF4Vk5VWUZtK0JHT01IRzR2cWp0M3g3dDF6Q0JyR2RxQ2VpOHMzWTVwdFVUUmlqUmI0RkkKeW4vZ3piUFhLVWltRDJuMjF1K1k4VHMyUk51QUdjQjRWZElGcjlJNFFxR3kxc3BHNFppQllmNlI2bmVwTlRXawp3V1BlT1E0SlgxMDdsd3c3cEFKQU9SY0xXRDBJNWhINFVHMWNNZjhDQXdFQUFhTWpNQ0V3RGdZRFZSMFBBUUgvCkJBUURBZ0dtTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUkzeGk0Rk8KZnNjcERrZklGVmNSbWFNa3B1N08yZVo5TXQxTlk0MWxGOWF5cTQ2TE5DbU54SEFoY2ZDZU41UDZ4UEwvb05GLwo3MC9Bb2REbXVobFZpOFFmWS9Cb3RZQU90V3hxRFhPazR0cy9JQ1Z4b1VtNEJBVUR4UmlpakxRWmJ5ZURZYkd6CnJjUE8rUXhsQ2VodHhOczFqSjVYc1FiNzRDYUR3d2o1dmxFSGw2c2RGSlloek9raVh6Vlk0UDhRcGJvZG9IWUIKcTk2dWQrUEdDK1d6YXpqZ1czVFh4NitxSmhjMzlJeitBb2tRem90TWRuOG02K2RWSmp4dFBhaEdaY1dCcUs3TAprdkxhOTBiUzhNaFhYcEU3TEYzQlAyemtacGNuTDJkdis2aEU0TS9EZjNyTFFGQlJ6eUhtS2Z5STk5S3IvNFhnClhWR0p5aVV4YjFMckJUMD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://api.che-6-dev.devx-che.k8s.sapcloud.io -contexts: -- name: shoot-garden-devx-che-che-6-dev - context: - cluster: shoot-garden-devx-che-che-6-dev - user: shoot-garden-devx-che-che-6-dev -users: -- name: shoot-garden-devx-che-che-6-dev - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBRENDQWVpZ0F3SUJBZ0lSQUxUMjRmOEdMNmRFNk1nRzQwRUJOUk13RFFZSktvWklodmNOQVFFTEJRQXcKRlRFVE1CRUdBMVVFQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T0RBeU1qZ3dPRFEyTVRoYUZ3MHlPREF5TWpndwpPRFEyTVRoYU1Dc3hGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1SQXdEZ1lEVlFRREV3ZHJkV0psClkyWm5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW1ubVhnblFpbUh3azFkQ1AKaHJjQUF4bG9Yb2psWnUxVEttdjJ3OUpXemthb2J6ZGNmRGVTZDZsS3JXRG5GQy91dTBTWVp1UzRnQTVOWmRDSgpoY3RTbDlxNVFJc3UvYVYxeCs0WENMYVAxR0hvQkM1QnpWQnJNUEdLN0p3SlRhTTk1YzMrOWVCeUc3RDUwL2tUCi91QWFlbWhMVjV5WmU0YlBwYmhUYld6K2p3QW5mZ2M1UlFGNmRIN29nSGRvcUJpMGgyMCs4eUw5Nnhyb1FRdTgKbzJ4SU9nWWdpK0puVTJkSzJLWGo5N3NCVnpxWG80QjRJMk9JU3pBcmRuL29ucitQdzJpSlV2SklDQ3REbnF4ZgphckNwTnloeG5zeUNhM3pnSXY0OGxrZTdSSWlJVnVBd1o1K29TMUhoSS8vUUkzMHRJYnZOaDRXdkRPRVRlUmc2ClEvUFpad0lEQVFBQm96VXdNekFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBUk94aHQ1cFhrd2JWSVA0QgpOSzcxeUZpeWZxRVhOcEEyT1V1TUNMMDhWZ1p5TWpsU0M5NFV4K3prV3k1N2lHZHNzb1c1NkZseXYyT285aE91CmN2bE1vRmQrajdLdU42d1VONmVWQU81MW1oRUdvMkpJcVZSdVVhQWh2TUxqM0NCTnZyTzJVTVdhSmc1ZERLSnoKWlQydTZzbk1uNnlaeDNUQStiSjJVVkxBZDNiTEo4L21kQUFyUjlwdkxQbUJ4V3pFa2NPNUFkRDFLZDNtd2U0cwpqK3FVbjZTWnlnUnQ4Vk1VbC9henNlaG9QUUh3TThlWnpCTW45dGR4d1o3dzFsSjNFNzFEWlA3R0dTL3YzTTVLCmZjUlJaQ2tEUm1hcTJGbUJ3SzZJVW82WnRYNmR3Qk1ON3JQZUswQmNJbUU3TU1aaVRCcFE0bFlSRnZpREZSSWgKV01reDN3PT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBbW5tWGduUWltSHdrMWRDUGhyY0FBeGxvWG9qbFp1MVRLbXYydzlKV3prYW9iemRjCmZEZVNkNmxLcldEbkZDL3V1MFNZWnVTNGdBNU5aZENKaGN0U2w5cTVRSXN1L2FWMXgrNFhDTGFQMUdIb0JDNUIKelZCck1QR0s3SndKVGFNOTVjMys5ZUJ5RzdENTAva1QvdUFhZW1oTFY1eVplNGJQcGJoVGJXeitqd0FuZmdjNQpSUUY2ZEg3b2dIZG9xQmkwaDIwKzh5TDk2eHJvUVF1OG8yeElPZ1lnaStKblUyZEsyS1hqOTdzQlZ6cVhvNEI0CkkyT0lTekFyZG4vb25yK1B3MmlKVXZKSUNDdERucXhmYXJDcE55aHhuc3lDYTN6Z0l2NDhsa2U3UklpSVZ1QXcKWjUrb1MxSGhJLy9RSTMwdElidk5oNFd2RE9FVGVSZzZRL1BaWndJREFRQUJBb0lCQUJCZGQxYWp0UktRZkZxRwppTjROdnh1VThvQ3BZaHhBWWtJcFEvQkU5VnRQRXdNTlMyZ0JmeXZjTElRbnN2TnBqSkljVjBUM1VEQ0kwMXhJCjluak5MSWZYN1M1UVVIOGdxMVN0L1pTM3VvOFdmRDBOSlgxNTJwRkoxWnp4ZnU3UnIzb01FOG02cUh3VWlMTVQKUFRJUVRkM1A5TU5vWEw1QWJ2a3dpTzRiMFBBWE92TFZ5bVdSVlhIQ0xzRDU3ZEFFT1dhQ3hpWGFSQ0h0UlF1awpUVkRLNi96RXFuUTI0MXVmS2dtQTE3QTViSzBZUDRwWVZXM1RoU3Z4bkZWQVM1bGVaaVJrTGpTeERXdzZrdnI0CmllVjZ6Q05PVUU4S2huRFhUZEZqRzRIRktsQSthRnQ0WXRQT24yWjFqTTlwRllZbVBnMmpYbmljRDA5d05IcVoKMkswcnh0RUNnWUVBd3J6UlFQeEhhMnNwcXpYa2paWlh3VGRyMWFwMXhKNUJTVTJscVF1a1FWNXJIbHhRdHlNNQovRmJpeFo4TGlIRE94ZDdUWHVpYVhvSE15SEtoTEl2c2R4ZUx6K3dwV2orMTFsYXhZM0FncmRPMSs2a3hWVE1EClY3TjgrckJiWW5iRGt0RE5BS1kxcWZnbXFVV2puREF3cFV0aG5mTVJVcDRFdFp4L0Z2NTFNbzhDZ1lFQXl4STYKUFFsYXRVbVR3VC9JTGhIS0N0aXVydzhSWGlvdEJwQTg3ZWdVUDZiUmJFVWdYRWxONEg1OEs1NGx3cC9Ra1BaKwpreWlKUThPYmZzamFLd2hqMWZEOEZIcXZvWExFNEt0ZUJzZ1BQWDdjN0dvOHhIUm1qbjV3MFFuWks2aGtTOWhGCmQvRnc5RjNUbWVsczhmRUZnaUJwY2xyenVBRUFTRjlvS1hjYmQ2a0NnWUJIY1JQbm5tWHBMNkJTMG11dDBla1IKMW00Mkxkb1VydVpPcVRETVNwd1E2ejJySHJ6eDR2ZUQ3ckExUmZycUxGQi9ZUmIwYTZzdVhyb3RFM2l6cWdXdgpUekVZcjVBZ0x0MWI2K1FhRWVtN083ODR1MEtBK2owUXNLVjZKcmJ2OFpnZ1JYL2Y3Qm9sNkFidTlNQm9MWG03Ck9tTnVtZHpTRFd5MjM5bjBLcGYrV3dLQmdBYk1XMnJEcjJlMlNONEZWcHhFT0RGWXc3QlVuczQ2Tnp1ckJIOHEKYjlNWnNKVWhVMDREbmpuUHdqUnJuUFFCQ2Fod3VCZ1JHVmROYXgwNWVDUk1xWnIxOEZwM0tQNE1xNDZoN2dubwpGS3FJWHJrRGJYbGVORGk4L3VYZ29JYVhvcFB2YjVQdVgwdXZBSEI4b2dzUGVKRzhxQXNPQkc2NmlkbmlaOGhMCmxuM1JBb0dBUmVuQU1uUEpzUmUrQVJjazhwQ0lnN0JnRmM1bnQrYzBReXBnWTcxUjB2RElwMWNoTys3dWZDUFYKN3hKekRBVXlkTDBoMmxHUFRlcTZ2T0c3bzlFa2kvaW1XSUdjN0ZoSmRzRnVvNGlvVE9GbmZDNTV0bGtLWHpQbwoxaFIyRUNHZ1AzSFFjSHY2KzRnc0Q1QmNUVVR2eXA4R1BJdWlQdCsweUVqK1JhbDhVWGs9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== -- name: shoot-garden-devx-che-che-6-dev-basic-auth - user: - username: admin - password: mpPPLP7RqKw4Accn5oYTXfcOAvGlhAsu \ No newline at end of file diff --git a/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml b/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml deleted file mode 100644 index 26ce84d344f..00000000000 --- a/dockerfiles/init/modules/che-kubernetes-helm/values-gardener.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# helm upgrade --install che --namespace che -f ./values-gardener.yaml ./ - -cheImage: guydaich/che-server:routing -cheImagePullPolicy: Always -cheKeycloakClientId: "che-public" -cheKeycloakRealm: "che" - -global: - cheNamespace: "" - multiuser: false - ingressDomain: ingress.che-6-dev.devx-che.k8s.sapcloud.io - ingressAnnotationsPrefix: "" - serverStrategy: single-host - tls: - enabled: true - useCertManager: true - useStaging: true - secretName: che-tls - diff --git a/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh b/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh index 95782cb7ecf..df56e9478b1 100755 --- a/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh +++ b/dockerfiles/init/modules/openshift/files/scripts/deploy_che.sh @@ -177,7 +177,7 @@ if [ "${OPENSHIFT_FLAVOR}" == "minishift" ]; then DEFAULT_CHE_DEBUG_SERVER="true" DEFAULT_OC_SKIP_TLS="true" DEFAULT_CHE_APPLY_RESOURCE_QUOTAS="false" - DEFAULT_IMAGE_PULL_POLICY="Always" + DEFAULT_IMAGE_PULL_POLICY="IfNotPresent" DEFAULT_ENABLE_SSL="false" DEFAULT_CHE_LOG_LEVEL="INFO" DEFAULT_CHE_PREDEFINED_STACKS_RELOAD="false" @@ -221,14 +221,14 @@ fi CHE_OPENSHIFT_PROJECT=${CHE_OPENSHIFT_PROJECT:-${DEFAULT_CHE_OPENSHIFT_PROJECT}} DEFAULT_COMMAND="deploy" DEFAULT_CHE_MULTIUSER="false" -DEFAULT_CHE_IMAGE_REPO="docker.io/guydaich/che-server" -DEFAULT_CHE_IMAGE_TAG="routing" +DEFAULT_CHE_IMAGE_REPO="docker.io/eclipse/che-server" +DEFAULT_CHE_IMAGE_TAG="nightly" DEFAULT_CHE_KEYCLOAK_OSO_ENDPOINT="https://sso.openshift.io/auth/realms/fabric8/broker/openshift-v3/token" DEFAULT_KEYCLOAK_GITHUB_ENDPOINT="https://sso.openshift.io/auth/realms/fabric8/broker/github/token" DEFAULT_CHE_KEYCLOAK_ADMIN_REQUIRE_UPDATE_PASSWORD="true" COMMAND=${COMMAND:-${DEFAULT_COMMAND}} -WAIT_FOR_CHE=${WAIT_FOR_CHE:-"true"} +WAIT_FOR_CHE=${WAIT_FOR_CHE:-"false"} CHE_MULTIUSER=${CHE_MULTIUSER:-${DEFAULT_CHE_MULTIUSER}} if [ "${CHE_MULTIUSER}" == "true" ]; then CHE_DEDICATED_KEYCLOAK=${CHE_DEDICATED_KEYCLOAK:-"true"} diff --git a/dockerfiles/init/modules/openshift/files/scripts/kubeconfig b/dockerfiles/init/modules/openshift/files/scripts/kubeconfig deleted file mode 100644 index f873cccc469..00000000000 --- a/dockerfiles/init/modules/openshift/files/scripts/kubeconfig +++ /dev/null @@ -1,68 +0,0 @@ -apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMVdoY05Nak13TXpFeApNVGMxTnpJMldqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE56YzBORFl3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNWbDZjZnVBQkNLVEJUeEJKcURJZloKWEI2c2VNc05sUGJGTEZHUm9mcGczMElOWXZUeUJJcU9CZ281YjlTR2s0TWZORVNVdHNZQVc1SFdlK0drcHI1cQpyQjRxejRGTnA2MzZvSS9MTTNtZVJaV0JDWCtIemtUYytCODNYU2EzUnMrSDJ3NnFUL3pvRjdCaGVmWWpGeElHCklNQ2xuT1p3Q2t3Q0FsRDI1U3MxMzZrRVRzNVBMVWxHS3c2dVdZbTlHK2VWWjJaMHhoMmh0a0VLZ2Jud09PZXQKYXAxN3ZFSnBncFg4WTAvSXp0YTJlVEdrenNob29YOW1wR1R1c3hRNU9RMU1mVUtyc1pjZThsL1dJS2pIcGZBKwpkcUU2WEx1NncvVW10NXN0bmdxVDVkTi9vQVFQZjluWTBkR1pXOXY2T2dMSzhHUlRFN1JNYmlqczBXZlRJY25wCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQXRLWVp0VzVvZlZ3cnIvcU9BdlZ2WDFyeEtPRmd2SWg4aGVZTnVlNis5OWpMYQpDNDJtOTM4SkRTS1dya3hoNzd4eHNiSm90Q1NyVTQzbW1JcnBkUldrUTY5SE16cUhFTml3Q25mOE1QMkRscDVECjhoZGhic2FGemhSc21rRFVMNFp2VldURDJ3SmZSRitxd1lXSHEybUduNkxwdHU3Smd5WUdIcjBZaHovRGJTa1kKR21hdHJQQWRaUjBzSnM3UnZDT001c3R1eGl5QmluVC96QU9oMElwVlNZMEFhSUNUU25sOEVrNlFveTJjbmhRVQpjTGQ3Z01ZcDFNL3JNQUZTRSs5OVB6c3dObUhnMVFkdS9na1ZNWS9ZWmZBRE9QM3JhODdHeFBlcFIzOGwyVVhJCmVBcDJFcmJhNXdjaHQ2NHorZSsyNjh2VHZaWUJ5OFU4YTU2a3RtUTMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://127.0.0.1:8443 - name: 127-0-0-1:8443 -- cluster: - insecure-skip-tls-verify: true - server: https://192.168.99.103:8443 - name: 192-168-99-103:8443 -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMVdoY05Nak13TXpFeApNVGMxTnpJMldqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE56YzBORFl3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUNWbDZjZnVBQkNLVEJUeEJKcURJZloKWEI2c2VNc05sUGJGTEZHUm9mcGczMElOWXZUeUJJcU9CZ281YjlTR2s0TWZORVNVdHNZQVc1SFdlK0drcHI1cQpyQjRxejRGTnA2MzZvSS9MTTNtZVJaV0JDWCtIemtUYytCODNYU2EzUnMrSDJ3NnFUL3pvRjdCaGVmWWpGeElHCklNQ2xuT1p3Q2t3Q0FsRDI1U3MxMzZrRVRzNVBMVWxHS3c2dVdZbTlHK2VWWjJaMHhoMmh0a0VLZ2Jud09PZXQKYXAxN3ZFSnBncFg4WTAvSXp0YTJlVEdrenNob29YOW1wR1R1c3hRNU9RMU1mVUtyc1pjZThsL1dJS2pIcGZBKwpkcUU2WEx1NncvVW10NXN0bmdxVDVkTi9vQVFQZjluWTBkR1pXOXY2T2dMSzhHUlRFN1JNYmlqczBXZlRJY25wCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQXRLWVp0VzVvZlZ3cnIvcU9BdlZ2WDFyeEtPRmd2SWg4aGVZTnVlNis5OWpMYQpDNDJtOTM4SkRTS1dya3hoNzd4eHNiSm90Q1NyVTQzbW1JcnBkUldrUTY5SE16cUhFTml3Q25mOE1QMkRscDVECjhoZGhic2FGemhSc21rRFVMNFp2VldURDJ3SmZSRitxd1lXSHEybUduNkxwdHU3Smd5WUdIcjBZaHovRGJTa1kKR21hdHJQQWRaUjBzSnM3UnZDT001c3R1eGl5QmluVC96QU9oMElwVlNZMEFhSUNUU25sOEVrNlFveTJjbmhRVQpjTGQ3Z01ZcDFNL3JNQUZTRSs5OVB6c3dObUhnMVFkdS9na1ZNWS9ZWmZBRE9QM3JhODdHeFBlcFIzOGwyVVhJCmVBcDJFcmJhNXdjaHQ2NHorZSsyNjh2VHZaWUJ5OFU4YTU2a3RtUTMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://192.168.99.104:8443 - name: 192-168-99-104:8443 -contexts: -- context: - cluster: 192-168-99-104:8443 - user: developer/192-168-99-104:8443 - name: /192-168-99-104:8443/developer -- context: - cluster: 127-0-0-1:8443 - namespace: default - user: system:admin/127-0-0-1:8443 - name: default/127-0-0-1:8443/system:admin -- context: - cluster: 192-168-99-104:8443 - namespace: default - user: system:admin/127-0-0-1:8443 - name: default/192-168-99-104:8443/system:admin -- context: - cluster: 192-168-99-103:8443 - namespace: eclipse-che - user: developer/192-168-99-103:8443 - name: eclipse-che/192-168-99-103:8443/developer -- context: - cluster: 192-168-99-104:8443 - namespace: eclipse-che - user: developer/192-168-99-104:8443 - name: eclipse-che/192-168-99-104:8443/developer -- context: - cluster: 192-168-99-104:8443 - namespace: myproject - user: developer/192-168-99-104:8443 - name: minishift -- context: - cluster: 192-168-99-103:8443 - namespace: myproject - user: developer/192-168-99-103:8443 - name: myproject/192-168-99-103:8443/developer -- context: - cluster: 192-168-99-104:8443 - namespace: myproject - user: developer/192-168-99-104:8443 - name: myproject/192-168-99-104:8443/developer -current-context: eclipse-che/192-168-99-104:8443/developer -kind: Config -preferences: {} -users: -- name: developer/192-168-99-103:8443 - user: - token: jfcILwn25kx0SJjpbBL6jbjRv8n8BvXhwQjsLabHp5M -- name: developer/192-168-99-104:8443 - user: - token: k0kpNdAtnH6hjA7AEf5Y58rWkVk2kYizcC_lLmadazM -- name: system:admin/127-0-0-1:8443 - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQnpBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TnpjME5EWXdIaGNOTVRnd016RXlNVGMxTnpJMldoY05NakF3TXpFeApNVGMxTnpJM1dqQTNNUjR3SEFZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNSbGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQUtWdmFZN3RXak0vQzR5TnVtakRwTUZkT1hKbzFRWUkrQ1Bpc090T1JKRVZWcndXdmMyTysyMDJYUDFDR2FmegpuQjVjeXgwOHVwUlFRZ1FnazZvOWVBVG9zY3dEUXl1WDBwRkg2Ymxxc3JUdGg1dS9mWVRGeWs1ZUFVNzVzcklCCjV2Ti9HVGpKS0hpYmVYSG5hb0s1dE0vMm1TVmhIUzNieHpDRS8yemR6ZHJkRHBPc214MFc1clNnbjM5M2NQTzUKd3lvNkNPT3I5V1pXNjRtcVRPdnNxaHRQMmNXK29CdXUvdnMyNVVPQzFSbjBwdG5mVmE5VklLR2s3OHdCUmduaAp2VzZ1SmxDUXBUQ2l3VkJTaXM1Y2tJWDUwbkZBNWpKd3pHMncvaFRiaFMvOXI2bnI0eThRRUt4QXFTdVg2OGhsCmt5TlFEMXBPVVVmTExEeHk4cWRuTDY4Q0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBQ2dmSWtlWXhLS2FvZFZsTGc4cEUzQ2FiMnhGaDRDMGt4TWJ5KzgxVFRCYmJCVngxVHR0NGtBRjNDUVFOZERUCkE5NXdPbmJFVzgzRVl6Tis0c2ZGditFekpET1F4aG1ybE04SjdNU2JPTjBoaU92aW1lTUEwUkxudEhTNFpQdzMKOHA5OE15OTJiZFRWaTJQZkEvbGoyeWMyaHIwaFZMQ3V6dkJjdFBJaEVNamo5ZWxubE9LK3ZRRzNHUzhldldCMQowdCtjd093WDZIQWFSQitVUnlDNTBLOGJRME9HVXM1aTNRNkUwTTBySmttaC9VN0xjWm5VdCtkaVVZbzZLempZCmkyS0s2S1J6L2QrMnVoQktsTm5wZjNndDlSMjJwZi9JaDYvdGhiTUZzOG5WWmcyUGgrNk1nQ3RUallwbndDdHoKdHZOS2FIaURNK0xHM2JQWit0OGJqYW89Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBcFc5cGp1MWFNejhMakkyNmFNT2t3VjA1Y21qVkJnajRJK0t3NjA1RWtSVld2QmE5CnpZNzdiVFpjL1VJWnAvT2NIbHpMSFR5NmxGQkNCQ0NUcWoxNEJPaXh6QU5ESzVmU2tVZnB1V3F5dE8ySG03OTkKaE1YS1RsNEJUdm15c2dIbTgzOFpPTWtvZUp0NWNlZHFncm0wei9hWkpXRWRMZHZITUlUL2JOM04ydDBPazZ5YgpIUmJtdEtDZmYzZHc4N25ES2pvSTQ2djFabGJyaWFwTTYreXFHMC9aeGI2Z0c2NysremJsUTRMVkdmU20yZDlWCnIxVWdvYVR2ekFGR0NlRzlicTRtVUpDbE1LTEJVRktLemx5UWhmblNjVURtTW5ETWJiRCtGTnVGTC8ydnFldmoKTHhBUXJFQ3BLNWZyeUdXVEkxQVBXazVSUjhzc1BITHlwMmN2cndJREFRQUJBb0lCQVFDRUcvOVFxc3dnSmxWagpyWDVSMFFKTmc5T3ZRSFgwdHM3cFlVcms3WUNsMTBPSE9pWGg5QzlsM0ViUDI2dy9TYk8vTDF6b0FTb0I3RUY3CnFFUWphNmpmU3E5SStzWDJGdXlKSmNOSVZTTldobVNIaEppSW9hWlhoSXhJOCsrMlpQeDRNR1FFeSthc3dZTnUKNlYxTi9WeWR3aEEwSUdRN3pjazRQc3oycy8yQ3EwSEJiYmZjRThSd2xESHRaU1lhVUtjQWh0THpNbEpVb0gzeQpiZWNBcnU0b050K0pIQ01aWHRUanB6aFZ5MW41Z3h1Yjcrd29DM2ZaRXFqK3JLNzh1VnNtN0pqejFEWmxpZzUxCi9zS0ZsVDZWSDgzbTQ0Qlkwa0c3SFZpMlFsSTQ1MU9LOHQ3THpDQjY3c2l0UFdSMi9kdkI2YWZ2Q0hnQzk4aWIKTUZqNlpneDVBb0dCQU1ScEZXdXUwWjh2VUlrSDRsaHJ5d2Q3M2RTV2l0NnBnMXV4T1Z6cW5WMVlKWERuOTE3MQoyci9RUXFlRm84WXB6UUR1eXkyWnA4ZCtWcCtSR05vWjYzdlNpUW1jRmJFMkw4ZlhzaThNeWxmZHhEckl2SmFhCm1sbXphcWNSTFJBa0NpbGRvcHI4YmpzSmFwVTl5Q0EvMStQMlo0SlNDR1oyamxxWjVtN0t2V0hGQW9HQkFOZWcKaGh0L3BiUkpzajFKNEJEKzVzY2tJcDBVRjZBK25ycnVSZC85L2wxa21nK1E1alBQbGhWZk5JazBLbUU1ZzJUSgpjUllIc3VwU1gveDlZc1ZsclAyMWNnTlVrMUpiZkZvRUI2NHVwUGhKaEQwbGNnWnNiQThQYVh5VUlSTHd2Si9ZClpLK1JaRlRleVRTRmRhb2ZSVTlYVFROU2t2SEtZcS9DMFpwTHdXYmpBb0dCQUl1N2V3cldIN29SYmtsZSs1QU8KZUM0RjJLYml4ejlyOTlFbS8zbDBUS3BaQ0tJUDFiU1FVcVUrSS8yTW5SeGhKc0R3SWtwNTA1eWc3RDJ2ZTYvRwoydnFIcVFqV0s3U2NxVmVTdytpblA5bE5JOHJ5ZndEaVVzZFlWcHN2SkJFa29yb1ZMSmI0MmU5VVhxaDRnTVU0CnhuNGZFanJyNDZBSjNuTGtwTVRUcGZKRkFvR0FjYXZ4SnN2N0dma0QycVY0VnQxWjRiK2Q4N3JrM1poRmEzd3oKSCtzeFRpQzd5dHJ6VUhydHZ1U0t1STNralk2WlF1ZWpFeDhKNWRkNVBJMEpKZEQ5Q2w2OTlSMS84Sm5FQzF3MgpoRStZcmo5clZDVEtZTEtGb01iYU1FK1N3LzVmSWRFYyt5VWxoRXhTTzdyamxjU1ljRVF3c1k2bFlvdnp6SDVpCnF2bW13a3NDZ1lFQW4xUjAydVFpVW52S2xCT3BIS3J1ajJnUGNFbGZEcWgrUllrT2xtWVQybnJDL29ZQjVRb2wKSmFQQTc2N0hnMjVpdXNjY3MzaXR2dUZRSmxqam5DYWNCNS9NNDd3S09GUWFCSmZ1WWFKVUt5NmNyRWFLQUxOUwpJVzBtWHhZOWxRdnZ3OEY3d3dKcUZLclkyZjVPc3RjdkFjL0JLZXY0UnJVZCtwbktheVFoWjNrPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= diff --git a/dockerfiles/init/modules/openshift/kubeconfig b/dockerfiles/init/modules/openshift/kubeconfig deleted file mode 100644 index 2ce3e00a866..00000000000 --- a/dockerfiles/init/modules/openshift/kubeconfig +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMFdoY05Nak13TXpFeApNVFF6TURRMVdqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE5qVXdORFV3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUREODFCVU9GUzkxeStIcUR2ODB3ZHAKWUNuNERRaDRrcXRjMkJlWTJmeEhKbU1PUzlPZGpGbUhDQWxvNk1TL0ZlNllHT1pXUWY5eVpmeENZZkJFSUIvdApLZG1nUXRUbFBZOUZlVXN3NDlORG5nNWxCUVNVS1REa2tXWTlTRWNaRUUwT3dzTnpaSndncDNSWDBSRzNNVHM2CkR3aGNTNFB5bEEzVWQ0ekhaSmhjZFZtMHVtallyRW8reFJyUXN3eGpvWmt3dVdycXMycWcyV1p6Q0ZyazVGbGMKN2FrTEVVT0N2SEZQTUtmZ1g5cXJtam9qVnZhaEZqS0pZYldJZVRKNlZOeUo1ZC9MUWR3ZHdjZXdsSHpHYWpiaQpIcG53bm13ZHp3MUdVRWM2ZTBha0xJQjBNc2wwY3BlcFZCNG41RHNENnl5eVJqekFQR0FXdXliakZJUUVaa3pwCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQjU3WFhMSlVhSTF4SFFTKytXSHNjNHZvRVhya3hIMk8yNm43UGFOc2NTQ1BKMApRNm5JbjZkemVscG5iQmI5NXJlUUxSRTJoV2d5dEx5Nm15VGVGL3lTSkxua3JNMjE4YmlFZHhCbStZTFJZdHhUCjVKcVU3QnZRbjV2RWxiSzlCVU5NdHgyY1lSQWNaT2d1N0R5eTlNQmtlRzBSMHV5R3laWXBlaE9FR2QyOCtSNGsKR2V3OThCMjV5Q20rVE55bkR1TGc3MmVIVVNKdlRTcDhPeXlEci9qbUNZazMwSWFSZkx3MElvUjEvNXoyd3FNbQo1MmRBaEJud01YdWVON1drUkpaMS85QmZKV3hlYzF2STlhNVNlek1sRnUxa1FneW5YTCtGZFk3WGJOT05YN1FDCitDNmZuS09qTVhnbTdueUY4dXVZd2EyWDcveVdWOFlweE5aU3lQWDMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://127.0.0.1:8443 - name: 127-0-0-1:8443 -- cluster: - certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM2akNDQWRLZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMFdoY05Nak13TXpFeApNVFF6TURRMVdqQW1NU1F3SWdZRFZRUUREQnR2Y0dWdWMyaHBablF0YzJsbmJtVnlRREUxTWpBNE5qVXdORFV3CmdnRWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUUREODFCVU9GUzkxeStIcUR2ODB3ZHAKWUNuNERRaDRrcXRjMkJlWTJmeEhKbU1PUzlPZGpGbUhDQWxvNk1TL0ZlNllHT1pXUWY5eVpmeENZZkJFSUIvdApLZG1nUXRUbFBZOUZlVXN3NDlORG5nNWxCUVNVS1REa2tXWTlTRWNaRUUwT3dzTnpaSndncDNSWDBSRzNNVHM2CkR3aGNTNFB5bEEzVWQ0ekhaSmhjZFZtMHVtallyRW8reFJyUXN3eGpvWmt3dVdycXMycWcyV1p6Q0ZyazVGbGMKN2FrTEVVT0N2SEZQTUtmZ1g5cXJtam9qVnZhaEZqS0pZYldJZVRKNlZOeUo1ZC9MUWR3ZHdjZXdsSHpHYWpiaQpIcG53bm13ZHp3MUdVRWM2ZTBha0xJQjBNc2wwY3BlcFZCNG41RHNENnl5eVJqekFQR0FXdXliakZJUUVaa3pwCkFnTUJBQUdqSXpBaE1BNEdBMVVkRHdFQi93UUVBd0lDcERBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUEwR0NTcUcKU0liM0RRRUJDd1VBQTRJQkFRQjU3WFhMSlVhSTF4SFFTKytXSHNjNHZvRVhya3hIMk8yNm43UGFOc2NTQ1BKMApRNm5JbjZkemVscG5iQmI5NXJlUUxSRTJoV2d5dEx5Nm15VGVGL3lTSkxua3JNMjE4YmlFZHhCbStZTFJZdHhUCjVKcVU3QnZRbjV2RWxiSzlCVU5NdHgyY1lSQWNaT2d1N0R5eTlNQmtlRzBSMHV5R3laWXBlaE9FR2QyOCtSNGsKR2V3OThCMjV5Q20rVE55bkR1TGc3MmVIVVNKdlRTcDhPeXlEci9qbUNZazMwSWFSZkx3MElvUjEvNXoyd3FNbQo1MmRBaEJud01YdWVON1drUkpaMS85QmZKV3hlYzF2STlhNVNlek1sRnUxa1FneW5YTCtGZFk3WGJOT05YN1FDCitDNmZuS09qTVhnbTdueUY4dXVZd2EyWDcveVdWOFlweE5aU3lQWDMKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= - server: https://192.168.99.103:8443 - name: 192-168-99-103:8443 -contexts: -- context: - cluster: 192-168-99-103:8443 - user: developer/192-168-99-103:8443 - name: /192-168-99-103:8443/developer -- context: - cluster: 127-0-0-1:8443 - namespace: default - user: system:admin/127-0-0-1:8443 - name: default/127-0-0-1:8443/system:admin -- context: - cluster: 192-168-99-103:8443 - namespace: default - user: system:admin/127-0-0-1:8443 - name: default/192-168-99-103:8443/system:admin -- context: - cluster: 192-168-99-103:8443 - namespace: myproject - user: developer/192-168-99-103:8443 - name: minishift -- context: - cluster: 192-168-99-103:8443 - namespace: myproject - user: developer/192-168-99-103:8443 - name: myproject/192-168-99-103:8443/developer -current-context: minishift -kind: Config -preferences: {} -users: -- name: developer/192-168-99-103:8443 - user: - token: _-QRfnZ0lSQVS4wUExp4yNMnlr5D6LHL8yE73Zjlm2Y -- name: system:admin/127-0-0-1:8443 - user: - client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lCQ0RBTkJna3Foa2lHOXcwQkFRc0ZBREFtTVNRd0lnWURWUVFEREJ0dmNHVnUKYzJocFpuUXRjMmxuYm1WeVFERTFNakE0TmpVd05EVXdIaGNOTVRnd016RXlNVFF6TURRMVdoY05NakF3TXpFeApNVFF6TURRMldqQTNNUjR3SEFZRFZRUUtFeFZ6ZVhOMFpXMDZZMngxYzNSbGNpMWhaRzFwYm5NeEZUQVRCZ05WCkJBTVRESE41YzNSbGJUcGhaRzFwYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUIKQUw5S25zWE04T2g5TlA5eWNyRDFnVGxTVkdCZ212bzAvYnZTQ1RXeXJxbU4xNGE5YnR6UUU2SWNZWTRtT0FBagoveFJNWjRHclBJSGpET2Z0MjhmMisvemtQZk15Q09tS3dvRTRtNFRtSCtBNnFHNDBua29JeGc4bXpFUlRNSzg4Cmtzd1ZPcmMzOXJXalVhbVIwT1ZwSDh1WTd6dmNueC9GcU54YlJBbU9TN3BoMU1UWXd6VmMvUWpiUkRCZGViYjIKV3VUS0hKSzM1bzZZSnVkUE5NUUpXeStaVmpMRUJXU1EraUc4SVFKSTd6T0lmQ2F6OXh5cEN2VHBicjZaV0NJRwpPV0wvSzV2NG80Nmk5Q3BDazA1Z2N6S0JiWVRZVkRvY3ZPV3ZZN2Vmbnhva3hZMENDZm9tM216NDBZOWRVT3BYCnJ6Zk1Zd0R0MHEySkltSmNhOWtKOFRVQ0F3RUFBYU0xTURNd0RnWURWUjBQQVFIL0JBUURBZ1dnTUJNR0ExVWQKSlFRTU1Bb0dDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBR2RsdWNWSFN3Uk9Dem13cmlza0hkWVhnczBVRWFSRWZZYTNET0RVeXJuR1hIMlVEVnVNSHM4REJ6Wnd1QTdOCkt6T1BFaFR4WFZ3SFdwWEtKME5VQXpaSkNhT2tZMmF3cGFNbkhnZHJMcWtXOStMTmRERk80SE10N08rNWVwbzMKTHBSK0puQmpkZFBUQTdFL3pFQm9sOUhmczZvM3BGMUVuZ2lVcWR3Y3hlUmR5SllwR21zTkNPSzBtcUFFUStsbgpvb050Z2J0TFdWNDJWR2F6OVhkaTk4SHZRcDJ6bWF1d3BjL3UweHlsdWNZQ0U4ZFY1Rk1UWU84UXZmUkdjTDJGCnJNMU9STm5GN3ZocGNjaSttRU52RzRKVGtHWnVEUVVCdVI4dXYvVE9uNDBEdVVLYm0rN2ltR1RsUVhCcU9henAKaHl3NE9EalVlV0tUR2ZtemQxeHdJVDQ9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K - client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdjBxZXhjenc2SDAwLzNKeXNQV0JPVkpVWUdDYStqVDl1OUlKTmJLdXFZM1hocjF1CjNOQVRvaHhoamlZNEFDUC9GRXhuZ2FzOGdlTU01KzNieC9iNy9PUTk4eklJNllyQ2dUaWJoT1lmNERxb2JqU2UKU2dqR0R5Yk1SRk13cnp5U3pCVTZ0emYydGFOUnFaSFE1V2tmeTVqdk85eWZIOFdvM0Z0RUNZNUx1bUhVeE5qRApOVno5Q050RU1GMTV0dlphNU1vY2tyZm1qcGdtNTA4MHhBbGJMNWxXTXNRRlpKRDZJYndoQWtqdk00aDhKclAzCkhLa0s5T2x1dnBsWUlnWTVZdjhybS9pampxTDBLa0tUVG1Cek1vRnRoTmhVT2h5ODVhOWp0NStmR2lURmpRSUoKK2liZWJQalJqMTFRNmxldk44eGpBTzNTcllraVlseHIyUW54TlFJREFRQUJBb0lCQVFDSWE1MERqMzZYTHdQbQowU1grRVhmUSsyZjFPN0FLbEZRSDZHaHRCVHNPN0hzeU9sS2Y0enk5TmVSVXplak9JTjIvQ2lZZkVaR2JSK05pClcvMkxoQlo5YWdETU9YaWxwVEhGbWlzL0FpYmxjSy9CdUlEU1o2Tm9GdEZDUU5uTmZ6TnBuQkk5ckFtanpBOW4KRVBpYlF2ZEw2WXRqYzVsL3ZTVUowWVNhRkFMcHJiT2E1QzVWT2x6T09yd0oxTlp3NFM0ZW1YME1aNW55R2lNNQp0Z1F1Q3JlU2ZoMlNTNjJLejhzTSs0Q01ZUU44V1ZJTGpHNWZ2THV3anJ4ak1hdzhyemNxRlNXNlBtbGdBMFlHCnE3QTFIUnY2UmJWRWNBN1VuMzdFK3VxTDRpZEhRUHJyUW9SM1lTUG5RZEx5b0t1Mk9KOXpqbjZsdzI4a2d0VXAKY1BOQVdSdUJBb0dCQU5iUjdlTVFoUis3Ni9uclV3QnpiSEpZYm9OaWZZQWM0ODVkNGNKSlVWaHhmcXg5L1ZNdQp3Z3dUUkUvYlhaNmxRV0orTUtpL1RVYUpVVzF3U0N0QzN6UDE4Y0ljR3hyYWdSejBhcy9wekF6K0hDTEFjR3dRCk1welZVV3B5MmVQa2NXL0R0M3BjKzFwNDNRdk1xVm01b0ZVNUczeC8yWTJiYXQ4dURMRThnMnVGQW9HQkFPUDIKRFR2VHIrYk9VckVDdEp3QXJ6RlNTZ2R0QzRNZ0NXOC9LSzlyZ2o5TElDRUM2TGptbkE2ZTI5TXJHR2VtMkR5VwpoZEN1UUxPTjBGblBKNkNWaEo1c1JkelZibi9abFN2ZVVRUU4wb1JyeTVRV0N6djVhcGdhVGdFZVo3NmtUdjAvCnpWYnB2dERvZEVZMmM4ZTluUS9sZkEzTUdLMzVIcWlmRGFLemdhWHhBb0dBYktRT290OGY5RVNkdXU4QU15SXMKbmtlSzNIZGE4UWVyVGhxOHFmMWFYbGhIc0FTbnNRSGNzUzZ0UlpXemF5QTRTUTk0bkY3alBlRUVoVXhiczBWRwpqSWk5azJXVGI2bEIwdHJwaWV5N2ZYYWwxQTF1emJnRFlMMmhSeXgrZFhwNnhBTS9MMnNHMDJKOHFCTUJNcGRtCk5yT0M2eHZkY25nL1BFK1ZxNnptNmVFQ2dZQTJ6OXpTdTgyWnc1WmlkWElUNko0M1Q3LzVGU0VsZ0RpRWhUMDEKSUxhS25YZTJPRXJZMnFvL1liY2RpVWt1OHhFZlVGb1FtVFY1ZHVuWURsVks2V2lmNXd6TlVveGxOVjRHMUVmSwpuOEEwa3U2NlJxcWcyeEhrVEw3Z3lmekwvQm42RHJOQzZLVTIrZzJyTEVDZWtGc0pqWFpNb3Z4MEtHaFV4eG15Ck8xTTdJUUtCZ1FDb1ZnQldlUXAyUUFTZTRlSk11cEF2RXFOTXd2QjdjcFQ4M2dtdUJyWVFMeDA1dFBwMjk3S1MKY2U4cUZTUU13M0o5MHRzOVpkeGZrcE8rWXk1OTVqNVZsYWxDY1dnbE8yeVFkc3VCYjhId0thclJHN2k2b3JLdQp1aE9vc3hHL3M4UmJUVlBzSlRkdE9zN2I0elBXSFVpcTUyNDhHUSt2a3FxZUdBZitiUENMY0E9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=