Merge pull request #8182 from sleshchenko/fix_server_resolving
CHE-7922 Change OpenShift machines servers resolving approach Remove redundant checking Runtime on null Fix java doc for RuntimeInfrastructure#prepare Add workspace information into bootstrapper debug logs6.19.x
commit
a5e759ee1e
|
|
@ -22,8 +22,8 @@ import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
|||
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
|
||||
|
||||
/**
|
||||
* Helps to convert {@link ServerConfig} objects to OpenShift infrastructure annotations and
|
||||
* vise-versa.
|
||||
* Helps to convert servers related entities (like {@link ServerConfig} and machine name) to
|
||||
* OpenShift annotations and vise-versa.
|
||||
*
|
||||
* @author Sergii Leshchenko
|
||||
*/
|
||||
|
|
@ -37,6 +37,8 @@ public class Annotations {
|
|||
public static final String SERVER_ATTR_ANNOTATION_FMT =
|
||||
ANNOTATION_PREFIX + "server.%s.attributes";
|
||||
|
||||
public static final String MACHINE_NAME_ANNOTATION = ANNOTATION_PREFIX + "machine.name";
|
||||
|
||||
/** Pattern that matches server annotations e.g. "org.eclipse.che.server.exec-agent.port". */
|
||||
private static final Pattern SERVER_ANNOTATION_PATTERN =
|
||||
Pattern.compile("org\\.eclipse\\.che\\.server\\.(?<ref>[\\w-/]+)\\..+");
|
||||
|
|
@ -86,6 +88,11 @@ public class Annotations {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Serializer machineName(String machineName) {
|
||||
annotations.put(MACHINE_NAME_ANNOTATION, machineName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Map<String, String> annotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
|
@ -121,6 +128,10 @@ public class Annotations {
|
|||
}
|
||||
return servers;
|
||||
}
|
||||
|
||||
public String machineName() {
|
||||
return annotations.get(MACHINE_NAME_ANNOTATION);
|
||||
}
|
||||
}
|
||||
|
||||
private Annotations() {}
|
||||
|
|
|
|||
|
|
@ -240,12 +240,13 @@ public class OpenShiftInternalRuntime extends InternalRuntime<OpenShiftRuntimeCo
|
|||
final Pod createdPod = project.pods().create(toCreate);
|
||||
final ObjectMeta podMetadata = createdPod.getMetadata();
|
||||
for (Container container : createdPod.getSpec().getContainers()) {
|
||||
String machineName = Names.machineName(toCreate, container);
|
||||
OpenShiftMachine machine =
|
||||
new OpenShiftMachine(
|
||||
Names.machineName(toCreate, container),
|
||||
machineName,
|
||||
podMetadata.getName(),
|
||||
container.getName(),
|
||||
serverResolver.resolve(createdPod, container),
|
||||
serverResolver.resolve(machineName),
|
||||
project);
|
||||
machines.put(machine.getName(), machine);
|
||||
sendStartingEvent(machine.getName());
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ import org.eclipse.che.workspace.infrastructure.openshift.provision.UniqueNamesP
|
|||
* {@link Service}. To make it also publicly accessible it is needed to create corresponding {@link
|
||||
* Route} for exposing this port.
|
||||
*
|
||||
* <p>Created services and routes will have serialized servers which are exposed by the
|
||||
* corresponding object and machine name to which these servers belongs to.
|
||||
*
|
||||
* <p>Container, service and route are linked in the following way:
|
||||
*
|
||||
* <pre>
|
||||
|
|
@ -144,6 +147,7 @@ public class ServerExposer {
|
|||
Service service =
|
||||
new ServiceBuilder()
|
||||
.withName(generate(SERVER_PREFIX, SERVER_UNIQUE_PART_SIZE) + '-' + machineName)
|
||||
.withMachineName(machineName)
|
||||
.withSelectorEntry(CHE_ORIGINAL_NAME_LABEL, pod.getMetadata().getName())
|
||||
.withPorts(new ArrayList<>(portToServicePort.values()))
|
||||
.withServers(internalServers)
|
||||
|
|
@ -164,6 +168,7 @@ public class ServerExposer {
|
|||
Route route =
|
||||
new RouteBuilder()
|
||||
.withName(serviceName + '-' + servicePort.getName())
|
||||
.withMachineName(machineName)
|
||||
.withTargetPort(servicePort.getName())
|
||||
.withServers(routesServers)
|
||||
.withTo(serviceName)
|
||||
|
|
@ -211,6 +216,7 @@ public class ServerExposer {
|
|||
|
||||
private static class ServiceBuilder {
|
||||
private String name;
|
||||
private String machineName;
|
||||
private Map<String, String> selector = new HashMap<>();
|
||||
private List<ServicePort> ports = Collections.emptyList();
|
||||
private Map<String, ? extends ServerConfig> serversConfigs = Collections.emptyMap();
|
||||
|
|
@ -241,7 +247,11 @@ public class ServerExposer {
|
|||
return builder
|
||||
.withNewMetadata()
|
||||
.withName(name.replace("/", "-"))
|
||||
.withAnnotations(Annotations.newSerializer().servers(serversConfigs).annotations())
|
||||
.withAnnotations(
|
||||
Annotations.newSerializer()
|
||||
.servers(serversConfigs)
|
||||
.machineName(machineName)
|
||||
.annotations())
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withSelector(selector)
|
||||
|
|
@ -249,6 +259,11 @@ public class ServerExposer {
|
|||
.endSpec()
|
||||
.build();
|
||||
}
|
||||
|
||||
public ServiceBuilder withMachineName(String machineName) {
|
||||
this.machineName = machineName;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RouteBuilder {
|
||||
|
|
@ -256,6 +271,7 @@ public class ServerExposer {
|
|||
private String serviceName;
|
||||
private IntOrString targetPort;
|
||||
private Map<String, ? extends ServerConfig> serversConfigs;
|
||||
private String machineName;
|
||||
|
||||
private RouteBuilder withName(String name) {
|
||||
this.name = name;
|
||||
|
|
@ -277,6 +293,11 @@ public class ServerExposer {
|
|||
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();
|
||||
|
|
@ -284,7 +305,11 @@ public class ServerExposer {
|
|||
return builder
|
||||
.withNewMetadata()
|
||||
.withName(name.replace("/", "-"))
|
||||
.withAnnotations(Annotations.newSerializer().servers(serversConfigs).annotations())
|
||||
.withAnnotations(
|
||||
Annotations.newSerializer()
|
||||
.servers(serversConfigs)
|
||||
.machineName(machineName)
|
||||
.annotations())
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withNewTo()
|
||||
|
|
|
|||
|
|
@ -10,40 +10,47 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Container;
|
||||
import io.fabric8.kubernetes.api.model.ContainerPort;
|
||||
import io.fabric8.kubernetes.api.model.IntOrString;
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import io.fabric8.kubernetes.api.model.Service;
|
||||
import io.fabric8.kubernetes.api.model.ServicePort;
|
||||
import io.fabric8.openshift.api.model.Route;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
|
||||
/**
|
||||
* Helps to resolve {@link ServerImpl servers} by container in pod according to specified {@link
|
||||
* Route routes} and {@link Service services}.
|
||||
* Helps to resolve {@link ServerImpl servers} by machine name according to specified {@link Route
|
||||
* routes} and {@link Service services}.
|
||||
*
|
||||
* <p>How {@link Container}, {@link Pod}, {@link Service} and {@link Route} are linked described in
|
||||
* {@link ServerExposer}.
|
||||
* <p>Objects annotations are used to check if {@link Service service} or {@link Route route}
|
||||
* exposes the specified machine servers.
|
||||
*
|
||||
* @author Sergii Leshchenko
|
||||
* @author Alexander Garagatyi
|
||||
* @see ServerExposer
|
||||
* @see Annotations
|
||||
*/
|
||||
public class ServerResolver {
|
||||
private final List<Service> services;
|
||||
private final List<Route> routes;
|
||||
private final Multimap<String, Service> services;
|
||||
private final Multimap<String, Route> routes;
|
||||
|
||||
private ServerResolver(List<Service> services, List<Route> routes) {
|
||||
this.services = services;
|
||||
this.routes = routes;
|
||||
this.services = ArrayListMultimap.create();
|
||||
for (Service service : services) {
|
||||
String machineName =
|
||||
Annotations.newDeserializer(service.getMetadata().getAnnotations()).machineName();
|
||||
this.services.put(machineName, service);
|
||||
}
|
||||
|
||||
this.routes = ArrayListMultimap.create();
|
||||
for (Route route : routes) {
|
||||
String machineName =
|
||||
Annotations.newDeserializer(route.getMetadata().getAnnotations()).machineName();
|
||||
this.routes.put(machineName, route);
|
||||
}
|
||||
}
|
||||
|
||||
public static ServerResolver of(List<Service> services, List<Route> routes) {
|
||||
|
|
@ -51,27 +58,15 @@ public class ServerResolver {
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolves servers by the specified container in the pod.
|
||||
* Resolves servers by the specified machine name.
|
||||
*
|
||||
* @param pod pod that should be matched by services
|
||||
* @param container container that expose ports for services
|
||||
* @param machineName machine to resolve servers
|
||||
* @return resolved servers
|
||||
*/
|
||||
public Map<String, ServerImpl> resolve(Pod pod, Container container) {
|
||||
Set<String> matchedServices =
|
||||
getMatchedServices(pod, container)
|
||||
.stream()
|
||||
.map(s -> s.getMetadata().getName())
|
||||
.collect(Collectors.toSet());
|
||||
public Map<String, ServerImpl> resolve(String machineName) {
|
||||
Map<String, ServerImpl> servers = new HashMap<>();
|
||||
services
|
||||
.stream()
|
||||
.filter(service -> matchedServices.contains(service.getMetadata().getName()))
|
||||
.forEach(service -> fillServiceServers(service, servers));
|
||||
routes
|
||||
.stream()
|
||||
.filter(route -> matchedServices.contains(route.getSpec().getTo().getName()))
|
||||
.forEach(route -> fillRouteServers(route, servers));
|
||||
services.get(machineName).forEach(service -> fillServiceServers(service, servers));
|
||||
routes.get(machineName).forEach(route -> fillRouteServers(route, servers));
|
||||
return servers;
|
||||
}
|
||||
|
||||
|
|
@ -134,46 +129,4 @@ public class ServerResolver {
|
|||
private String removeSuffix(String port) {
|
||||
return port.split("/")[0];
|
||||
}
|
||||
|
||||
private List<Service> getMatchedServices(Pod pod, Container container) {
|
||||
return services
|
||||
.stream()
|
||||
.filter(service -> isExposedByService(pod, service))
|
||||
.filter(service -> isExposedByService(container, service))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean isExposedByService(Pod pod, Service service) {
|
||||
Map<String, String> labels = pod.getMetadata().getLabels();
|
||||
Map<String, String> selectorLabels = service.getSpec().getSelector();
|
||||
if (labels == null) {
|
||||
return false;
|
||||
}
|
||||
for (Map.Entry<String, String> selectorLabelEntry : selectorLabels.entrySet()) {
|
||||
if (!selectorLabelEntry.getValue().equals(labels.get(selectorLabelEntry.getKey()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isExposedByService(Container container, Service service) {
|
||||
for (ServicePort servicePort : service.getSpec().getPorts()) {
|
||||
IntOrString targetPort = servicePort.getTargetPort();
|
||||
if (targetPort.getIntVal() != null) {
|
||||
for (ContainerPort containerPort : container.getPorts()) {
|
||||
if (targetPort.getIntVal().equals(containerPort.getContainerPort())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ContainerPort containerPort : container.getPorts()) {
|
||||
if (targetPort.getStrVal().equals(containerPort.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,14 +114,16 @@ public class OpenShiftBootstrapper extends AbstractBootstrapper {
|
|||
}
|
||||
|
||||
private void injectBootstrapper() throws InfrastructureException {
|
||||
LOG.debug("Creating folder for bootstrapper");
|
||||
String machineName = openShiftMachine.getName();
|
||||
LOG.debug(
|
||||
"Bootstrapping {}:{}. Creating folder for bootstrapper", runtimeIdentity, machineName);
|
||||
openShiftMachine.exec("mkdir", "-p", BOOTSTRAPPER_DIR);
|
||||
LOG.debug("Downloading bootstrapper binary");
|
||||
LOG.debug("Bootstrapping {}:{}. Downloading bootstrapper binary", runtimeIdentity, machineName);
|
||||
openShiftMachine.exec(
|
||||
"curl", "-o", BOOTSTRAPPER_DIR + BOOTSTRAPPER_FILE, bootstrapperBinaryUrl);
|
||||
openShiftMachine.exec("chmod", "+x", BOOTSTRAPPER_DIR + BOOTSTRAPPER_FILE);
|
||||
|
||||
LOG.debug("Creating bootstrapper config file");
|
||||
LOG.debug("Bootstrapping {}:{}. Creating config file", runtimeIdentity, machineName);
|
||||
openShiftMachine.exec(
|
||||
"sh",
|
||||
"-c",
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public class AnnotationsTest {
|
|||
.servers(
|
||||
ImmutableMap.of(
|
||||
"my-server2", new ServerConfigImpl("8080/tcp", "ws", "/connect", emptyMap())))
|
||||
.machineName("test-machine")
|
||||
.annotations();
|
||||
Map<String, String> expected =
|
||||
ImmutableMap.<String, String>builder()
|
||||
|
|
@ -54,6 +55,7 @@ public class AnnotationsTest {
|
|||
.put("org.eclipse.che.server.my-server2.protocol", "ws")
|
||||
.put("org.eclipse.che.server.my-server2.path", "/connect")
|
||||
.put("org.eclipse.che.server.my-server2.attributes", stringEmptyAttributes)
|
||||
.put("org.eclipse.che.machine.name", "test-machine")
|
||||
.build();
|
||||
|
||||
assertEquals(serialized, expected);
|
||||
|
|
@ -74,12 +76,15 @@ public class AnnotationsTest {
|
|||
.put("org.eclipse.che.server.my-server3.port", "7070/tcp")
|
||||
.put("org.eclipse.che.server.my-server3.protocol", "http")
|
||||
.put("org.eclipse.che.server.my-server3.attributes", stringEmptyAttributes)
|
||||
.put("org.eclipse.che.machine.name", "test-machine")
|
||||
.build();
|
||||
|
||||
Annotations.Deserializer deserializer = Annotations.newDeserializer(annotations);
|
||||
|
||||
Map<String, ServerConfigImpl> servers = deserializer.servers();
|
||||
|
||||
assertEquals(deserializer.machineName(), "test-machine");
|
||||
|
||||
Map<String, ServerConfigImpl> expected = new HashMap<>();
|
||||
expected.put("my-server1/http", new ServerConfigImpl("8000/tcp", "http", "/api/info", null));
|
||||
expected.put("my-server2", new ServerConfigImpl("8080/tcp", "ws", "/connect", ATTRIBUTES));
|
||||
|
|
|
|||
|
|
@ -45,12 +45,14 @@ import org.testng.annotations.Test;
|
|||
* @author Sergii Leshchenko
|
||||
*/
|
||||
public class ServerExposerTest {
|
||||
|
||||
private static final Map<String, String> ATTRIBUTES_MAP = singletonMap("key", "value");
|
||||
private static final Map<String, String> 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 ServerExposer serverExposer;
|
||||
private OpenShiftEnvironment openShiftEnvironment;
|
||||
|
|
@ -71,7 +73,7 @@ public class ServerExposerTest {
|
|||
|
||||
openShiftEnvironment =
|
||||
OpenShiftEnvironment.builder().setPods(ImmutableMap.of("pod", pod)).build();
|
||||
this.serverExposer = new ServerExposer("pod/main", pod, container, openShiftEnvironment);
|
||||
this.serverExposer = new ServerExposer(MACHINE_NAME, pod, container, openShiftEnvironment);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -87,6 +89,7 @@ public class ServerExposerTest {
|
|||
|
||||
// then
|
||||
assertThatExternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"http-server",
|
||||
"tcp",
|
||||
8080,
|
||||
|
|
@ -113,11 +116,13 @@ public class ServerExposerTest {
|
|||
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,
|
||||
|
|
@ -144,11 +149,13 @@ public class ServerExposerTest {
|
|||
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,
|
||||
|
|
@ -171,6 +178,7 @@ public class ServerExposerTest {
|
|||
assertEquals(openShiftEnvironment.getServices().size(), 1);
|
||||
assertEquals(openShiftEnvironment.getRoutes().size(), 1);
|
||||
assertThatExternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"http-server",
|
||||
"TCP",
|
||||
8080,
|
||||
|
|
@ -197,6 +205,7 @@ public class ServerExposerTest {
|
|||
|
||||
// then
|
||||
assertThatExternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"http-server",
|
||||
"tcp",
|
||||
8080,
|
||||
|
|
@ -226,6 +235,7 @@ public class ServerExposerTest {
|
|||
assertEquals(container.getPorts().get(1).getContainerPort(), new Integer(8080));
|
||||
assertEquals(container.getPorts().get(1).getProtocol(), "UDP");
|
||||
assertThatExternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"server",
|
||||
"udp",
|
||||
8080,
|
||||
|
|
@ -245,6 +255,7 @@ public class ServerExposerTest {
|
|||
|
||||
// then
|
||||
assertThatInternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"http-server",
|
||||
"tcp",
|
||||
8080,
|
||||
|
|
@ -266,11 +277,13 @@ public class ServerExposerTest {
|
|||
|
||||
// then
|
||||
assertThatInternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"int-server",
|
||||
"tcp",
|
||||
8080,
|
||||
new ServerConfigImpl(internalServerConfig).withAttributes(INTERNAL_SERVER_ATTRIBUTE_MAP));
|
||||
assertThatExternalServerIsExposed(
|
||||
MACHINE_NAME,
|
||||
"ext-server",
|
||||
"tcp",
|
||||
9090,
|
||||
|
|
@ -278,7 +291,11 @@ public class ServerExposerTest {
|
|||
}
|
||||
|
||||
private void assertThatExternalServerIsExposed(
|
||||
String serverNameRegex, String portProtocol, Integer port, ServerConfigImpl expected) {
|
||||
String machineName,
|
||||
String serverNameRegex,
|
||||
String portProtocol,
|
||||
Integer port,
|
||||
ServerConfigImpl expected) {
|
||||
// then
|
||||
assertTrue(
|
||||
container
|
||||
|
|
@ -313,21 +330,31 @@ public class ServerExposerTest {
|
|||
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 annotationsDeserializer =
|
||||
Annotations.Deserializer routeAnnotations =
|
||||
Annotations.newDeserializer(route.getMetadata().getAnnotations());
|
||||
Map<String, ServerConfigImpl> servers = annotationsDeserializer.servers();
|
||||
Map<String, ServerConfigImpl> servers = routeAnnotations.servers();
|
||||
ServerConfig serverConfig = servers.get(serverNameRegex);
|
||||
assertEquals(serverConfig, expected);
|
||||
|
||||
assertEquals(routeAnnotations.machineName(), machineName);
|
||||
}
|
||||
|
||||
private void assertThatInternalServerIsExposed(
|
||||
String serverNameRegex, String portProtocol, Integer port, ServerConfigImpl expected) {
|
||||
String machineName,
|
||||
String serverNameRegex,
|
||||
String portProtocol,
|
||||
Integer port,
|
||||
ServerConfigImpl expected) {
|
||||
// then
|
||||
assertTrue(
|
||||
container
|
||||
|
|
@ -362,9 +389,11 @@ public class ServerExposerTest {
|
|||
assertEquals(servicePort.getPort(), port);
|
||||
assertEquals(servicePort.getName(), SERVER_PREFIX + "-" + port);
|
||||
|
||||
Annotations.Deserializer annotationsDeserializer =
|
||||
Annotations.Deserializer serviceAnnotations =
|
||||
Annotations.newDeserializer(service.getMetadata().getAnnotations());
|
||||
Map<String, ServerConfigImpl> servers = annotationsDeserializer.servers();
|
||||
assertEquals(serviceAnnotations.machineName(), machineName);
|
||||
|
||||
Map<String, ServerConfigImpl> servers = serviceAnnotations.servers();
|
||||
ServerConfig serverConfig = servers.get(serverNameRegex);
|
||||
assertEquals(serverConfig, expected);
|
||||
|
||||
|
|
@ -374,10 +403,12 @@ public class ServerExposerTest {
|
|||
assertEquals(route.getSpec().getTo().getName(), service.getMetadata().getName());
|
||||
assertEquals(route.getSpec().getPort().getTargetPort().getStrVal(), servicePort.getName());
|
||||
|
||||
Annotations.Deserializer routeAnnotationsDeserializer =
|
||||
Annotations.Deserializer routeAnnotations =
|
||||
Annotations.newDeserializer(route.getMetadata().getAnnotations());
|
||||
Map<String, ServerConfigImpl> routeServers = routeAnnotationsDeserializer.servers();
|
||||
Map<String, ServerConfigImpl> routeServers = routeAnnotations.servers();
|
||||
ServerConfig routeServerConfig = routeServers.get(serverNameRegex);
|
||||
assertNull(routeServerConfig);
|
||||
|
||||
assertEquals(routeAnnotations.machineName(), machineName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
package org.eclipse.che.workspace.infrastructure.openshift;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.runtime.ServerStatus.UNKNOWN;
|
||||
|
|
@ -18,11 +18,6 @@ import static org.testng.Assert.assertEquals;
|
|||
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.ServiceBuilder;
|
||||
import io.fabric8.kubernetes.api.model.ServicePortBuilder;
|
||||
|
|
@ -31,6 +26,7 @@ import io.fabric8.openshift.api.model.RouteBuilder;
|
|||
import java.util.Map;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
|
||||
import org.eclipse.che.workspace.infrastructure.openshift.Annotations.Serializer;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
|
@ -39,20 +35,21 @@ import org.testng.annotations.Test;
|
|||
* @author Sergii Leshchenko
|
||||
*/
|
||||
public class ServerResolverTest {
|
||||
|
||||
private static final Map<String, String> ATTRIBUTES_MAP = singletonMap("key", "value");
|
||||
private static final int CONTAINER_PORT = 3054;
|
||||
private static final String ROUTE_HOST = "localhost";
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsNoMatchedServiceByPodLabels() {
|
||||
public void
|
||||
testResolvingServersWhenThereIsNoTheCorrespondingServiceAndRouteForTheSpecifiedMachine() {
|
||||
// given
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(ImmutableMap.of("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("nonMatched", CONTAINER_PORT, ImmutableMap.of("kind", "db"), null);
|
||||
createService("nonMatched", "foreignMachine", CONTAINER_PORT, null);
|
||||
Route route =
|
||||
createRoute(
|
||||
"nonMatched",
|
||||
"foreignMachine",
|
||||
ImmutableMap.of(
|
||||
"http-server", new ServerConfigImpl("3054", "http", "/api", ATTRIBUTES_MAP)));
|
||||
|
||||
|
|
@ -60,83 +57,46 @@ public class ServerResolverTest {
|
|||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
|
||||
// when
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
// then
|
||||
assertTrue(resolved.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsNoMatchedServiceByContainerPort() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(ImmutableMap.of("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("nonMatched", 7777, ImmutableMap.of("kind", "web-app"), null);
|
||||
Route route =
|
||||
createRoute(
|
||||
"nonMatched",
|
||||
ImmutableMap.of(
|
||||
"http-server", new ServerConfigImpl("3054", "http", "/api", ATTRIBUTES_MAP)));
|
||||
|
||||
ServerResolver serverResolver =
|
||||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
|
||||
assertTrue(resolved.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsMatchedServiceForContainer() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(ImmutableMap.of("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("matched", CONTAINER_PORT, ImmutableMap.of("kind", "web-app"), null);
|
||||
public void testResolvingServersWhenThereIsMatchedRouteForTheSpecifiedMachine() {
|
||||
Route route =
|
||||
createRoute(
|
||||
"matched",
|
||||
"machine",
|
||||
ImmutableMap.of(
|
||||
"http-server",
|
||||
new ServerConfigImpl("3054", "http", "/api", ATTRIBUTES_MAP),
|
||||
"ws-server",
|
||||
new ServerConfigImpl("3054", "ws", "/connect", ATTRIBUTES_MAP)));
|
||||
"http-server", new ServerConfigImpl("3054", "http", "/api", ATTRIBUTES_MAP)));
|
||||
|
||||
ServerResolver serverResolver =
|
||||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
ServerResolver serverResolver = ServerResolver.of(emptyList(), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 2);
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
resolved.get("http-server"),
|
||||
new ServerImpl()
|
||||
.withUrl("http://localhost/api")
|
||||
.withStatus(UNKNOWN)
|
||||
.withAttributes(ATTRIBUTES_MAP));
|
||||
assertEquals(
|
||||
resolved.get("ws-server"),
|
||||
new ServerImpl()
|
||||
.withUrl("ws://localhost/connect")
|
||||
.withStatus(UNKNOWN)
|
||||
.withAttributes(ATTRIBUTES_MAP));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsMatchedServiceForContainerAndServerPathIsNull() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(singletonMap("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("matched", CONTAINER_PORT, singletonMap("kind", "web-app"), null);
|
||||
public void testResolvingServersWhenThereIsMatchedRouteForMachineAndServerPathIsNull() {
|
||||
Route route =
|
||||
createRoute(
|
||||
"matched",
|
||||
"machine",
|
||||
singletonMap(
|
||||
"http-server", new ServerConfigImpl("3054", "http", null, ATTRIBUTES_MAP)));
|
||||
|
||||
ServerResolver serverResolver =
|
||||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
ServerResolver serverResolver = ServerResolver.of(emptyList(), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
|
|
@ -148,20 +108,16 @@ public class ServerResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsMatchedServiceForContainerAndServerPathIsEmpty() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(singletonMap("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("matched", CONTAINER_PORT, singletonMap("kind", "web-app"), null);
|
||||
public void testResolvingServersWhenThereIsMatchedRouteForMachineAndServerPathIsEmpty() {
|
||||
Route route =
|
||||
createRoute(
|
||||
"matched",
|
||||
"machine",
|
||||
singletonMap("http-server", new ServerConfigImpl("3054", "http", "", ATTRIBUTES_MAP)));
|
||||
|
||||
ServerResolver serverResolver =
|
||||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
ServerResolver serverResolver = ServerResolver.of(emptyList(), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
|
|
@ -173,21 +129,17 @@ public class ServerResolverTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testResolvingServersWhenThereIsMatchedServiceForContainerAndServerPathIsRelative() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(singletonMap("kind", "web-app"));
|
||||
Service nonMatchedByPodService =
|
||||
createService("matched", CONTAINER_PORT, singletonMap("kind", "web-app"), null);
|
||||
public void testResolvingServersWhenThereIsMatchedRouteForMachineAndServerPathIsRelative() {
|
||||
Route route =
|
||||
createRoute(
|
||||
"matched",
|
||||
"machine",
|
||||
singletonMap(
|
||||
"http-server", new ServerConfigImpl("3054", "http", "api", ATTRIBUTES_MAP)));
|
||||
|
||||
ServerResolver serverResolver =
|
||||
ServerResolver.of(singletonList(nonMatchedByPodService), singletonList(route));
|
||||
ServerResolver serverResolver = ServerResolver.of(emptyList(), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
|
|
@ -200,20 +152,18 @@ public class ServerResolverTest {
|
|||
|
||||
@Test
|
||||
public void testResolvingInternalServers() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(singletonMap("kind", "web-app"));
|
||||
Service service =
|
||||
createService(
|
||||
"service11",
|
||||
"machine",
|
||||
CONTAINER_PORT,
|
||||
singletonMap("kind", "web-app"),
|
||||
singletonMap(
|
||||
"http-server", new ServerConfigImpl("3054", "http", "api", ATTRIBUTES_MAP)));
|
||||
Route route = createRoute("matched", null);
|
||||
Route route = createRoute("matched", "machine", null);
|
||||
|
||||
ServerResolver serverResolver = ServerResolver.of(singletonList(service), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
|
|
@ -226,20 +176,18 @@ public class ServerResolverTest {
|
|||
|
||||
@Test
|
||||
public void testResolvingInternalServersWithPortWithTransportProtocol() {
|
||||
Container container = createContainer();
|
||||
Pod pod = createPod(singletonMap("kind", "web-app"));
|
||||
Service service =
|
||||
createService(
|
||||
"service11",
|
||||
"machine",
|
||||
CONTAINER_PORT,
|
||||
singletonMap("kind", "web-app"),
|
||||
singletonMap(
|
||||
"http-server", new ServerConfigImpl("3054/udp", "xxx", "api", ATTRIBUTES_MAP)));
|
||||
Route route = createRoute("matched", null);
|
||||
Route route = createRoute("matched", "machine", null);
|
||||
|
||||
ServerResolver serverResolver = ServerResolver.of(singletonList(service), singletonList(route));
|
||||
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve(pod, container);
|
||||
Map<String, ServerImpl> resolved = serverResolver.resolve("machine");
|
||||
|
||||
assertEquals(resolved.size(), 1);
|
||||
assertEquals(
|
||||
|
|
@ -250,32 +198,20 @@ public class ServerResolverTest {
|
|||
.withAttributes(ATTRIBUTES_MAP));
|
||||
}
|
||||
|
||||
private Pod createPod(Map<String, String> labels) {
|
||||
return new PodBuilder().withNewMetadata().withLabels(labels).endMetadata().build();
|
||||
}
|
||||
|
||||
private Container createContainer() {
|
||||
return new ContainerBuilder()
|
||||
.withPorts(new ContainerPortBuilder().withContainerPort(CONTAINER_PORT).build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Service createService(
|
||||
String name,
|
||||
Integer port,
|
||||
Map<String, String> selector,
|
||||
Map<String, ServerConfigImpl> servers) {
|
||||
Map<String, String> annotations = emptyMap();
|
||||
String name, String machineName, Integer port, Map<String, ServerConfigImpl> servers) {
|
||||
Serializer serializer = Annotations.newSerializer();
|
||||
serializer.machineName(machineName);
|
||||
if (servers != null) {
|
||||
annotations = Annotations.newSerializer().servers(servers).annotations();
|
||||
serializer.servers(servers);
|
||||
}
|
||||
|
||||
return new ServiceBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.withAnnotations(annotations)
|
||||
.withAnnotations(serializer.annotations())
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withSelector(selector)
|
||||
.withPorts(
|
||||
new ServicePortBuilder()
|
||||
.withPort(port)
|
||||
|
|
@ -287,16 +223,17 @@ public class ServerResolverTest {
|
|||
.build();
|
||||
}
|
||||
|
||||
// TODO Think about common builders
|
||||
private Route createRoute(String name, Map<String, ServerConfigImpl> servers) {
|
||||
Map<String, String> annotations = emptyMap();
|
||||
private Route createRoute(
|
||||
String name, String machineName, Map<String, ServerConfigImpl> servers) {
|
||||
Serializer serializer = Annotations.newSerializer();
|
||||
serializer.machineName(machineName);
|
||||
if (servers != null) {
|
||||
annotations = Annotations.newSerializer().servers(servers).annotations();
|
||||
serializer.servers(servers);
|
||||
}
|
||||
return new RouteBuilder()
|
||||
.withNewMetadata()
|
||||
.withName(name)
|
||||
.withAnnotations(annotations)
|
||||
.withAnnotations(serializer.annotations())
|
||||
.endMetadata()
|
||||
.withNewSpec()
|
||||
.withHost(ROUTE_HOST)
|
||||
|
|
|
|||
|
|
@ -211,13 +211,8 @@ public class WorkspaceRuntimes {
|
|||
try {
|
||||
InternalEnvironment internalEnv = createInternalEnvironment(environment);
|
||||
RuntimeContext runtimeContext = infrastructure.prepare(runtimeId, internalEnv);
|
||||
|
||||
InternalRuntime runtime = runtimeContext.getRuntime();
|
||||
if (runtime == null) {
|
||||
throw new IllegalStateException(
|
||||
"SPI contract violated. RuntimeInfrastructure.start(...) must not return null: "
|
||||
+ RuntimeInfrastructure.class);
|
||||
}
|
||||
|
||||
RuntimeState state = new RuntimeState(runtime, STARTING);
|
||||
if (isStartRefused.get()) {
|
||||
throw new ConflictException(
|
||||
|
|
|
|||
|
|
@ -79,9 +79,15 @@ public abstract class RuntimeInfrastructure {
|
|||
}
|
||||
|
||||
/**
|
||||
* Making Runtime is a two phase process. On the first phase implementation MUST prepare
|
||||
* RuntimeContext, this is supposedly "fast" method On the second phase Runtime is created with
|
||||
* RuntimeContext.start() which is supposedly "long" method.
|
||||
* Starting the Runtime is a two phase process:
|
||||
*
|
||||
* <pre>
|
||||
* <ul>
|
||||
* <li>On the first phase implementation MUST prepare RuntimeContext;</li>
|
||||
* <li>On the second phase the Runtime that can be fetched from RuntimeContext
|
||||
* should be started with InternalRuntime.start().</li>
|
||||
* </ul>
|
||||
* </pre>
|
||||
*
|
||||
* @param id the RuntimeIdentity
|
||||
* @param environment incoming internal environment
|
||||
|
|
|
|||
Loading…
Reference in New Issue