Make a workspace run without any user env (#11890)
Allows running Che 7 workspace without any user environment but with Che 7 tooling set. Workspace without environment has an empty list of environments and null value in `defaultEnv` field. Field `activeEnv` is supposed to be `null` too. What is changed: - Migration of DB - make defaultEnv nullable - remove env_name from runtimes primary key - make env_name in runtimes nullable - Make code respect the fact that there are workspaces with no env - settings API that returns the list of supported environment types returns no-environment type that - indicates that infrastructure support workspace with no environment at all. Signed-off-by: Oleksandr Garagatyi <ogaragat@redhat.com>6.19.x
parent
8fe1172cb1
commit
aaa8f424cd
|
|
@ -70,7 +70,6 @@
|
|||
<class>org.eclipse.che.multiuser.machine.authentication.server.signature.model.impl.SignatureKeyPairImpl</class>
|
||||
|
||||
<class>org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState</class>
|
||||
<class>org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesRuntimeState.RuntimeId</class>
|
||||
|
||||
<class>org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl</class>
|
||||
<class>org.eclipse.che.workspace.infrastructure.kubernetes.model.KubernetesMachineImpl.MachineId</class>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -162,6 +162,9 @@ public class WorkspaceLoadingTrackerImpl
|
|||
EnvironmentImpl defaultEnvironment =
|
||||
appContext.getWorkspace().getConfig().getEnvironments().get(defaultEnvironmentName);
|
||||
|
||||
if (defaultEnvironment == null) {
|
||||
return;
|
||||
}
|
||||
Map<String, MachineConfigImpl> 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<String, MachineConfigImpl> 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<String, MachineConfigImpl> machines = defaultEnvironment.getMachines();
|
||||
for (final String machineName : machines.keySet()) {
|
||||
MachineConfigImpl machineConfig = machines.get(machineName);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<WorkspaceImpl> startById(String id, String envName) {
|
||||
String url = baseHttpUrl + "/" + id + "/runtime" + "?environment=" + envName;
|
||||
Promise<WorkspaceImpl> startById(String id, @Nullable String envName) {
|
||||
String url = baseHttpUrl + "/" + id + "/runtime";
|
||||
if (envName != null) {
|
||||
url += "?environment=" + envName;
|
||||
}
|
||||
|
||||
return asyncRequestFactory
|
||||
.createPostRequest(url, null)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-lang</artifactId>
|
||||
|
|
|
|||
|
|
@ -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<Compos
|
|||
|
||||
@Override
|
||||
protected ComposeEnvironment doCreate(
|
||||
InternalRecipe recipe, Map<String, InternalMachineConfig> machines, List<Warning> warnings)
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> 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");
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String, InternalMachineConfig> machines, List<Warning> warnings)
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String, InternalMachineConfig> machines, List<Warning> warnings)
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<KubernetesRuntimeState> 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
|
||||
|
|
|
|||
|
|
@ -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<String, InternalMachineConfig> machines,
|
||||
List<Warning> sourceWarnings)
|
||||
throws InfrastructureException, ValidationException {
|
||||
checkNotNull(recipe, "Null recipe is not supported by kubernetes environment factory");
|
||||
List<Warning> warnings = new ArrayList<>();
|
||||
if (sourceWarnings != null) {
|
||||
warnings.addAll(sourceWarnings);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
+ '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> 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<String, Pod> 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) {
|
||||
|
||||
|
|
|
|||
|
|
@ -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<E extends KubernetesEnvironment>
|
|||
"-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))
|
||||
|
|
|
|||
|
|
@ -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<RuntimeId, KubernetesRuntimeState> runtimesStates = new HashMap<>();
|
||||
private Map<RuntimeIdentity, KubernetesRuntimeState> runtimesStates = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public Set<RuntimeIdentity> 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<WorkspaceStatus> 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<KubernetesRuntimeState> 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<String, KubernetesServerImpl> 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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Container> containers;
|
||||
KubernetesPluginsToolingApplier applier;
|
||||
private KubernetesEnvironment internalEnvironment;
|
||||
private List<Container> containers;
|
||||
private KubernetesPluginsToolingApplier applier;
|
||||
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
internalEnvironment = spy(KubernetesEnvironment.builder().build());
|
||||
applier = new KubernetesPluginsToolingApplier(TEST_IMAGE_POLICY, MEMORY_LIMIT_MB, false);
|
||||
|
||||
Map<String, InternalMachineConfig> machines = new HashMap<>();
|
||||
containers = new ArrayList<>();
|
||||
Map<String, Service> 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<String, String> 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()));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -135,6 +135,12 @@ public class OpenShiftEnvironment extends KubernetesEnvironment {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder setAttributes(Map<String, String> attributes) {
|
||||
this.attributes.putAll(attributes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setRoutes(Map<String, Route> route) {
|
||||
this.routes.putAll(route);
|
||||
return this;
|
||||
|
|
|
|||
|
|
@ -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<Open
|
|||
|
||||
@Override
|
||||
protected OpenShiftEnvironment doCreate(
|
||||
InternalRecipe recipe,
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> sourceWarnings)
|
||||
throws InfrastructureException, ValidationException {
|
||||
checkNotNull(recipe, "Null recipe is not supported by openshift environment factory");
|
||||
List<Warning> warnings = new ArrayList<>();
|
||||
if (sourceWarnings != null) {
|
||||
warnings.addAll(sourceWarnings);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,9 @@ public class LimitsCheckingWorkspaceManager extends WorkspaceManager {
|
|||
if (maxRamPerEnvMB < 0) {
|
||||
return;
|
||||
}
|
||||
if (config.getEnvironments().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, ? extends Environment> 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 =
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -75,7 +75,6 @@ public class CheckSimpleGwtAppTest {
|
|||
|
||||
WorkspaceConfigDto workspace =
|
||||
workspaceDtoDeserializer.deserializeWorkspaceTemplate(UBUNTU_JDK8);
|
||||
|
||||
workspace
|
||||
.getEnvironments()
|
||||
.get("replaced_name")
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ProjectConfigDto> projects);
|
||||
|
||||
@Override
|
||||
@FactoryParameter(obligation = MANDATORY)
|
||||
@FactoryParameter(obligation = OPTIONAL)
|
||||
Map<String, EnvironmentDto> getEnvironments();
|
||||
|
||||
void setEnvironments(Map<String, EnvironmentDto> environments);
|
||||
|
|
|
|||
|
|
@ -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<InternalEnvironment> {
|
||||
|
||||
@Inject
|
||||
public NoEnvironmentFactory(
|
||||
InstallerRegistry installerRegistry,
|
||||
RecipeRetriever recipeRetriever,
|
||||
MachineConfigsValidator machinesValidator) {
|
||||
super(installerRegistry, recipeRetriever, machinesValidator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InternalEnvironment doCreate(
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> 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 {}
|
||||
}
|
||||
|
|
@ -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. <br>
|
||||
* This indicates whether this workspace is Che6 or Che7 compatible.
|
||||
*/
|
||||
public static boolean isSidecarBasedWorkspace(Map<String, String> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String, String> options)
|
||||
private void startAsync(
|
||||
WorkspaceImpl workspace, @Nullable String envName, Map<String, String> 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> 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(
|
||||
|
|
|
|||
|
|
@ -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<Void> startAsync(
|
||||
Workspace workspace, String envName, Map<String, String> options)
|
||||
Workspace workspace, @Nullable String envName, Map<String, String> 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<String, String> workspaceConfigAttributes)
|
||||
@VisibleForTesting
|
||||
InternalEnvironment createInternalEnvironment(
|
||||
@Nullable Environment environment, Map<String, String> 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(
|
||||
|
|
|
|||
|
|
@ -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<String, ? extends MachineConfig> 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<String, ? extends MachineConfig> 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<String, String> 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.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ public abstract class InternalRuntime<T extends RuntimeContext> {
|
|||
}
|
||||
|
||||
/** Returns name of the active environment. */
|
||||
@Nullable
|
||||
public String getActiveEnv() {
|
||||
return context.getIdentity().getEnvName();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T extends InternalEnvironment>
|
|||
* @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<String, InternalMachineConfig> machines = new HashMap<>();
|
||||
List<Warning> warnings = new ArrayList<>();
|
||||
InternalRecipe recipe = null;
|
||||
|
||||
InternalRecipe recipe = recipeRetriever.getRecipe(sourceEnv.getRecipe());
|
||||
if (sourceEnv != null) {
|
||||
recipe = recipeRetriever.getRecipe(sourceEnv.getRecipe());
|
||||
|
||||
for (Map.Entry<String, ? extends MachineConfig> machineEntry :
|
||||
sourceEnv.getMachines().entrySet()) {
|
||||
MachineConfig machineConfig = machineEntry.getValue();
|
||||
for (Map.Entry<String, ? extends MachineConfig> machineEntry :
|
||||
sourceEnv.getMachines().entrySet()) {
|
||||
MachineConfig machineConfig = machineEntry.getValue();
|
||||
|
||||
List<Installer> installers;
|
||||
try {
|
||||
installers = installerRegistry.getOrderedInstallers(machineConfig.getInstallers());
|
||||
} catch (InstallerException e) {
|
||||
throw new InfrastructureException(e);
|
||||
List<Installer> 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<T extends InternalEnvironment>
|
|||
* @throws ValidationException if validation fails
|
||||
*/
|
||||
protected abstract T doCreate(
|
||||
InternalRecipe recipe, Map<String, InternalMachineConfig> machines, List<Warning> warnings)
|
||||
@Nullable InternalRecipe recipe,
|
||||
Map<String, InternalMachineConfig> machines,
|
||||
List<Warning> warnings)
|
||||
throws InfrastructureException, ValidationException;
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
|
|||
|
|
@ -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<InternalEnvironment> 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");
|
||||
|
|
|
|||
|
|
@ -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<CommandDto> commandDtos = new ArrayList<>();
|
||||
commandDtos.add(
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
@ -185,7 +185,6 @@ public class CascadeRemovalTest {
|
|||
SshPairImpl.class,
|
||||
VolumeImpl.class,
|
||||
KubernetesRuntimeState.class,
|
||||
KubernetesRuntimeState.RuntimeId.class,
|
||||
KubernetesMachineImpl.class,
|
||||
KubernetesMachineImpl.MachineId.class,
|
||||
KubernetesServerImpl.class,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue