diff --git a/assembly/assembly-wsmaster-war/src/main/resources/META-INF/persistence.xml b/assembly/assembly-wsmaster-war/src/main/resources/META-INF/persistence.xml
index 1a974886c7..03e25ae1a5 100644
--- a/assembly/assembly-wsmaster-war/src/main/resources/META-INF/persistence.xml
+++ b/assembly/assembly-wsmaster-war/src/main/resources/META-INF/persistence.xml
@@ -70,7 +70,6 @@
org.eclipse.che.multiuser.machine.authentication.server.signature.model.impl.SignatureKeyPairImpl
org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState
- org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId
org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl
org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl.MachineId
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Runtime.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Runtime.java
index f97da65599..dd82a4f5f6 100644
--- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Runtime.java
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/Runtime.java
@@ -14,6 +14,7 @@ package org.eclipse.che.api.core.model.workspace;
import java.util.List;
import java.util.Map;
import org.eclipse.che.api.core.model.workspace.runtime.Machine;
+import org.eclipse.che.commons.annotation.Nullable;
/**
* Defines a contract for workspace runtime.
@@ -34,6 +35,7 @@ public interface Runtime {
* Returns an active environment name. The environment with such name must exist in {@link
* WorkspaceConfig#getEnvironments()}.
*/
+ @Nullable
String getActiveEnv();
/**
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java
index b55fbefd39..0e99779e64 100644
--- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/WorkspaceConfig.java
@@ -37,6 +37,7 @@ public interface WorkspaceConfig {
* Returns default environment name. It is mandatory, implementation should guarantee that
* environment with returned name exists for current workspace config.
*/
+ @Nullable
String getDefaultEnv();
/**
diff --git a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/runtime/RuntimeIdentity.java b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/runtime/RuntimeIdentity.java
index ff0e136feb..921aa8a1fc 100644
--- a/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/runtime/RuntimeIdentity.java
+++ b/core/che-core-api-model/src/main/java/org/eclipse/che/api/core/model/workspace/runtime/RuntimeIdentity.java
@@ -11,10 +11,13 @@
*/
package org.eclipse.che.api.core.model.workspace.runtime;
+import org.eclipse.che.commons.annotation.Nullable;
+
/** @author gazarenkov */
public interface RuntimeIdentity {
String getWorkspaceId();
+ @Nullable
String getEnvName();
String getOwnerId();
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
index 9bca18da4c..01e16a2b22 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/context/AppContextImpl.java
@@ -52,6 +52,7 @@ import org.eclipse.che.ide.api.selection.SelectionChangedHandler;
import org.eclipse.che.ide.api.workspace.WorkspaceReadyEvent;
import org.eclipse.che.ide.api.workspace.WsAgentServerUtil;
import org.eclipse.che.ide.api.workspace.event.WorkspaceStoppedEvent;
+import org.eclipse.che.ide.api.workspace.model.EnvironmentImpl;
import org.eclipse.che.ide.api.workspace.model.ServerImpl;
import org.eclipse.che.ide.api.workspace.model.VolumeImpl;
import org.eclipse.che.ide.api.workspace.model.WorkspaceImpl;
@@ -286,17 +287,16 @@ public class AppContextImpl
wsAgentServerUtilProvider.get().getWsAgentServerMachine().get().getName();
String activeEnv = workspace.getRuntime().getActiveEnv();
- VolumeImpl vol =
- workspace
- .getConfig()
- .getEnvironments()
- .get(activeEnv)
- .getMachines()
- .get(machineName)
- .getVolume("projects");
+ EnvironmentImpl environment = workspace.getConfig().getEnvironments().get(activeEnv);
+ VolumeImpl vol = null;
+ if (environment != null) {
+ vol = environment.getMachines().get(machineName).getVolume("projects");
+ }
// if voulme exists return its path, otherwise use backward compatible path (/projects)
- if (vol != null) projectsRoot = Path.valueOf(vol.getPath());
+ if (vol != null) {
+ projectsRoot = Path.valueOf(vol.getPath());
+ }
}
Log.debug(
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/loading/WorkspaceLoadingTrackerImpl.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/loading/WorkspaceLoadingTrackerImpl.java
index 4040038d07..ce90206409 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/loading/WorkspaceLoadingTrackerImpl.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/loading/WorkspaceLoadingTrackerImpl.java
@@ -162,6 +162,9 @@ public class WorkspaceLoadingTrackerImpl
EnvironmentImpl defaultEnvironment =
appContext.getWorkspace().getConfig().getEnvironments().get(defaultEnvironmentName);
+ if (defaultEnvironment == null) {
+ return;
+ }
Map environmentMachines = defaultEnvironment.getMachines();
for (final String machineName : environmentMachines.keySet()) {
MachineConfigImpl machineConfig = environmentMachines.get(machineName);
@@ -178,8 +181,10 @@ public class WorkspaceLoadingTrackerImpl
EnvironmentImpl defaultEnvironment =
appContext.getWorkspace().getConfig().getEnvironments().get(defaultEnvironmentName);
+ if (defaultEnvironment == null) {
+ return;
+ }
Map machines = defaultEnvironment.getMachines();
-
for (final String machineName : machines.keySet()) {
MachineConfigImpl machineConfig = machines.get(machineName);
view.addMachine(machineName);
@@ -219,6 +224,9 @@ public class WorkspaceLoadingTrackerImpl
EnvironmentImpl defaultEnvironment =
appContext.getWorkspace().getConfig().getEnvironments().get(defaultEnvironmentName);
+ if (defaultEnvironment == null) {
+ return;
+ }
Map machines = defaultEnvironment.getMachines();
for (final String machineName : machines.keySet()) {
MachineConfigImpl machineConfig = machines.get(machineName);
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/runtime/ContextBasedRuntimeInfoProvider.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/runtime/ContextBasedRuntimeInfoProvider.java
index 6d8d75e024..613ddebd7d 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/runtime/ContextBasedRuntimeInfoProvider.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/processes/runtime/ContextBasedRuntimeInfoProvider.java
@@ -57,6 +57,10 @@ public class ContextBasedRuntimeInfoProvider implements RuntimeInfoProvider {
return emptyList();
}
+ if (workspace.getConfig().getDefaultEnv() == null) {
+ return emptyList();
+ }
+
// map with servers where probably port is set
MachineConfigImpl preConfiguredRuntime =
workspace
diff --git a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceServiceClient.java b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceServiceClient.java
index 112148297a..18e9e0858e 100644
--- a/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceServiceClient.java
+++ b/ide/che-core-ide-app/src/main/java/org/eclipse/che/ide/workspace/WorkspaceServiceClient.java
@@ -23,6 +23,7 @@ import org.eclipse.che.api.promises.client.Function;
import org.eclipse.che.api.promises.client.Promise;
import org.eclipse.che.api.workspace.shared.dto.CommandDto;
import org.eclipse.che.api.workspace.shared.dto.WorkspaceDto;
+import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.ide.api.app.AppContext;
import org.eclipse.che.ide.api.command.CommandImpl;
import org.eclipse.che.ide.api.workspace.model.WorkspaceImpl;
@@ -88,8 +89,11 @@ public class WorkspaceServiceClient {
* @param envName the name of the workspace environment that should be used for start
* @return a promise that resolves to the {@link WorkspaceImpl}, or rejects with an error
*/
- Promise startById(String id, String envName) {
- String url = baseHttpUrl + "/" + id + "/runtime" + "?environment=" + envName;
+ Promise startById(String id, @Nullable String envName) {
+ String url = baseHttpUrl + "/" + id + "/runtime";
+ if (envName != null) {
+ url += "?environment=" + envName;
+ }
return asyncRequestFactory
.createPostRequest(url, null)
diff --git a/infrastructures/docker/environment/pom.xml b/infrastructures/docker/environment/pom.xml
index 25efbf7fad..a50f5a443c 100644
--- a/infrastructures/docker/environment/pom.xml
+++ b/infrastructures/docker/environment/pom.xml
@@ -71,6 +71,10 @@
org.eclipse.che.core
che-core-api-workspace
+
+ org.eclipse.che.core
+ che-core-commons-annotations
+
org.eclipse.che.core
che-core-commons-lang
diff --git a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/compose/ComposeEnvironmentFactory.java b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/compose/ComposeEnvironmentFactory.java
index 0a61322101..5e6e8d7317 100644
--- a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/compose/ComposeEnvironmentFactory.java
+++ b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/compose/ComposeEnvironmentFactory.java
@@ -11,7 +11,6 @@
*/
package org.eclipse.che.workspace.infrastructure.docker.environment.compose;
-import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
import static java.util.stream.Collectors.joining;
@@ -30,7 +29,13 @@ import org.eclipse.che.api.core.ValidationException;
import org.eclipse.che.api.core.model.workspace.Warning;
import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
-import org.eclipse.che.api.workspace.server.spi.environment.*;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
+import org.eclipse.che.api.workspace.server.spi.environment.MachineConfigsValidator;
+import org.eclipse.che.api.workspace.server.spi.environment.MemoryAttributeProvisioner;
+import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
+import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.model.ComposeRecipe;
import org.eclipse.che.workspace.infrastructure.docker.environment.compose.model.ComposeService;
@@ -63,8 +68,11 @@ public class ComposeEnvironmentFactory extends InternalEnvironmentFactory machines, List warnings)
+ @Nullable InternalRecipe recipe,
+ Map machines,
+ List warnings)
throws InfrastructureException, ValidationException {
+ checkNotNull(recipe, "Null recipe is not supported by compose environment factory");
String contentType = recipe.getContentType();
checkNotNull(contentType, "Recipe content type should not be null");
diff --git a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerfile/DockerfileEnvironmentFactory.java b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerfile/DockerfileEnvironmentFactory.java
index 74ae1e9746..5e6b87f85b 100644
--- a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerfile/DockerfileEnvironmentFactory.java
+++ b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerfile/DockerfileEnvironmentFactory.java
@@ -23,6 +23,7 @@ import org.eclipse.che.api.core.model.workspace.Warning;
import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.*;
+import org.eclipse.che.commons.annotation.Nullable;
/** @author Sergii Leshchenko */
@Singleton
@@ -43,8 +44,11 @@ public class DockerfileEnvironmentFactory
@Override
protected DockerfileEnvironment doCreate(
- InternalRecipe recipe, Map machines, List warnings)
+ @Nullable InternalRecipe recipe,
+ Map machines,
+ List warnings)
throws InfrastructureException, ValidationException {
+ checkNotNull(recipe, "Null recipe is not supported by docker file environment factory");
if (!DockerfileEnvironment.TYPE.equals(recipe.getType())) {
throw new ValidationException(
format(
@@ -66,4 +70,12 @@ public class DockerfileEnvironmentFactory
memoryProvisioner.provision(machineConfig, 0L, 0L);
}
}
+
+ private static void checkNotNull(
+ Object object, String errorMessageTemplate, Object... errorMessageParams)
+ throws ValidationException {
+ if (object == null) {
+ throw new ValidationException(format(errorMessageTemplate, errorMessageParams));
+ }
+ }
}
diff --git a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerimage/DockerImageEnvironmentFactory.java b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerimage/DockerImageEnvironmentFactory.java
index 61c1bbc830..4649bcce3f 100644
--- a/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerimage/DockerImageEnvironmentFactory.java
+++ b/infrastructures/docker/environment/src/main/java/org/eclipse/che/workspace/infrastructure/docker/environment/dockerimage/DockerImageEnvironmentFactory.java
@@ -25,6 +25,7 @@ import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.*;
+import org.eclipse.che.commons.annotation.Nullable;
/** @author Sergii Leshchenko */
@Singleton
@@ -46,6 +47,8 @@ public class DockerImageEnvironmentFactory
@Override
public DockerImageEnvironment create(Environment sourceEnv)
throws InfrastructureException, ValidationException {
+ checkNotNull(
+ sourceEnv, "Null environment is not supported by docker image environment factory");
if (sourceEnv.getRecipe().getLocation() != null) {
// move image from location to content
EnvironmentImpl envCopy = new EnvironmentImpl(sourceEnv);
@@ -58,8 +61,11 @@ public class DockerImageEnvironmentFactory
@Override
protected DockerImageEnvironment doCreate(
- InternalRecipe recipe, Map machines, List warnings)
+ @Nullable InternalRecipe recipe,
+ Map machines,
+ List warnings)
throws InfrastructureException, ValidationException {
+ checkNotNull(recipe, "Null recipe is not supported by docker image environment factory");
if (!DockerImageEnvironment.TYPE.equals(recipe.getType())) {
throw new ValidationException(
format(
@@ -81,4 +87,12 @@ public class DockerImageEnvironmentFactory
memoryProvisioner.provision(machineConfig, 0L, 0L);
}
}
+
+ private static void checkNotNull(
+ Object object, String errorMessageTemplate, Object... errorMessageParams)
+ throws ValidationException {
+ if (object == null) {
+ throw new ValidationException(format(errorMessageTemplate, errorMessageParams));
+ }
+ }
}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java
index 96bbad2264..0c6b68c606 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfraModule.java
@@ -26,12 +26,14 @@ import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import java.util.Map;
import org.eclipse.che.api.system.server.ServiceTermination;
+import org.eclipse.che.api.workspace.server.NoEnvironmentFactory;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiExternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiInternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.EnvVarProvider;
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
+import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.bootstrapper.KubernetesBootstrapperFactory;
@@ -73,6 +75,7 @@ public class KubernetesInfraModule extends AbstractModule {
factories.addBinding(KubernetesEnvironment.TYPE).to(KubernetesEnvironmentFactory.class);
factories.addBinding(DockerImageEnvironment.TYPE).to(DockerImageEnvironmentFactory.class);
+ factories.addBinding(Constants.NO_ENVIRONMENT_RECIPE_TYPE).to(NoEnvironmentFactory.class);
bind(RuntimeInfrastructure.class).to(KubernetesInfrastructure.class);
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfrastructure.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfrastructure.java
index 6cd6f54e84..f928518511 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfrastructure.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInfrastructure.java
@@ -20,11 +20,13 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.notification.EventService;
+import org.eclipse.che.api.workspace.server.NoEnvironmentFactory.NoEnvInternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.provision.InternalEnvironmentProvisioner;
+import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
@@ -49,7 +51,10 @@ public class KubernetesInfrastructure extends RuntimeInfrastructure {
KubernetesRuntimeStateCache runtimeStatusesCache) {
super(
NAME,
- ImmutableSet.of(KubernetesEnvironment.TYPE, DockerImageEnvironment.TYPE),
+ ImmutableSet.of(
+ KubernetesEnvironment.TYPE,
+ DockerImageEnvironment.TYPE,
+ Constants.NO_ENVIRONMENT_RECIPE_TYPE),
eventService,
internalEnvProvisioners);
this.runtimeContextFactory = runtimeContextFactory;
@@ -70,10 +75,14 @@ public class KubernetesInfrastructure extends RuntimeInfrastructure {
private KubernetesEnvironment asKubernetesEnv(InternalEnvironment source)
throws InfrastructureException {
- if (source instanceof KubernetesEnvironment) {
+ if (source instanceof NoEnvInternalEnvironment) {
+ return KubernetesEnvironment.builder()
+ .setAttributes(source.getAttributes())
+ .setWarnings(source.getWarnings())
+ .build();
+ } else if (source instanceof KubernetesEnvironment) {
return (KubernetesEnvironment) source;
- }
- if (source instanceof DockerImageEnvironment) {
+ } else if (source instanceof DockerImageEnvironment) {
return dockerImageEnvConverter.convert((DockerImageEnvironment) source);
}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaKubernetesRuntimeStateCache.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaKubernetesRuntimeStateCache.java
index 548eec43c9..3994ea8661 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaKubernetesRuntimeStateCache.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaKubernetesRuntimeStateCache.java
@@ -24,7 +24,6 @@ import javax.inject.Provider;
import javax.inject.Singleton;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
@@ -36,7 +35,6 @@ import org.eclipse.che.core.db.jpa.DuplicateKeyException;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.BeforeKubernetesRuntimeStateRemovedEvent;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -109,7 +107,7 @@ public class JpaKubernetesRuntimeStateCache implements KubernetesRuntimeStateCac
throws InfrastructureException {
try {
return Optional.ofNullable(
- managerProvider.get().find(KubernetesRuntimeState.class, new RuntimeId(runtimeId)));
+ managerProvider.get().find(KubernetesRuntimeState.class, runtimeId.getWorkspaceId()));
} catch (RuntimeException x) {
throw new InfrastructureException(x.getMessage(), x);
}
@@ -152,15 +150,8 @@ public class JpaKubernetesRuntimeStateCache implements KubernetesRuntimeStateCac
protected Optional find(String workspaceId)
throws InfrastructureException {
try {
- KubernetesRuntimeState queried =
- managerProvider
- .get()
- .createNamedQuery("KubernetesRuntime.getByWorkspaceId", KubernetesRuntimeState.class)
- .setParameter("workspaceId", workspaceId)
- .getSingleResult();
- return Optional.of(queried);
- } catch (NoResultException e) {
- return Optional.empty();
+ return Optional.ofNullable(
+ managerProvider.get().find(KubernetesRuntimeState.class, workspaceId));
} catch (RuntimeException x) {
throw new InfrastructureException(x.getMessage(), x);
}
@@ -171,7 +162,7 @@ public class JpaKubernetesRuntimeStateCache implements KubernetesRuntimeStateCac
EntityManager em = managerProvider.get();
KubernetesRuntimeState runtime =
- em.find(KubernetesRuntimeState.class, new RuntimeId(runtimeIdentity));
+ em.find(KubernetesRuntimeState.class, runtimeIdentity.getWorkspaceId());
if (runtime != null) {
eventService
@@ -245,7 +236,7 @@ public class JpaKubernetesRuntimeStateCache implements KubernetesRuntimeStateCac
k8sRuntimes.find(event.getWorkspace().getId());
if (k8sRuntimeStateOpt.isPresent()) {
KubernetesRuntimeState existingK8sRuntimeState = k8sRuntimeStateOpt.get();
- RuntimeId runtimeId = existingK8sRuntimeState.getRuntimeId();
+ RuntimeIdentity runtimeId = existingK8sRuntimeState.getRuntimeId();
// It is not normal case when non STOPPED workspace is going to be removed.
// Need to log error to investigate why it may happen
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactory.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactory.java
index 1334af93b0..93cdcf8633 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactory.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/environment/KubernetesEnvironmentFactory.java
@@ -36,6 +36,7 @@ import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.*;
+import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.Containers;
@@ -85,10 +86,11 @@ public class KubernetesEnvironmentFactory
@Override
protected KubernetesEnvironment doCreate(
- InternalRecipe recipe,
+ @Nullable InternalRecipe recipe,
Map machines,
List sourceWarnings)
throws InfrastructureException, ValidationException {
+ checkNotNull(recipe, "Null recipe is not supported by kubernetes environment factory");
List warnings = new ArrayList<>();
if (sourceWarnings != null) {
warnings.addAll(sourceWarnings);
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/model/KubernetesRuntimeState.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/model/KubernetesRuntimeState.java
index d59df1e103..466c46843d 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/model/KubernetesRuntimeState.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/model/KubernetesRuntimeState.java
@@ -13,26 +13,31 @@ package org.eclipse.che.workspace.infrastructure.kubernetes.model;
import java.util.Objects;
import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
+import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl;
/** @author Sergii Leshchenko */
@Entity(name = "KubernetesRuntime")
@Table(name = "che_k8s_runtime")
@NamedQueries({
- @NamedQuery(name = "KubernetesRuntime.getAll", query = "SELECT r FROM KubernetesRuntime r"),
- @NamedQuery(
- name = "KubernetesRuntime.getByWorkspaceId",
- query = "SELECT r FROM KubernetesRuntime r WHERE r.runtimeId.workspaceId = :workspaceId")
+ @NamedQuery(name = "KubernetesRuntime.getAll", query = "SELECT r FROM KubernetesRuntime r")
})
public class KubernetesRuntimeState {
- @EmbeddedId private RuntimeId runtimeId;
+ @Id
+ @Column(name = "workspace_id")
+ private String workspaceId;
+
+ @Column(name = "env_name")
+ private String envName;
+
+ @Column(name = "owner_id")
+ private String ownerId;
@Column(name = "namespace")
private String namespace;
@@ -44,11 +49,9 @@ public class KubernetesRuntimeState {
public KubernetesRuntimeState(
RuntimeIdentity runtimeIdentity, String namespace, WorkspaceStatus status) {
- this.runtimeId =
- new RuntimeId(
- runtimeIdentity.getWorkspaceId(),
- runtimeIdentity.getEnvName(),
- runtimeIdentity.getOwnerId());
+ this.envName = runtimeIdentity.getEnvName();
+ this.workspaceId = runtimeIdentity.getWorkspaceId();
+ this.ownerId = runtimeIdentity.getOwnerId();
this.namespace = namespace;
this.status = status;
}
@@ -61,8 +64,8 @@ public class KubernetesRuntimeState {
return namespace;
}
- public RuntimeId getRuntimeId() {
- return runtimeId;
+ public RuntimeIdentity getRuntimeId() {
+ return new RuntimeIdentityImpl(workspaceId, envName, ownerId);
}
public WorkspaceStatus getStatus() {
@@ -79,33 +82,38 @@ public class KubernetesRuntimeState {
}
@Override
- public boolean equals(Object obj) {
- if (this == obj) {
+ public boolean equals(Object o) {
+ if (this == o) {
return true;
}
- if (!(obj instanceof KubernetesRuntimeState)) {
+ if (!(o instanceof KubernetesRuntimeState)) {
return false;
}
- final KubernetesRuntimeState that = (KubernetesRuntimeState) obj;
- return Objects.equals(runtimeId, that.runtimeId)
- && Objects.equals(namespace, that.namespace)
- && Objects.equals(status, that.status);
+ KubernetesRuntimeState that = (KubernetesRuntimeState) o;
+ return Objects.equals(workspaceId, that.workspaceId)
+ && Objects.equals(envName, that.envName)
+ && Objects.equals(ownerId, that.ownerId)
+ && Objects.equals(getNamespace(), that.getNamespace())
+ && getStatus() == that.getStatus();
}
@Override
public int hashCode() {
- int hash = 7;
- hash = 31 * hash + Objects.hashCode(runtimeId);
- hash = 31 * hash + Objects.hashCode(namespace);
- hash = 31 * hash + Objects.hashCode(status);
- return hash;
+ return Objects.hash(workspaceId, envName, ownerId, getNamespace(), getStatus());
}
@Override
public String toString() {
return "KubernetesRuntimeState{"
- + "runtimeId="
- + runtimeId
+ + "workspaceId='"
+ + workspaceId
+ + '\''
+ + ", envName='"
+ + envName
+ + '\''
+ + ", ownerId='"
+ + ownerId
+ + '\''
+ ", namespace='"
+ namespace
+ '\''
@@ -113,82 +121,4 @@ public class KubernetesRuntimeState {
+ status
+ '}';
}
-
- @Embeddable
- public static class RuntimeId implements RuntimeIdentity {
-
- @Column(name = "workspace_id")
- private String workspaceId;
-
- @Column(name = "env_name")
- private String envName;
-
- @Column(name = "owner_id")
- private String ownerId;
-
- public RuntimeId() {}
-
- public RuntimeId(String workspaceId, String envName, String ownerId) {
- this.workspaceId = workspaceId;
- this.envName = envName;
- this.ownerId = ownerId;
- }
-
- public RuntimeId(RuntimeIdentity identity) {
- this(identity.getWorkspaceId(), identity.getEnvName(), identity.getOwnerId());
- }
-
- @Override
- public String getWorkspaceId() {
- return workspaceId;
- }
-
- @Override
- public String getEnvName() {
- return envName;
- }
-
- @Override
- public String getOwnerId() {
- return ownerId;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof RuntimeId)) {
- return false;
- }
- final RuntimeId that = (RuntimeId) obj;
- return Objects.equals(workspaceId, that.workspaceId)
- && Objects.equals(envName, that.envName)
- && Objects.equals(ownerId, that.ownerId);
- }
-
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 31 * hash + Objects.hashCode(workspaceId);
- hash = 31 * hash + Objects.hashCode(envName);
- hash = 31 * hash + Objects.hashCode(ownerId);
- return hash;
- }
-
- @Override
- public String toString() {
- return "RuntimeId{"
- + "workspaceId='"
- + workspaceId
- + '\''
- + ", envName='"
- + envName
- + '\''
- + ", ownerId='"
- + ownerId
- + '\''
- + '}';
- }
- }
}
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplier.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplier.java
index 72cc51754e..6a300b28a9 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplier.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplier.java
@@ -19,6 +19,7 @@ import com.google.common.collect.Sets;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.EnvVar;
import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodBuilder;
import io.fabric8.kubernetes.api.model.Service;
import java.util.Collection;
import java.util.List;
@@ -49,6 +50,8 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
private static final Set validImagePullPolicies =
Sets.newHashSet("Always", "Never", "IfNotPresent");
+ private static final String CHE_WORKSPACE_POD = "che-workspace-pod";
+
private final String defaultSidecarMemoryLimitBytes;
private final String sidecarImagePullPolicy;
private final boolean isAuthEnabled;
@@ -74,9 +77,15 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
KubernetesEnvironment kubernetesEnvironment = (KubernetesEnvironment) internalEnvironment;
Map pods = kubernetesEnvironment.getPods();
- if (pods.size() != 1) {
- throw new InfrastructureException(
- "Che plugins tooling configuration can be applied to a workspace with one pod only");
+ switch (pods.size()) {
+ case 0:
+ addToolingPod(kubernetesEnvironment);
+ break;
+ case 1:
+ break;
+ default:
+ throw new InfrastructureException(
+ "Che plugins tooling configuration can be applied to a workspace with one pod only");
}
Pod pod = pods.values().iterator().next();
@@ -94,6 +103,19 @@ public class KubernetesPluginsToolingApplier implements ChePluginsApplier {
}
}
+ private void addToolingPod(KubernetesEnvironment kubernetesEnvironment) {
+ Pod pod =
+ new PodBuilder()
+ .withNewMetadata()
+ .withName(CHE_WORKSPACE_POD)
+ .endMetadata()
+ .withNewSpec()
+ .endSpec()
+ .build();
+
+ kubernetesEnvironment.getPods().put(CHE_WORKSPACE_POD, pod);
+ }
+
private void populateWorkspaceEnvVars(
ChePlugin chePlugin, KubernetesEnvironment kubernetesEnvironment) {
diff --git a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/brokerphases/BrokerEnvironmentFactory.java b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/brokerphases/BrokerEnvironmentFactory.java
index bb9e41fbd9..6fadf9b2e4 100644
--- a/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/brokerphases/BrokerEnvironmentFactory.java
+++ b/infrastructures/kubernetes/src/main/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/brokerphases/BrokerEnvironmentFactory.java
@@ -16,6 +16,7 @@ import static java.lang.String.format;
import static java.util.Collections.singletonMap;
import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.gson.Gson;
@@ -166,7 +167,9 @@ public abstract class BrokerEnvironmentFactory
"-runtime-id",
String.format(
"%s:%s:%s",
- runtimeId.getWorkspaceId(), runtimeId.getEnvName(), runtimeId.getOwnerId()))
+ runtimeId.getWorkspaceId(),
+ MoreObjects.firstNonNull(runtimeId.getEnvName(), ""),
+ runtimeId.getOwnerId()))
.withImagePullPolicy(brokerPullPolicy)
.withVolumeMounts(
new VolumeMount(CONF_FOLDER + "/", null, brokerVolumeName, true, null))
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
index 070d0bf5f6..a2849fd94a 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/KubernetesInternalRuntimeTest.java
@@ -110,7 +110,6 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.environment.Kubernete
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl.MachineId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesServerImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesConfigsMaps;
import org.eclipse.che.workspace.infrastructure.kubernetes.namespace.KubernetesDeployments;
@@ -859,7 +858,7 @@ public class KubernetesInternalRuntimeTest {
}
private static class MapBasedRuntimeStateCache implements KubernetesRuntimeStateCache {
- private Map runtimesStates = new HashMap<>();
+ private Map runtimesStates = new HashMap<>();
@Override
public Set getIdentities() throws InfrastructureException {
@@ -874,14 +873,14 @@ public class KubernetesInternalRuntimeTest {
@Override
public void updateStatus(RuntimeIdentity runtimeId, WorkspaceStatus newStatus)
throws InfrastructureException {
- runtimesStates.get(new RuntimeId(runtimeId)).setStatus(newStatus);
+ runtimesStates.get(new RuntimeIdentityImpl(runtimeId)).setStatus(newStatus);
}
@Override
public boolean updateStatus(
RuntimeIdentity identity, Predicate predicate, WorkspaceStatus newStatus)
throws InfrastructureException {
- KubernetesRuntimeState state = runtimesStates.get(new RuntimeId(identity));
+ KubernetesRuntimeState state = runtimesStates.get(new RuntimeIdentityImpl(identity));
if (predicate.test(state.getStatus())) {
state.setStatus(newStatus);
return true;
@@ -891,18 +890,18 @@ public class KubernetesInternalRuntimeTest {
@Override
public WorkspaceStatus getStatus(RuntimeIdentity runtimeId) throws InfrastructureException {
- return runtimesStates.get(new RuntimeId(runtimeId)).getStatus();
+ return runtimesStates.get(new RuntimeIdentityImpl(runtimeId)).getStatus();
}
@Override
public Optional get(RuntimeIdentity runtimeId)
throws InfrastructureException {
- return Optional.ofNullable(runtimesStates.get(new RuntimeId(runtimeId)));
+ return Optional.ofNullable(runtimesStates.get(new RuntimeIdentityImpl(runtimeId)));
}
@Override
public void remove(RuntimeIdentity runtimeId) throws InfrastructureException {
- runtimesStates.remove(new RuntimeId(runtimeId));
+ runtimesStates.remove(new RuntimeIdentityImpl(runtimeId));
}
}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaTckModule.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaTckModule.java
index 737d1c5e6e..76ee394a3c 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaTckModule.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/jpa/JpaTckModule.java
@@ -38,7 +38,6 @@ import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRunti
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl.MachineId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesServerImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesServerImpl.ServerId;
import org.h2.Driver;
@@ -65,7 +64,6 @@ public class JpaTckModule extends TckModule {
CommandImpl.class,
AccountImpl.class,
KubernetesRuntimeState.class,
- RuntimeId.class,
KubernetesMachineImpl.class,
MachineId.class,
KubernetesServerImpl.class,
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesMachinesCacheTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesMachinesCacheTest.java
index 49e2428269..8bda90caee 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesMachinesCacheTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesMachinesCacheTest.java
@@ -12,7 +12,10 @@
package org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck;
import static java.util.Arrays.asList;
-import static org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck.TestObjects.*;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck.TestObjects.createMachine;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck.TestObjects.createRuntimeState;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck.TestObjects.createServer;
+import static org.eclipse.che.workspace.infrastructure.kubernetes.cache.tck.TestObjects.createWorkspace;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -23,6 +26,7 @@ import java.util.Optional;
import javax.inject.Inject;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.core.model.workspace.runtime.MachineStatus;
+import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
@@ -32,7 +36,6 @@ import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesMachineCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesServerImpl;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -150,7 +153,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldGetMachines() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
// when
machineCache.getMachines(runtimeId);
@@ -165,7 +168,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldGetServer() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
KubernetesMachineImpl machine = machines[0];
Entry serverToFetch =
machine.getServers().entrySet().iterator().next();
@@ -183,7 +186,7 @@ public class KubernetesMachinesCacheTest {
expectedExceptionsMessageRegExp = "Server with name 'non-existing' was not found")
public void shouldThrowExceptionWhenServerWasNotFoundOnGetting() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
KubernetesMachineImpl machine = machines[0];
// when
@@ -193,7 +196,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldUpdateMachineStatusServerStatus() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
// when
machineCache.updateServerStatus(
@@ -209,7 +212,7 @@ public class KubernetesMachinesCacheTest {
expectedExceptionsMessageRegExp = "Server with name 'non-existing' was not found")
public void shouldThrowExceptionWhenServerWasNotFoundOnStatusUpdating() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
KubernetesMachineImpl machine = machines[0];
// when
@@ -220,7 +223,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldUpdateMachineStatus() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
KubernetesMachineImpl machine = machines[0];
String machineName = machine.getName();
@@ -243,7 +246,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldUpdateServerStatus() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
// when
machineCache.updateServerStatus(
@@ -257,7 +260,7 @@ public class KubernetesMachinesCacheTest {
@Test
public void shouldRemoveMachines() throws Exception {
// given
- RuntimeId runtimeId = runtimeStates[0].getRuntimeId();
+ RuntimeIdentity runtimeId = runtimeStates[0].getRuntimeId();
// when
machineCache.remove(runtimeId);
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesRuntimeStateCacheTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesRuntimeStateCacheTest.java
index b544003bb9..3b7ead0fdc 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesRuntimeStateCacheTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/KubernetesRuntimeStateCacheTest.java
@@ -25,6 +25,7 @@ import javax.inject.Inject;
import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
+import org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.commons.test.tck.TckListener;
@@ -32,7 +33,6 @@ import org.eclipse.che.commons.test.tck.repository.TckRepository;
import org.eclipse.che.commons.test.tck.repository.TckRepositoryException;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Listeners;
@@ -140,7 +140,7 @@ public class KubernetesRuntimeStateCacheTest {
public void shouldThrowExceptionWhenThereIsNotRuntimeStateWhileStatusRetrieving()
throws Exception {
// when
- runtimesStatesCache.getStatus(new RuntimeId("non-existent-ws", "defEnv", "acc1"));
+ runtimesStatesCache.getStatus(new RuntimeIdentityImpl("non-existent-ws", "defEnv", "acc1"));
}
@Test(dependsOnMethods = "shouldReturnRuntimeStatus")
@@ -203,7 +203,7 @@ public class KubernetesRuntimeStateCacheTest {
throws Exception {
// when
runtimesStatesCache.updateStatus(
- new RuntimeId("non-existent-ws", "defEnv", "acc1"), WorkspaceStatus.STOPPED);
+ new RuntimeIdentityImpl("non-existent-ws", "defEnv", "acc1"), WorkspaceStatus.STOPPED);
}
@Test(
@@ -214,7 +214,7 @@ public class KubernetesRuntimeStateCacheTest {
throws Exception {
// when
runtimesStatesCache.updateStatus(
- new RuntimeId("non-existent-ws", "defEnv", "acc1"),
+ new RuntimeIdentityImpl("non-existent-ws", "defEnv", "acc1"),
s -> s.equals(WorkspaceStatus.STOPPING),
WorkspaceStatus.STOPPED);
}
@@ -255,7 +255,7 @@ public class KubernetesRuntimeStateCacheTest {
public void shouldRemoveRuntimeState() throws Exception {
// given
KubernetesRuntimeState runtimeState = createRuntimeState(workspaces[0]);
- RuntimeId toRemove = runtimeState.getRuntimeId();
+ RuntimeIdentity toRemove = runtimeState.getRuntimeId();
// when
runtimesStatesCache.remove(toRemove);
@@ -268,7 +268,7 @@ public class KubernetesRuntimeStateCacheTest {
public void shouldDoNothingIfStateIsAlreadyRemove() throws Exception {
// given
KubernetesRuntimeState runtimeState = createRuntimeState(workspaces[2]);
- RuntimeId toRemove = runtimeState.getRuntimeId();
+ RuntimeIdentity toRemove = runtimeState.getRuntimeId();
// when
runtimesStatesCache.remove(toRemove);
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/TestObjects.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/TestObjects.java
index fc57788188..cf356e33d1 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/TestObjects.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/cache/tck/TestObjects.java
@@ -21,12 +21,12 @@ import org.eclipse.che.account.spi.AccountImpl;
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
import org.eclipse.che.api.core.model.workspace.runtime.MachineStatus;
import org.eclipse.che.api.core.model.workspace.runtime.ServerStatus;
+import org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl;
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.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl;
import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState;
-import org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId;
/** @author Sergii Leshchenko */
public class TestObjects {
@@ -51,7 +51,7 @@ public class TestObjects {
public static KubernetesRuntimeState createRuntimeState(WorkspaceImpl workspace) {
return new KubernetesRuntimeState(
- new RuntimeId(workspace.getId(), "defEnv", workspace.getAccount().getId()),
+ new RuntimeIdentityImpl(workspace.getId(), "defEnv", workspace.getAccount().getId()),
generate("namespace", 5),
WorkspaceStatus.RUNNING);
}
diff --git a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplierTest.java b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplierTest.java
index 51e3bc7621..db90ca5752 100644
--- a/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplierTest.java
+++ b/infrastructures/kubernetes/src/test/java/org/eclipse/che/workspace/infrastructure/kubernetes/wsplugins/KubernetesPluginsToolingApplierTest.java
@@ -21,9 +21,8 @@ import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMO
import static org.eclipse.che.commons.lang.NameGenerator.generate;
import static org.eclipse.che.workspace.infrastructure.kubernetes.Constants.CHE_ORIGINAL_NAME_LABEL;
import static org.eclipse.che.workspace.infrastructure.kubernetes.server.secure.SecureServerExposerFactoryProvider.SECURE_EXPOSER_IMPL_PROPERTY;
-import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
@@ -83,40 +82,29 @@ public class KubernetesPluginsToolingApplierTest {
@Mock Pod pod;
@Mock PodSpec podSpec;
@Mock ObjectMeta meta;
- @Mock KubernetesEnvironment internalEnvironment;
@Mock Container userContainer;
@Mock InternalMachineConfig userMachineConfig;
- List containers;
- KubernetesPluginsToolingApplier applier;
+ private KubernetesEnvironment internalEnvironment;
+ private List containers;
+ private KubernetesPluginsToolingApplier applier;
@BeforeMethod
public void setUp() {
+ internalEnvironment = spy(KubernetesEnvironment.builder().build());
applier = new KubernetesPluginsToolingApplier(TEST_IMAGE_POLICY, MEMORY_LIMIT_MB, false);
Map machines = new HashMap<>();
containers = new ArrayList<>();
- Map services = new HashMap<>();
-
containers.add(userContainer);
machines.put(USER_MACHINE_NAME, userMachineConfig);
- when(internalEnvironment.getPods()).thenReturn(of(POD_NAME, pod));
+ internalEnvironment.getPods().put(POD_NAME, pod);
when(pod.getSpec()).thenReturn(podSpec);
when(podSpec.getContainers()).thenReturn(containers);
when(pod.getMetadata()).thenReturn(meta);
when(meta.getName()).thenReturn(POD_NAME);
- when(internalEnvironment.getMachines()).thenReturn(machines);
- lenient().when(internalEnvironment.getServices()).thenReturn(services);
- Map attributes = new HashMap<>();
- when(internalEnvironment.getAttributes()).thenReturn(attributes);
- }
-
- @Test
- public void doesNothingIfChePluginsListIsEmpty() throws Exception {
- applier.apply(internalEnvironment, emptyList());
-
- verifyZeroInteractions(internalEnvironment);
+ internalEnvironment.getMachines().putAll(machines);
}
@Test(
@@ -138,6 +126,17 @@ public class KubernetesPluginsToolingApplierTest {
verifyContainer(toolingContainer);
}
+ @Test
+ public void createsPodAndAddToolingIfNoPodIsPresent() throws Exception {
+ internalEnvironment.getPods().clear();
+
+ applier.apply(internalEnvironment, singletonList(createChePlugin()));
+
+ verifyPodAndContainersNumber(1);
+ Container toolingContainer = getOneAndOnlyNonUserContainer(internalEnvironment);
+ verifyContainer(toolingContainer);
+ }
+
@Test
public void canAddMultipleToolingContainersToAPodFromOnePlugin() throws Exception {
applier.apply(internalEnvironment, singletonList(createChePluginWith2Containers()));
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
index 6a07ec6f2e..6b651d9b05 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfraModule.java
@@ -22,12 +22,14 @@ import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import org.eclipse.che.api.system.server.ServiceTermination;
+import org.eclipse.che.api.workspace.server.NoEnvironmentFactory;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiExternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.CheApiInternalEnvVarProvider;
import org.eclipse.che.api.workspace.server.spi.provision.env.EnvVarProvider;
import org.eclipse.che.api.workspace.server.wsplugins.ChePluginsApplier;
+import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironment;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironmentFactory;
import org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesClientTermination;
@@ -73,6 +75,7 @@ public class OpenShiftInfraModule extends AbstractModule {
factories.addBinding(OpenShiftEnvironment.TYPE).to(OpenShiftEnvironmentFactory.class);
factories.addBinding(KubernetesEnvironment.TYPE).to(KubernetesEnvironmentFactory.class);
factories.addBinding(DockerImageEnvironment.TYPE).to(DockerImageEnvironmentFactory.class);
+ factories.addBinding(Constants.NO_ENVIRONMENT_RECIPE_TYPE).to(NoEnvironmentFactory.class);
bind(RuntimeInfrastructure.class).to(OpenShiftInfrastructure.class);
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfrastructure.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfrastructure.java
index 0f2a875439..22c2b39605 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfrastructure.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/OpenShiftInfrastructure.java
@@ -20,11 +20,13 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
import org.eclipse.che.api.core.notification.EventService;
+import org.eclipse.che.api.workspace.server.NoEnvironmentFactory.NoEnvInternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
import org.eclipse.che.api.workspace.server.spi.RuntimeInfrastructure;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.provision.InternalEnvironmentProvisioner;
+import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.workspace.infrastructure.docker.environment.dockerimage.DockerImageEnvironment;
import org.eclipse.che.workspace.infrastructure.kubernetes.cache.KubernetesRuntimeStateCache;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment;
@@ -51,7 +53,10 @@ public class OpenShiftInfrastructure extends RuntimeInfrastructure {
super(
NAME,
ImmutableSet.of(
- OpenShiftEnvironment.TYPE, KubernetesEnvironment.TYPE, DockerImageEnvironment.TYPE),
+ OpenShiftEnvironment.TYPE,
+ KubernetesEnvironment.TYPE,
+ DockerImageEnvironment.TYPE,
+ Constants.NO_ENVIRONMENT_RECIPE_TYPE),
eventService,
internalEnvProvisioners);
this.runtimeContextFactory = runtimeContextFactory;
@@ -72,15 +77,16 @@ public class OpenShiftInfrastructure extends RuntimeInfrastructure {
private OpenShiftEnvironment asOpenShiftEnv(InternalEnvironment source)
throws InfrastructureException {
- if (source instanceof OpenShiftEnvironment) {
+ if (source instanceof NoEnvInternalEnvironment) {
+ return OpenShiftEnvironment.builder()
+ .setAttributes(source.getAttributes())
+ .setWarnings(source.getWarnings())
+ .build();
+ } else if (source instanceof OpenShiftEnvironment) {
return (OpenShiftEnvironment) source;
- }
-
- if (source instanceof KubernetesEnvironment) {
+ } else if (source instanceof KubernetesEnvironment) {
return new OpenShiftEnvironment((KubernetesEnvironment) source);
- }
-
- if (source instanceof DockerImageEnvironment) {
+ } else if (source instanceof DockerImageEnvironment) {
KubernetesEnvironment k8sEnv =
dockerImageEnvConverter.convert((DockerImageEnvironment) source);
return new OpenShiftEnvironment(k8sEnv);
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
index 3af1455273..0ba15fca00 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironment.java
@@ -135,6 +135,12 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
return this;
}
+ @Override
+ public Builder setAttributes(Map attributes) {
+ this.attributes.putAll(attributes);
+ return this;
+ }
+
public Builder setRoutes(Map route) {
this.routes.putAll(route);
return this;
diff --git a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
index bdb01e59dc..2d872eabab 100644
--- a/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
+++ b/infrastructures/openshift/src/main/java/org/eclipse/che/workspace/infrastructure/openshift/environment/OpenShiftEnvironmentFactory.java
@@ -37,6 +37,7 @@ import org.eclipse.che.api.installer.server.InstallerRegistry;
import org.eclipse.che.api.workspace.server.model.impl.WarningImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.*;
+import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.workspace.infrastructure.kubernetes.Names;
import org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironmentValidator;
import org.eclipse.che.workspace.infrastructure.kubernetes.util.Containers;
@@ -86,10 +87,11 @@ public class OpenShiftEnvironmentFactory extends InternalEnvironmentFactory machines,
List sourceWarnings)
throws InfrastructureException, ValidationException {
+ checkNotNull(recipe, "Null recipe is not supported by openshift environment factory");
List warnings = new ArrayList<>();
if (sourceWarnings != null) {
warnings.addAll(sourceWarnings);
diff --git a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/EnvironmentRamCalculator.java b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/EnvironmentRamCalculator.java
index bd1635c61b..a0cfca4c7e 100644
--- a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/EnvironmentRamCalculator.java
+++ b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/EnvironmentRamCalculator.java
@@ -25,6 +25,7 @@ import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
+import org.eclipse.che.commons.annotation.Nullable;
/**
* Helps to calculate amount of RAM defined in {@link Environment environment}
@@ -46,7 +47,10 @@ public class EnvironmentRamCalculator {
* Parses (and fetches if needed) recipe of environment and sums RAM size of all machines in
* environment in megabytes.
*/
- public long calculate(Environment environment) throws ServerException {
+ public long calculate(@Nullable Environment environment) throws ServerException {
+ if (environment == null) {
+ return 0;
+ }
try {
return getInternalEnvironment(environment)
.getMachines()
diff --git a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/RamResourceUsageTracker.java b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/RamResourceUsageTracker.java
index f3f44b4e2e..1bdad6b8ee 100644
--- a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/RamResourceUsageTracker.java
+++ b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/usage/tracker/RamResourceUsageTracker.java
@@ -77,7 +77,9 @@ public class RamResourceUsageTracker implements ResourceUsageTracker {
.getConfig()
.getEnvironments()
.get(activeWorkspace.getRuntime().getActiveEnv());
- currentlyUsedRamMB += environmentRamCalculator.calculate(startingEnvironment);
+ if (startingEnvironment != null) {
+ currentlyUsedRamMB += environmentRamCalculator.calculate(startingEnvironment);
+ }
} else {
currentlyUsedRamMB += environmentRamCalculator.calculate(activeWorkspace.getRuntime());
}
diff --git a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/workspace/LimitsCheckingWorkspaceManager.java b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/workspace/LimitsCheckingWorkspaceManager.java
index ab403a434d..18841cce14 100644
--- a/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/workspace/LimitsCheckingWorkspaceManager.java
+++ b/multiuser/api/che-multiuser-api-resource/src/main/java/org/eclipse/che/multiuser/resource/api/workspace/LimitsCheckingWorkspaceManager.java
@@ -157,6 +157,9 @@ public class LimitsCheckingWorkspaceManager extends WorkspaceManager {
if (maxRamPerEnvMB < 0) {
return;
}
+ if (config.getEnvironments().isEmpty()) {
+ return;
+ }
for (Map.Entry envEntry : config.getEnvironments().entrySet()) {
Environment env = envEntry.getValue();
final long workspaceRam = environmentRamCalculator.calculate(env);
@@ -181,6 +184,9 @@ public class LimitsCheckingWorkspaceManager extends WorkspaceManager {
String accountId, String namespace, WorkspaceConfig config, @Nullable String envName)
throws NotFoundException, ServerException, ConflictException {
+ if (config.getEnvironments().isEmpty()) {
+ return;
+ }
final Environment environment =
config.getEnvironments().get(firstNonNull(envName, config.getDefaultEnv()));
final ResourceImpl ramToUse =
diff --git a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/CheTestWorkspaceServiceClient.java b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/CheTestWorkspaceServiceClient.java
index 5fa5831298..b40e526661 100644
--- a/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/CheTestWorkspaceServiceClient.java
+++ b/selenium/che-selenium-core/src/main/java/org/eclipse/che/selenium/core/client/CheTestWorkspaceServiceClient.java
@@ -65,7 +65,6 @@ public class CheTestWorkspaceServiceClient extends AbstractTestWorkspaceServiceC
workspace.getEnvironments().put(workspaceName, environment);
workspace.setName(workspaceName);
workspace.setDefaultEnv(workspaceName);
-
WorkspaceDto workspaceDto =
requestFactory
.fromUrl(getBaseUrl())
diff --git a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/gwt/CheckSimpleGwtAppTest.java b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/gwt/CheckSimpleGwtAppTest.java
index 77fb0b3d01..1275985322 100644
--- a/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/gwt/CheckSimpleGwtAppTest.java
+++ b/selenium/che-selenium-test/src/test/java/org/eclipse/che/selenium/gwt/CheckSimpleGwtAppTest.java
@@ -75,7 +75,6 @@ public class CheckSimpleGwtAppTest {
WorkspaceConfigDto workspace =
workspaceDtoDeserializer.deserializeWorkspaceTemplate(UBUNTU_JDK8);
-
workspace
.getEnvironments()
.get("replaced_name")
diff --git a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/Constants.java b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/Constants.java
index fe86edc1c6..1da44c0dbf 100644
--- a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/Constants.java
+++ b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/Constants.java
@@ -160,5 +160,7 @@ public final class Constants {
public static final String SUPPORTED_RECIPE_TYPES = "supportedRecipeTypes";
+ public static final String NO_ENVIRONMENT_RECIPE_TYPE = "no-environment";
+
private Constants() {}
}
diff --git a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/WorkspaceConfigDto.java b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/WorkspaceConfigDto.java
index 53c3f97de8..5741ceb849 100644
--- a/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/WorkspaceConfigDto.java
+++ b/wsmaster/che-core-api-workspace-shared/src/main/java/org/eclipse/che/api/workspace/shared/dto/WorkspaceConfigDto.java
@@ -35,7 +35,7 @@ public interface WorkspaceConfigDto extends WorkspaceConfig, Hyperlinks {
void setName(String name);
@Override
- @FactoryParameter(obligation = MANDATORY)
+ @FactoryParameter(obligation = OPTIONAL)
String getDefaultEnv();
void setDefaultEnv(String defaultEnvironment);
@@ -67,7 +67,7 @@ public interface WorkspaceConfigDto extends WorkspaceConfig, Hyperlinks {
WorkspaceConfigDto withProjects(List projects);
@Override
- @FactoryParameter(obligation = MANDATORY)
+ @FactoryParameter(obligation = OPTIONAL)
Map getEnvironments();
void setEnvironments(Map environments);
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/NoEnvironmentFactory.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/NoEnvironmentFactory.java
new file mode 100644
index 0000000000..8ce8fe8fd6
--- /dev/null
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/NoEnvironmentFactory.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.workspace.server;
+
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import org.eclipse.che.api.core.model.workspace.Warning;
+import org.eclipse.che.api.installer.server.InstallerRegistry;
+import org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalMachineConfig;
+import org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe;
+import org.eclipse.che.api.workspace.server.spi.environment.MachineConfigsValidator;
+import org.eclipse.che.api.workspace.server.spi.environment.RecipeRetriever;
+import org.eclipse.che.commons.annotation.Nullable;
+
+/**
+ * Fake environment factory for a case when sidecar-based workspace has no environment.
+ *
+ * @author Alexander Garagatyi
+ */
+public class NoEnvironmentFactory extends InternalEnvironmentFactory {
+
+ @Inject
+ public NoEnvironmentFactory(
+ InstallerRegistry installerRegistry,
+ RecipeRetriever recipeRetriever,
+ MachineConfigsValidator machinesValidator) {
+ super(installerRegistry, recipeRetriever, machinesValidator);
+ }
+
+ @Override
+ protected InternalEnvironment doCreate(
+ @Nullable InternalRecipe recipe,
+ Map machines,
+ List warnings)
+ throws InternalInfrastructureException {
+ if (recipe != null) {
+ throw new InternalInfrastructureException(
+ "No environment factory doesn't accept non-null workspace recipes");
+ }
+ return new NoEnvInternalEnvironment();
+ }
+
+ public static class NoEnvInternalEnvironment extends InternalEnvironment {}
+}
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/SidecarToolingWorkspaceUtil.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/SidecarToolingWorkspaceUtil.java
new file mode 100644
index 0000000000..3cf852aafc
--- /dev/null
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/SidecarToolingWorkspaceUtil.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.workspace.server;
+
+import com.google.common.base.Strings;
+import java.util.Map;
+import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
+import org.eclipse.che.api.workspace.shared.Constants;
+
+/**
+ * Util class to deal with sidecar based workspaces.
+ *
+ * @author Alexander Garagatyi
+ */
+public class SidecarToolingWorkspaceUtil {
+
+ /**
+ * Checks whether provided workspace config attributes {@link WorkspaceConfig#getAttributes()}
+ * contains configuration of sidecars.
+ * This indicates whether this workspace is Che6 or Che7 compatible.
+ */
+ public static boolean isSidecarBasedWorkspace(Map attributes) {
+ boolean hasPlugins =
+ !Strings.isNullOrEmpty(
+ attributes.getOrDefault(Constants.WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE, null));
+ boolean hasEditor =
+ !Strings.isNullOrEmpty(
+ attributes.getOrDefault(Constants.WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, null));
+ return hasPlugins || hasEditor;
+ }
+}
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
index f4e06e66c9..fe6b64a158 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
@@ -11,7 +11,6 @@
*/
package org.eclipse.che.api.workspace.server;
-import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.String.format;
import static java.lang.System.currentTimeMillis;
import static java.util.Objects.requireNonNull;
@@ -351,24 +350,11 @@ public class WorkspaceManager {
}
/** Asynchronously starts given workspace. */
- private void startAsync(WorkspaceImpl workspace, String envName, Map options)
+ private void startAsync(
+ WorkspaceImpl workspace, @Nullable String envName, Map options)
throws ConflictException, NotFoundException, ServerException {
- if (envName != null && !workspace.getConfig().getEnvironments().containsKey(envName)) {
- throw new NotFoundException(
- format(
- "Workspace '%s:%s' doesn't contain environment '%s'",
- workspace.getNamespace(), workspace.getConfig().getName(), envName));
- }
+ String env = getValidatedEnvironmentName(workspace, envName);
workspace.getAttributes().put(UPDATED_ATTRIBUTE_NAME, Long.toString(currentTimeMillis()));
- final String env = firstNonNull(envName, workspace.getConfig().getDefaultEnv());
-
- // validate environment in advance
- try {
- runtimes.validate(workspace.getConfig().getEnvironments().get(env));
- } catch (InfrastructureException | ValidationException e) {
- throw new ServerException(e);
- }
-
workspaceDao.update(workspace);
runtimes
.startAsync(workspace, env, firstNonNull(options, Collections.emptyMap()))
@@ -384,6 +370,45 @@ public class WorkspaceManager {
});
}
+ private String getValidatedEnvironmentName(WorkspaceImpl workspace, @Nullable String envName)
+ throws NotFoundException, ServerException {
+ if (envName != null && !workspace.getConfig().getEnvironments().containsKey(envName)) {
+ throw new NotFoundException(
+ format(
+ "Workspace '%s:%s' doesn't contain environment '%s'",
+ workspace.getNamespace(), workspace.getConfig().getName(), envName));
+ }
+
+ envName = firstNonNull(envName, workspace.getConfig().getDefaultEnv());
+
+ if (envName == null
+ && SidecarToolingWorkspaceUtil.isSidecarBasedWorkspace(
+ workspace.getConfig().getAttributes())) {
+ // Sidecar-based workspaces are allowed not to have any environments
+ return null;
+ }
+
+ // validate environment in advance
+ if (envName == null) {
+ throw new NotFoundException(
+ format(
+ "Workspace %s:%s can't use null environment",
+ workspace.getNamespace(), workspace.getConfig().getName()));
+ }
+ try {
+ runtimes.validate(workspace.getConfig().getEnvironments().get(envName));
+ } catch (InfrastructureException | ValidationException e) {
+ throw new ServerException(e);
+ }
+
+ return envName;
+ }
+
+ /** Returns first non-null argument or null if both are null. */
+ private T firstNonNull(T first, T second) {
+ return first != null ? first : second;
+ }
+
private void checkWorkspaceIsRunningOrStarting(WorkspaceImpl workspace) throws ConflictException {
if (workspace.getStatus() != RUNNING && workspace.getStatus() != STARTING) {
throw new ConflictException(
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimes.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimes.java
index 6caf03d815..8c5390fe89 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimes.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimes.java
@@ -70,7 +70,9 @@ import org.eclipse.che.api.workspace.server.spi.RuntimeStartInterruptedException
import org.eclipse.che.api.workspace.server.spi.WorkspaceDao;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment;
import org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironmentFactory;
+import org.eclipse.che.api.workspace.shared.Constants;
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
+import org.eclipse.che.commons.annotation.Nullable;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.lang.NameGenerator;
import org.eclipse.che.commons.lang.concurrent.ThreadLocalPropagateContext;
@@ -281,16 +283,19 @@ public class WorkspaceRuntimes {
* @see WorkspaceStatus#RUNNING
*/
public CompletableFuture startAsync(
- Workspace workspace, String envName, Map options)
+ Workspace workspace, @Nullable String envName, Map options)
throws ConflictException, NotFoundException, ServerException {
- final EnvironmentImpl environment = copyEnv(workspace, envName);
final String workspaceId = workspace.getId();
-
- requireNonNull(environment, "Environment should not be null " + workspaceId);
- requireNonNull(environment.getRecipe(), "Recipe should not be null " + workspaceId);
- requireNonNull(
- environment.getRecipe().getType(), "Recipe type should not be null " + workspaceId);
+ // Sidecar-based workspaces allowed not to have environments
+ EnvironmentImpl environment = null;
+ if (envName != null) {
+ environment = copyEnv(workspace, envName);
+ requireNonNull(environment, "Environment should not be null " + workspaceId);
+ requireNonNull(environment.getRecipe(), "Recipe should not be null " + workspaceId);
+ requireNonNull(
+ environment.getRecipe().getType(), "Recipe type should not be null " + workspaceId);
+ }
if (isStartRefused.get()) {
throw new ConflictException(
@@ -620,12 +625,15 @@ public class WorkspaceRuntimes {
identity.getWorkspaceId(), identity.getEnvName()));
}
- Environment environment = workspace.getConfig().getEnvironments().get(identity.getEnvName());
- if (environment == null) {
- throw new ServerException(
- format(
- "Environment configuration is missing for the runtime '%s:%s'. Runtime won't be recovered",
- identity.getWorkspaceId(), identity.getEnvName()));
+ Environment environment = null;
+ if (identity.getEnvName() != null) {
+ environment = workspace.getConfig().getEnvironments().get(identity.getEnvName());
+ if (environment == null) {
+ throw new ServerException(
+ format(
+ "Environment configuration is missing for the runtime '%s:%s'. Runtime won't be recovered",
+ identity.getWorkspaceId(), identity.getEnvName()));
+ }
}
InternalRuntime runtime;
@@ -785,10 +793,16 @@ public class WorkspaceRuntimes {
return environmentFactories.keySet();
}
- private InternalEnvironment createInternalEnvironment(
- Environment environment, Map workspaceConfigAttributes)
+ @VisibleForTesting
+ InternalEnvironment createInternalEnvironment(
+ @Nullable Environment environment, Map workspaceConfigAttributes)
throws InfrastructureException, ValidationException, NotFoundException {
- String recipeType = environment.getRecipe().getType();
+ String recipeType;
+ if (environment == null) {
+ recipeType = Constants.NO_ENVIRONMENT_RECIPE_TYPE;
+ } else {
+ recipeType = environment.getRecipe().getType();
+ }
InternalEnvironmentFactory factory = environmentFactories.get(recipeType);
if (factory == null) {
throw new NotFoundException(
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java
index 09f7987901..347463f45b 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceValidator.java
@@ -15,8 +15,8 @@ import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.String.format;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_LIMIT_ATTRIBUTE;
import static org.eclipse.che.api.core.model.workspace.config.MachineConfig.MEMORY_REQUEST_ATTRIBUTE;
+import static org.eclipse.che.api.workspace.server.SidecarToolingWorkspaceUtil.isSidecarBasedWorkspace;
-import com.google.common.base.Strings;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
@@ -31,7 +31,6 @@ import org.eclipse.che.api.core.model.workspace.config.Environment;
import org.eclipse.che.api.core.model.workspace.config.MachineConfig;
import org.eclipse.che.api.core.model.workspace.config.Recipe;
import org.eclipse.che.api.core.model.workspace.config.Volume;
-import org.eclipse.che.api.workspace.shared.Constants;
/**
* Validator for {@link Workspace}.
@@ -69,24 +68,7 @@ public class WorkspaceValidator {
+ "latin letters, underscores, dots, dashes and must start and end only with digits, "
+ "latin letters or underscores");
- // environments
- check(!isNullOrEmpty(config.getDefaultEnv()), "Workspace default environment name required");
- checkNotNull(config.getEnvironments(), "Workspace must contain at least one environment");
- check(
- config.getEnvironments().containsKey(config.getDefaultEnv()),
- "Workspace default environment configuration required");
-
- for (Environment environment : config.getEnvironments().values()) {
- checkNotNull(environment, "Environment must not be null");
- Recipe recipe = environment.getRecipe();
- checkNotNull(recipe, "Environment recipe must not be null");
- checkNotNull(recipe.getType(), "Environment recipe type must not be null");
-
- for (Entry machineEntry :
- environment.getMachines().entrySet()) {
- validateMachine(machineEntry.getKey(), machineEntry.getValue());
- }
- }
+ validateEnvironments(config);
// commands
for (Command command : config.getCommands()) {
@@ -127,6 +109,34 @@ public class WorkspaceValidator {
}
}
+ private void validateEnvironments(WorkspaceConfig config) throws ValidationException {
+ boolean environmentIsNotSet =
+ (config.getEnvironments() == null || config.getEnvironments().isEmpty())
+ && isNullOrEmpty(config.getDefaultEnv());
+ boolean isSidecarWorkspace = isSidecarBasedWorkspace(config.getAttributes());
+ if (environmentIsNotSet && isSidecarWorkspace) {
+ // sidecar based workspaces allowed not to have environment
+ return;
+ }
+ check(!isNullOrEmpty(config.getDefaultEnv()), "Workspace default environment name required");
+ checkNotNull(config.getEnvironments(), "Workspace must contain at least one environment");
+ check(
+ config.getEnvironments().containsKey(config.getDefaultEnv()),
+ "Workspace default environment configuration required");
+
+ for (Environment environment : config.getEnvironments().values()) {
+ checkNotNull(environment, "Environment must not be null");
+ Recipe recipe = environment.getRecipe();
+ checkNotNull(recipe, "Environment recipe must not be null");
+ checkNotNull(recipe.getType(), "Environment recipe type must not be null");
+
+ for (Entry machineEntry :
+ environment.getMachines().entrySet()) {
+ validateMachine(machineEntry.getKey(), machineEntry.getValue());
+ }
+ }
+ }
+
private void validateMachine(String machineName, MachineConfig machine)
throws ValidationException {
validateLongAttribute(
@@ -189,13 +199,7 @@ public class WorkspaceValidator {
.flatMap(machine -> machine.getInstallers().stream())
.findAny();
Map attributes = config.getAttributes();
- boolean hasPlugins =
- !Strings.isNullOrEmpty(
- attributes.getOrDefault(Constants.WORKSPACE_TOOLING_PLUGINS_ATTRIBUTE, null));
- boolean hasEditor =
- !Strings.isNullOrEmpty(
- attributes.getOrDefault(Constants.WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, null));
- if ((hasPlugins || hasEditor) && installers.isPresent()) {
+ if (isSidecarBasedWorkspace(attributes) && installers.isPresent()) {
throw new ValidationException("Workspace config cannot have both plugins and installers.");
}
}
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/bootstrap/AbstractBootstrapper.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/bootstrap/AbstractBootstrapper.java
index fe66430ddb..0a3a9a7228 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/bootstrap/AbstractBootstrapper.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/bootstrap/AbstractBootstrapper.java
@@ -11,6 +11,7 @@
*/
package org.eclipse.che.api.workspace.server.bootstrap;
+import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -55,7 +56,7 @@ public abstract class AbstractBootstrapper {
// check bootstrapper belongs to current runtime and machine
RuntimeIdentityDto runtimeId = event.getRuntimeId();
if (event.getMachineName().equals(machineName)
- && runtimeIdentity.getEnvName().equals(runtimeId.getEnvName())
+ && Objects.equals(runtimeIdentity.getEnvName(), runtimeId.getEnvName())
&& runtimeIdentity.getWorkspaceId().equals(runtimeId.getWorkspaceId())) {
finishEventFuture.complete(event);
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/RuntimeIdentityImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/RuntimeIdentityImpl.java
index 64e0016783..d629cea170 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/RuntimeIdentityImpl.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/RuntimeIdentityImpl.java
@@ -11,6 +11,7 @@
*/
package org.eclipse.che.api.workspace.server.model.impl;
+import java.util.Objects;
import org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity;
/** @author gazarenkov */
@@ -20,6 +21,10 @@ public final class RuntimeIdentityImpl implements RuntimeIdentity {
private final String envName;
private final String ownerId;
+ public RuntimeIdentityImpl(RuntimeIdentity id) {
+ this(id.getWorkspaceId(), id.getEnvName(), id.getOwnerId());
+ }
+
public RuntimeIdentityImpl(String workspaceId, String envName, String ownerId) {
this.workspaceId = workspaceId;
this.envName = envName;
@@ -43,14 +48,16 @@ public final class RuntimeIdentityImpl implements RuntimeIdentity {
@Override
public int hashCode() {
- return (workspaceId + envName).hashCode();
+ return Objects.hash(workspaceId, envName, ownerId);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof RuntimeIdentityImpl)) return false;
RuntimeIdentityImpl other = (RuntimeIdentityImpl) obj;
- return workspaceId.equals(other.workspaceId) && envName.equals(other.envName);
+ return workspaceId.equals(other.workspaceId)
+ && Objects.equals(envName, other.envName)
+ && Objects.equals(ownerId, other.ownerId);
}
@Override
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceConfigImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceConfigImpl.java
index 1b92aa5399..2d1015e975 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceConfigImpl.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceConfigImpl.java
@@ -63,7 +63,7 @@ public class WorkspaceConfigImpl implements WorkspaceConfig {
@Column(name = "description", columnDefinition = "TEXT")
private String description;
- @Column(name = "defaultenv", nullable = false)
+ @Column(name = "defaultenv", nullable = true)
private String defaultEnv;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalRuntime.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalRuntime.java
index c9ce43d85d..b67fedce68 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalRuntime.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/InternalRuntime.java
@@ -79,6 +79,7 @@ public abstract class InternalRuntime {
}
/** Returns name of the active environment. */
+ @Nullable
public String getActiveEnv() {
return context.getIdentity().getEnvName();
}
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactory.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactory.java
index 6d59c718af..955151d42a 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactory.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactory.java
@@ -28,6 +28,7 @@ import org.eclipse.che.api.installer.server.exception.InstallerException;
import org.eclipse.che.api.installer.shared.model.Installer;
import org.eclipse.che.api.workspace.server.model.impl.ServerConfigImpl;
import org.eclipse.che.api.workspace.server.spi.InfrastructureException;
+import org.eclipse.che.commons.annotation.Nullable;
/**
* Creates a valid instance of InternalEnvironment.
@@ -78,36 +79,40 @@ public abstract class InternalEnvironmentFactory
* @throws InfrastructureException if infrastructure specific error occurs
* @throws ValidationException if validation fails
*/
- public T create(final Environment sourceEnv) throws InfrastructureException, ValidationException {
+ public T create(@Nullable final Environment sourceEnv)
+ throws InfrastructureException, ValidationException {
Map machines = new HashMap<>();
List warnings = new ArrayList<>();
+ InternalRecipe recipe = null;
- InternalRecipe recipe = recipeRetriever.getRecipe(sourceEnv.getRecipe());
+ if (sourceEnv != null) {
+ recipe = recipeRetriever.getRecipe(sourceEnv.getRecipe());
- for (Map.Entry machineEntry :
- sourceEnv.getMachines().entrySet()) {
- MachineConfig machineConfig = machineEntry.getValue();
+ for (Map.Entry machineEntry :
+ sourceEnv.getMachines().entrySet()) {
+ MachineConfig machineConfig = machineEntry.getValue();
- List installers;
- try {
- installers = installerRegistry.getOrderedInstallers(machineConfig.getInstallers());
- } catch (InstallerException e) {
- throw new InfrastructureException(e);
+ List installers;
+ try {
+ installers = installerRegistry.getOrderedInstallers(machineConfig.getInstallers());
+ } catch (InstallerException e) {
+ throw new InfrastructureException(e);
+ }
+
+ machines.put(
+ machineEntry.getKey(),
+ new InternalMachineConfig(
+ installers,
+ normalizeServers(machineConfig.getServers()),
+ machineConfig.getEnv(),
+ machineConfig.getAttributes(),
+ machineConfig.getVolumes()));
}
- machines.put(
- machineEntry.getKey(),
- new InternalMachineConfig(
- installers,
- normalizeServers(machineConfig.getServers()),
- machineConfig.getEnv(),
- machineConfig.getAttributes(),
- machineConfig.getVolumes()));
+ machinesValidator.validate(machines);
}
- machinesValidator.validate(machines);
-
return doCreate(recipe, machines, warnings);
}
@@ -127,7 +132,9 @@ public abstract class InternalEnvironmentFactory
* @throws ValidationException if validation fails
*/
protected abstract T doCreate(
- InternalRecipe recipe, Map machines, List warnings)
+ @Nullable InternalRecipe recipe,
+ Map machines,
+ List warnings)
throws InfrastructureException, ValidationException;
@VisibleForTesting
diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimesTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimesTest.java
index 906ca3df01..855a4acd5b 100644
--- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimesTest.java
+++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceRuntimesTest.java
@@ -14,6 +14,7 @@ package org.eclipse.che.api.workspace.server;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static org.eclipse.che.api.workspace.shared.Constants.ERROR_MESSAGE_ATTRIBUTE_NAME;
+import static org.eclipse.che.api.workspace.shared.Constants.NO_ENVIRONMENT_RECIPE_TYPE;
import static org.eclipse.che.api.workspace.shared.Constants.STOPPED_ABNORMALLY_ATTRIBUTE_NAME;
import static org.eclipse.che.api.workspace.shared.Constants.STOPPED_ATTRIBUTE_NAME;
import static org.mockito.ArgumentMatchers.any;
@@ -119,6 +120,53 @@ public class WorkspaceRuntimesTest {
lockService);
}
+ @Test
+ public void internalEnvironmentCreationShouldRespectNoEnvironmentCase() throws Exception {
+ InternalEnvironmentFactory noEnvFactory =
+ mock(InternalEnvironmentFactory.class);
+ runtimes =
+ new WorkspaceRuntimes(
+ eventService,
+ ImmutableMap.of(
+ TEST_ENVIRONMENT_TYPE, testEnvFactory, NO_ENVIRONMENT_RECIPE_TYPE, noEnvFactory),
+ infrastructure,
+ sharedPool,
+ workspaceDao,
+ dbInitializer,
+ probeScheduler,
+ statuses,
+ lockService);
+ InternalEnvironment expectedEnvironment = mock(InternalEnvironment.class);
+ when(noEnvFactory.create(eq(null))).thenReturn(expectedEnvironment);
+
+ InternalEnvironment actualEnvironment = runtimes.createInternalEnvironment(null, emptyMap());
+
+ assertEquals(actualEnvironment, expectedEnvironment);
+ }
+
+ @Test(
+ expectedExceptions = NotFoundException.class,
+ expectedExceptionsMessageRegExp =
+ "InternalEnvironmentFactory is not configured for recipe type: 'not-supported-type'")
+ public void internalEnvironmentShouldThrowExceptionWhenNoEnvironmentFactoryFoundForRecipeType()
+ throws Exception {
+ EnvironmentImpl environment = new EnvironmentImpl();
+ environment.setRecipe(new RecipeImpl("not-supported-type", "", "", null));
+ runtimes.createInternalEnvironment(environment, emptyMap());
+ }
+
+ @Test(
+ expectedExceptions = NotFoundException.class,
+ expectedExceptionsMessageRegExp =
+ "InternalEnvironmentFactory is not configured for recipe type: '"
+ + NO_ENVIRONMENT_RECIPE_TYPE
+ + "'")
+ public void
+ internalEnvironmentShouldThrowExceptionWhenNoEnvironmentFactoryFoundForNoEnvironmentWorkspaceCase()
+ throws Exception {
+ runtimes.createInternalEnvironment(null, emptyMap());
+ }
+
@Test
public void runtimeIsRecovered() throws Exception {
RuntimeIdentity identity = new RuntimeIdentityImpl("workspace123", "my-env", "myId");
diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java
index f018c762b0..7c2808b1a0 100644
--- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java
+++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/WorkspaceValidatorTest.java
@@ -143,7 +143,7 @@ public class WorkspaceValidatorTest {
@Test(
expectedExceptions = ValidationException.class,
expectedExceptionsMessageRegExp = "Workspace default environment name required")
- public void shouldFailValidationIfDefaultEnvNameIsNull() throws Exception {
+ public void shouldFailValidationOfChe6WSIfDefaultEnvNameIsNull() throws Exception {
final WorkspaceConfigDto config = createConfig();
config.setDefaultEnv(null);
@@ -153,13 +153,24 @@ public class WorkspaceValidatorTest {
@Test(
expectedExceptions = ValidationException.class,
expectedExceptionsMessageRegExp = "Workspace default environment name required")
- public void shouldFailValidationIfDefaultEnvNameIsEmpty() throws Exception {
+ public void shouldFailValidationOfChe6WSIfDefaultEnvNameIsEmpty() throws Exception {
final WorkspaceConfigDto config = createConfig();
config.setDefaultEnv("");
wsValidator.validateConfig(config);
}
+ @Test
+ public void shouldNotFailValidationOfChe7WSIfDefaultEnvNameIsNullAndNoEnvIsPresent()
+ throws Exception {
+ final WorkspaceConfigDto config = createConfig();
+ config.setDefaultEnv(null);
+ config.getEnvironments().clear();
+ config.getAttributes().put(Constants.WORKSPACE_TOOLING_EDITOR_ATTRIBUTE, "something");
+
+ wsValidator.validateConfig(config);
+ }
+
@Test(
expectedExceptions = ValidationException.class,
expectedExceptionsMessageRegExp = "Workspace default environment configuration required")
@@ -370,7 +381,7 @@ public class WorkspaceValidatorTest {
.withType("type")
.withContent("content")
.withContentType("content type"));
- workspaceConfigDto.setEnvironments(singletonMap("dev-env", env));
+ workspaceConfigDto.setEnvironments(new HashMap<>(singletonMap("dev-env", env)));
List commandDtos = new ArrayList<>();
commandDtos.add(
diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactoryTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactoryTest.java
index 2888fa4bb6..2a685b713c 100644
--- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactoryTest.java
+++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/environment/InternalEnvironmentFactoryTest.java
@@ -155,6 +155,20 @@ public class InternalEnvironmentFactoryTest {
assertEquals(createdEnv, expectedEnv);
}
+ @Test
+ public void shouldPassNullRecipeIfEnvironmentIsNull() throws Exception {
+ // given
+ InternalEnvironment expectedEnv = mock(InternalEnvironment.class);
+ when(environmentFactory.doCreate(any(), any(), any())).thenReturn(expectedEnv);
+
+ // when
+ InternalEnvironment createdEnv = environmentFactory.create(null);
+
+ // then
+ assertEquals(createdEnv, expectedEnv);
+ verify(environmentFactory).doCreate(eq(null), any(), any());
+ }
+
@Test
public void normalizeServersProtocols() throws InfrastructureException {
ServerConfigImpl serverWithoutProtocol =
diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/1__remove_not_null_constraint_from_env_name_fields.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/1__remove_not_null_constraint_from_env_name_fields.sql
new file mode 100644
index 0000000000..fd4d4066ff
--- /dev/null
+++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/1__remove_not_null_constraint_from_env_name_fields.sql
@@ -0,0 +1,20 @@
+--
+-- Copyright (c) 2012-2018 Red Hat, Inc.
+-- This program and the accompanying materials are made
+-- available under the terms of the Eclipse Public License 2.0
+-- which is available at https://www.eclipse.org/legal/epl-2.0/
+--
+-- SPDX-License-Identifier: EPL-2.0
+--
+-- Contributors:
+-- Red Hat, Inc. - initial API and implementation
+--
+
+-- Allow null as defaultEnv field in workspace config
+ALTER TABLE workspaceconfig ALTER COLUMN defaultenv DROP NOT NULL;
+
+ALTER TABLE che_k8s_runtime DROP PRIMARY KEY;
+ALTER TABLE che_k8s_runtime ADD PRIMARY KEY (workspace_id);
+
+-- Allow null as env_name field in kubernetes runtime
+ALTER TABLE che_k8s_runtime ALTER COLUMN env_name DROP NOT NULL;
diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/mysql/1__remove_not_null_constraint_from_env_name_fields.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/mysql/1__remove_not_null_constraint_from_env_name_fields.sql
new file mode 100644
index 0000000000..557eedc41f
--- /dev/null
+++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/mysql/1__remove_not_null_constraint_from_env_name_fields.sql
@@ -0,0 +1,20 @@
+--
+-- Copyright (c) 2012-2018 Red Hat, Inc.
+-- This program and the accompanying materials are made
+-- available under the terms of the Eclipse Public License 2.0
+-- which is available at https://www.eclipse.org/legal/epl-2.0/
+--
+-- SPDX-License-Identifier: EPL-2.0
+--
+-- Contributors:
+-- Red Hat, Inc. - initial API and implementation
+--
+
+-- Allow null as defaultEnv field in workspace config
+ALTER TABLE workspaceconfig MODIFY COLUMN defaultenv VARCHAR(255);
+
+ALTER TABLE che_k8s_runtime DROP PRIMARY KEY;
+ALTER TABLE che_k8s_runtime ADD PRIMARY KEY (workspace_id);
+
+-- Allow null as env_name field in kubernetes runtime
+ALTER TABLE che_k8s_runtime MODIFY COLUMN env_name VARCHAR(255);
diff --git a/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/postgresql/1__remove_not_null_constraint_from_env_name_fields.sql b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/postgresql/1__remove_not_null_constraint_from_env_name_fields.sql
new file mode 100644
index 0000000000..b373d20778
--- /dev/null
+++ b/wsmaster/che-core-sql-schema/src/main/resources/che-schema/6.15.0/postgresql/1__remove_not_null_constraint_from_env_name_fields.sql
@@ -0,0 +1,20 @@
+--
+-- Copyright (c) 2012-2018 Red Hat, Inc.
+-- This program and the accompanying materials are made
+-- available under the terms of the Eclipse Public License 2.0
+-- which is available at https://www.eclipse.org/legal/epl-2.0/
+--
+-- SPDX-License-Identifier: EPL-2.0
+--
+-- Contributors:
+-- Red Hat, Inc. - initial API and implementation
+--
+
+-- Allow null as defaultEnv field in workspace config
+ALTER TABLE workspaceconfig ALTER COLUMN defaultenv DROP NOT NULL;
+
+ALTER TABLE che_k8s_runtime DROP CONSTRAINT che_k8s_runtime_pkey;
+ALTER TABLE che_k8s_runtime ADD PRIMARY KEY (workspace_id);
+
+-- Allow null as env_name field in kubernetes runtime
+ALTER TABLE che_k8s_runtime ALTER COLUMN env_name DROP NOT NULL;
diff --git a/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/CascadeRemovalTest.java b/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/CascadeRemovalTest.java
index 21c30ab33b..09d01ec342 100644
--- a/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/CascadeRemovalTest.java
+++ b/wsmaster/integration-tests/cascade-removal/src/test/java/org/eclipse/che/core/db/jpa/CascadeRemovalTest.java
@@ -185,7 +185,6 @@ public class CascadeRemovalTest {
SshPairImpl.class,
VolumeImpl.class,
KubernetesRuntimeState.class,
- KubernetesRuntimeState.RuntimeId.class,
KubernetesMachineImpl.class,
KubernetesMachineImpl.MachineId.class,
KubernetesServerImpl.class,
diff --git a/wsmaster/integration-tests/mysql-tck/src/test/java/MySqlTckModule.java b/wsmaster/integration-tests/mysql-tck/src/test/java/MySqlTckModule.java
index 7f1d0dd7b6..8a57877ad6 100644
--- a/wsmaster/integration-tests/mysql-tck/src/test/java/MySqlTckModule.java
+++ b/wsmaster/integration-tests/mysql-tck/src/test/java/MySqlTckModule.java
@@ -136,7 +136,6 @@ public class MySqlTckModule extends TckModule {
SignatureKeyPairImpl.class,
// k8s-runtimes
KubernetesRuntimeState.class,
- KubernetesRuntimeState.RuntimeId.class,
KubernetesMachineImpl.class,
KubernetesMachineImpl.MachineId.class,
KubernetesServerImpl.class,
diff --git a/wsmaster/integration-tests/postgresql-tck/src/test/java/PostgreSqlTckModule.java b/wsmaster/integration-tests/postgresql-tck/src/test/java/PostgreSqlTckModule.java
index c207da1f9a..2e816b32b7 100644
--- a/wsmaster/integration-tests/postgresql-tck/src/test/java/PostgreSqlTckModule.java
+++ b/wsmaster/integration-tests/postgresql-tck/src/test/java/PostgreSqlTckModule.java
@@ -131,7 +131,6 @@ public class PostgreSqlTckModule extends TckModule {
VolumeImpl.class,
// k8s-runtimes
KubernetesRuntimeState.class,
- KubernetesRuntimeState.RuntimeId.class,
KubernetesMachineImpl.class,
KubernetesMachineImpl.MachineId.class,
KubernetesServerImpl.class,