Add snapshotting status (#2829)
parent
f2661c97f4
commit
e316ba7945
|
|
@ -46,6 +46,18 @@ public enum WorkspaceStatus {
|
|||
*/
|
||||
RUNNING,
|
||||
|
||||
/**
|
||||
* Workspace is in SNAPSHOTTING status if and only if the workspace
|
||||
* is currently creating snapshots of it's machines.
|
||||
*
|
||||
* <p>Workspace is in SNAPSHOTTING status after it was {@link #RUNNING}.
|
||||
* The status map:
|
||||
* <pre>
|
||||
* RUNNING -> <b>SNAPSHOTTING</b> -> RUNNING (normal behaviour/error while snapshotting)
|
||||
* </pre>
|
||||
*/
|
||||
SNAPSHOTTING,
|
||||
|
||||
/**
|
||||
* Workspace considered as stopping if and only if its active environment is shutting down.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import javax.inject.Provider;
|
|||
import javax.inject.Singleton;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
|
@ -117,6 +118,20 @@ public class JpaSnapshotDao implements SnapshotDao {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotImpl> replaceSnapshots(String workspaceId,
|
||||
String envName,
|
||||
Collection<? extends SnapshotImpl> newSnapshots) throws SnapshotException {
|
||||
requireNonNull(workspaceId, "Required non-null workspace id");
|
||||
requireNonNull(envName, "Required non-null environment name");
|
||||
requireNonNull(newSnapshots, "Required non-null new snapshots");
|
||||
try {
|
||||
return doReplaceSnapshots(workspaceId, envName, newSnapshots);
|
||||
} catch (RuntimeException x) {
|
||||
throw new SnapshotException(x.getLocalizedMessage(), x);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected void doSave(SnapshotImpl snapshot) {
|
||||
managerProvider.get().persist(snapshot);
|
||||
|
|
@ -131,4 +146,19 @@ public class JpaSnapshotDao implements SnapshotDao {
|
|||
}
|
||||
manager.remove(snapshot);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
protected List<SnapshotImpl> doReplaceSnapshots(String workspaceId,
|
||||
String envName,
|
||||
Collection<? extends SnapshotImpl> newSnapshots) {
|
||||
final EntityManager manager = managerProvider.get();
|
||||
final List<SnapshotImpl> existing = manager.createNamedQuery("Snapshot.findByWorkspaceAndEnvironment", SnapshotImpl.class)
|
||||
.setParameter("workspaceId", workspaceId)
|
||||
.setParameter("envName", envName)
|
||||
.getResultList();
|
||||
existing.forEach(manager::remove);
|
||||
manager.flush();
|
||||
newSnapshots.forEach(manager::persist);
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,12 @@ import java.util.Objects;
|
|||
@NamedQuery(name = "Snapshot.findSnapshots",
|
||||
query = "SELECT snapshot " +
|
||||
"FROM Snapshot snapshot " +
|
||||
"WHERE snapshot.workspaceId = :workspaceId")
|
||||
"WHERE snapshot.workspaceId = :workspaceId"),
|
||||
@NamedQuery(name = "Snapshot.findByWorkspaceAndEnvironment",
|
||||
query = "SELECT snapshot " +
|
||||
"FROM Snapshot snapshot " +
|
||||
"WHERE snapshot.workspaceId = :workspaceId " +
|
||||
" AND snapshot.envName = :envName")
|
||||
}
|
||||
)
|
||||
@Table(indexes = @Index(columnList = "workspaceId, envName, machineName", unique = true))
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import org.eclipse.che.api.core.NotFoundException;
|
|||
import org.eclipse.che.api.machine.server.exception.SnapshotException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -86,4 +87,24 @@ public interface SnapshotDao {
|
|||
* if other error occur
|
||||
*/
|
||||
void removeSnapshot(String snapshotId) throws NotFoundException, SnapshotException;
|
||||
|
||||
/**
|
||||
* Replaces all the existing snapshots related to the given workspace
|
||||
* with a new list of snapshots.
|
||||
*
|
||||
* @param workspaceId
|
||||
* the id of the workspace to replace snapshots
|
||||
* @param envName
|
||||
* the name of the environment in workspace with given id
|
||||
* which is used to search those snapshots that should be replaced
|
||||
* @param newSnapshots
|
||||
* the list of the snapshots which will be stored instead of existing ones
|
||||
* @return the list of replaced(removed/old) snapshots for given workspace and environment,
|
||||
* or an empty list when there is no a single snapshot for the given workspace
|
||||
* @throws SnapshotException
|
||||
* when any error occurs
|
||||
*/
|
||||
List<SnapshotImpl> replaceSnapshots(String workspaceId,
|
||||
String envName,
|
||||
Collection<? extends SnapshotImpl> newSnapshots) throws SnapshotException;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.che.api.machine.server.spi.tck;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
|
|
@ -30,6 +31,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
|
|
@ -180,6 +182,22 @@ public class SnapshotDaoTest {
|
|||
snapshotDao.removeSnapshot(null);
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "shouldFindSnapshotsByWorkspaceAndNamespace")
|
||||
public void replacesSnapshots() throws Exception {
|
||||
final SnapshotImpl newSnapshot = createSnapshot("new-snapshot",
|
||||
snapshots[0].getWorkspaceId(),
|
||||
snapshots[0].getEnvName(),
|
||||
snapshots[0].getMachineName());
|
||||
|
||||
final List<SnapshotImpl> replaced = snapshotDao.replaceSnapshots(newSnapshot.getWorkspaceId(),
|
||||
newSnapshot.getEnvName(),
|
||||
singletonList(newSnapshot));
|
||||
|
||||
assertEquals(new HashSet<>(replaced), Sets.newHashSet(snapshots[0], snapshots[1]));
|
||||
assertEquals(new HashSet<>(snapshotDao.findSnapshots(snapshots[0].getWorkspaceId())),
|
||||
Sets.newHashSet(newSnapshot, snapshots[2]));
|
||||
}
|
||||
|
||||
@DataProvider(name = "missingSnapshots")
|
||||
public Object[][] missingSnapshots() {
|
||||
final SnapshotImpl snapshot = snapshots[0];
|
||||
|
|
|
|||
|
|
@ -26,10 +26,11 @@ import org.eclipse.che.api.core.model.workspace.Workspace;
|
|||
import org.eclipse.che.api.core.model.workspace.WorkspaceConfig;
|
||||
import org.eclipse.che.api.core.model.workspace.WorkspaceStatus;
|
||||
import org.eclipse.che.api.core.notification.EventService;
|
||||
import org.eclipse.che.api.machine.server.spi.SnapshotDao;
|
||||
import org.eclipse.che.api.machine.server.exception.SnapshotException;
|
||||
import org.eclipse.che.api.machine.server.model.impl.MachineImpl;
|
||||
import org.eclipse.che.api.machine.server.model.impl.SnapshotImpl;
|
||||
import org.eclipse.che.api.machine.server.spi.Instance;
|
||||
import org.eclipse.che.api.machine.server.spi.SnapshotDao;
|
||||
import org.eclipse.che.api.workspace.server.WorkspaceRuntimes.RuntimeDescriptor;
|
||||
import org.eclipse.che.api.workspace.server.event.WorkspaceCreatedEvent;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
|
||||
|
|
@ -43,11 +44,15 @@ import org.eclipse.che.commons.annotation.Nullable;
|
|||
import org.eclipse.che.commons.env.EnvironmentContext;
|
||||
import org.eclipse.che.commons.lang.concurrent.ThreadLocalPropagateContext;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
|
@ -57,7 +62,9 @@ import static com.google.common.base.MoreObjects.firstNonNull;
|
|||
import static java.lang.Boolean.parseBoolean;
|
||||
import static java.lang.String.format;
|
||||
import static java.lang.System.currentTimeMillis;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.STOPPED;
|
||||
|
|
@ -67,7 +74,6 @@ import static org.eclipse.che.api.workspace.shared.Constants.WORKSPACE_STOPPED_B
|
|||
import static org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent.EventType.SNAPSHOT_CREATED;
|
||||
import static org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent.EventType.SNAPSHOT_CREATING;
|
||||
import static org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent.EventType.SNAPSHOT_CREATION_ERROR;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
|
||||
/**
|
||||
* Facade for Workspace related operations.
|
||||
|
|
@ -449,10 +455,32 @@ public class WorkspaceManager {
|
|||
public void stopWorkspace(String workspaceId) throws ServerException,
|
||||
NotFoundException,
|
||||
ConflictException {
|
||||
stopWorkspace(workspaceId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously stops the workspace,
|
||||
* creates a snapshot of it if {@code createSnapshot} is set to true.
|
||||
*
|
||||
* @param workspaceId
|
||||
* the id of the workspace to stop
|
||||
* @param createSnapshot
|
||||
* true if create snapshot, false if don't,
|
||||
* null if default behaviour should be used
|
||||
* @throws ServerException
|
||||
* when any server error occurs
|
||||
* @throws NullPointerException
|
||||
* when {@code workspaceId} is null
|
||||
* @throws NotFoundException
|
||||
* when workspace {@code workspaceId} doesn't have runtime
|
||||
*/
|
||||
public void stopWorkspace(String workspaceId, @Nullable Boolean createSnapshot) throws ConflictException,
|
||||
NotFoundException,
|
||||
ServerException {
|
||||
requireNonNull(workspaceId, "Required non-null workspace id");
|
||||
final WorkspaceImpl workspace = normalizeState(workspaceDao.get(workspaceId));
|
||||
checkWorkspaceIsRunning(workspace, "stop");
|
||||
performAsyncStop(workspace);
|
||||
performAsyncStop(workspace, createSnapshot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -487,9 +515,9 @@ public class WorkspaceManager {
|
|||
final WorkspaceImpl workspace = normalizeState(workspaceDao.get(workspaceId));
|
||||
checkWorkspaceIsRunning(workspace, "create a snapshot of");
|
||||
executor.execute(ThreadLocalPropagateContext.wrap(() -> {
|
||||
createSnapshotSync(workspace.getRuntime(),
|
||||
workspace.getNamespace(),
|
||||
workspaceId);
|
||||
createSnapshotSync(workspace.getNamespace(),
|
||||
workspaceId,
|
||||
workspace.getRuntime().getActiveEnv());
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -644,15 +672,20 @@ public class WorkspaceManager {
|
|||
* attribute set to true) and then stops the workspace(even if snapshot creation failed).
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void performAsyncStop(WorkspaceImpl workspace) throws ConflictException {
|
||||
void performAsyncStop(WorkspaceImpl workspace, @Nullable Boolean createSnapshot) throws ConflictException {
|
||||
checkWorkspaceIsRunning(workspace, "stop");
|
||||
final String autoSnapshotAttr = workspace.getAttributes().get(AUTO_CREATE_SNAPSHOT);
|
||||
boolean createSnapshot;
|
||||
|
||||
final boolean snapshotBeforeStop;
|
||||
if (workspace.isTemporary()) {
|
||||
createSnapshot = false;
|
||||
snapshotBeforeStop = false;
|
||||
} else if (createSnapshot != null) {
|
||||
snapshotBeforeStop = createSnapshot;
|
||||
} else if (workspace.getAttributes().containsKey(AUTO_CREATE_SNAPSHOT)) {
|
||||
snapshotBeforeStop = parseBoolean(workspace.getAttributes().get(AUTO_CREATE_SNAPSHOT));
|
||||
} else {
|
||||
createSnapshot = autoSnapshotAttr == null ? defaultAutoSnapshot : parseBoolean(autoSnapshotAttr);
|
||||
snapshotBeforeStop = defaultAutoSnapshot;
|
||||
}
|
||||
|
||||
executor.execute(ThreadLocalPropagateContext.wrap(() -> {
|
||||
final String stoppedBy = sessionUserNameOr(workspace.getAttributes().get(WORKSPACE_STOPPED_BY));
|
||||
LOG.info("Workspace '{}:{}' with id '{}' is being stopped by user '{}'",
|
||||
|
|
@ -660,7 +693,9 @@ public class WorkspaceManager {
|
|||
workspace.getConfig().getName(),
|
||||
workspace.getId(),
|
||||
firstNonNull(stoppedBy, "undefined"));
|
||||
if (createSnapshot && !createSnapshotSync(workspace.getRuntime(), workspace.getNamespace(), workspace.getId())) {
|
||||
if (snapshotBeforeStop && !createSnapshotSync(workspace.getNamespace(),
|
||||
workspace.getId(),
|
||||
workspace.getRuntime().getActiveEnv())) {
|
||||
LOG.warn("Could not create a snapshot of the workspace '{}:{}' with workspace id '{}'. The workspace will be stopped",
|
||||
workspace.getNamespace(),
|
||||
workspace.getConfig().getName(),
|
||||
|
|
@ -702,81 +737,81 @@ public class WorkspaceManager {
|
|||
* otherwise returns false.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean createSnapshotSync(WorkspaceRuntimeImpl runtime, String namespace, String workspaceId) {
|
||||
eventService.publish(newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATING)
|
||||
.withWorkspaceId(workspaceId));
|
||||
String devMachineSnapshotFailMessage = null;
|
||||
for (MachineImpl machine : runtime.getMachines()) {
|
||||
String error = replaceSnapshot(machine, namespace);
|
||||
if (error != null && machine.getConfig().isDev()) {
|
||||
devMachineSnapshotFailMessage = error;
|
||||
}
|
||||
}
|
||||
if (devMachineSnapshotFailMessage != null) {
|
||||
eventService.publish(newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATION_ERROR)
|
||||
.withWorkspaceId(workspaceId)
|
||||
.withError(devMachineSnapshotFailMessage));
|
||||
} else {
|
||||
eventService.publish(newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATED)
|
||||
.withWorkspaceId(workspaceId));
|
||||
}
|
||||
return devMachineSnapshotFailMessage == null;
|
||||
}
|
||||
|
||||
private String replaceSnapshot(MachineImpl machine, String namespace) {
|
||||
boolean createSnapshotSync(String namespace, String workspaceId, String envName) {
|
||||
try {
|
||||
runtimes.beginSnapshotting(workspaceId);
|
||||
} catch (NotFoundException | ConflictException x) {
|
||||
LOG.warn("Couldn't start snapshot creation of workspace '{}' due to error: '{}'",
|
||||
workspaceId,
|
||||
x.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
publishEvent(SNAPSHOT_CREATING, workspaceId);
|
||||
|
||||
final List<MachineImpl> machines;
|
||||
try {
|
||||
machines = runtimes.get(workspaceId).getRuntime().getMachines();
|
||||
} catch (Exception x) {
|
||||
throw new IllegalStateException(x.getLocalizedMessage(), x);
|
||||
}
|
||||
|
||||
LOG.info("Creating snapshot of workspace '{}', machines to snapshot: '{}'", workspaceId, machines.size());
|
||||
final List<SnapshotImpl> newSnapshots = new ArrayList<>(machines.size());
|
||||
Collections.sort(machines, comparing(m -> !m.getConfig().isDev(), Boolean::compare));
|
||||
for (MachineImpl machine : machines) {
|
||||
try {
|
||||
SnapshotImpl oldSnapshot = snapshotDao.getSnapshot(machine.getWorkspaceId(),
|
||||
machine.getEnvName(),
|
||||
machine.getConfig().getName());
|
||||
snapshotDao.removeSnapshot(oldSnapshot.getId());
|
||||
|
||||
runtimes.removeSnapshot(oldSnapshot);
|
||||
} catch (NotFoundException ignored) {
|
||||
// Do nothing if no snapshot found
|
||||
newSnapshots.add(runtimes.saveMachine(namespace, workspaceId, machine.getId()));
|
||||
} catch (Exception x) {
|
||||
if (machine.getConfig().isDev()) {
|
||||
runtimes.finishSnapshotting(workspaceId);
|
||||
publishEvent(SNAPSHOT_CREATION_ERROR, workspaceId, x.getMessage());
|
||||
return false;
|
||||
}
|
||||
LOG.warn(format("Couldn't create snapshot of machine '%s:%s:%s' in workspace '%s'",
|
||||
namespace,
|
||||
machine.getEnvName(),
|
||||
machine.getConfig().getName(),
|
||||
workspaceId));
|
||||
}
|
||||
}
|
||||
|
||||
SnapshotImpl snapshot = null;
|
||||
try {
|
||||
LOG.info("Saving new snapshots metadata, workspace id '{}'", workspaceId);
|
||||
final List<SnapshotImpl> removed = snapshotDao.replaceSnapshots(workspaceId, envName, newSnapshots);
|
||||
if (!removed.isEmpty()) {
|
||||
LOG.info("Removing old snapshots, workspace id '{}', snapshots to remove '{}'", workspaceId, removed.size());
|
||||
removeSnapshotsBinaries(removed);
|
||||
}
|
||||
} catch (SnapshotException x) {
|
||||
LOG.error(format("Couldn't remove existing snapshots metadata for workspace '%s'", workspaceId), x);
|
||||
LOG.info("Removing newly created snapshots, workspace id '{}', snapshots to remove '{}'", workspaceId, newSnapshots.size());
|
||||
removeSnapshotsBinaries(newSnapshots);
|
||||
runtimes.finishSnapshotting(workspaceId);
|
||||
publishEvent(SNAPSHOT_CREATION_ERROR, workspaceId, x.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
runtimes.finishSnapshotting(workspaceId);
|
||||
publishEvent(SNAPSHOT_CREATED, workspaceId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void removeSnapshotsBinaries(Collection<? extends SnapshotImpl> snapshots) {
|
||||
for (SnapshotImpl snapshot : snapshots) {
|
||||
try {
|
||||
snapshot = runtimes.saveMachine(namespace,
|
||||
machine.getWorkspaceId(),
|
||||
machine.getId());
|
||||
// check if the workspace exists before creating a snapshot,
|
||||
// if it is not an integrity constraint violation exception will occur,
|
||||
// this may happen when workspace stop called simultaneously.
|
||||
// The issue https://github.com/eclipse/che/issues/2683 should fix it
|
||||
// in a way that it won't be possible to snapshot workspace simultaneously.
|
||||
if (exists(machine.getWorkspaceId())) {
|
||||
snapshotDao.saveSnapshot(snapshot);
|
||||
} else {
|
||||
LOG.warn("Snapshot for a workspace '{}' won't be saved, as the workspace doesn't exist anymore",
|
||||
machine.getWorkspaceId());
|
||||
runtimes.removeSnapshot(snapshot);
|
||||
}
|
||||
} catch (ApiException e) {
|
||||
if (snapshot != null) {
|
||||
try {
|
||||
runtimes.removeSnapshot(snapshot);
|
||||
} catch (ApiException e1) {
|
||||
LOG.error(format("Snapshot removal failed. Snapshot: %s. Error: %s",
|
||||
snapshot,
|
||||
e1.getLocalizedMessage()),
|
||||
e1);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
runtimes.removeSnapshot(snapshot);
|
||||
} catch (ServerException | NotFoundException x) {
|
||||
LOG.error(format("Couldn't remove snapshot '%s', workspace id '%s'",
|
||||
snapshot.getId(),
|
||||
snapshot.getWorkspaceId()),
|
||||
x);
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (ApiException apiEx) {
|
||||
LOG.error("Snapshot creation failed. Error: " + apiEx.getLocalizedMessage(), apiEx);
|
||||
return apiEx.getLocalizedMessage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
void checkWorkspaceIsRunning(WorkspaceImpl workspace, String operation) throws ConflictException {
|
||||
if (workspace.getStatus() != RUNNING) {
|
||||
|
|
@ -808,6 +843,17 @@ public class WorkspaceManager {
|
|||
}
|
||||
}
|
||||
|
||||
private void publishEvent(EventType type, String workspaceId, String error) {
|
||||
eventService.publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(type)
|
||||
.withWorkspaceId(workspaceId)
|
||||
.withError(error));
|
||||
}
|
||||
|
||||
private void publishEvent(EventType type, String workspaceId) {
|
||||
publishEvent(type, workspaceId, null);
|
||||
}
|
||||
|
||||
private WorkspaceImpl normalizeState(WorkspaceImpl workspace, RuntimeDescriptor descriptor) {
|
||||
if (descriptor != null) {
|
||||
workspace.setStatus(descriptor.getRuntimeStatus());
|
||||
|
|
@ -856,14 +902,4 @@ public class WorkspaceManager {
|
|||
final String namespace = nsPart.isEmpty() ? sessionUser().getUserName() : nsPart;
|
||||
return workspaceDao.get(wsName, namespace);
|
||||
}
|
||||
|
||||
/** Returns true if workspace exists and false otherwise. */
|
||||
private boolean exists(String workspaceId) throws ServerException {
|
||||
try {
|
||||
workspaceDao.get(workspaceId);
|
||||
} catch (NotFoundException x) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ import java.util.concurrent.Executors;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.SNAPSHOTTING;
|
||||
import static org.eclipse.che.api.machine.shared.Constants.ENVIRONMENT_OUTPUT_CHANNEL_TEMPLATE;
|
||||
import static org.eclipse.che.dto.server.DtoFactory.newDto;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
|
@ -401,10 +403,7 @@ public class WorkspaceRuntimes {
|
|||
NotFoundException {
|
||||
|
||||
try (StripedLocks.ReadLock lock = stripedLocks.acquireReadLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
if (workspaceState == null || workspaceState.status != WorkspaceStatus.RUNNING) {
|
||||
throw new ConflictException(format("Environment of workspace '%s' is not running", workspaceId));
|
||||
}
|
||||
getRunningState(workspaceId);
|
||||
}
|
||||
|
||||
List<String> agents = Collections.singletonList("org.eclipse.che.terminal");
|
||||
|
|
@ -413,7 +412,7 @@ public class WorkspaceRuntimes {
|
|||
|
||||
try (StripedLocks.WriteLock lock = stripedLocks.acquireWriteLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
if (workspaceState == null || workspaceState.status != WorkspaceStatus.RUNNING) {
|
||||
if (workspaceState == null || workspaceState.status != RUNNING) {
|
||||
try {
|
||||
environmentEngine.stopMachine(workspaceId, instance.getId());
|
||||
} catch (NotFoundException | ServerException | ConflictException e) {
|
||||
|
|
@ -426,6 +425,41 @@ public class WorkspaceRuntimes {
|
|||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes workspace runtimes status from RUNNING to SNAPSHOTTING.
|
||||
*
|
||||
* @param workspaceId
|
||||
* the id of the workspace to begin snapshotting for
|
||||
* @throws NotFoundException
|
||||
* when workspace with such id doesn't have runtime
|
||||
* @throws ConflictException
|
||||
* when workspace status is different from SNAPSHOTTING
|
||||
* @see WorkspaceStatus#SNAPSHOTTING
|
||||
*/
|
||||
public void beginSnapshotting(String workspaceId) throws NotFoundException, ConflictException {
|
||||
try (StripedLocks.WriteLock ignored = stripedLocks.acquireWriteLock(workspaceId)) {
|
||||
getRunningState(workspaceId).status = SNAPSHOTTING;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes workspace runtimes status from SNAPSHOTTING back to RUNNING.
|
||||
* This method won't affect workspace runtime or throw any exception
|
||||
* if workspace is not in running status or doesn't have runtime.
|
||||
*
|
||||
* @param workspaceId
|
||||
* the id of the workspace to finish snapshotting for
|
||||
* @see WorkspaceStatus#SNAPSHOTTING
|
||||
*/
|
||||
public void finishSnapshotting(String workspaceId) {
|
||||
try (StripedLocks.WriteLock ignored = stripedLocks.acquireWriteLock(workspaceId)) {
|
||||
final WorkspaceState state = workspaces.get(workspaceId);
|
||||
if (state != null && state.status == SNAPSHOTTING) {
|
||||
state.status = RUNNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops machine in a running environment.
|
||||
*
|
||||
|
|
@ -447,7 +481,7 @@ public class WorkspaceRuntimes {
|
|||
ConflictException {
|
||||
try (StripedLocks.ReadLock lock = stripedLocks.acquireReadLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
if (workspaceState == null || workspaceState.status != WorkspaceStatus.RUNNING) {
|
||||
if (workspaceState == null || workspaceState.status != RUNNING) {
|
||||
throw new ConflictException(format("Environment of workspace '%s' is not running", workspaceId));
|
||||
}
|
||||
}
|
||||
|
|
@ -479,8 +513,8 @@ public class WorkspaceRuntimes {
|
|||
|
||||
try (StripedLocks.ReadLock lock = stripedLocks.acquireReadLock(workspaceId)) {
|
||||
WorkspaceState workspaceState = workspaces.get(workspaceId);
|
||||
if (workspaceState == null || workspaceState.status != WorkspaceStatus.RUNNING) {
|
||||
throw new ConflictException(format("Environment of workspace '%s' is not running", workspaceId));
|
||||
if (workspaceState == null || !(workspaceState.status == SNAPSHOTTING || workspaceState.status == RUNNING)) {
|
||||
throw new ConflictException(format("Environment of workspace '%s' is not running or snapshotting", workspaceId));
|
||||
}
|
||||
}
|
||||
return environmentEngine.saveSnapshot(namespace, workspaceId, machineId);
|
||||
|
|
@ -549,7 +583,7 @@ public class WorkspaceRuntimes {
|
|||
.build());
|
||||
try (StripedLocks.WriteAllLock lock = stripedLocks.acquireWriteAllLock()) {
|
||||
for (Map.Entry<String, WorkspaceState> workspace : workspaces.entrySet()) {
|
||||
if (workspace.getValue().status.equals(WorkspaceStatus.RUNNING) ||
|
||||
if (workspace.getValue().status.equals(RUNNING) ||
|
||||
workspace.getValue().status.equals(WorkspaceStatus.STARTING)) {
|
||||
stopEnvExecutor.execute(() -> {
|
||||
try {
|
||||
|
|
@ -586,29 +620,30 @@ public class WorkspaceRuntimes {
|
|||
.withError(error));
|
||||
}
|
||||
|
||||
private Instance getDevMachine(List<Instance> machines) throws ServerException {
|
||||
Optional<Instance> devMachineOpt = machines.stream()
|
||||
.filter(machine -> machine.getConfig().isDev())
|
||||
.findAny();
|
||||
|
||||
if (devMachineOpt.isPresent()) {
|
||||
return devMachineOpt.get();
|
||||
}
|
||||
throw new ServerException(
|
||||
"Environment has booted but it doesn't contain dev machine. Environment has been stopped.");
|
||||
}
|
||||
|
||||
private void ensurePreDestroyIsNotExecuted() throws ServerException {
|
||||
if (isPreDestroyInvoked) {
|
||||
throw new ServerException("Could not perform operation because application server is stopping");
|
||||
}
|
||||
}
|
||||
|
||||
private WorkspaceState getRunningState(String workspaceId) throws NotFoundException, ConflictException {
|
||||
final WorkspaceState state = workspaces.get(workspaceId);
|
||||
if (state == null) {
|
||||
throw new NotFoundException("Workspace with id '" + workspaceId + "' is not running");
|
||||
}
|
||||
if (state.getStatus() != RUNNING) {
|
||||
throw new ConflictException(format("Workspace with id '%s' is not in 'RUNNING', it's status is '%s'",
|
||||
workspaceId,
|
||||
state.getStatus()));
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
protected void launchAgents(Instance instance, List<String> agents) throws ServerException {
|
||||
try {
|
||||
for (AgentKey agentKey : agentSorter.sort(agents)) {
|
||||
LOG.info("Launching '{}' agent", agentKey.getName());
|
||||
|
||||
|
||||
Agent agent = agentRegistry.getAgent(agentKey);
|
||||
AgentLauncher launcher = launcherFactory.find(agentKey.getName(), instance.getConfig().getType());
|
||||
launcher.launch(instance, agent);
|
||||
|
|
|
|||
|
|
@ -346,11 +346,13 @@ public class WorkspaceService extends Service {
|
|||
@ApiResponse(code = 404, message = "The workspace with specified id doesn't exist"),
|
||||
@ApiResponse(code = 403, message = "The user is not workspace owner"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public void stop(@ApiParam("The workspace id") @PathParam("id") String id) throws ForbiddenException,
|
||||
NotFoundException,
|
||||
ServerException,
|
||||
ConflictException {
|
||||
workspaceManager.stopWorkspace(id);
|
||||
public void stop(@ApiParam("The workspace id") @PathParam("id") String id,
|
||||
@ApiParam("Whether to snapshot workspace before stopping it")
|
||||
@QueryParam("create-snapshot") Boolean createSnapshot) throws ForbiddenException,
|
||||
NotFoundException,
|
||||
ServerException,
|
||||
ConflictException {
|
||||
workspaceManager.stopWorkspace(id, createSnapshot);
|
||||
}
|
||||
|
||||
@POST
|
||||
|
|
@ -506,10 +508,10 @@ public class WorkspaceService extends Service {
|
|||
@ApiParam(value = "The name of the environment", required = true)
|
||||
@QueryParam("name")
|
||||
String envName) throws ServerException,
|
||||
BadRequestException,
|
||||
NotFoundException,
|
||||
ConflictException,
|
||||
ForbiddenException {
|
||||
BadRequestException,
|
||||
NotFoundException,
|
||||
ConflictException,
|
||||
ForbiddenException {
|
||||
requiredNotNull(newEnvironment, "New environment");
|
||||
requiredNotNull(envName, "New environment name");
|
||||
final WorkspaceImpl workspace = workspaceManager.getWorkspace(id);
|
||||
|
|
@ -673,7 +675,7 @@ public class WorkspaceService extends Service {
|
|||
@ApiResponse(code = 404, message = "The workspace with specified id does not exist"),
|
||||
@ApiResponse(code = 500, message = "Internal server error occurred")})
|
||||
public WsAgentHealthStateDto checkAgentHealth(@ApiParam(value = "Workspace id")
|
||||
@PathParam("id") String key) throws NotFoundException, ServerException{
|
||||
@PathParam("id") String key) throws NotFoundException, ServerException {
|
||||
final WorkspaceImpl workspace = workspaceManager.getWorkspace(key);
|
||||
if (WorkspaceStatus.RUNNING != workspace.getStatus()) {
|
||||
return newDto(WsAgentHealthStateDto.class).withWorkspaceStatus(workspace.getStatus());
|
||||
|
|
|
|||
|
|
@ -204,13 +204,14 @@ public class WorkspaceConfigImpl implements WorkspaceConfig {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UsersWorkspaceImpl{" +
|
||||
return "WorkspaceConfigImpl{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", defaultEnv='" + defaultEnv + '\'' +
|
||||
", commands=" + commands +
|
||||
", projects=" + projects +
|
||||
", environments=" + environments +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
|
|||
import org.eclipse.che.commons.env.EnvironmentContext;
|
||||
import org.eclipse.che.commons.subject.Subject;
|
||||
import org.eclipse.che.commons.subject.SubjectImpl;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.InOrder;
|
||||
|
|
@ -51,11 +52,14 @@ import org.testng.annotations.Listeners;
|
|||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
|
|
@ -77,6 +81,7 @@ import static org.mockito.Mockito.doReturn;
|
|||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
|
@ -99,23 +104,23 @@ public class WorkspaceManagerTest {
|
|||
private static final String NAMESPACE_2 = "userNS2";
|
||||
|
||||
@Mock
|
||||
private EventService eventService;
|
||||
private EventService eventService;
|
||||
@Mock
|
||||
private WorkspaceDao workspaceDao;
|
||||
private WorkspaceDao workspaceDao;
|
||||
@Mock
|
||||
private WorkspaceValidator workspaceConfigValidator;
|
||||
private WorkspaceValidator workspaceConfigValidator;
|
||||
@Mock
|
||||
private MachineProcessManager client;
|
||||
private MachineProcessManager client;
|
||||
@Mock
|
||||
private WorkspaceRuntimes runtimes;
|
||||
private WorkspaceRuntimes runtimes;
|
||||
@Mock
|
||||
private AccountManager accountManager;
|
||||
private AccountManager accountManager;
|
||||
@Mock
|
||||
private SnapshotDao snapshotDao;
|
||||
@Mock
|
||||
private WorkspaceFilesCleaner workspaceFilesCleaner;
|
||||
private SnapshotDao snapshotDao;
|
||||
@Captor
|
||||
private ArgumentCaptor<WorkspaceImpl> workspaceCaptor;
|
||||
private ArgumentCaptor<WorkspaceImpl> workspaceCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<SnapshotImpl>> snapshotsCaptor;
|
||||
|
||||
private WorkspaceManager workspaceManager;
|
||||
|
||||
|
|
@ -530,62 +535,105 @@ public class WorkspaceManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCreateSnapshotIfWorkspaceIsTemporaryAndAutoCreateSnapshotActivated() throws Exception {
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "true");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
workspace.setTemporary(true);
|
||||
public void createsSnapshotBeforeStoppingWorkspace() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(workspaceManager, timeout(2000).never()).createSnapshotSync(anyObject(), anyString(), anyString());
|
||||
verify(runtimes, timeout(2000)).stop(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).beginSnapshotting(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).finishSnapshotting(workspace.getId());
|
||||
final Iterator<MachineImpl> machineIt = workspace.getRuntime().getMachines().iterator();
|
||||
verify(runtimes).saveMachine(workspace.getNamespace(), workspace.getId(), machineIt.next().getId());
|
||||
verify(runtimes).saveMachine(workspace.getNamespace(), workspace.getId(), machineIt.next().getId());
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATING)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATED)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCreateSnapshotIfWorkspaceIsTemporaryAndAutoCreateSnapshotDisactivated() throws Exception {
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "false");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
workspace.setTemporary(true);
|
||||
public void failsToCreateSnapshotWhenDevMachineSnapshottingFailed() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
when(runtimes.saveMachine(any(), any(), any())).thenThrow( new ServerException("test"));
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(workspaceManager, timeout(2000).never()).createSnapshotSync(anyObject(), anyString(), anyString());
|
||||
verify(runtimes, timeout(2000)).stop(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).beginSnapshotting(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).finishSnapshotting(workspace.getId());
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATING)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATION_ERROR)
|
||||
.withWorkspaceId(workspace.getId())
|
||||
.withError("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateWorkspaceSnapshotBeforeStoppingWorkspace() throws Exception {
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "true");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
public void removesNewlyCreatedSnapshotsWhenFailedToSaveTheirsMetadata() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
when(snapshotDao.replaceSnapshots(eq(workspace.getId()),
|
||||
eq(workspace.getRuntime().getActiveEnv()),
|
||||
anyObject())).thenThrow(new SnapshotException("test"));
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(workspaceManager, timeout(2000)).createSnapshotSync(anyObject(), anyString(), anyString());
|
||||
verify(runtimes, timeout(2000)).stop(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).beginSnapshotting(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).finishSnapshotting(workspace.getId());
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATING)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATION_ERROR)
|
||||
.withWorkspaceId(workspace.getId())
|
||||
.withError("test"));
|
||||
verify(snapshotDao).replaceSnapshots(eq(workspace.getId()),
|
||||
eq(workspace.getRuntime().getActiveEnv()),
|
||||
snapshotsCaptor.capture());
|
||||
final Iterator<SnapshotImpl> snapshotsIt = snapshotsCaptor.getValue().iterator();
|
||||
verify(runtimes).removeSnapshot(snapshotsIt.next());
|
||||
verify(runtimes).removeSnapshot(snapshotsIt.next());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removesOldSnapshotsWhenNewSnapshotsMetadataSuccessfullySaved() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
final SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.replaceSnapshots(eq(workspace.getId()),
|
||||
eq(workspace.getRuntime().getActiveEnv()),
|
||||
anyObject())).thenReturn(singletonList(oldSnapshot));
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(runtimes, timeout(2000)).beginSnapshotting(workspace.getId());
|
||||
verify(runtimes, timeout(2000)).finishSnapshotting(workspace.getId());
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATING)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
verify(eventService).publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATED)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
verify(runtimes).removeSnapshot(oldSnapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passedCreateSnapshotParameterIsUsedInPreferenceToAttribute() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId(), false);
|
||||
|
||||
verify(runtimes, never()).beginSnapshotting(workspace.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void passedNullCreateSnapshotParameterIsIgnored() throws Exception {
|
||||
final WorkspaceImpl workspace = createRunningWorkspace();
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId(), null);
|
||||
|
||||
verify(runtimes, timeout(2000)).beginSnapshotting(workspace.getId());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ConflictException.class,
|
||||
|
|
@ -658,6 +706,46 @@ public class WorkspaceManagerTest {
|
|||
assertEquals(snapshots.get(0), wsSnapshot);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCreateSnapshotIfWorkspaceIsTemporaryAndAutoCreateSnapshotActivated() throws Exception {
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "true");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
workspace.setTemporary(true);
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(workspaceManager, timeout(2000).never()).createSnapshotSync(anyObject(), anyString(), anyString());
|
||||
verify(runtimes, timeout(2000)).stop(workspace.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotCreateSnapshotIfWorkspaceIsTemporaryAndAutoCreateSnapshotDisactivated() throws Exception {
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "false");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
workspace.setTemporary(true);
|
||||
|
||||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
verify(workspaceManager, timeout(2000).never()).createSnapshotSync(anyObject(), anyString(), anyString());
|
||||
verify(runtimes, timeout(2000)).stop(workspace.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateWorkspaceSnapshotUsingDefaultValueForAutoRestore() throws Exception {
|
||||
// given
|
||||
|
|
@ -682,7 +770,9 @@ public class WorkspaceManagerTest {
|
|||
workspaceManager.stopWorkspace(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(workspaceManager, timeout(2000)).createSnapshotSync(workspace.getRuntime(), workspace.getNamespace(), workspace.getId());
|
||||
verify(workspaceManager, timeout(2000)).createSnapshotSync(workspace.getNamespace(),
|
||||
workspace.getId(),
|
||||
workspace.getRuntime().getActiveEnv());
|
||||
verify(runtimes, timeout(2000)).stop(any());
|
||||
}
|
||||
|
||||
|
|
@ -838,9 +928,9 @@ public class WorkspaceManagerTest {
|
|||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(workspaceManager, timeout(1_000)).createSnapshotSync(any(WorkspaceRuntimeImpl.class),
|
||||
eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()));
|
||||
verify(workspaceManager, timeout(1_000)).createSnapshotSync(eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()),
|
||||
anyString());
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ConflictException.class,
|
||||
|
|
@ -856,29 +946,6 @@ public class WorkspaceManagerTest {
|
|||
workspaceManager.createSnapshot(workspace.getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSnapshotAllMachinesInWs() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(runtimes, timeout(1_000).times(2)).saveMachine(eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()),
|
||||
anyString());
|
||||
verify(snapshotDao, timeout(1_000).times(2)).saveSnapshot(any(SnapshotImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSendEventOnStartSnapshotSaving() throws Exception {
|
||||
// given
|
||||
|
|
@ -923,228 +990,6 @@ public class WorkspaceManagerTest {
|
|||
.withWorkspaceId(workspace.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSendSnapshotSavingFailedEventIfDevMachineSnapshotSavingFailed() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
for (MachineImpl machine : descriptor.getRuntime().getMachines()) {
|
||||
if (machine.getConfig().isDev()) {
|
||||
when(runtimes.saveMachine(workspace.getNamespace(), workspace.getId(), machine.getId()))
|
||||
.thenThrow(new ServerException("test error"));
|
||||
}
|
||||
}
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(eventService, timeout(1_000)).publish(eq(newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATION_ERROR)
|
||||
.withWorkspaceId(workspace.getId())
|
||||
.withError("test error")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotSendSnapshotSavingFailedEventIfNonDevMachineSnapshotSavingFailed() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
for (MachineImpl machine : descriptor.getRuntime().getMachines()) {
|
||||
if (!machine.getConfig().isDev()) {
|
||||
when(runtimes.saveMachine(workspace.getNamespace(), workspace.getId(), machine.getId()))
|
||||
.thenThrow(new ServerException("test error"));
|
||||
}
|
||||
}
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(eventService, timeout(1_000)).publish(eq(newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(SNAPSHOT_CREATED)
|
||||
.withWorkspaceId(workspace.getId())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnFalseOnFailureSnapshotSavingIfDevMachineSavingFailed() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
for (MachineImpl machine : descriptor.getRuntime().getMachines()) {
|
||||
if (machine.getConfig().isDev()) {
|
||||
when(runtimes.saveMachine(workspace.getNamespace(), workspace.getId(), machine.getId()))
|
||||
.thenThrow(new ServerException("test error"));
|
||||
}
|
||||
}
|
||||
|
||||
// when
|
||||
boolean snapshotSavingStatus = workspaceManager.createSnapshotSync(
|
||||
new WorkspaceRuntimeImpl(descriptor.getRuntime()), workspace.getNamespace(), workspace.getId());
|
||||
|
||||
// then
|
||||
assertFalse(snapshotSavingStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnTrueOnSuccessfulSavingSnapshotsForSeveralMachines() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
|
||||
// when
|
||||
boolean snapshotSavingStatus = workspaceManager.createSnapshotSync(
|
||||
new WorkspaceRuntimeImpl(descriptor.getRuntime()), workspace.getNamespace(), workspace.getId());
|
||||
|
||||
// then
|
||||
assertTrue(snapshotSavingStatus);
|
||||
// ensure that multiple machines were saved
|
||||
verify(snapshotDao, timeout(1_000).atLeast(2)).saveSnapshot(any(SnapshotImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnTrueOnSavingSnapshotsForSeveralMachinesWhenNonDevMachineSavingFailed() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
for (MachineImpl machine : descriptor.getRuntime().getMachines()) {
|
||||
if (!machine.getConfig().isDev()) {
|
||||
when(runtimes.saveMachine(workspace.getNamespace(), workspace.getId(), machine.getId()))
|
||||
.thenThrow(new ServerException("test error"));
|
||||
}
|
||||
}
|
||||
|
||||
// when
|
||||
boolean snapshotSavingStatus = workspaceManager.createSnapshotSync(
|
||||
new WorkspaceRuntimeImpl(descriptor.getRuntime()), workspace.getNamespace(), workspace.getId());
|
||||
|
||||
// then
|
||||
assertTrue(snapshotSavingStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveRuntimeSnapshotIfSavingSnapshotInDaoFails() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
doThrow(new SnapshotException("test error")).when(snapshotDao).saveSnapshot(any(SnapshotImpl.class));
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(runtimes, timeout(1_000).times(2)).removeSnapshot(any(SnapshotImpl.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreNotFoundExceptionOnOldSnapshotRemoval1() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
doThrow(new NotFoundException("test error")).when(snapshotDao).removeSnapshot(anyString());
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(workspaceManager, timeout(1_000)).createSnapshotSync(any(WorkspaceRuntimeImpl.class),
|
||||
eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreNotFoundExceptionOnOldSnapshotRemoval2() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
SnapshotImpl oldSnapshot = mock(SnapshotImpl.class);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenReturn(oldSnapshot);
|
||||
doThrow(new NotFoundException("test error")).when(runtimes).removeSnapshot(any(SnapshotImpl.class));
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(workspaceManager, timeout(1_000)).createSnapshotSync(any(WorkspaceRuntimeImpl.class),
|
||||
eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldIgnoreNotFoundExceptionOnOldSnapshotRemoval3() throws Exception {
|
||||
// given
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(any())).thenReturn(descriptor);
|
||||
when(snapshotDao.getSnapshot(eq(workspace.getId()),
|
||||
eq(workspace.getConfig().getDefaultEnv()),
|
||||
anyString()))
|
||||
.thenThrow(new NotFoundException("test error"));
|
||||
|
||||
// when
|
||||
workspaceManager.createSnapshot(workspace.getId());
|
||||
|
||||
// then
|
||||
verify(workspaceManager, timeout(1_000)).createSnapshotSync(any(WorkspaceRuntimeImpl.class),
|
||||
eq(workspace.getNamespace()),
|
||||
eq(workspace.getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldBeAbleToStopMachine() throws Exception {
|
||||
// given
|
||||
|
|
@ -1206,22 +1051,64 @@ public class WorkspaceManagerTest {
|
|||
verify(runtimes).getMachine(workspace.getId(), machine.getId());
|
||||
}
|
||||
|
||||
private RuntimeDescriptor createDescriptor(WorkspaceImpl workspace, WorkspaceStatus status) {
|
||||
private RuntimeDescriptor createDescriptor(WorkspaceImpl workspace, WorkspaceStatus status)
|
||||
throws ServerException, NotFoundException, ConflictException {
|
||||
EnvironmentImpl environment = workspace.getConfig().getEnvironments().get(workspace.getConfig().getDefaultEnv());
|
||||
assertNotNull(environment);
|
||||
|
||||
final WorkspaceRuntimeImpl runtime = new WorkspaceRuntimeImpl(workspace.getConfig().getDefaultEnv());
|
||||
MachineImpl machine = spy(createMachine(workspace.getId(), workspace.getConfig().getDefaultEnv(), true));
|
||||
runtime.getMachines().add(machine);
|
||||
MachineImpl machine2 = spy(createMachine(workspace.getId(), workspace.getConfig().getDefaultEnv(), false));
|
||||
runtime.getMachines().add(machine2);
|
||||
final MachineImpl machine1 = spy(createMachine(workspace.getId(), workspace.getConfig().getDefaultEnv(), true));
|
||||
final MachineImpl machine2 = spy(createMachine(workspace.getId(), workspace.getConfig().getDefaultEnv(), false));
|
||||
final Map<String, MachineImpl> machines = new HashMap<>();
|
||||
machines.put(machine1.getId(), machine1);
|
||||
machines.put(machine2.getId(), machine2);
|
||||
runtime.getMachines().addAll(machines.values());
|
||||
runtime.setDevMachine(machine1);
|
||||
|
||||
when(runtimes.saveMachine(any(), any(), anyObject())).thenAnswer(inv -> {
|
||||
final String machineId = (String)inv.getArguments()[2];
|
||||
final MachineImpl machine = machines.get(machineId);
|
||||
if (machine == null) {
|
||||
return null;
|
||||
}
|
||||
return SnapshotImpl.builder()
|
||||
.setWorkspaceId(machine.getWorkspaceId())
|
||||
.useCurrentCreationDate()
|
||||
.generateId()
|
||||
.setDescription("test")
|
||||
.setDev(machine.getConfig().isDev())
|
||||
.setEnvName(machine.getEnvName())
|
||||
.setMachineName(machine.getConfig().getName())
|
||||
.build();
|
||||
});
|
||||
|
||||
final RuntimeDescriptor descriptor = mock(RuntimeDescriptor.class);
|
||||
when(descriptor.getRuntimeStatus()).thenReturn(status);
|
||||
when(descriptor.getRuntime()).thenReturn(runtime);
|
||||
workspace.setRuntime(runtime);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
private WorkspaceImpl createRunningWorkspace() throws ServerException, NotFoundException, ConflictException {
|
||||
// should be snapshotted when stopped
|
||||
final WorkspaceImpl workspace = workspaceManager.createWorkspace(createConfig(), NAMESPACE);
|
||||
workspace.getAttributes().put(Constants.AUTO_CREATE_SNAPSHOT, "true");
|
||||
when(workspaceDao.get(workspace.getId())).thenReturn(workspace);
|
||||
|
||||
// has runtime
|
||||
final RuntimeDescriptor descriptor = createDescriptor(workspace, RUNNING);
|
||||
when(runtimes.get(workspace.getId())).thenReturn(descriptor);
|
||||
|
||||
// doesn't have snapshots
|
||||
when(snapshotDao.findSnapshots(workspace.getId())).thenReturn(emptyList());
|
||||
when(snapshotDao.replaceSnapshots(eq(workspace.getId()),
|
||||
eq(workspace.getRuntime().getActiveEnv()),
|
||||
any())).thenReturn(emptyList());
|
||||
|
||||
return workspace;
|
||||
}
|
||||
|
||||
|
||||
private static WorkspaceConfigImpl createConfig() {
|
||||
EnvironmentImpl environment = new EnvironmentImpl(new EnvironmentRecipeImpl("type",
|
||||
"contentType",
|
||||
|
|
|
|||
|
|
@ -36,8 +36,11 @@ import org.eclipse.che.api.workspace.server.model.impl.EnvironmentImpl;
|
|||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
|
||||
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceRuntimeImpl;
|
||||
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent;
|
||||
import org.eclipse.che.api.workspace.shared.dto.event.WorkspaceStatusEvent.EventType;
|
||||
import org.eclipse.che.commons.lang.NameGenerator;
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.testng.MockitoTestNGListener;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
|
|
@ -51,23 +54,29 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.eclipse.che.api.core.model.workspace.WorkspaceStatus.RUNNING;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Yevhenii Voevodin
|
||||
|
|
@ -436,8 +445,8 @@ public class WorkspaceRuntimesTest {
|
|||
verify(runtimes).launchAgents(instance, singletonList("org.eclipse.che.terminal"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = ConflictException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment of workspace '.*' is not running")
|
||||
@Test(expectedExceptions = NotFoundException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace with id '.*' is not running")
|
||||
public void shouldNotStartMachineIfEnvironmentIsNotRunning() throws Exception {
|
||||
// when
|
||||
MachineConfigImpl config = createConfig(false);
|
||||
|
|
@ -493,7 +502,7 @@ public class WorkspaceRuntimesTest {
|
|||
}
|
||||
|
||||
@Test(expectedExceptions = ConflictException.class,
|
||||
expectedExceptionsMessageRegExp = "Environment of workspace '.*' is not running")
|
||||
expectedExceptionsMessageRegExp = "Environment of workspace 'workspaceId' is not running or snapshotting")
|
||||
public void shouldNotSaveMachineIfEnvironmentIsNotRunning() throws Exception {
|
||||
// when
|
||||
runtimes.saveMachine("namespace", "workspaceId", "machineId");
|
||||
|
|
@ -572,6 +581,72 @@ public class WorkspaceRuntimesTest {
|
|||
assertEquals(actualWorkspaces, expectedWorkspaces);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changesStatusFromRunningToSnapshotting() throws Exception {
|
||||
final WorkspaceImpl workspace = createWorkspace();
|
||||
runtimes.start(workspace, workspace.getConfig().getDefaultEnv(), false);
|
||||
|
||||
runtimes.beginSnapshotting(workspace.getId());
|
||||
|
||||
assertEquals(runtimes.get(workspace.getId()).getRuntimeStatus(), WorkspaceStatus.SNAPSHOTTING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changesStatusFromSnapshottingToRunning() throws Exception {
|
||||
final WorkspaceImpl workspace = createWorkspace();
|
||||
runtimes.start(workspace, workspace.getConfig().getDefaultEnv(), false);
|
||||
runtimes.beginSnapshotting(workspace.getId());
|
||||
|
||||
runtimes.finishSnapshotting(workspace.getId());
|
||||
|
||||
assertEquals(runtimes.get(workspace.getId()).getRuntimeStatus(), WorkspaceStatus.RUNNING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNothingWhenWorkspaceDoesNotHaveRuntimeAndFinishSnapshottingIsCalled() throws Exception {
|
||||
runtimes.finishSnapshotting("fake");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNothingWhenWorkspaceStatusIsNotSnapshottingAndFinishSnapshottingIsCalled() throws Exception {
|
||||
final WorkspaceImpl workspace = createWorkspace();
|
||||
runtimes.start(workspace, workspace.getConfig().getDefaultEnv(), false);
|
||||
|
||||
runtimes.finishSnapshotting(workspace.getId());
|
||||
|
||||
assertEquals(runtimes.get(workspace.getId()).getRuntimeStatus(), WorkspaceStatus.RUNNING);
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NotFoundException.class,
|
||||
expectedExceptionsMessageRegExp = "Workspace with id 'non-existing' is not running")
|
||||
public void throwsNotFoundExceptionWhenBeginningSnapshottingForNonExistingWorkspace() throws Exception {
|
||||
runtimes.beginSnapshotting("non-existing");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsConflictExceptionWhenBeginningSnapshottingForNotRunningWorkspace() throws Exception {
|
||||
final WorkspaceImpl workspace = createWorkspace();
|
||||
|
||||
doAnswer(inv -> {
|
||||
// checking exception here
|
||||
try {
|
||||
runtimes.beginSnapshotting(workspace.getId());
|
||||
fail("Expected to get an exception");
|
||||
} catch (ConflictException x) {
|
||||
assertEquals(x.getMessage(), format("Workspace with id '%s' is not in '%s', it's status is '%s'",
|
||||
workspace.getId(),
|
||||
WorkspaceStatus.RUNNING,
|
||||
WorkspaceStatus.STARTING));
|
||||
}
|
||||
return null;
|
||||
}).when(eventService)
|
||||
.publish(DtoFactory.newDto(WorkspaceStatusEvent.class)
|
||||
.withEventType(EventType.STARTING)
|
||||
.withWorkspaceId(workspace.getId()));
|
||||
|
||||
runtimes.start(workspace, workspace.getConfig().getDefaultEnv(), false);
|
||||
}
|
||||
|
||||
private static Instance createMachine(boolean isDev) {
|
||||
return createMachine(createConfig(isDev));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ public class WorkspaceServiceTest {
|
|||
.delete(SECURE_PATH + "/workspace/" + workspace.getId() + "/runtime");
|
||||
|
||||
assertEquals(response.getStatusCode(), 204);
|
||||
verify(wsManager).stopWorkspace(workspace.getId());
|
||||
verify(wsManager).stopWorkspace(workspace.getId(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -36,26 +36,10 @@
|
|||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.inject.extensions</groupId>
|
||||
<artifactId>guice-persist</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
|
|
@ -64,14 +48,6 @@
|
|||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.ws.rs</groupId>
|
||||
<artifactId>javax.ws.rs-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-account</artifactId>
|
||||
|
|
@ -80,22 +56,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-dto</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-machine</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-machine-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-model</artifactId>
|
||||
|
|
@ -104,18 +68,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-ssh</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-ssh-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-user</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-user-shared</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-api-workspace</artifactId>
|
||||
|
|
@ -128,22 +84,10 @@
|
|||
<groupId>org.eclipse.che.core</groupId>
|
||||
<artifactId>che-core-commons-lang</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>eclipselink</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.persistence</groupId>
|
||||
<artifactId>javax.persistence</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.everrest</groupId>
|
||||
<artifactId>everrest-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.everrest</groupId>
|
||||
<artifactId>everrest-websockets</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
|
@ -218,26 +162,4 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>unpack-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
|
||||
<includeArtifactIds>che-core-api-user,
|
||||
che-core-api-machine,
|
||||
che-core-api-ssh</includeArtifactIds>
|
||||
<includeScope>test</includeScope>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import javax.annotation.PreDestroy;
|
|||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -119,6 +120,12 @@ public class LocalSnapshotDaoImpl implements SnapshotDao {
|
|||
snapshots.remove(snapshotId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SnapshotImpl> replaceSnapshots(String workspaceId, String envName, Collection<? extends SnapshotImpl> newSnapshots)
|
||||
throws SnapshotException {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public synchronized void loadSnapshots() {
|
||||
snapshots.putAll(snapshotStorage.loadMap(new TypeToken<Map<String, SnapshotImpl>>() {}));
|
||||
|
|
|
|||
Loading…
Reference in New Issue