CHE-7561: add internal server concept into workspace API

Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>
6.19.x
Oleksandr Garagatyi 2017-12-07 17:14:58 +02:00
parent 576ecd6337
commit 6b7b1c6468
4 changed files with 311 additions and 5 deletions

View File

@ -11,6 +11,7 @@
package org.eclipse.che.api.core.model.workspace.config;
import java.util.Map;
import org.eclipse.che.api.core.model.workspace.runtime.Server;
import org.eclipse.che.commons.annotation.Nullable;
/**
@ -20,6 +21,13 @@ import org.eclipse.che.commons.annotation.Nullable;
*/
public interface ServerConfig {
/**
* {@link ServerConfig} and {@link Server} attribute name which can identify server as internal or
* external. Attribute value {@code true} makes a server internal, any other value or lack of the
* attribute makes the server external.
*/
String INTERNAL_SERVER_ATTRIBUTE = "internal";
/**
* Port used by server.
*

View File

@ -306,7 +306,7 @@ public class WorkspacePermissionsFilterTest {
assertEquals(response.getStatusCode(), 204);
verify(superPrivilegesChecker).hasSuperPrivileges();
verify(workspaceService).getByKey(eq("workspace123"));
verify(workspaceService).getByKey(eq("workspace123"), eq("false"));
verify(subject).hasPermission(eq("workspace"), eq("workspace123"), eq("read"));
}
@ -327,7 +327,7 @@ public class WorkspacePermissionsFilterTest {
assertEquals(response.getStatusCode(), 204);
verify(superPrivilegesChecker).hasSuperPrivileges();
verify(workspaceService).getByKey(eq("workspace123"));
verify(workspaceService).getByKey(eq("workspace123"), eq("false"));
verify(subject, never()).hasPermission(eq("workspace"), eq("workspace123"), eq("read"));
}
@ -351,7 +351,7 @@ public class WorkspacePermissionsFilterTest {
.get(SECURE_PATH + "/workspace/{key}");
assertEquals(response.getStatusCode(), 204);
verify(workspaceService).getByKey(eq("userok:myWorkspace"));
verify(workspaceService).getByKey(eq("userok:myWorkspace"), eq("false"));
verify(subject).hasPermission(eq("workspace"), eq("workspace123"), eq("read"));
}

View File

@ -10,6 +10,7 @@
*/
package org.eclipse.che.api.workspace.server;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.toList;
@ -47,6 +48,7 @@ import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.workspace.Workspace;
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.core.rest.Service;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
@ -56,9 +58,11 @@ import org.eclipse.che.api.workspace.server.token.MachineTokenException;
import org.eclipse.che.api.workspace.server.token.MachineTokenProvider;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.api.workspace.shared.dto.MachineDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.RecipeDto;
import org.eclipse.che.api.workspace.shared.dto.RuntimeDto;
import org.eclipse.che.api.workspace.shared.dto.ServerDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
import org.eclipse.che.commons.env.EnvironmentContext;
@ -184,10 +188,17 @@ public class WorkspaceService extends Service {
})
)
@PathParam("key")
String key)
String key,
@ApiParam("Whether to include internal servers into runtime or not")
@DefaultValue("false")
@QueryParam("includeInternalServers")
String includeInternalServers)
throws NotFoundException, ServerException, ForbiddenException, BadRequestException {
validateKey(key);
return asDtoWithLinksAndToken(workspaceManager.getWorkspace(key));
boolean bIncludeInternalServers =
isNullOrEmpty(includeInternalServers) || Boolean.parseBoolean(includeInternalServers);
return filterServers(
asDtoWithLinksAndToken(workspaceManager.getWorkspace(key)), bIncludeInternalServers);
}
@GET
@ -797,4 +808,30 @@ public class WorkspaceService extends Service {
return workspaceDto;
}
private WorkspaceDto filterServers(WorkspaceDto workspace, boolean includeInternal) {
// no runtime - nothing to filter
if (workspace.getRuntime() == null) {
return workspace;
}
// if it is needed to include internal there is nothing to filter
if (includeInternal) {
return workspace;
}
for (MachineDto machine : workspace.getRuntime().getMachines().values()) {
Map<String, ServerDto> filteredServers = new HashMap<>();
machine
.getServers()
.forEach(
(name, server) -> {
if (!"true"
.equals(server.getAttributes().get(ServerConfig.INTERNAL_SERVER_ATTRIBUTE))) {
filteredServers.put(name, server);
}
});
machine.withServers(filteredServers);
}
return workspace;
}
}

View File

@ -31,6 +31,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
@ -45,19 +46,28 @@ import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.config.ProjectConfig;
import org.eclipse.che.api.core.model.workspace.config.ServerConfig;
import org.eclipse.che.api.core.model.workspace.runtime.Machine;
import org.eclipse.che.api.core.model.workspace.runtime.Server;
import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus;
import org.eclipse.che.api.core.rest.ApiExceptionMapper;
import org.eclipse.che.api.core.rest.shared.dto.ServiceError;
import org.eclipse.che.api.workspace.server.model.impl.CommandImpl;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.model.impl.MachineConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.MachineImpl;
import org.eclipse.che.api.workspace.server.model.impl.RecipeImpl;
import org.eclipse.che.api.workspace.server.model.impl.RuntimeImpl;
import org.eclipse.che.api.workspace.server.model.impl.ServerImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.token.MachineTokenProvider;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
import org.eclipse.che.api.workspace.shared.dto.MachineDto;
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
import org.eclipse.che.api.workspace.shared.dto.RuntimeDto;
import org.eclipse.che.api.workspace.shared.dto.ServerDto;
import org.eclipse.che.api.workspace.shared.dto.SourceStorageDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
@ -308,6 +318,241 @@ public class WorkspaceServiceTest {
return new Object[][] {{"workspaceId"}, {"namespace:name"}, {":name"}};
}
@Test
public void shouldGetWorkspaceWithExternalServersByDefault() throws Exception {
// given
WorkspaceImpl workspace = createWorkspace(createConfigDto());
String externalServerKey = "server2";
ServerImpl externalServer = createExternalServer();
Map<String, Server> servers =
ImmutableMap.of("server1", createInternalServer(), externalServerKey, externalServer);
Map<String, Machine> machines =
singletonMap("machine1", new MachineImpl(singletonMap("key", "value"), servers));
workspace.setRuntime(new RuntimeImpl("activeEnv", machines, "user123"));
when(wsManager.getWorkspace(workspace.getId())).thenReturn(workspace);
Map<String, MachineDto> expected =
singletonMap(
"machine1",
newDto(MachineDto.class)
.withAttributes(singletonMap("key", "value"))
.withServers(
singletonMap(
externalServerKey,
newDto(ServerDto.class)
.withUrl(externalServer.getUrl())
.withStatus(externalServer.getStatus())
.withAttributes(externalServer.getAttributes()))));
// when
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/workspace/" + workspace.getId());
// then
assertEquals(response.getStatusCode(), 200);
RuntimeDto retrievedRuntime = unwrapDto(response, WorkspaceDto.class).getRuntime();
assertNotNull(retrievedRuntime);
assertEquals(expected, retrievedRuntime.getMachines());
}
@Test
public void shouldTreatServerWithInternalServerAttributeNotEqualToTrueExternal()
throws Exception {
// given
WorkspaceImpl workspace = createWorkspace(createConfigDto());
String externalServerKey = "server2";
ServerImpl externalServer =
createInternalServer()
.withAttributes(singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, ""));
Map<String, Server> servers =
ImmutableMap.of("server1", createInternalServer(), externalServerKey, externalServer);
Map<String, Machine> machines =
singletonMap("machine1", new MachineImpl(singletonMap("key", "value"), servers));
workspace.setRuntime(new RuntimeImpl("activeEnv", machines, "user123"));
when(wsManager.getWorkspace(workspace.getId())).thenReturn(workspace);
Map<String, MachineDto> expected =
singletonMap(
"machine1",
newDto(MachineDto.class)
.withAttributes(singletonMap("key", "value"))
.withServers(
singletonMap(
externalServerKey,
newDto(ServerDto.class)
.withUrl(externalServer.getUrl())
.withStatus(externalServer.getStatus())
.withAttributes(externalServer.getAttributes()))));
// when
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.when()
.get(SECURE_PATH + "/workspace/" + workspace.getId());
// then
assertEquals(response.getStatusCode(), 200);
RuntimeDto retrievedRuntime = unwrapDto(response, WorkspaceDto.class).getRuntime();
assertNotNull(retrievedRuntime);
assertEquals(expected, retrievedRuntime.getMachines());
}
@Test
public void shouldGetWorkspaceWithInternalServers() throws Exception {
// given
WorkspaceImpl workspace = createWorkspace(createConfigDto());
String externalServerKey = "server2";
String internalServerKey = "server1";
ServerImpl externalServer = createExternalServer();
ServerImpl internalServer = createInternalServer();
Map<String, Server> servers =
ImmutableMap.of(
internalServerKey, createInternalServer(), externalServerKey, externalServer);
Map<String, Machine> machines =
singletonMap("machine1", new MachineImpl(singletonMap("key", "value"), servers));
workspace.setRuntime(new RuntimeImpl("activeEnv", machines, "user123"));
when(wsManager.getWorkspace(workspace.getId())).thenReturn(workspace);
Map<String, MachineDto> expected =
singletonMap(
"machine1",
newDto(MachineDto.class)
.withAttributes(singletonMap("key", "value"))
.withServers(
ImmutableMap.of(
externalServerKey,
newDto(ServerDto.class)
.withUrl(externalServer.getUrl())
.withStatus(externalServer.getStatus())
.withAttributes(externalServer.getAttributes()),
internalServerKey,
newDto(ServerDto.class)
.withUrl(createInternalServer().getUrl())
.withStatus(internalServer.getStatus())
.withAttributes(internalServer.getAttributes()))));
// when
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.queryParameter("includeInternalServers", Boolean.TRUE.toString())
.when()
.get(SECURE_PATH + "/workspace/" + workspace.getId());
// then
assertEquals(response.getStatusCode(), 200);
RuntimeDto retrievedRuntime = unwrapDto(response, WorkspaceDto.class).getRuntime();
assertNotNull(retrievedRuntime);
assertEquals(expected, retrievedRuntime.getMachines());
}
@Test
public void shouldGetWorkspaceWithInternalServersIfCorrespondingQueryParamHasEmptyValue()
throws Exception {
// given
WorkspaceImpl workspace = createWorkspace(createConfigDto());
String externalServerKey = "server2";
String internalServerKey = "server1";
ServerImpl externalServer = createExternalServer();
ServerImpl internalServer = createInternalServer();
Map<String, Server> servers =
ImmutableMap.of(
internalServerKey, createInternalServer(), externalServerKey, externalServer);
Map<String, Machine> machines =
singletonMap("machine1", new MachineImpl(singletonMap("key", "value"), servers));
workspace.setRuntime(new RuntimeImpl("activeEnv", machines, "user123"));
when(wsManager.getWorkspace(workspace.getId())).thenReturn(workspace);
Map<String, MachineDto> expected =
singletonMap(
"machine1",
newDto(MachineDto.class)
.withAttributes(singletonMap("key", "value"))
.withServers(
ImmutableMap.of(
externalServerKey,
newDto(ServerDto.class)
.withUrl(externalServer.getUrl())
.withStatus(externalServer.getStatus())
.withAttributes(externalServer.getAttributes()),
internalServerKey,
newDto(ServerDto.class)
.withUrl(createInternalServer().getUrl())
.withStatus(internalServer.getStatus())
.withAttributes(internalServer.getAttributes()))));
// when
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.queryParameter("includeInternalServers", "")
.when()
.get(SECURE_PATH + "/workspace/" + workspace.getId());
// then
assertEquals(response.getStatusCode(), 200);
RuntimeDto retrievedRuntime = unwrapDto(response, WorkspaceDto.class).getRuntime();
assertNotNull(retrievedRuntime);
assertEquals(expected, retrievedRuntime.getMachines());
}
@Test
public void shouldGetWorkspaceWithInternalServersIfCorrespondingQueryParamHasNoValue()
throws Exception {
// given
WorkspaceImpl workspace = createWorkspace(createConfigDto());
String externalServerKey = "server2";
String internalServerKey = "server1";
ServerImpl externalServer = createExternalServer();
ServerImpl internalServer = createInternalServer();
Map<String, Server> servers =
ImmutableMap.of(
internalServerKey, createInternalServer(), externalServerKey, externalServer);
Map<String, Machine> machines =
singletonMap("machine1", new MachineImpl(singletonMap("key", "value"), servers));
workspace.setRuntime(new RuntimeImpl("activeEnv", machines, "user123"));
when(wsManager.getWorkspace(workspace.getId())).thenReturn(workspace);
Map<String, MachineDto> expected =
singletonMap(
"machine1",
newDto(MachineDto.class)
.withAttributes(singletonMap("key", "value"))
.withServers(
ImmutableMap.of(
externalServerKey,
newDto(ServerDto.class)
.withUrl(externalServer.getUrl())
.withStatus(externalServer.getStatus())
.withAttributes(externalServer.getAttributes()),
internalServerKey,
newDto(ServerDto.class)
.withUrl(createInternalServer().getUrl())
.withStatus(internalServer.getStatus())
.withAttributes(internalServer.getAttributes()))));
// when
Response response =
given()
.auth()
.basic(ADMIN_USER_NAME, ADMIN_USER_PASSWORD)
.queryParameter("includeInternalServers")
.when()
.get(SECURE_PATH + "/workspace/" + workspace.getId());
// then
assertEquals(response.getStatusCode(), 200);
RuntimeDto retrievedRuntime = unwrapDto(response, WorkspaceDto.class).getRuntime();
assertNotNull(retrievedRuntime);
assertEquals(expected, retrievedRuntime.getMachines());
}
@Test
public void shouldReturnWorkspaceWithTokenIfRuntimeExists() throws Exception {
final WorkspaceImpl workspace = createWorkspace(createConfigDto());
@ -935,6 +1180,22 @@ public class WorkspaceServiceTest {
return DtoConverter.asDto(config);
}
private ServerImpl createInternalServer() {
return new ServerImpl()
.withStatus(ServerStatus.UNKNOWN)
.withUrl("http://localhost:7070")
.withAttributes(
singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, Boolean.TRUE.toString()));
}
private ServerImpl createExternalServer() {
return new ServerImpl()
.withStatus(ServerStatus.UNKNOWN)
.withUrl("http://localhost:7070")
.withAttributes(
singletonMap(ServerConfig.INTERNAL_SERVER_ATTRIBUTE, Boolean.FALSE.toString()));
}
@Filter
public static class EnvironmentFilter implements RequestFilter {
@Override