Skip to content

Commit c669d18

Browse files
committed
Provide ability to create user's workspaces in one OpenShift project
1 parent f238405 commit c669d18

16 files changed

Lines changed: 247 additions & 72 deletions

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInternalRuntime.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.eclipse.che.api.workspace.shared.dto.event.ServerStatusEvent;
4848
import org.eclipse.che.dto.server.DtoFactory;
4949
import org.eclipse.che.workspace.infrastructure.openshift.bootstrapper.OpenShiftBootstrapperFactory;
50+
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
5051
import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProject;
5152
import org.slf4j.Logger;
5253
import org.slf4j.LoggerFactory;
@@ -71,13 +72,13 @@ public class OpenShiftInternalRuntime extends InternalRuntime<OpenShiftRuntimeCo
7172

7273
@Inject
7374
public OpenShiftInternalRuntime(
74-
@Assisted OpenShiftRuntimeContext context,
75-
@Assisted OpenShiftProject project,
75+
@Named("che.infra.openshift.machine_start_timeout_min") int machineStartTimeoutMin,
7676
URLRewriter.NoOpURLRewriter urlRewriter,
7777
EventService eventService,
7878
OpenShiftBootstrapperFactory bootstrapperFactory,
7979
ServersCheckerFactory serverCheckerFactory,
80-
@Named("che.infra.openshift.machine_start_timeout_min") int machineStartTimeoutMin) {
80+
@Assisted OpenShiftRuntimeContext context,
81+
@Assisted OpenShiftProject project) {
8182
super(context, urlRewriter, false);
8283
this.eventService = eventService;
8384
this.bootstrapperFactory = bootstrapperFactory;
@@ -90,16 +91,16 @@ public OpenShiftInternalRuntime(
9091
@Override
9192
protected void internalStart(Map<String, String> startOptions) throws InfrastructureException {
9293
try {
93-
94-
prepareOpenShiftPVCs(getContext().getOpenShiftEnvironment().getPersistentVolumeClaims());
94+
final OpenShiftEnvironment osEnv = getContext().getOpenShiftEnvironment();
95+
prepareOpenShiftPVCs(osEnv.getPersistentVolumeClaims());
9596

9697
List<Service> createdServices = new ArrayList<>();
97-
for (Service service : getContext().getOpenShiftEnvironment().getServices().values()) {
98+
for (Service service : osEnv.getServices().values()) {
9899
createdServices.add(project.services().create(service));
99100
}
100101

101102
List<Route> createdRoutes = new ArrayList<>();
102-
for (Route route : getContext().getOpenShiftEnvironment().getRoutes().values()) {
103+
for (Route route : osEnv.getRoutes().values()) {
103104
createdRoutes.add(project.routes().create(route));
104105
}
105106

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftRuntimeContext.java

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
*/
1111
package org.eclipse.che.workspace.infrastructure.openshift;
1212

13-
import static com.google.common.base.Strings.isNullOrEmpty;
14-
1513
import com.google.inject.assistedinject.Assisted;
1614
import java.net.URI;
1715
import javax.inject.Inject;
@@ -24,36 +22,32 @@
2422
import org.eclipse.che.api.workspace.server.spi.InternalRuntime;
2523
import org.eclipse.che.api.workspace.server.spi.RuntimeContext;
2624
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
27-
import org.eclipse.che.commons.annotation.Nullable;
2825
import org.eclipse.che.workspace.infrastructure.openshift.environment.OpenShiftEnvironment;
29-
import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProject;
26+
import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProjectFactory;
3027

3128
/** @author Sergii Leshchenko */
3229
public class OpenShiftRuntimeContext extends RuntimeContext {
33-
private final OpenShiftClientFactory clientFactory;
30+
3431
private final OpenShiftEnvironment openShiftEnvironment;
3532
private final OpenShiftRuntimeFactory runtimeFactory;
33+
private final OpenShiftProjectFactory projectFactory;
3634
private final String websocketOutputEndpoint;
37-
private final String projectName;
3835

3936
@Inject
4037
public OpenShiftRuntimeContext(
38+
@Named("che.websocket.endpoint") String cheWebsocketEndpoint,
39+
OpenShiftProjectFactory projectFactory,
40+
OpenShiftRuntimeFactory runtimeFactory,
4141
@Assisted InternalEnvironment environment,
4242
@Assisted OpenShiftEnvironment openShiftEnvironment,
4343
@Assisted RuntimeIdentity identity,
44-
@Assisted RuntimeInfrastructure infrastructure,
45-
OpenShiftClientFactory clientFactory,
46-
OpenShiftRuntimeFactory runtimeFactory,
47-
@Named("che.websocket.endpoint") String cheWebsocketEndpoint,
48-
@Nullable @Named("che.infra.openshift.project") String projectName)
44+
@Assisted RuntimeInfrastructure infrastructure)
4945
throws ValidationException, InfrastructureException {
50-
5146
super(environment, identity, infrastructure);
52-
this.clientFactory = clientFactory;
47+
this.projectFactory = projectFactory;
5348
this.runtimeFactory = runtimeFactory;
5449
this.openShiftEnvironment = openShiftEnvironment;
5550
this.websocketOutputEndpoint = cheWebsocketEndpoint;
56-
this.projectName = projectName;
5751
}
5852

5953
/** Returns OpenShift environment which based on normalized context environment configuration. */
@@ -73,8 +67,6 @@ public URI getOutputChannel() throws InfrastructureException {
7367

7468
@Override
7569
public InternalRuntime getRuntime() throws InfrastructureException {
76-
String name = isNullOrEmpty(projectName) ? getIdentity().getWorkspaceId() : projectName;
77-
OpenShiftProject project = new OpenShiftProject(name, clientFactory);
78-
return runtimeFactory.create(this, project);
70+
return runtimeFactory.create(this, projectFactory.create(getIdentity()));
7971
}
8072
}

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftRuntimeContextFactory.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
*/
1111
package org.eclipse.che.workspace.infrastructure.openshift;
1212

13-
import com.google.inject.assistedinject.Assisted;
1413
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
1514
import org.eclipse.che.api.workspace.server.spi.InternalEnvironment;
1615
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
@@ -19,8 +18,8 @@
1918
/** @author Sergii Leshchenko */
2019
public interface OpenShiftRuntimeContextFactory {
2120
OpenShiftRuntimeContext create(
22-
@Assisted InternalEnvironment environment,
23-
@Assisted OpenShiftEnvironment openShiftEnvironment,
24-
@Assisted RuntimeIdentity identity,
25-
@Assisted RuntimeInfrastructure infrastructure);
21+
InternalEnvironment environment,
22+
OpenShiftEnvironment openShiftEnvironment,
23+
RuntimeIdentity identity,
24+
RuntimeInfrastructure infrastructure);
2625
}

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftRuntimeFactory.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@
1010
*/
1111
package org.eclipse.che.workspace.infrastructure.openshift;
1212

13-
import com.google.inject.assistedinject.Assisted;
1413
import org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProject;
1514

1615
/** @author Sergii Leshchenko */
1716
public interface OpenShiftRuntimeFactory {
18-
OpenShiftInternalRuntime create(
19-
@Assisted OpenShiftRuntimeContext context, @Assisted OpenShiftProject openShiftProject);
17+
OpenShiftInternalRuntime create(OpenShiftRuntimeContext context, OpenShiftProject namespace);
2018
}

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/ServerExposer.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import static java.lang.Integer.parseInt;
1414
import static java.util.stream.Collectors.toMap;
15+
import static org.eclipse.che.commons.lang.NameGenerator.generate;
1516
import static org.eclipse.che.workspace.infrastructure.openshift.Constants.CHE_POD_NAME_LABEL;
1617

1718
import io.fabric8.kubernetes.api.model.Container;
@@ -92,6 +93,9 @@
9293
*/
9394
public class ServerExposer {
9495

96+
public static final int SERVER_UNIQUE_PART_SIZE = 8;
97+
public static final String SERVER_PREFIX = "server";
98+
9599
private final String machineName;
96100
private final Container container;
97101
private final OpenShiftEnvironment openShiftEnvironment;
@@ -106,20 +110,20 @@ public ServerExposer(
106110
/**
107111
* Exposes specified servers.
108112
*
109-
* @param namePrefix name prefix that will be used for generated objects
110113
* @param servers servers to expose
111114
*/
112-
public void expose(String namePrefix, Map<String, ? extends ServerConfig> servers) {
115+
public void expose(Map<String, ? extends ServerConfig> servers) {
113116
Map<String, ServicePort> portToServicePort = exposePort(servers.values());
114117

115118
Service service =
116119
new ServiceBuilder()
117-
.withName(namePrefix + '-' + machineName)
120+
.withName(generate(SERVER_PREFIX, SERVER_UNIQUE_PART_SIZE) + '-' + machineName)
118121
.withSelectorEntry(CHE_POD_NAME_LABEL, machineName.split("/")[0])
119122
.withPorts(new ArrayList<>(portToServicePort.values()))
120123
.build();
121124

122-
openShiftEnvironment.getServices().put(service.getMetadata().getName(), service);
125+
String serviceName = service.getMetadata().getName();
126+
openShiftEnvironment.getServices().put(serviceName, service);
123127

124128
for (ServicePort servicePort : portToServicePort.values()) {
125129
int port = servicePort.getTargetPort().getIntVal();
@@ -132,10 +136,10 @@ public void expose(String namePrefix, Map<String, ? extends ServerConfig> server
132136

133137
Route route =
134138
new RouteBuilder()
135-
.withName(namePrefix + '-' + machineName + '-' + servicePort.getName())
139+
.withName(serviceName + '-' + servicePort.getName())
136140
.withTargetPort(servicePort.getName())
137141
.withServers(routesServers)
138-
.withTo(service.getMetadata().getName())
142+
.withTo(serviceName)
139143
.build();
140144
openShiftEnvironment.getRoutes().put(route.getMetadata().getName(), route);
141145
}

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ private void normalizeEnvironment(
162162
if (machineConfig != null && !machineConfig.getServers().isEmpty()) {
163163
ServerExposer serverExposer =
164164
new ServerExposer(machineName, containerConfig, openShiftEnvironment);
165-
serverExposer.expose("servers", machineConfig.getServers());
165+
serverExposer.expose(machineConfig.getServers());
166166
}
167167
}
168168
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright (c) 2012-2017 Red Hat, Inc.
3+
* All rights reserved. This program and the accompanying materials
4+
* are made available under the terms of the Eclipse Public License v1.0
5+
* which accompanies this distribution, and is available at
6+
* http://www.eclipse.org/legal/epl-v10.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
*/
11+
package org.eclipse.che.workspace.infrastructure.openshift.project;
12+
13+
import io.fabric8.kubernetes.api.model.HasMetadata;
14+
import io.fabric8.kubernetes.api.model.ObjectMeta;
15+
import io.fabric8.kubernetes.api.model.Service;
16+
import io.fabric8.kubernetes.api.model.ServiceSpec;
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
20+
/**
21+
* Helps to work with OpenShift objects.
22+
*
23+
* @author Anton Korneta
24+
*/
25+
class OpenShiftObjectUtil {
26+
27+
/** Adds label to target OpenShift object. */
28+
static void putLabel(HasMetadata target, String key, String value) {
29+
ObjectMeta metadata = target.getMetadata();
30+
31+
if (metadata == null) {
32+
target.setMetadata(metadata = new ObjectMeta());
33+
}
34+
35+
Map<String, String> labels = metadata.getLabels();
36+
if (labels == null) {
37+
metadata.setLabels(labels = new HashMap<>());
38+
}
39+
40+
labels.put(key, value);
41+
}
42+
43+
/** Adds selector into target OpenShift service. */
44+
static void putSelector(Service target, String key, String value) {
45+
ServiceSpec spec = target.getSpec();
46+
47+
if (spec == null) {
48+
target.setSpec(spec = new ServiceSpec());
49+
}
50+
51+
Map<String, String> selector = spec.getSelector();
52+
if (selector == null) {
53+
spec.setSelector(selector = new HashMap<>());
54+
}
55+
56+
selector.put(key, value);
57+
}
58+
}

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftPods.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
package org.eclipse.che.workspace.infrastructure.openshift.project;
1212

1313
import static java.util.concurrent.CompletableFuture.allOf;
14+
import static org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftObjectUtil.putLabel;
15+
import static org.eclipse.che.workspace.infrastructure.openshift.project.OpenShiftProject.CHE_WORKSPACE_ID_LABEL;
1416

1517
import io.fabric8.kubernetes.api.model.DoneablePod;
1618
import io.fabric8.kubernetes.api.model.Pod;
@@ -52,10 +54,12 @@ public class OpenShiftPods {
5254
private final String namespace;
5355
private final OpenShiftClientFactory clientFactory;
5456
private final ConcurrentLinkedQueue<PodActionHandler> handlers;
57+
private final String workspaceId;
5558
private Watch watch;
5659

57-
OpenShiftPods(String namespace, OpenShiftClientFactory clientFactory) {
60+
OpenShiftPods(String namespace, String workspaceId, OpenShiftClientFactory clientFactory) {
5861
this.namespace = namespace;
62+
this.workspaceId = workspaceId;
5963
this.clientFactory = clientFactory;
6064
this.handlers = new ConcurrentLinkedQueue<>();
6165
}
@@ -68,6 +72,7 @@ public class OpenShiftPods {
6872
* @throws InfrastructureException when any exception occurs
6973
*/
7074
public Pod create(Pod pod) throws InfrastructureException {
75+
putLabel(pod, CHE_WORKSPACE_ID_LABEL, workspaceId);
7176
try (OpenShiftClient client = clientFactory.create()) {
7277
return client.pods().inNamespace(namespace).create(pod);
7378
} catch (KubernetesClientException e) {
@@ -82,7 +87,12 @@ public Pod create(Pod pod) throws InfrastructureException {
8287
*/
8388
public List<Pod> get() throws InfrastructureException {
8489
try (OpenShiftClient client = clientFactory.create()) {
85-
return client.pods().inNamespace(namespace).list().getItems();
90+
return client
91+
.pods()
92+
.inNamespace(namespace)
93+
.withLabel(CHE_WORKSPACE_ID_LABEL, workspaceId)
94+
.list()
95+
.getItems();
8696
} catch (KubernetesClientException e) {
8797
throw new InfrastructureException(e.getMessage(), e);
8898
}
@@ -185,7 +195,12 @@ public void eventReceived(Action action, Pod pod) {
185195
public void onClose(KubernetesClientException ignored) {}
186196
};
187197
try (OpenShiftClient client = clientFactory.create()) {
188-
watch = client.pods().inNamespace(namespace).watch(watcher);
198+
watch =
199+
client
200+
.pods()
201+
.inNamespace(namespace)
202+
.withLabel(CHE_WORKSPACE_ID_LABEL, workspaceId)
203+
.watch(watcher);
189204
} catch (KubernetesClientException ex) {
190205
throw new InfrastructureException(ex.getMessage());
191206
}
@@ -252,7 +267,13 @@ public void exec(String podName, String containerName, int timeoutMin, String[]
252267
public void delete() throws InfrastructureException {
253268
try (OpenShiftClient client = clientFactory.create()) {
254269
//pods are removed with some delay related to stopping of containers. It is need to wait them
255-
List<Pod> pods = client.pods().inNamespace(namespace).list().getItems();
270+
List<Pod> pods =
271+
client
272+
.pods()
273+
.inNamespace(namespace)
274+
.withLabel(CHE_WORKSPACE_ID_LABEL, workspaceId)
275+
.list()
276+
.getItems();
256277
List<CompletableFuture> deleteFutures = new ArrayList<>();
257278
for (Pod pod : pods) {
258279
PodResource<Pod, DoneablePod> podResource =

infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/project/OpenShiftProject.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,25 @@
2121
import org.eclipse.che.workspace.infrastructure.openshift.OpenShiftClientFactory;
2222

2323
/**
24-
* Defines an internal API for managing {@link Project} instance and objects inside it.
24+
* Defines an internal API for managing subset of objects inside {@link Project} instance.
2525
*
2626
* @author Sergii Leshchenko
2727
*/
2828
public class OpenShiftProject {
29+
30+
public static final String CHE_WORKSPACE_ID_LABEL = "CHE_WORKSPACE_ID";
31+
2932
private final OpenShiftPods pods;
3033
private final OpenShiftServices services;
3134
private final OpenShiftRoutes routes;
3235
private final OpenShiftPersistentVolumeClaims pvcs;
3336

34-
public OpenShiftProject(String name, OpenShiftClientFactory clientFactory)
37+
public OpenShiftProject(OpenShiftClientFactory clientFactory, String name, String workspaceId)
3538
throws InfrastructureException {
36-
this.pods = new OpenShiftPods(name, clientFactory);
37-
this.services = new OpenShiftServices(name, clientFactory);
38-
this.routes = new OpenShiftRoutes(name, clientFactory);
39+
this.pods = new OpenShiftPods(name, workspaceId, clientFactory);
40+
this.services = new OpenShiftServices(name, workspaceId, clientFactory);
41+
this.routes = new OpenShiftRoutes(name, workspaceId, clientFactory);
3942
this.pvcs = new OpenShiftPersistentVolumeClaims(name, clientFactory);
40-
4143
try (OpenShiftClient client = clientFactory.create()) {
4244
if (get(name, client) == null) {
4345
create(name, client);

0 commit comments

Comments
 (0)