use of org.eclipse.che.api.core.ValidationException in project che-server by eclipse-che.
the class KubernetesEnvironmentFactoryTest method exceptionOnRecipeLoadError.
@Test(expectedExceptions = ValidationException.class)
public void exceptionOnRecipeLoadError() throws Exception {
when(k8sRecipeParser.parse(any(InternalRecipe.class))).thenThrow(new ValidationException("Could not parse recipe"));
k8sEnvFactory.doCreate(internalRecipe, emptyMap(), emptyList());
}
use of org.eclipse.che.api.core.ValidationException in project che-server by eclipse-che.
the class PodMergerTest method shouldBeAbleToMergeTerminationGracePeriodS.
@Test(dataProvider = "terminationGracePeriodProvider")
public void shouldBeAbleToMergeTerminationGracePeriodS(List<Long> terminationGracePeriods, Long expectedResultLong) throws ValidationException {
List<PodData> podData = terminationGracePeriods.stream().map(p -> new PodData(new PodSpecBuilder().withTerminationGracePeriodSeconds(p).build(), new ObjectMetaBuilder().build())).collect(Collectors.toList());
// when
Deployment merged = podMerger.merge(podData);
// then
PodTemplateSpec podTemplate = merged.getSpec().getTemplate();
assertEquals(podTemplate.getSpec().getTerminationGracePeriodSeconds(), expectedResultLong);
}
use of org.eclipse.che.api.core.ValidationException in project che-server by eclipse-che.
the class KubernetesNamespaceFactory method checkIfNamespaceIsAllowed.
/**
* Checks if the current user is able to use the specified namespace for their new workspaces.
*
* @param namespaceName namespace name to check
* @throws ValidationException if the specified namespace is not permitted for the current user
*/
public void checkIfNamespaceIsAllowed(String namespaceName) throws ValidationException {
NamespaceResolutionContext context = new NamespaceResolutionContext(EnvironmentContext.getCurrent().getSubject());
final String defaultNamespace = findStoredNamespace(context).orElse(evalPlaceholders(defaultNamespaceName, context));
if (!namespaceName.equals(defaultNamespace)) {
try {
List<KubernetesNamespaceMeta> labeledNamespaces = findPreparedNamespaces(context);
if (labeledNamespaces.stream().noneMatch(n -> n.getName().equals(namespaceName))) {
throw new ValidationException(format("User defined namespaces are not allowed. Only the default namespace '%s' is available.", defaultNamespace));
}
} catch (InfrastructureException e) {
throw new ValidationException("Some infrastructure failure caused failed validation.", e);
}
}
}
use of org.eclipse.che.api.core.ValidationException in project che-server by eclipse-che.
the class PodMerger method merge.
/**
* Creates a new deployments that contains all pods from the specified pods data lists.
*
* <p>If multiple pods have labels, annotations, additionalProperties with the same key then
* override will happen and result pod template will have only the last value. You may need to
* reconfigure objects that rely on these value, like selector field in Service. You can use all
* of pod template labels for reconfiguring or single {@link #DEFAULT_DEPLOYMENT_NAME} label that
* contains deployment name;
*
* @param podsData the pods data to be merged
* @return a new Deployment that have pod template that is result of merging the specified lists
* @throws ValidationException if pods can not be merged because of critical names collisions like
* volumes names
*/
public Deployment merge(List<PodData> podsData) throws ValidationException {
Deployment baseDeployment = createEmptyDeployment(DEFAULT_DEPLOYMENT_NAME);
PodTemplateSpec basePodTemplate = baseDeployment.getSpec().getTemplate();
ObjectMeta basePodMeta = basePodTemplate.getMetadata();
PodSpec baseSpec = basePodTemplate.getSpec();
Set<String> containerNames = new HashSet<>();
Set<String> initContainerNames = new HashSet<>();
Set<String> volumes = new HashSet<>();
Set<String> pullSecrets = new HashSet<>();
for (PodData podData : podsData) {
// if there are entries with such keys then values will be overridden
ObjectMeta podMeta = podData.getMetadata();
putLabels(basePodMeta, podMeta.getLabels());
putAnnotations(basePodMeta, podMeta.getAnnotations());
basePodMeta.getAdditionalProperties().putAll(podMeta.getAdditionalProperties());
for (Container container : podData.getSpec().getContainers()) {
String containerName = container.getName();
// generate container name to avoid collisions
while (!containerNames.add(container.getName())) {
containerName = NameGenerator.generate(container.getName(), 4);
container.setName(containerName);
}
// store original recipe machine name
Names.putMachineName(basePodMeta, containerName, Names.machineName(podMeta, container));
baseSpec.getContainers().add(container);
}
for (Container initContainer : podData.getSpec().getInitContainers()) {
// generate container name to avoid collisions
while (!initContainerNames.add(initContainer.getName())) {
initContainer.setName(NameGenerator.generate(initContainer.getName(), 4));
}
// store original recipe machine name
Names.putMachineName(basePodMeta, initContainer.getName(), Names.machineName(podMeta, initContainer));
baseSpec.getInitContainers().add(initContainer);
}
for (Volume volume : podData.getSpec().getVolumes()) {
if (!volumes.add(volume.getName())) {
if (volume.getName().equals(PROJECTS_VOLUME_NAME)) {
// project volume already added, can be skipped
continue;
}
throw new ValidationException(format("Pods have to have volumes with unique names but there are multiple `%s` volumes", volume.getName()));
}
baseSpec.getVolumes().add(volume);
}
for (LocalObjectReference pullSecret : podData.getSpec().getImagePullSecrets()) {
if (pullSecrets.add(pullSecret.getName())) {
// add pull secret only if it is not present yet
baseSpec.getImagePullSecrets().add(pullSecret);
}
}
if (podData.getSpec().getTerminationGracePeriodSeconds() != null) {
if (baseSpec.getTerminationGracePeriodSeconds() != null) {
baseSpec.setTerminationGracePeriodSeconds(Long.max(baseSpec.getTerminationGracePeriodSeconds(), podData.getSpec().getTerminationGracePeriodSeconds()));
} else {
baseSpec.setTerminationGracePeriodSeconds(podData.getSpec().getTerminationGracePeriodSeconds());
}
}
baseSpec.setSecurityContext(mergeSecurityContexts(baseSpec.getSecurityContext(), podData.getSpec().getSecurityContext()));
baseSpec.setServiceAccount(mergeServiceAccount(baseSpec.getServiceAccount(), podData.getSpec().getServiceAccount()));
baseSpec.setServiceAccountName(mergeServiceAccountName(baseSpec.getServiceAccountName(), podData.getSpec().getServiceAccountName()));
baseSpec.setNodeSelector(mergeNodeSelector(baseSpec.getNodeSelector(), podData.getSpec().getNodeSelector()));
// if there are entries with such keys then values will be overridden
baseSpec.getAdditionalProperties().putAll(podData.getSpec().getAdditionalProperties());
// add tolerations to baseSpec if any
for (Toleration toleration : podData.getSpec().getTolerations()) {
if (!baseSpec.getTolerations().contains(toleration)) {
baseSpec.getTolerations().add(toleration);
}
}
}
Map<String, String> matchLabels = new HashMap<>();
matchLabels.put(DEPLOYMENT_NAME_LABEL, baseDeployment.getMetadata().getName());
putLabels(basePodMeta, matchLabels);
baseDeployment.getSpec().getSelector().setMatchLabels(matchLabels);
return baseDeployment;
}
use of org.eclipse.che.api.core.ValidationException in project che-server by eclipse-che.
the class WorkspaceRuntimes method startAsync.
/**
* Starts all machines from specified workspace environment, creates workspace runtime instance
* based on that environment.
*
* <p>During the start of the workspace its runtime is visible with {@link
* WorkspaceStatus#STARTING} status.
*
* @param workspace workspace which environment should be started
* @param envName optional environment name to run
* @param options whether machines should be recovered(true) or not(false)
* @return completable future of start execution.
* @throws ConflictException when workspace is already running
* @throws ConflictException when start is interrupted
* @throws NotFoundException when any not found exception occurs during environment start
* @throws ServerException other error occurs during environment start
* @see WorkspaceStatus#STARTING
* @see WorkspaceStatus#RUNNING
*/
@Traced
public CompletableFuture<Void> startAsync(WorkspaceImpl workspace, @Nullable String envName, Map<String, String> options) throws ConflictException, NotFoundException, ServerException {
TracingTags.WORKSPACE_ID.set(workspace.getId());
final String workspaceId = workspace.getId();
if (isStartRefused.get()) {
throw new ConflictException(format("Start of the workspace '%s' is rejected by the system, " + "no more workspaces are allowed to start", workspace.getName()));
}
WorkspaceConfigImpl config = workspace.getConfig();
if (config == null) {
config = devfileConverter.convert(workspace.getDevfile());
}
if (envName == null) {
envName = config.getDefaultEnv();
}
String infraNamespace = workspace.getAttributes().get(WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE);
if (isNullOrEmpty(infraNamespace)) {
throw new ServerException(String.format("Workspace does not have infrastructure namespace " + "specified. Please set value of '%s' workspace attribute.", WORKSPACE_INFRASTRUCTURE_NAMESPACE_ATTRIBUTE));
}
final RuntimeIdentity runtimeId = new RuntimeIdentityImpl(workspaceId, envName, EnvironmentContext.getCurrent().getSubject().getUserId(), infraNamespace);
try {
InternalEnvironment internalEnv = createInternalEnvironment(config.getEnvironments().get(envName), config.getAttributes(), config.getCommands(), config.getDevfile());
RuntimeContext runtimeContext = infrastructure.prepare(runtimeId, internalEnv);
InternalRuntime runtime = runtimeContext.getRuntime();
try (Unlocker ignored = lockService.writeLock(workspaceId)) {
final WorkspaceStatus existingStatus = statuses.putIfAbsent(workspaceId, STARTING);
if (existingStatus != null) {
throw new ConflictException(format("Could not start workspace '%s' because its state is '%s'", workspaceId, existingStatus));
}
setRuntimesId(workspaceId);
runtimes.put(workspaceId, runtime);
}
LOG.info("Starting workspace '{}/{}' with id '{}' by user '{}'", workspace.getNamespace(), workspace.getName(), workspace.getId(), sessionUserNameOr("undefined"));
publishWorkspaceStatusEvent(workspaceId, STARTING, STOPPED, null, true, options);
return CompletableFuture.runAsync(ThreadLocalPropagateContext.wrap(new StartRuntimeTask(workspace, options, runtime)), sharedPool.getExecutor());
} catch (ValidationException e) {
LOG.error(e.getLocalizedMessage(), e);
throw new ConflictException(e.getLocalizedMessage());
} catch (InfrastructureException e) {
LOG.error(e.getLocalizedMessage(), e);
throw new ServerException(e.getLocalizedMessage(), e);
}
}
Aggregations