Search in sources :

Example 26 with ValidationException

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());
}
Also used : ValidationException(org.eclipse.che.api.core.ValidationException) InternalRecipe(org.eclipse.che.api.workspace.server.spi.environment.InternalRecipe) Test(org.testng.annotations.Test)

Example 27 with ValidationException

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);
}
Also used : PodSecurityContext(io.fabric8.kubernetes.api.model.PodSecurityContext) Arrays(java.util.Arrays) Container(io.fabric8.kubernetes.api.model.Container) DataProvider(org.testng.annotations.DataProvider) Assert.assertEquals(org.testng.Assert.assertEquals) Test(org.testng.annotations.Test) PodTemplateSpec(io.fabric8.kubernetes.api.model.PodTemplateSpec) LocalObjectReference(io.fabric8.kubernetes.api.model.LocalObjectReference) ValidationException(org.eclipse.che.api.core.ValidationException) HashSet(java.util.HashSet) PodSpecBuilder(io.fabric8.kubernetes.api.model.PodSpecBuilder) PodSpec(io.fabric8.kubernetes.api.model.PodSpec) Map(java.util.Map) ContainerBuilder(io.fabric8.kubernetes.api.model.ContainerBuilder) ObjectMetaBuilder(io.fabric8.kubernetes.api.model.ObjectMetaBuilder) Assert.assertNotEquals(org.testng.Assert.assertNotEquals) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeMethod(org.testng.annotations.BeforeMethod) Toleration(io.fabric8.kubernetes.api.model.Toleration) VolumeBuilder(io.fabric8.kubernetes.api.model.VolumeBuilder) Collectors(java.util.stream.Collectors) LocalObjectReferenceBuilder(io.fabric8.kubernetes.api.model.LocalObjectReferenceBuilder) List(java.util.List) PodSecurityContextBuilder(io.fabric8.kubernetes.api.model.PodSecurityContextBuilder) PROJECTS_VOLUME_NAME(org.eclipse.che.api.workspace.shared.Constants.PROJECTS_VOLUME_NAME) ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) PodData(org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData) Assert.assertTrue(org.testng.Assert.assertTrue) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) Collections(java.util.Collections) PodSpecBuilder(io.fabric8.kubernetes.api.model.PodSpecBuilder) PodData(org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData) PodTemplateSpec(io.fabric8.kubernetes.api.model.PodTemplateSpec) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) ObjectMetaBuilder(io.fabric8.kubernetes.api.model.ObjectMetaBuilder) Test(org.testng.annotations.Test)

Example 28 with ValidationException

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);
        }
    }
}
Also used : NamespaceResolutionContext(org.eclipse.che.api.workspace.server.spi.NamespaceResolutionContext) ValidationException(org.eclipse.che.api.core.ValidationException) KubernetesNamespaceMeta(org.eclipse.che.workspace.infrastructure.kubernetes.api.shared.KubernetesNamespaceMeta) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException)

Example 29 with ValidationException

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;
}
Also used : ObjectMeta(io.fabric8.kubernetes.api.model.ObjectMeta) ValidationException(org.eclipse.che.api.core.ValidationException) PodSpec(io.fabric8.kubernetes.api.model.PodSpec) HashMap(java.util.HashMap) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) PodData(org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData) PodTemplateSpec(io.fabric8.kubernetes.api.model.PodTemplateSpec) Container(io.fabric8.kubernetes.api.model.Container) Volume(io.fabric8.kubernetes.api.model.Volume) LocalObjectReference(io.fabric8.kubernetes.api.model.LocalObjectReference) Toleration(io.fabric8.kubernetes.api.model.Toleration) HashSet(java.util.HashSet)

Example 30 with ValidationException

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);
    }
}
Also used : ServerException(org.eclipse.che.api.core.ServerException) ValidationException(org.eclipse.che.api.core.ValidationException) ConflictException(org.eclipse.che.api.core.ConflictException) InternalRuntime(org.eclipse.che.api.workspace.server.spi.InternalRuntime) RuntimeIdentity(org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity) Unlocker(org.eclipse.che.commons.lang.concurrent.Unlocker) InternalEnvironment(org.eclipse.che.api.workspace.server.spi.environment.InternalEnvironment) WorkspaceConfigImpl(org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl) WorkspaceStatus(org.eclipse.che.api.core.model.workspace.WorkspaceStatus) RuntimeContext(org.eclipse.che.api.workspace.server.spi.RuntimeContext) RuntimeIdentityImpl(org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException) InternalInfrastructureException(org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException) Traced(org.eclipse.che.commons.annotation.Traced)

Aggregations

ValidationException (org.eclipse.che.api.core.ValidationException)42 Test (org.testng.annotations.Test)16 InfrastructureException (org.eclipse.che.api.workspace.server.spi.InfrastructureException)12 Deployment (io.fabric8.kubernetes.api.model.apps.Deployment)10 WorkspaceImpl (org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl)10 PodData (org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment.PodData)8 ConfigMap (io.fabric8.kubernetes.api.model.ConfigMap)6 HasMetadata (io.fabric8.kubernetes.api.model.HasMetadata)6 ObjectMeta (io.fabric8.kubernetes.api.model.ObjectMeta)6 Pod (io.fabric8.kubernetes.api.model.Pod)6 PodTemplateSpec (io.fabric8.kubernetes.api.model.PodTemplateSpec)6 HashMap (java.util.HashMap)6 Map (java.util.Map)6 ConflictException (org.eclipse.che.api.core.ConflictException)6 ServerException (org.eclipse.che.api.core.ServerException)6 WorkspaceStatus (org.eclipse.che.api.core.model.workspace.WorkspaceStatus)6 RuntimeIdentityImpl (org.eclipse.che.api.workspace.server.model.impl.RuntimeIdentityImpl)6 WorkspaceConfigImpl (org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl)6 InternalInfrastructureException (org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException)6 Traced (org.eclipse.che.commons.annotation.Traced)6