Signed-off-by: Michal Vala <mvala@redhat.com>7.20.x
parent
917425bb73
commit
e541b7ee8d
|
|
@ -257,6 +257,12 @@ che.infra.kubernetes.server_strategy=multi-host
|
|||
# - 'gateway': Exposes servers using reverse-proxy gateway.
|
||||
che.infra.kubernetes.singlehost.workspace.exposure=native
|
||||
|
||||
# Defines the way how to expose devfile endpoints, thus end-user's applications, in single-host server strategy.
|
||||
# They can either follow the single-host strategy and be exposed on subpaths, or they can be exposed on subdomains.
|
||||
# - 'multi-host': expose on subdomains
|
||||
# - 'single-host': expose on subpaths
|
||||
che.infra.kubernetes.singlehost.workspace.devfile_endpoint_exposure=multi-host
|
||||
|
||||
# Defines labels which will be set to ConfigMaps configuring single-host gateway.
|
||||
che.infra.kubernetes.singlehost.gateway.configmap_labels=app=che,component=che-gateway-config
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,11 @@ public interface ServerConfig {
|
|||
*/
|
||||
String SERVICE_PORT_ATTRIBUTE = "servicePort";
|
||||
|
||||
/**
|
||||
* This attributes is marking that server come from the devfile endpoint. Used internally only.
|
||||
*/
|
||||
String DEVFILE_ENDPOINT = "devfileEndpoint";
|
||||
|
||||
/**
|
||||
* Port used by server.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -69,10 +69,13 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.server.PreviewUrlExpo
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.WorkspaceExposureType;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.DefaultHostExternalServiceExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServiceExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.GatewayServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.IngressServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.KubernetesExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.MultiHostExternalServiceExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.MultihostIngressServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ServiceExposureStrategyProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.SingleHostExternalServiceExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposer;
|
||||
|
|
@ -162,15 +165,21 @@ public class KubernetesInfraModule extends AbstractModule {
|
|||
|
||||
MapBinder<WorkspaceExposureType, ExternalServerExposer<KubernetesEnvironment>>
|
||||
exposureStrategies =
|
||||
MapBinder.newMapBinder(
|
||||
binder(),
|
||||
new TypeLiteral<WorkspaceExposureType>() {},
|
||||
new TypeLiteral<ExternalServerExposer<KubernetesEnvironment>>() {});
|
||||
exposureStrategies.addBinding(WorkspaceExposureType.NATIVE).to(IngressServerExposer.class);
|
||||
MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>() {});
|
||||
exposureStrategies
|
||||
.addBinding(WorkspaceExposureType.NATIVE)
|
||||
.to(new TypeLiteral<IngressServerExposer<KubernetesEnvironment>>() {});
|
||||
exposureStrategies
|
||||
.addBinding(WorkspaceExposureType.GATEWAY)
|
||||
.to(new TypeLiteral<GatewayServerExposer<KubernetesEnvironment>>() {});
|
||||
|
||||
bind(new TypeLiteral<ExternalServerExposer<KubernetesEnvironment>>() {})
|
||||
.annotatedWith(com.google.inject.name.Names.named("multihost-exposer"))
|
||||
.to(new TypeLiteral<MultihostIngressServerExposer<KubernetesEnvironment>>() {});
|
||||
|
||||
bind(new TypeLiteral<ExternalServerExposerProvider<KubernetesEnvironment>>() {})
|
||||
.to(new TypeLiteral<KubernetesExternalServerExposerProvider<KubernetesEnvironment>>() {});
|
||||
|
||||
bind(ServersConverter.class).to(new TypeLiteral<ServersConverter<KubernetesEnvironment>>() {});
|
||||
bind(PreviewUrlExposer.class)
|
||||
.to(new TypeLiteral<PreviewUrlExposer<KubernetesEnvironment>>() {});
|
||||
|
|
|
|||
|
|
@ -141,7 +141,8 @@ public class DockerimageComponentToWorkspaceApplier implements ComponentToWorksp
|
|||
.getEndpoints()
|
||||
.stream()
|
||||
.collect(
|
||||
Collectors.toMap(Endpoint::getName, ServerConfigImpl::createFromEndpoint)));
|
||||
Collectors.toMap(
|
||||
Endpoint::getName, e -> ServerConfigImpl.createFromEndpoint(e, true))));
|
||||
|
||||
dockerimageComponent
|
||||
.getVolumes()
|
||||
|
|
|
|||
|
|
@ -264,7 +264,8 @@ public class KubernetesComponentToWorkspaceApplier implements ComponentToWorkspa
|
|||
.getEndpoints()
|
||||
.stream()
|
||||
.collect(
|
||||
Collectors.toMap(Endpoint::getName, ServerConfigImpl::createFromEndpoint)));
|
||||
Collectors.toMap(
|
||||
Endpoint::getName, e -> ServerConfigImpl.createFromEndpoint(e, true))));
|
||||
}
|
||||
|
||||
private void provisionVolumes(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.external;
|
||||
|
||||
import static java.lang.Boolean.FALSE;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.DEVFILE_ENDPOINT;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.ServicePort;
|
||||
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.environment.KubernetesEnvironment;
|
||||
|
||||
/**
|
||||
* This {@link ExternalServerExposer} is used in single-host mode when we need to expose some
|
||||
* servers on subdomain, instead of subpaths.
|
||||
*
|
||||
* <p>It aggregates 2 {@link ExternalServerExposer}s, using one to expose servers on subdomand, and
|
||||
* 2nd to expose servers on subpaths. It determines which to use for individual server based on some
|
||||
* attribute in {@link ServerConfig#getAttributes()} (see implementation {@link
|
||||
* CombinedSingleHostServerExposer#expose(KubernetesEnvironment, String, String, String,
|
||||
* ServicePort, Map)} for the details).
|
||||
*
|
||||
* @param <T> environment type
|
||||
*/
|
||||
public class CombinedSingleHostServerExposer<T extends KubernetesEnvironment>
|
||||
implements ExternalServerExposer<T> {
|
||||
|
||||
private final ExternalServerExposer<T> subdomainServerExposer;
|
||||
private final ExternalServerExposer<T> subpathServerExposer;
|
||||
|
||||
public CombinedSingleHostServerExposer(
|
||||
ExternalServerExposer<T> subdomainServerExposer,
|
||||
ExternalServerExposer<T> subpathServerExposer) {
|
||||
this.subdomainServerExposer = subdomainServerExposer;
|
||||
this.subpathServerExposer = subpathServerExposer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes given 'externalServers' to either subdomain or subpath, using 2 different {@link
|
||||
* ExternalServerExposer}s. Which one to use for individual server is determined with {@link
|
||||
* ServerConfig#DEVFILE_ENDPOINT} attribute.
|
||||
*
|
||||
* @param k8sEnv environment
|
||||
* @param machineName machine containing servers
|
||||
* @param serviceName service associated with machine, mapping all machine server ports
|
||||
* @param serverId non-null for a unique server, null for a compound set of servers that should be
|
||||
* exposed together.
|
||||
* @param servicePort specific service port to be exposed externally
|
||||
* @param externalServers server configs of servers to be exposed externally
|
||||
*/
|
||||
@Override
|
||||
public void expose(
|
||||
T k8sEnv,
|
||||
String machineName,
|
||||
String serviceName,
|
||||
String serverId,
|
||||
ServicePort servicePort,
|
||||
Map<String, ServerConfig> externalServers) {
|
||||
|
||||
if (serverId == null) {
|
||||
// this is the ID for non-unique servers
|
||||
serverId = servicePort.getName();
|
||||
}
|
||||
|
||||
Map<String, ServerConfig> subpathServers = new HashMap<>();
|
||||
Map<String, ServerConfig> subdomainServers = new HashMap<>();
|
||||
|
||||
for (String esKey : externalServers.keySet()) {
|
||||
ServerConfig serverConfig = externalServers.get(esKey);
|
||||
if (Boolean.parseBoolean(
|
||||
serverConfig.getAttributes().getOrDefault(DEVFILE_ENDPOINT, FALSE.toString()))) {
|
||||
subdomainServers.put(esKey, serverConfig);
|
||||
} else {
|
||||
subpathServers.put(esKey, serverConfig);
|
||||
}
|
||||
}
|
||||
|
||||
if (!subpathServers.isEmpty()) {
|
||||
subpathServerExposer.expose(
|
||||
k8sEnv, machineName, serviceName, serverId, servicePort, subpathServers);
|
||||
}
|
||||
|
||||
if (!subdomainServers.isEmpty()) {
|
||||
subdomainServerExposer.expose(
|
||||
k8sEnv, machineName, serviceName, serverId, servicePort, subdomainServers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,33 +11,13 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.external;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.inject.Provider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.AbstractExposureStrategyAwareProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.WorkspaceExposureType;
|
||||
|
||||
/**
|
||||
* Provides {@link ExternalServerExposer} based on `che.infra.kubernetes.server_strategy` and
|
||||
* `che.infra.kubernetes.singlehost.workspace.exposure` properties.
|
||||
* Provides {@link ExternalServerExposer} implementations based on configuration.
|
||||
*
|
||||
* @param <T> type of environment
|
||||
*/
|
||||
@Singleton
|
||||
public class ExternalServerExposerProvider<T extends KubernetesEnvironment>
|
||||
extends AbstractExposureStrategyAwareProvider<ExternalServerExposer<T>> {
|
||||
@Inject
|
||||
public ExternalServerExposerProvider(
|
||||
@Named("che.infra.kubernetes.server_strategy") String exposureStrategy,
|
||||
@Named("che.infra.kubernetes.singlehost.workspace.exposure") String exposureType,
|
||||
Map<WorkspaceExposureType, ExternalServerExposer<T>> exposers) {
|
||||
|
||||
super(
|
||||
exposureStrategy,
|
||||
exposureType,
|
||||
exposers,
|
||||
"Could not find an external server exposer implementation for the exposure type '%s'.");
|
||||
}
|
||||
}
|
||||
public interface ExternalServerExposerProvider<T extends KubernetesEnvironment>
|
||||
extends Provider<ExternalServerExposer<T>> {}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.server.KubernetesServ
|
|||
* @see ExternalServerExposer
|
||||
*/
|
||||
@Singleton
|
||||
public class IngressServerExposer implements ExternalServerExposer<KubernetesEnvironment> {
|
||||
public class IngressServerExposer<T extends KubernetesEnvironment>
|
||||
implements ExternalServerExposer<T> {
|
||||
|
||||
/**
|
||||
* A string to look for in the value of the "che.infra.kubernetes.ingress.path_transform"
|
||||
|
|
@ -69,7 +70,7 @@ public class IngressServerExposer implements ExternalServerExposer<KubernetesEnv
|
|||
*/
|
||||
@Override
|
||||
public void expose(
|
||||
KubernetesEnvironment k8sEnv,
|
||||
T k8sEnv,
|
||||
@Nullable String machineName,
|
||||
String serviceName,
|
||||
String serverId,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.external;
|
||||
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.server.external.MultiHostExternalServiceExposureStrategy.MULTI_HOST_STRATEGY;
|
||||
import static org.eclipse.che.workspace.infrastructure.kubernetes.server.external.SingleHostExternalServiceExposureStrategy.SINGLE_HOST_STRATEGY;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.AbstractExposureStrategyAwareProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.WorkspaceExposureType;
|
||||
|
||||
/**
|
||||
* Provides {@link ExternalServerExposer} based on `che.infra.kubernetes.server_strategy` and
|
||||
* `che.infra.kubernetes.singlehost.workspace.exposure` properties.
|
||||
*
|
||||
* <p>Based on server strategy, it can create a {@link CombinedSingleHostServerExposer} with
|
||||
* Kubernetes specific {@link IngressServerExposer} for exposing servers on subdomains.
|
||||
*
|
||||
* @param <T> type of environment
|
||||
*/
|
||||
@Singleton
|
||||
public class KubernetesExternalServerExposerProvider<T extends KubernetesEnvironment>
|
||||
extends AbstractExposureStrategyAwareProvider<ExternalServerExposer<T>>
|
||||
implements ExternalServerExposerProvider<T> {
|
||||
|
||||
private final ExternalServerExposer<T> combinedInstance;
|
||||
|
||||
@Inject
|
||||
public KubernetesExternalServerExposerProvider(
|
||||
@Named("che.infra.kubernetes.server_strategy") String exposureStrategy,
|
||||
@Named("che.infra.kubernetes.singlehost.workspace.exposure") String exposureType,
|
||||
@Named("che.infra.kubernetes.singlehost.workspace.devfile_endpoint_exposure")
|
||||
String devfileEndpointsExposure,
|
||||
@Named("multihost-exposer") ExternalServerExposer<T> multihostExposer,
|
||||
Map<WorkspaceExposureType, ExternalServerExposer<T>> exposers) {
|
||||
super(
|
||||
exposureStrategy,
|
||||
exposureType,
|
||||
exposers,
|
||||
"Could not find an external server exposer implementation for the exposure type '%s'.");
|
||||
|
||||
if (SINGLE_HOST_STRATEGY.equals(exposureStrategy)
|
||||
&& MULTI_HOST_STRATEGY.equals(devfileEndpointsExposure)) {
|
||||
this.combinedInstance = new CombinedSingleHostServerExposer<>(multihostExposer, instance);
|
||||
} else {
|
||||
this.combinedInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExternalServerExposer<T> get() {
|
||||
return combinedInstance != null ? combinedInstance : instance;
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ import org.eclipse.che.inject.ConfigurationException;
|
|||
public class MultiHostExternalServiceExposureStrategy implements ExternalServiceExposureStrategy {
|
||||
|
||||
public static final String MULTI_HOST_STRATEGY = "multi-host";
|
||||
private static final String INGRESS_DOMAIN_PROPERTY = "che.infra.kubernetes.ingress.domain";
|
||||
protected static final String INGRESS_DOMAIN_PROPERTY = "che.infra.kubernetes.ingress.domain";
|
||||
|
||||
private final String domain;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.external;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.extensions.Ingress;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import org.eclipse.che.commons.annotation.Nullable;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
|
||||
|
||||
/**
|
||||
* Uses Kubernetes {@link Ingress}es to expose the services using subdomains a.k.a. multi-host.
|
||||
*
|
||||
* @see ExternalServerExposer
|
||||
*/
|
||||
@Singleton
|
||||
public class MultihostIngressServerExposer<T extends KubernetesEnvironment>
|
||||
extends IngressServerExposer<T> implements ExternalServerExposer<T> {
|
||||
@Inject
|
||||
public MultihostIngressServerExposer(
|
||||
MultiHostExternalServiceExposureStrategy serviceExposureStrategy,
|
||||
@Named("infra.kubernetes.ingress.annotations") Map<String, String> annotations,
|
||||
@Nullable @Named("che.infra.kubernetes.ingress.labels") String labelsProperty,
|
||||
@Nullable @Named("che.infra.kubernetes.ingress.path_transform") String pathTransformFmt) {
|
||||
super(serviceExposureStrategy, annotations, labelsProperty, pathTransformFmt);
|
||||
}
|
||||
}
|
||||
|
|
@ -76,12 +76,4 @@ public abstract class AbstractServerResolver implements ServerResolver {
|
|||
.build(),
|
||||
(s1, s2) -> s2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve external servers from implementation specific k8s object and it's annotations.
|
||||
*
|
||||
* @param machineName machine to resolve servers
|
||||
* @return resolved servers
|
||||
*/
|
||||
protected abstract Map<String, ServerImpl> resolveExternalServers(String machineName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import com.google.common.collect.ArrayListMultimap;
|
|||
import com.google.common.collect.Multimap;
|
||||
import io.fabric8.kubernetes.api.model.ConfigMap;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -27,10 +28,15 @@ public class ConfigMapServerResolver extends AbstractServerResolver {
|
|||
|
||||
private final Multimap<String, ConfigMap> configMaps;
|
||||
private final String cheHost;
|
||||
private final ServerResolver nativeServerResolver;
|
||||
|
||||
public ConfigMapServerResolver(
|
||||
Iterable<Service> services, Iterable<ConfigMap> configMaps, String cheHost) {
|
||||
Iterable<Service> services,
|
||||
Iterable<ConfigMap> configMaps,
|
||||
String cheHost,
|
||||
ServerResolver nativeServerResolver) {
|
||||
super(services);
|
||||
this.nativeServerResolver = nativeServerResolver;
|
||||
this.cheHost = cheHost;
|
||||
|
||||
this.configMaps = ArrayListMultimap.create();
|
||||
|
|
@ -44,13 +50,17 @@ public class ConfigMapServerResolver extends AbstractServerResolver {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
return configMaps
|
||||
.get(machineName)
|
||||
.stream()
|
||||
.map(this::fillGatewayServers)
|
||||
.flatMap(m -> m.entrySet().stream())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (s1, s2) -> s2));
|
||||
public Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
Map<String, ServerImpl> serverMap = new HashMap<>();
|
||||
serverMap.putAll(nativeServerResolver.resolveExternalServers(machineName));
|
||||
serverMap.putAll(
|
||||
configMaps
|
||||
.get(machineName)
|
||||
.stream()
|
||||
.map(this::fillGatewayServers)
|
||||
.flatMap(m -> m.entrySet().stream())
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (s1, s2) -> s2)));
|
||||
return serverMap;
|
||||
}
|
||||
|
||||
private Map<String, ServerImpl> fillGatewayServers(ConfigMap configMap) {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ public class IngressServerResolver extends AbstractServerResolver {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
public Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
return ingresses
|
||||
.get(machineName)
|
||||
.stream()
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ public class KubernetesServerResolverFactory extends AbstractServerResolverFacto
|
|||
exposureStrategy,
|
||||
wsExposureType,
|
||||
ImmutableMap.of(
|
||||
GATEWAY, (ss, is, cs) -> new ConfigMapServerResolver(ss, cs, cheHost),
|
||||
GATEWAY,
|
||||
(ss, is, cs) ->
|
||||
new ConfigMapServerResolver(
|
||||
ss, cs, cheHost, new IngressServerResolver(pathTransformInverter, ss, is)),
|
||||
NATIVE, (ss, is, cs) -> new IngressServerResolver(pathTransformInverter, ss, is)),
|
||||
"Failed to initialize KubernetesServerResolverFactory for workspace exposure type '%s'.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,4 +35,12 @@ public interface ServerResolver {
|
|||
* @return resolved servers
|
||||
*/
|
||||
Map<String, ServerImpl> resolve(String machineName);
|
||||
|
||||
/**
|
||||
* Resolve external servers from implementation specific k8s object and it's annotations.
|
||||
*
|
||||
* @param machineName machine to resolve servers
|
||||
* @return resolved servers
|
||||
*/
|
||||
Map<String, ServerImpl> resolveExternalServers(String machineName);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ public class DockerimageComponentToWorkspaceApplierTest {
|
|||
Map<String, String> attributes = serverConfig.getAttributes();
|
||||
assertEquals(attributes.get(ServerConfig.INTERNAL_SERVER_ATTRIBUTE), "true");
|
||||
assertEquals(attributes.get("secure"), "false");
|
||||
assertEquals(attributes.get(ServerConfig.DEVFILE_ENDPOINT), "true");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import static java.util.Collections.singletonList;
|
|||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.Command.MACHINE_NAME_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.DEVFILE_COMPONENT_ALIAS_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.DEVFILE_ENDPOINT;
|
||||
import static org.eclipse.che.api.workspace.server.devfile.Constants.COMPONENT_ALIAS_COMMAND_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.workspace.server.devfile.Constants.KUBERNETES_COMPONENT_TYPE;
|
||||
import static org.eclipse.che.api.workspace.server.devfile.Constants.OPENSHIFT_COMPONENT_TYPE;
|
||||
|
|
@ -678,6 +679,8 @@ public class KubernetesComponentToWorkspaceApplierTest {
|
|||
assertEquals(serverConfigs.get(endpointName).getPort(), endpointPort.toString());
|
||||
assertEquals(serverConfigs.get(endpointName).getPath(), endpointPath);
|
||||
assertEquals(serverConfigs.get(endpointName).getProtocol(), endpointProtocol);
|
||||
assertEquals(
|
||||
serverConfigs.get(endpointName).getAttributes().get(DEVFILE_ENDPOINT), "true");
|
||||
assertEquals(
|
||||
serverConfigs.get(endpointName).isSecure(), Boolean.parseBoolean(endpointSecure));
|
||||
assertEquals(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.external;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.DEVFILE_ENDPOINT;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
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.api.workspace.server.model.impl.ServerConfigImpl;
|
||||
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;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class CombinedSingleHostServerExposerTest {
|
||||
|
||||
@Mock private KubernetesEnvironment env;
|
||||
|
||||
private final String MACHINE = "machine";
|
||||
private final String SERVICE = "service";
|
||||
private final String SERVER = "server";
|
||||
private final ServicePort PORT = new ServicePort();
|
||||
|
||||
@Mock private ExternalServerExposer<KubernetesEnvironment> subdomainExposer;
|
||||
@Mock private ExternalServerExposer<KubernetesEnvironment> subpathExposer;
|
||||
|
||||
@Test
|
||||
public void shouldExposeDevfileServersOnSubdomans() {
|
||||
// given
|
||||
ServerConfig s1 = new ServerConfigImpl("1", "http", "/", emptyMap());
|
||||
ServerConfig s2 =
|
||||
new ServerConfigImpl("2", "http", "/", singletonMap(DEVFILE_ENDPOINT, "false"));
|
||||
ServerConfig s3 =
|
||||
new ServerConfigImpl("3", "http", "/", singletonMap(DEVFILE_ENDPOINT, "true"));
|
||||
|
||||
CombinedSingleHostServerExposer<KubernetesEnvironment> serverExposer =
|
||||
new CombinedSingleHostServerExposer<>(subdomainExposer, subpathExposer);
|
||||
|
||||
// when
|
||||
serverExposer.expose(env, MACHINE, SERVICE, SERVER, PORT, Map.of("s1", s1, "s2", s2, "s3", s3));
|
||||
|
||||
// then
|
||||
verify(subdomainExposer).expose(env, MACHINE, SERVICE, SERVER, PORT, Map.of("s3", s3));
|
||||
verify(subpathExposer).expose(env, MACHINE, SERVICE, SERVER, PORT, Map.of("s1", s1, "s2", s2));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.kubernetes.server.resolver;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Listeners(MockitoTestNGListener.class)
|
||||
public class ConfigMapServerResolverTest {
|
||||
@Mock private ServerResolver nativeServerResolver;
|
||||
|
||||
@Test
|
||||
public void shouldIncludeServersFromNativeResolver() {
|
||||
// given
|
||||
ServerImpl server = new ServerImpl("server", ServerStatus.UNKNOWN, emptyMap());
|
||||
when(nativeServerResolver.resolveExternalServers("test"))
|
||||
.thenReturn(singletonMap("s1", server));
|
||||
|
||||
ConfigMapServerResolver serverResolver =
|
||||
new ConfigMapServerResolver(emptyList(), emptyList(), "che.host", nativeServerResolver);
|
||||
|
||||
// when
|
||||
Map<String, ServerImpl> resolvedServers = serverResolver.resolve("test");
|
||||
|
||||
// then
|
||||
assertTrue(resolvedServers.containsKey("s1"));
|
||||
assertEquals(resolvedServers.get("s1"), server);
|
||||
}
|
||||
}
|
||||
|
|
@ -72,6 +72,7 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.provision.server.Serv
|
|||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.PreviewUrlExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.WorkspaceExposureType;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServiceExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.GatewayServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ServiceExposureStrategyProvider;
|
||||
|
|
@ -101,6 +102,7 @@ import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftCookie
|
|||
import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftPreviewUrlExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.server.OpenShiftServerExposureStrategy;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.server.RouteServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.server.external.OpenShiftExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.wsplugins.brokerphases.OpenshiftBrokerEnvironmentFactory;
|
||||
|
||||
/** @author Sergii Leshchenko */
|
||||
|
|
@ -146,15 +148,19 @@ public class OpenShiftInfraModule extends AbstractModule {
|
|||
|
||||
MapBinder<WorkspaceExposureType, ExternalServerExposer<OpenShiftEnvironment>>
|
||||
exposureStrategies =
|
||||
MapBinder.newMapBinder(
|
||||
binder(),
|
||||
new TypeLiteral<WorkspaceExposureType>() {},
|
||||
new TypeLiteral<ExternalServerExposer<OpenShiftEnvironment>>() {});
|
||||
MapBinder.newMapBinder(binder(), new TypeLiteral<>() {}, new TypeLiteral<>() {});
|
||||
exposureStrategies.addBinding(WorkspaceExposureType.NATIVE).to(RouteServerExposer.class);
|
||||
exposureStrategies
|
||||
.addBinding(WorkspaceExposureType.GATEWAY)
|
||||
.to(new TypeLiteral<GatewayServerExposer<OpenShiftEnvironment>>() {});
|
||||
|
||||
bind(new TypeLiteral<ExternalServerExposer<OpenShiftEnvironment>>() {})
|
||||
.annotatedWith(com.google.inject.name.Names.named("multihost-exposer"))
|
||||
.to(RouteServerExposer.class);
|
||||
|
||||
bind(new TypeLiteral<ExternalServerExposerProvider<OpenShiftEnvironment>>() {})
|
||||
.to(OpenShiftExternalServerExposerProvider.class);
|
||||
|
||||
bind(ServersConverter.class).to(new TypeLiteral<ServersConverter<OpenShiftEnvironment>>() {});
|
||||
bind(PreviewUrlExposer.class).to(new TypeLiteral<OpenShiftPreviewUrlExposer>() {});
|
||||
bind(PreviewUrlCommandProvisioner.class)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ public class OpenShiftServerResolverFactory extends AbstractServerResolverFactor
|
|||
exposureStrategy,
|
||||
wsExposureType,
|
||||
ImmutableMap.of(
|
||||
GATEWAY, (ss, rs, cs) -> new ConfigMapServerResolver(ss, cs, cheHost),
|
||||
GATEWAY,
|
||||
(ss, rs, cs) ->
|
||||
new ConfigMapServerResolver(ss, cs, cheHost, new RouteServerResolver(ss, rs)),
|
||||
NATIVE, (ss, rs, cs) -> new RouteServerResolver(ss, rs)),
|
||||
"Failed to initialize OpenShiftServerResolverFactory for workspace exposure type '%s'.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class RouteServerResolver extends AbstractServerResolver {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
public Map<String, ServerImpl> resolveExternalServers(String machineName) {
|
||||
return routes
|
||||
.get(machineName)
|
||||
.stream()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2018 Red Hat, Inc.
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*
|
||||
* Contributors:
|
||||
* Red Hat, Inc. - initial API and implementation
|
||||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift.server.external;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.WorkspaceExposureType;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.CombinedSingleHostServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposer;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.ExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.kubernetes.server.external.KubernetesExternalServerExposerProvider;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.server.RouteServerExposer;
|
||||
|
||||
/**
|
||||
* Provides {@link ExternalServerExposer} based on `che.infra.kubernetes.server_strategy` and
|
||||
* `che.infra.kubernetes.singlehost.workspace.exposure` properties.
|
||||
*
|
||||
* <p>Based on server strategy, it can create a {@link CombinedSingleHostServerExposer} with
|
||||
* OpenShift specific {@link RouteServerExposer} for exposing servers on subdomains.
|
||||
*/
|
||||
public class OpenShiftExternalServerExposerProvider
|
||||
extends KubernetesExternalServerExposerProvider<OpenShiftEnvironment>
|
||||
implements ExternalServerExposerProvider<OpenShiftEnvironment> {
|
||||
|
||||
@Inject
|
||||
public OpenShiftExternalServerExposerProvider(
|
||||
@Named("che.infra.kubernetes.server_strategy") String exposureStrategy,
|
||||
@Named("che.infra.kubernetes.singlehost.workspace.exposure") String exposureType,
|
||||
@Named("che.infra.kubernetes.singlehost.workspace.devfile_endpoint_exposure")
|
||||
String devfileEndpointExposure,
|
||||
@Named("multihost-exposer") ExternalServerExposer<OpenShiftEnvironment> multihostExposer,
|
||||
Map<WorkspaceExposureType, ExternalServerExposer<OpenShiftEnvironment>> exposers) {
|
||||
super(exposureStrategy, exposureType, devfileEndpointExposure, multihostExposer, exposers);
|
||||
}
|
||||
}
|
||||
|
|
@ -180,7 +180,7 @@ public class ServerConfigImpl implements ServerConfig {
|
|||
+ '}';
|
||||
}
|
||||
|
||||
public static ServerConfigImpl createFromEndpoint(Endpoint endpoint) {
|
||||
public static ServerConfigImpl createFromEndpoint(Endpoint endpoint, boolean devfileEndpoint) {
|
||||
HashMap<String, String> attributes = new HashMap<>(endpoint.getAttributes());
|
||||
attributes.put(SERVER_NAME_ATTRIBUTE, endpoint.getName());
|
||||
|
||||
|
|
@ -196,6 +196,14 @@ public class ServerConfigImpl implements ServerConfig {
|
|||
ServerConfig.setInternal(attributes, true);
|
||||
}
|
||||
|
||||
if (devfileEndpoint) {
|
||||
attributes.put(DEVFILE_ENDPOINT, Boolean.TRUE.toString());
|
||||
}
|
||||
|
||||
return new ServerConfigImpl(Integer.toString(endpoint.getPort()), protocol, path, attributes);
|
||||
}
|
||||
|
||||
public static ServerConfigImpl createFromEndpoint(Endpoint endpoint) {
|
||||
return createFromEndpoint(endpoint, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,13 @@ package org.eclipse.che.api.workspace.server.model.impl;
|
|||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.DEVFILE_ENDPOINT;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.INTERNAL_SERVER_ATTRIBUTE;
|
||||
import static org.eclipse.che.api.core.model.workspace.config.ServerConfig.SERVER_NAME_ATTRIBUTE;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.devfile.EndpointImpl;
|
||||
|
|
@ -106,4 +108,29 @@ public class ServerConfigImplTest {
|
|||
assertEquals(
|
||||
serverConfig.getAttributes().get(INTERNAL_SERVER_ATTRIBUTE), Boolean.TRUE.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromEndpointDevfileEndpointAttributeSet() {
|
||||
ServerConfig serverConfig =
|
||||
ServerConfigImpl.createFromEndpoint(new EndpointImpl("name", 123, new HashMap<>()), true);
|
||||
|
||||
assertTrue(serverConfig.getAttributes().containsKey(DEVFILE_ENDPOINT));
|
||||
assertTrue(Boolean.parseBoolean(serverConfig.getAttributes().get(DEVFILE_ENDPOINT)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromEndpointDevfileEndpointAttributeNotSet() {
|
||||
ServerConfig serverConfig =
|
||||
ServerConfigImpl.createFromEndpoint(new EndpointImpl("name", 123, new HashMap<>()), false);
|
||||
|
||||
assertFalse(serverConfig.getAttributes().containsKey(DEVFILE_ENDPOINT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromEndpointDevfileEndpointAttributeNotSetWhenDefault() {
|
||||
ServerConfig serverConfig =
|
||||
ServerConfigImpl.createFromEndpoint(new EndpointImpl("name", 123, new HashMap<>()));
|
||||
|
||||
assertFalse(serverConfig.getAttributes().containsKey(DEVFILE_ENDPOINT));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue