CHE-22: check environment parameter on workspace start
Signed-off-by: Alexander Garagatyi <agaragatyi@codenvy.com>6.19.x
parent
8482352de5
commit
29865528df
|
|
@ -30,7 +30,7 @@ import static java.lang.String.format;
|
|||
@Singleton
|
||||
public class DefaultWorkspaceConfigValidator implements WorkspaceConfigValidator {
|
||||
/* should contain [3, 20] characters, first and last character is letter or digit, available characters {A-Za-z0-9.-_}*/
|
||||
private static final Pattern WS_NAME = Pattern.compile("[\\w][\\w\\.\\-]{1,18}[\\w]");
|
||||
private static final Pattern WS_NAME = Pattern.compile("[a-zA-Z0-9][-_.a-zA-Z0-9]{1,18}[a-zA-Z0-9]");
|
||||
|
||||
/**
|
||||
* Checks that workspace configuration is valid.
|
||||
|
|
@ -49,58 +49,67 @@ public class DefaultWorkspaceConfigValidator implements WorkspaceConfigValidator
|
|||
@Override
|
||||
public void validate(WorkspaceConfig config) throws BadRequestException {
|
||||
// configuration object itself
|
||||
requiredNotNull(config.getName(), "Workspace name required");
|
||||
if (!WS_NAME.matcher(config.getName()).matches()) {
|
||||
throw new BadRequestException("Incorrect workspace name, it must be between 3 and 20 characters and may contain digits, " +
|
||||
"latin letters, underscores, dots, dashes and should start and end only with digits, " +
|
||||
"latin letters or underscores");
|
||||
}
|
||||
checkNotNull(config.getName(), "Workspace name required");
|
||||
checkArgument(WS_NAME.matcher(config.getName()).matches(),
|
||||
"Incorrect workspace name, it must be between 3 and 20 characters and may contain digits, " +
|
||||
"latin letters, underscores, dots, dashes and should start and end only with digits, " +
|
||||
"latin letters or underscores");
|
||||
|
||||
//attributes
|
||||
for (String attributeName : config.getAttributes().keySet()) {
|
||||
//attribute name should not be empty and should not start with codenvy
|
||||
if (attributeName.trim().isEmpty() || attributeName.toLowerCase().startsWith("codenvy")) {
|
||||
throw new BadRequestException(format("Attribute name '%s' is not valid", attributeName));
|
||||
}
|
||||
checkArgument(attributeName != null && !attributeName.trim().isEmpty() && !attributeName.toLowerCase().startsWith("codenvy"),
|
||||
"Attribute name '%s' is not valid",
|
||||
attributeName);
|
||||
}
|
||||
|
||||
//environments
|
||||
requiredNotNull(config.getDefaultEnv(), "Workspace default environment name required");
|
||||
if (!config.getEnvironments().stream().anyMatch(env -> env.getName().equals(config.getDefaultEnv()))) {
|
||||
throw new BadRequestException("Workspace default environment configuration required");
|
||||
}
|
||||
checkArgument(!isNullOrEmpty(config.getDefaultEnv()), "Workspace default environment name required");
|
||||
checkArgument(config.getEnvironments()
|
||||
.stream()
|
||||
.anyMatch(env -> config.getDefaultEnv().equals(env.getName())),
|
||||
"Workspace default environment configuration required");
|
||||
|
||||
for (Environment environment : config.getEnvironments()) {
|
||||
final String envName = environment.getName();
|
||||
requiredNotNull(envName, "Environment name should not be null");
|
||||
checkArgument(!isNullOrEmpty(envName), "Environment name should be neither null nor empty");
|
||||
|
||||
checkArgument(environment.getRecipe() == null || "docker".equals(environment.getRecipe().getType()),
|
||||
"Couldn't start workspace '%s' from environment '%s', environment recipe has unsupported type '%s'",
|
||||
config.getName(),
|
||||
envName,
|
||||
environment.getRecipe() != null ? environment.getRecipe().getType() : null);
|
||||
|
||||
//machine configs
|
||||
if (environment.getMachineConfigs().isEmpty()) {
|
||||
throw new BadRequestException("Environment '" + envName + "' should contain at least 1 machine");
|
||||
}
|
||||
checkArgument(!environment.getMachineConfigs().isEmpty(), "Environment '%s' should contain at least 1 machine", envName);
|
||||
|
||||
final long devCount = environment.getMachineConfigs()
|
||||
.stream()
|
||||
.filter(MachineConfig::isDev)
|
||||
.count();
|
||||
if (devCount != 1) {
|
||||
throw new BadRequestException(format("Environment should contain exactly 1 dev machine, but '%s' contains '%d'",
|
||||
envName,
|
||||
devCount));
|
||||
}
|
||||
checkArgument(devCount == 1,
|
||||
"Environment should contain exactly 1 dev machine, but '%s' contains '%d'",
|
||||
envName,
|
||||
devCount);
|
||||
for (MachineConfig machineCfg : environment.getMachineConfigs()) {
|
||||
if (isNullOrEmpty(machineCfg.getName())) {
|
||||
throw new BadRequestException("Environment " + envName + " contains machine without of name");
|
||||
}
|
||||
requiredNotNull(machineCfg.getSource(), "Environment " + envName + " contains machine without of source");
|
||||
//TODO require type?
|
||||
checkArgument(!isNullOrEmpty(machineCfg.getName()), "Environment %s contains machine with null or empty name", envName);
|
||||
checkNotNull(machineCfg.getSource(), "Environment " + envName + " contains machine without source");
|
||||
checkArgument("docker".equals(machineCfg.getType()),
|
||||
"Type of machine %s in environment %s is not supported. Supported value is 'docker'.",
|
||||
machineCfg.getName(),
|
||||
envName);
|
||||
}
|
||||
}
|
||||
|
||||
//commands
|
||||
for (Command command : config.getCommands()) {
|
||||
requiredNotNull(command.getName(), "Workspace " + config.getName() + " contains command without of name");
|
||||
requiredNotNull(command.getCommandLine(), format("Command line required for command '%s' in workspace '%s'",
|
||||
command.getName(),
|
||||
config.getName()));
|
||||
checkArgument(!isNullOrEmpty(command.getName()),
|
||||
"Workspace %s contains command with null or empty name",
|
||||
config.getName());
|
||||
checkArgument(!isNullOrEmpty(command.getCommandLine()),
|
||||
"Command line required for command '%s' in workspace '%s'",
|
||||
command.getName(),
|
||||
config.getName());
|
||||
}
|
||||
|
||||
//projects
|
||||
|
|
@ -111,9 +120,31 @@ public class DefaultWorkspaceConfigValidator implements WorkspaceConfigValidator
|
|||
* Checks that object reference is not null, throws {@link BadRequestException}
|
||||
* in the case of null {@code object} with given {@code message}.
|
||||
*/
|
||||
private void requiredNotNull(Object object, String message) throws BadRequestException {
|
||||
private void checkNotNull(Object object, String message) throws BadRequestException {
|
||||
if (object == null) {
|
||||
throw new BadRequestException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that expression is true, throws {@link BadRequestException} otherwise.
|
||||
*
|
||||
* <p>Exception uses error message built from error message template and error message parameters.
|
||||
*/
|
||||
private void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageParams) throws BadRequestException {
|
||||
if (!expression) {
|
||||
throw new BadRequestException(format(errorMessageTemplate, errorMessageParams));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that expression is true, throws {@link BadRequestException} otherwise.
|
||||
*
|
||||
* <p>Exception uses error message built from error message template and error message parameters.
|
||||
*/
|
||||
private void checkArgument(boolean expression, String errorMessage) throws BadRequestException {
|
||||
if (!expression) {
|
||||
throw new BadRequestException(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
|
|
@ -65,6 +64,9 @@ import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPING;
|
|||
* second for <i>owner -> list of workspaces</i> mapping(which speeds up fetching workspaces by owner).
|
||||
* Maps are guarded by {@link ReentrantReadWriteLock}.
|
||||
*
|
||||
* <p>The implementation doesn't validate parameters.
|
||||
* They should be validated by caller of methods of this class.
|
||||
*
|
||||
* @author Yevhenii Voevodin
|
||||
* @author Alexander Garagatyi
|
||||
*/
|
||||
|
|
@ -120,7 +122,6 @@ public class RuntimeWorkspaceRegistry {
|
|||
BadRequestException,
|
||||
NotFoundException {
|
||||
checkRegistryIsNotStopped();
|
||||
checkWorkspaceIsValidForStart(usersWorkspace, envName);
|
||||
// Prepare runtime workspace for start
|
||||
final RuntimeWorkspaceImpl newRuntime = RuntimeWorkspaceImpl.builder()
|
||||
.fromWorkspace(usersWorkspace)
|
||||
|
|
@ -367,43 +368,6 @@ public class RuntimeWorkspaceRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if workspace is valid for start.
|
||||
*/
|
||||
private void checkWorkspaceIsValidForStart(UsersWorkspace workspace, String envName) throws BadRequestException {
|
||||
if (workspace == null) {
|
||||
throw new BadRequestException("Required non-null workspace");
|
||||
}
|
||||
if (envName == null) {
|
||||
throw new BadRequestException(format("Couldn't start workspace '%s', environment name is null",
|
||||
workspace.getConfig().getName()));
|
||||
}
|
||||
final Optional<? extends Environment> environmentOptional = workspace.getConfig()
|
||||
.getEnvironments()
|
||||
.stream()
|
||||
.filter(env -> env.getName().equals(envName))
|
||||
.findFirst();
|
||||
if (!environmentOptional.isPresent()) {
|
||||
throw new BadRequestException(format("Couldn't start workspace '%s', workspace doesn't have environment '%s'",
|
||||
workspace.getConfig().getName(),
|
||||
envName));
|
||||
}
|
||||
Environment environment = environmentOptional.get();
|
||||
if (environment.getRecipe() != null && !"docker".equals(environment.getRecipe().getType())) {
|
||||
throw new BadRequestException(format("Couldn't start workspace '%s' from environment '%s', " +
|
||||
"environment recipe has unsupported type '%s'",
|
||||
workspace.getConfig().getName(),
|
||||
envName,
|
||||
environment.getRecipe().getType()));
|
||||
}
|
||||
if (findDev(environment.getMachineConfigs()) == null) {
|
||||
throw new BadRequestException(format("Couldn't start workspace '%s' from environment '%s', " +
|
||||
"environment doesn't contain dev-machine",
|
||||
workspace.getConfig().getName(),
|
||||
envName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds given machine to the running workspace, if the workspace exists.
|
||||
* Sets up this machine as dev-machine if it is dev.
|
||||
|
|
|
|||
|
|
@ -399,11 +399,13 @@ public class WorkspaceManager {
|
|||
* @see WorkspaceHooks#beforeCreate(UsersWorkspace, String)
|
||||
* @see RuntimeWorkspaceRegistry#start(UsersWorkspace, String)
|
||||
*/
|
||||
public RuntimeWorkspaceImpl startTemporaryWorkspace(WorkspaceConfig workspaceConfig, @Nullable String accountId) throws ServerException,
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
NotFoundException,
|
||||
ConflictException {
|
||||
public RuntimeWorkspaceImpl startTemporaryWorkspace(WorkspaceConfig workspaceConfig,
|
||||
@Nullable String accountId) throws ServerException,
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
NotFoundException,
|
||||
ConflictException {
|
||||
|
||||
final UsersWorkspaceImpl workspace = fromConfig(workspaceConfig, getCurrentUserId());
|
||||
workspace.setTemporary(true);
|
||||
// Temporary workspace is not persistent one, which means
|
||||
|
|
@ -573,7 +575,9 @@ public class WorkspaceManager {
|
|||
UsersWorkspaceImpl performAsyncStart(UsersWorkspaceImpl workspace,
|
||||
String envName,
|
||||
boolean recover,
|
||||
@Nullable String accountId) throws ConflictException {
|
||||
@Nullable String accountId) throws ConflictException,
|
||||
BadRequestException {
|
||||
|
||||
// Runtime workspace registry performs this check as well
|
||||
// but this check needed here because permanent workspace start performed asynchronously
|
||||
// which means that even if registry won't start workspace client receives workspace object
|
||||
|
|
@ -588,6 +592,17 @@ public class WorkspaceManager {
|
|||
}
|
||||
workspace.setTemporary(false);
|
||||
workspace.setStatus(WorkspaceStatus.STARTING);
|
||||
|
||||
if (envName != null && !workspace.getConfig()
|
||||
.getEnvironments()
|
||||
.stream()
|
||||
.anyMatch(env -> env.getName().equals(envName))) {
|
||||
|
||||
throw new BadRequestException(format("Couldn't start workspace '%s', workspace doesn't have environment '%s'",
|
||||
workspace.getConfig().getName(),
|
||||
envName));
|
||||
}
|
||||
|
||||
executor.execute(ThreadLocalPropagateContext.wrap(() -> {
|
||||
try {
|
||||
performSyncStart(workspace, firstNonNull(envName, workspace.getConfig().getDefaultEnv()), recover, accountId);
|
||||
|
|
|
|||
|
|
@ -11,20 +11,24 @@
|
|||
package org.eclipse.che.api.workspace.server;
|
||||
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
|
||||
import org.eclipse.che.api.machine.shared.dto.CommandDto;
|
||||
import org.eclipse.che.api.machine.shared.dto.MachineConfigDto;
|
||||
import org.eclipse.che.api.machine.shared.dto.MachineSourceDto;
|
||||
import org.eclipse.che.api.workspace.shared.dto.EnvironmentDto;
|
||||
import org.eclipse.che.api.workspace.shared.dto.RecipeDto;
|
||||
import org.eclipse.che.api.workspace.shared.dto.WorkspaceConfigDto;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.AssertJUnit.assertNotNull;
|
||||
|
||||
/**
|
||||
* Tests for {@link WorkspaceConfigValidator} and {@link DefaultWorkspaceConfigValidator}
|
||||
|
|
@ -41,52 +45,328 @@ public class DefaultWorkspaceConfigValidatorTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeNotValidationHaveNotDevMachineInConfig() throws Exception {
|
||||
BadRequestException exResult = null;
|
||||
try {
|
||||
wsValidator.validate(createConfig("dev-workspace", false));
|
||||
} catch (BadRequestException e) {
|
||||
exResult = e;
|
||||
}
|
||||
assertNotNull(exResult);
|
||||
public void shouldValidateCorrectWorkspace() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace name required")
|
||||
public void shouldFailValidationIfNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.withName(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "invalidNameProvider",
|
||||
expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Incorrect workspace name, it must be between 3 and 20 characters and may contain digits, " +
|
||||
"latin letters, underscores, dots, dashes and should start and end only with digits, " +
|
||||
"latin letters or underscores")
|
||||
public void shouldFailValidationIfNameIsInvalid(String name) throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.withName(name);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@DataProvider(name = "invalidNameProvider")
|
||||
public static Object[][] invalidNameProvider() {
|
||||
return new Object[][] {
|
||||
{".name"},
|
||||
{"name."},
|
||||
{"-name"},
|
||||
{"name-"},
|
||||
{"long-name12345678901234567890"},
|
||||
{"_name"},
|
||||
{"name_"}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "validNameProvider")
|
||||
public void shouldValidateCorrectWorkspaceName(String name) throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.withName(name);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@DataProvider(name = "validNameProvider")
|
||||
public static Object[][] validNameProvider() {
|
||||
return new Object[][] {
|
||||
{"name"},
|
||||
{"quiteLongName1234567"},
|
||||
{"name-with-dashes"},
|
||||
{"name.with.dots"},
|
||||
{"name0with1digits"},
|
||||
{"mixed-symbols.name12"},
|
||||
{"123456"},
|
||||
{"name_name"},
|
||||
{"123-456.78"}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Attribute name 'null' is not valid")
|
||||
public void shouldFailValidationIfAttributeNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getAttributes()
|
||||
.put(null, "value1");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Attribute name '' is not valid")
|
||||
public void shouldFailValidationIfAttributeNameIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getAttributes()
|
||||
.put("", "value1");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Attribute name '.*' is not valid")
|
||||
public void shouldFailValidationIfAttributeNameStartsWithWordCodenvy() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getAttributes()
|
||||
.put("codenvy_key", "value1");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace default environment name required")
|
||||
public void shouldFailValidationIfDefaultEnvNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.setDefaultEnv(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace default environment name required")
|
||||
public void shouldFailValidationIfDefaultEnvNameIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.setDefaultEnv("");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace default environment configuration required")
|
||||
public void shouldFailValidationIfEnvWithDefaultEnvNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.setEnvironments(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment name should be neither null nor empty")
|
||||
public void shouldFailValidationIfEnvNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.add(newDto(EnvironmentDto.class).withName(null)
|
||||
.withMachineConfigs(config.getEnvironments()
|
||||
.get(0)
|
||||
.getMachineConfigs()));
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment name should be neither null nor empty")
|
||||
public void shouldFailValidationIfEnvNameIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.add(newDto(EnvironmentDto.class).withName("")
|
||||
.withMachineConfigs(config.getEnvironments()
|
||||
.get(0)
|
||||
.getMachineConfigs()));
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '.*' from environment '.*', environment recipe has unsupported type '.*'")
|
||||
public void shouldFailValidationIfEnvironmentRecipeTypeIsNotDocker() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.get(0)
|
||||
.withRecipe(newDto(RecipeDto.class).withType("kubernetes"));
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeValidationHaveDevMachineInConfig() throws Exception {
|
||||
Exception exResult = null;
|
||||
try {
|
||||
wsValidator.validate(createConfig("dev-workspace", true));
|
||||
} catch (BadRequestException e) {
|
||||
exResult = e;
|
||||
}
|
||||
assertNull(exResult);
|
||||
public void shouldNotFailValidationIfEnvironmentRecipeTypeIsDocker() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.get(0)
|
||||
.withRecipe(newDto(RecipeDto.class).withType("docker"));
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotBeValidationHaveDevMachineInConfigButWsNameNull() throws Exception {
|
||||
Exception exResult = null;
|
||||
try {
|
||||
wsValidator.validate(createConfig(null, true));
|
||||
} catch (BadRequestException e) {
|
||||
exResult = e;
|
||||
}
|
||||
assertNotNull(exResult);
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment '.*' should contain at least 1 machine")
|
||||
public void shouldFailValidationIfMachinesListIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.get(0)
|
||||
.withMachineConfigs(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotBeValidationHaveNotDevMachineInConfigButWsNameNull() throws Exception {
|
||||
Exception exResult = null;
|
||||
try {
|
||||
wsValidator.validate(createConfig(null, false));
|
||||
} catch (BadRequestException e) {
|
||||
exResult = e;
|
||||
}
|
||||
assertNotNull(exResult);
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment should contain exactly 1 dev machine, but '.*' contains '0'")
|
||||
public void shouldFailValidationIfNoDevMachineFound() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments()
|
||||
.get(0)
|
||||
.getMachineConfigs()
|
||||
.stream()
|
||||
.filter(MachineConfigDto::isDev)
|
||||
.forEach(machine -> machine.withDev(false));
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment should contain exactly 1 dev machine, but '.*' contains '2'")
|
||||
public void shouldFailValidationIf2DevMachinesFound() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
final Optional<MachineConfigDto> devMachine = config.getEnvironments()
|
||||
.get(0)
|
||||
.getMachineConfigs()
|
||||
.stream()
|
||||
.filter(MachineConfigDto::isDev)
|
||||
.findAny();
|
||||
config.getEnvironments()
|
||||
.get(0)
|
||||
.getMachineConfigs()
|
||||
.add(devMachine.get().withName("other-name"));
|
||||
|
||||
private static WorkspaceConfig createConfig(String wsName, boolean isDevMachine) {
|
||||
MachineConfigDto devMachine = newDto(MachineConfigDto.class).withDev(isDevMachine)
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment .* contains machine with null or empty name")
|
||||
public void shouldFailValidationIfMachineNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments().get(0).getMachineConfigs().get(0).withName(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment .* contains machine with null or empty name")
|
||||
public void shouldFailValidationIfMachineNameIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments().get(0).getMachineConfigs().get(0).withName("");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment .* contains machine without source")
|
||||
public void shouldFailValidationIfMachineSourceIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments().get(0).getMachineConfigs().get(0).withSource(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Type of machine .* in environment .* is not supported. Supported value is 'docker'.")
|
||||
public void shouldFailValidationIfMachineTypeIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments().get(0).getMachineConfigs().get(0).withType(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Type of machine .* in environment .* is not supported. Supported value is 'docker'.")
|
||||
public void shouldFailValidationIfMachineTypeIsNotDocker() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getEnvironments().get(0).getMachineConfigs().get(0).withType("compose");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace .* contains command with null or empty name")
|
||||
public void shouldFailValidationIfCommandNameIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getCommands().get(0).withName(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace .* contains command with null or empty name")
|
||||
public void shouldFailValidationIfCommandNameIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getCommands().get(0).withName(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Command line required for command .* in workspace .*")
|
||||
public void shouldFailValidationIfCommandLineIsNull() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getCommands().get(0).withCommandLine(null);
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Command line required for command .* in workspace .*")
|
||||
public void shouldFailValidationIfCommandLineIsEmpty() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
config.getCommands().get(0).withCommandLine("");
|
||||
|
||||
|
||||
wsValidator.validate(config);
|
||||
}
|
||||
|
||||
private static WorkspaceConfigDto createConfig() {
|
||||
final WorkspaceConfigDto workspaceConfigDto = newDto(WorkspaceConfigDto.class).withName("ws-name")
|
||||
.withDefaultEnv("dev-env");
|
||||
|
||||
MachineConfigDto devMachine = newDto(MachineConfigDto.class).withDev(true)
|
||||
.withName("dev-machine")
|
||||
.withType("docker")
|
||||
.withSource(newDto(MachineSourceDto.class).withLocation("location")
|
||||
|
|
@ -94,8 +374,17 @@ public class DefaultWorkspaceConfigValidatorTest {
|
|||
EnvironmentDto devEnv = newDto(EnvironmentDto.class).withName("dev-env")
|
||||
.withMachineConfigs(new ArrayList<>(singletonList(devMachine)))
|
||||
.withRecipe(null);
|
||||
return newDto(WorkspaceConfigDto.class).withName(wsName)
|
||||
.withEnvironments(new ArrayList<>(singletonList(devEnv)))
|
||||
.withDefaultEnv("dev-env");
|
||||
workspaceConfigDto.setEnvironments(new ArrayList<>(singletonList(devEnv)));
|
||||
|
||||
List<CommandDto> commandDtos = new ArrayList<>();
|
||||
commandDtos.add(newDto(CommandDto.class).withName("command_name")
|
||||
.withType("maven")
|
||||
.withCommandLine("mvn clean install")
|
||||
.withAttributes(new HashMap<>(singletonMap("cmd-attribute-name", "cmd-attribute-value"))));
|
||||
workspaceConfigDto.setCommands(commandDtos);
|
||||
|
||||
workspaceConfigDto.withAttributes(new HashMap<>(singletonMap("ws-attribute-name", "ws-attribute-value")));
|
||||
|
||||
return workspaceConfigDto;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.api.workspace.server;
|
||||
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
|
|
@ -22,7 +21,6 @@ import org.eclipse.che.api.core.model.machine.Recipe;
|
|||
import org.eclipse.che.api.machine.server.exception.MachineException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineConfigImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
|
||||
import org.eclipse.che.api.machine.server.recipe.RecipeImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.RuntimeWorkspaceImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.UsersWorkspaceImpl;
|
||||
|
|
@ -37,7 +35,6 @@ import org.testng.annotations.Test;
|
|||
import java.util.Collections;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
|
|
@ -78,48 +75,6 @@ public class RuntimeWorkspaceRegistryTest {
|
|||
registry = new RuntimeWorkspaceRegistry(machineManagerMock);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class, expectedExceptionsMessageRegExp = "Required non-null workspace")
|
||||
public void testStartWithNullWorkspace() throws Exception {
|
||||
registry.start(null, "environment");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '.*', environment name is null")
|
||||
public void testStartWithNullEnvName() throws Exception {
|
||||
registry.start(workspaceMock(), null);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '', workspace doesn't have environment 'non-existing'")
|
||||
public void testStartWithNonExistingEnvironmentName() throws Exception {
|
||||
registry.start(workspaceMock(), "non-existing");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '.*' from environment '.*', " +
|
||||
"environment recipe has unsupported type 'non-docker'")
|
||||
public void testStartWithNonDockerEnvironmentRecipe() throws Exception {
|
||||
final UsersWorkspaceImpl workspaceMock = workspaceMock();
|
||||
EnvironmentImpl environment = new EnvironmentImpl(workspaceMock.getConfig().getDefaultEnv(),
|
||||
new RecipeImpl().withType("non-docker"),
|
||||
null);
|
||||
when(workspaceMock.getConfig().getEnvironments()).thenReturn(singletonList(environment));
|
||||
|
||||
registry.start(workspaceMock, workspaceMock.getConfig().getDefaultEnv());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '.*' from environment '.*', environment doesn't contain dev-machine")
|
||||
public void testStartWithEnvironmentWhichDoesNotContainDevMachine() throws Exception {
|
||||
final UsersWorkspaceImpl workspaceMock = workspaceMock();
|
||||
EnvironmentImpl environment = new EnvironmentImpl(workspaceMock.getConfig().getDefaultEnv(),
|
||||
new RecipeImpl().withType("docker"), null);
|
||||
environment.setMachineConfigs(emptyList());
|
||||
when(workspaceMock.getConfig().getEnvironments()).thenReturn(singletonList(environment));
|
||||
|
||||
registry.start(workspaceMock, workspaceMock.getConfig().getDefaultEnv());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void workspaceShouldBeInStartingStatusUntilDevMachineIsNotStarted() throws Exception {
|
||||
final MachineManager machineManagerMock = mock(MachineManager.class);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.api.workspace.server;
|
||||
|
||||
import org.eclipse.che.api.core.BadRequestException;
|
||||
import org.eclipse.che.api.core.ConflictException;
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.api.core.ServerException;
|
||||
|
|
@ -17,6 +18,7 @@ import org.eclipse.che.api.core.model.workspace.UsersWorkspace;
|
|||
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.machine.server.MachineManager;
|
||||
import org.eclipse.che.api.machine.server.impl.SnapshotImpl;
|
||||
import org.eclipse.che.api.machine.shared.dto.MachineConfigDto;
|
||||
import org.eclipse.che.api.machine.shared.dto.MachineSourceDto;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.RuntimeWorkspaceImpl;
|
||||
|
|
@ -52,6 +54,7 @@ import static org.mockito.Mockito.doNothing;
|
|||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
|
@ -89,7 +92,7 @@ public class WorkspaceManagerTest {
|
|||
private WorkspaceManager workspaceManager;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUpManager() throws Exception {
|
||||
public void setUp() throws Exception {
|
||||
workspaceManager = spy(new WorkspaceManager(workspaceDao, registry, workspaceConfigValidator, eventService, machineManager));
|
||||
workspaceManager.setHooks(workspaceHooks);
|
||||
|
||||
|
|
@ -371,10 +374,49 @@ public class WorkspaceManagerTest {
|
|||
workspaceManager.performSyncStart(workspace, workspace.getConfig().getDefaultEnv(), false, "account");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performAsyncStartShouldUseDefaultEnvIfNullEnvNameProvided() throws Exception {
|
||||
final UsersWorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), "user123", "account");
|
||||
when(registry.get(workspace.getId())).thenThrow(new NotFoundException(""));
|
||||
when(registry.start(any(), anyString(), anyBoolean())).thenReturn(createRuntime(workspace));
|
||||
|
||||
workspaceManager.performAsyncStart(workspace, null, false, "account");
|
||||
|
||||
// timeout is needed because this invocation will run in separate thread asynchronously
|
||||
verify(registry, timeout(2000)).start(workspace, workspace.getConfig().getDefaultEnv(), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performAsyncStartShouldUseProvidedEnvInsteadOfDefault() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
final EnvironmentDto nonDefaultEnv = newDto(EnvironmentDto.class).withName("non-default-env")
|
||||
.withMachineConfigs(
|
||||
config.getEnvironments().get(0).getMachineConfigs())
|
||||
.withRecipe(null);
|
||||
config.getEnvironments().add(nonDefaultEnv);
|
||||
final UsersWorkspaceImpl workspace = workspaceManager.createWorkspace(config, "user123", "account");
|
||||
when(registry.get(workspace.getId())).thenThrow(new NotFoundException(""));
|
||||
when(registry.start(any(), anyString(), anyBoolean())).thenReturn(createRuntime(workspace));
|
||||
|
||||
workspaceManager.performAsyncStart(workspace, nonDefaultEnv.getName(), false, "account");
|
||||
|
||||
// timeout is needed because this invocation will run in separate thread asynchronously
|
||||
verify(registry, timeout(2000)).start(workspace, nonDefaultEnv.getName(), false);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = BadRequestException.class,
|
||||
expectedExceptionsMessageRegExp = "Couldn't start workspace '.*', workspace doesn't have environment '.*'")
|
||||
public void performAsyncStartShouldCheckThatEnvWithProvidedEnvNameExists() throws Exception {
|
||||
final UsersWorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), "user123", "account");
|
||||
when(registry.get(workspace.getId())).thenThrow(new NotFoundException(""));
|
||||
|
||||
workspaceManager.performAsyncStart(workspace, "not-existing-env-name", false, "account");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToStartTemporaryWorkspace() throws Exception {
|
||||
final WorkspaceConfigDto config = createConfig();
|
||||
final UsersWorkspace workspace = workspaceManager.createWorkspace(config, "user123", "account");
|
||||
final UsersWorkspaceImpl workspace = workspaceManager.createWorkspace(config, "user123", "account");
|
||||
when(registry.start(workspaceCaptor.capture(), anyString(), anyBoolean())).thenReturn(createRuntime(workspace));
|
||||
|
||||
final RuntimeWorkspaceImpl runtime = workspaceManager.startTemporaryWorkspace(config, "account");
|
||||
|
|
@ -388,6 +430,8 @@ public class WorkspaceManagerTest {
|
|||
.get(0));
|
||||
verify(workspaceHooks).beforeCreate(captured, "account");
|
||||
verify(workspaceHooks).afterCreate(runtime, "account");
|
||||
verify(workspaceHooks).beforeStart(captured, config.getDefaultEnv(), "account");
|
||||
verify(workspaceManager).performSyncStart(captured, config.getDefaultEnv(), false, "account");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -424,7 +468,9 @@ public class WorkspaceManagerTest {
|
|||
public void shouldBeAbleToGetSnapshots() throws Exception {
|
||||
when(machineManager.getSnapshots("user123", "workspace123")).thenReturn(singletonList(any()));
|
||||
|
||||
assertEquals(workspaceManager.getSnapshot("workspace123").size(), 1);
|
||||
final List<SnapshotImpl> snapshots = workspaceManager.getSnapshot("workspace123");
|
||||
|
||||
assertEquals(snapshots.size(), 1);
|
||||
}
|
||||
|
||||
private RuntimeWorkspaceImpl createRuntime(UsersWorkspace workspace) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue