Search in sources :

Example 86 with InfrastructureException

use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project devspaces-images by redhat-developer.

the class KubernetesDeployments method delete.

/**
 * Deletes all existing pods and the Deployments that control them.
 *
 * <p>Note that this method will mark Kubernetes pods as interrupted and then will wait until all
 * pods will be killed.
 *
 * @throws InfrastructureException when {@link Thread} is interrupted while command executing
 * @throws InfrastructureException when pods removal timeout is reached
 * @throws InfrastructureException when any other exception occurs
 */
public void delete() throws InfrastructureException {
    try {
        final List<CompletableFuture<Void>> deleteFutures = new ArrayList<>();
        // We first delete all deployments, then clean up any bare Pods.
        List<Deployment> deployments = clientFactory.create(workspaceId).apps().deployments().inNamespace(namespace).withLabel(CHE_WORKSPACE_ID_LABEL, workspaceId).list().getItems();
        for (Deployment deployment : deployments) {
            deleteFutures.add(doDeleteDeployment(deployment.getMetadata().getName()));
        }
        // We have to be careful to not include pods that are controlled by a deployment
        List<Pod> pods = clientFactory.create(workspaceId).pods().inNamespace(namespace).withLabel(CHE_WORKSPACE_ID_LABEL, workspaceId).withoutLabel(CHE_DEPLOYMENT_NAME_LABEL).list().getItems();
        for (Pod pod : pods) {
            List<OwnerReference> ownerReferences = pod.getMetadata().getOwnerReferences();
            if (ownerReferences == null || ownerReferences.isEmpty()) {
                deleteFutures.add(doDeletePod(pod.getMetadata().getName()));
            }
        }
        final CompletableFuture<Void> removed = allOf(deleteFutures.toArray(new CompletableFuture[deleteFutures.size()]));
        try {
            removed.get(POD_REMOVAL_TIMEOUT_MIN, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new InfrastructureException("Interrupted while waiting for pod removal. " + e.getMessage());
        } catch (ExecutionException e) {
            throw new InfrastructureException("Error occurred while waiting for pod removing. " + e.getMessage());
        } catch (TimeoutException ex) {
            throw new InfrastructureException("Pods removal timeout reached " + ex.getMessage());
        }
    } catch (KubernetesClientException e) {
        throw new KubernetesInfrastructureException(e);
    }
}
Also used : Pod(io.fabric8.kubernetes.api.model.Pod) ArrayList(java.util.ArrayList) Deployment(io.fabric8.kubernetes.api.model.apps.Deployment) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) CompletableFuture(java.util.concurrent.CompletableFuture) OwnerReference(io.fabric8.kubernetes.api.model.OwnerReference) ExecutionException(java.util.concurrent.ExecutionException) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException) TimeoutException(java.util.concurrent.TimeoutException) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 87 with InfrastructureException

use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project devspaces-images by redhat-developer.

the class KubernetesDeployments method handleStartingPodStatus.

private void handleStartingPodStatus(CompletableFuture<Void> podRunningFuture, Pod pod) {
    PodStatus status = pod.getStatus();
    String podPhase = status.getPhase();
    if (POD_STATUS_PHASE_RUNNING.equals(podPhase)) {
        // check that all the containers are ready...
        Map<String, String> terminatedContainers = new HashMap<>();
        List<String> restartingContainers = new ArrayList<>();
        for (ContainerStatus cs : status.getContainerStatuses()) {
            ContainerStateTerminated terminated = cs.getState().getTerminated();
            if (terminated == null) {
                ContainerStateWaiting waiting = cs.getState().getWaiting();
                // we've caught the container waiting for a restart after a failure
                if (waiting != null) {
                    terminated = cs.getLastState().getTerminated();
                }
            }
            if (terminated != null) {
                terminatedContainers.put(cs.getName(), format("reason = '%s', exit code = %d, message = '%s'", terminated.getReason(), terminated.getExitCode(), terminated.getMessage()));
            }
            if (cs.getRestartCount() != null && cs.getRestartCount() > 0) {
                restartingContainers.add(cs.getName());
            }
        }
        if (terminatedContainers.isEmpty() && restartingContainers.isEmpty()) {
            podRunningFuture.complete(null);
        } else {
            StringBuilder errorMessage = new StringBuilder();
            if (!restartingContainers.isEmpty()) {
                errorMessage.append("The following containers have restarted during the startup:\n");
                errorMessage.append(String.join(", ", restartingContainers));
            }
            if (!terminatedContainers.isEmpty()) {
                if (errorMessage.length() > 0) {
                    errorMessage.append("\n");
                }
                errorMessage.append("The following containers have terminated:\n");
                errorMessage.append(terminatedContainers.entrySet().stream().map(e -> e.getKey() + ": " + e.getValue()).collect(Collectors.joining("" + "\n")));
            }
            podRunningFuture.completeExceptionally(new InfrastructureException(errorMessage.toString()));
        }
        return;
    }
    if (POD_STATUS_PHASE_SUCCEEDED.equals(podPhase)) {
        podRunningFuture.completeExceptionally(new InfrastructureException("Pod container has been terminated. Container must be configured to use a non-terminating command."));
        return;
    }
    if (POD_STATUS_PHASE_FAILED.equals(podPhase)) {
        String exceptionMessage = "Pod '" + pod.getMetadata().getName() + "' failed to start.";
        String reason = pod.getStatus().getReason();
        if (Strings.isNullOrEmpty(reason)) {
            try {
                String podLog = clientFactory.create(workspaceId).pods().inNamespace(namespace).withName(pod.getMetadata().getName()).getLog();
                exceptionMessage = exceptionMessage.concat(" Pod logs: ").concat(podLog);
            } catch (InfrastructureException | KubernetesClientException e) {
                exceptionMessage = exceptionMessage.concat(" Error occurred while fetching pod logs: " + e.getMessage());
            }
        } else {
            exceptionMessage = exceptionMessage.concat(" Reason: ").concat(reason);
        }
        podRunningFuture.completeExceptionally(new InfrastructureException(exceptionMessage));
        LOG.warn(exceptionMessage);
    }
}
Also used : ContainerStateWaiting(io.fabric8.kubernetes.api.model.ContainerStateWaiting) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) ContainerStateTerminated(io.fabric8.kubernetes.api.model.ContainerStateTerminated) PodStatus(io.fabric8.kubernetes.api.model.PodStatus) ContainerStatus(io.fabric8.kubernetes.api.model.ContainerStatus) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 88 with InfrastructureException

use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project devspaces-images by redhat-developer.

the class KubernetesIngresses method wait.

public Ingress wait(String name, long timeout, TimeUnit timeoutUnit, Predicate<Ingress> predicate) throws InfrastructureException {
    CompletableFuture<Ingress> future = new CompletableFuture<>();
    Watch watch = null;
    try {
        Resource<Ingress> ingressResource = clientFactory.create(workspaceId).network().v1().ingresses().inNamespace(namespace).withName(name);
        watch = ingressResource.watch(new Watcher<>() {

            @Override
            public void eventReceived(Action action, Ingress ingress) {
                if (predicate.test(ingress)) {
                    future.complete(ingress);
                }
            }

            @Override
            public void onClose(WatcherException cause) {
                future.completeExceptionally(new InfrastructureException("Waiting for ingress '" + name + "' was interrupted"));
            }
        });
        Ingress actualIngress = ingressResource.get();
        if (actualIngress == null) {
            throw new InfrastructureException("Specified ingress " + name + " doesn't exist");
        }
        if (predicate.test(actualIngress)) {
            return actualIngress;
        }
        try {
            return future.get(timeout, timeoutUnit);
        } catch (ExecutionException e) {
            throw new InfrastructureException(e.getCause().getMessage(), e);
        } catch (TimeoutException e) {
            throw new InfrastructureException("Waiting for ingress '" + name + "' reached timeout");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new InfrastructureException("Waiting for ingress '" + name + "' was interrupted");
        }
    } catch (KubernetesClientException e) {
        throw new KubernetesInfrastructureException(e);
    } finally {
        if (watch != null) {
            watch.close();
        }
    }
}
Also used : Ingress(io.fabric8.kubernetes.api.model.networking.v1.Ingress) Watcher(io.fabric8.kubernetes.client.Watcher) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) WatcherException(io.fabric8.kubernetes.client.WatcherException) CompletableFuture(java.util.concurrent.CompletableFuture) Watch(io.fabric8.kubernetes.client.Watch) ExecutionException(java.util.concurrent.ExecutionException) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) TimeoutException(java.util.concurrent.TimeoutException) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 89 with InfrastructureException

use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project devspaces-images by redhat-developer.

the class KubernetesNamespace method annotate.

/**
 * Applies given `ensureAnnotations` into given `namespace` and update the `namespace` in the
 * Kubernetes.
 *
 * <p>If we do not have permissions to do so (code=403), this method does not throw any exception.
 *
 * @param namespace namespace to annotate
 * @param ensureAnnotations these annotations should be applied on given `namespace`
 * @throws InfrastructureException if something goes wrong with update, except lack of permissions
 */
protected void annotate(Namespace namespace, Map<String, String> ensureAnnotations) throws InfrastructureException {
    if (ensureAnnotations.isEmpty()) {
        return;
    }
    Map<String, String> currentAnnotations = namespace.getMetadata().getAnnotations();
    Map<String, String> newAnnotations = currentAnnotations != null ? new HashMap<>(currentAnnotations) : new HashMap<>();
    if (newAnnotations.entrySet().containsAll(ensureAnnotations.entrySet())) {
        LOG.debug("Nothing to do, namespace [{}] already has all required annotations.", namespace.getMetadata().getName());
        return;
    }
    try {
        // update the namespace with new annotations
        cheSAClientFactory.create().namespaces().createOrReplace(new NamespaceBuilder(namespace).editMetadata().addToAnnotations(ensureAnnotations).endMetadata().build());
    } catch (KubernetesClientException kce) {
        if (kce.getCode() == 403) {
            LOG.warn("Can't annotate the namespace due to lack of permissions. Grant cluster-wide permissions " + "to `get` and `update` the `namespaces` to the `che` service account " + "(Che operator might have already prepared a cluster role called " + "`che-namespace-editor` for this, depending on its configuration). " + "Alternatively, consider disabling the feature by setting " + "`che.infra.kubernetes.namepsace.annotate` to `false`.");
            return;
        }
        throw new InfrastructureException(kce);
    }
}
Also used : NamespaceBuilder(io.fabric8.kubernetes.api.model.NamespaceBuilder) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) InternalInfrastructureException(org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException) KubernetesClientException(io.fabric8.kubernetes.client.KubernetesClientException)

Example 90 with InfrastructureException

use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project devspaces-images by redhat-developer.

the class KubernetesNamespace method prepare.

/**
 * Prepare namespace for using.
 *
 * <p>Preparing includes creating if needed and waiting for default service account.
 *
 * <p>The method will try to label the namespace with provided `labels`. It does not matter if the
 * namespace already exists or we create new one. If update labels operation fail due to lack of
 * permission, we do not fail completely.
 *
 * <p>The method will try to annotate the namespace with provided `annotations`. It does not
 * matter if the namespace already exists or we create new one. If update annotations operation
 * fail due to lack of permission, we do not fail completely.
 *
 * @param canCreate defines what to do when the namespace is not found. The namespace is created
 *     when {@code true}, otherwise an exception is thrown.
 * @param labels labels that should be set to the namespace
 * @param annotations annotations that should be set to the namespace
 * @throws InfrastructureException if any exception occurs during namespace preparation or if the
 *     namespace doesn't exist and {@code canCreate} is {@code false}.
 */
void prepare(boolean canCreate, Map<String, String> labels, Map<String, String> annotations) throws InfrastructureException {
    KubernetesClient client = cheSAClientFactory.create(workspaceId);
    Namespace namespace = get(name, client);
    if (namespace == null) {
        if (!canCreate) {
            throw new InfrastructureException(format("Creating the namespace '%s' is not allowed, yet it was not found.", name));
        }
        namespace = create(name, client);
    }
    label(namespace, labels);
    annotate(namespace, annotations);
}
Also used : KubernetesClient(io.fabric8.kubernetes.client.KubernetesClient) Namespace(io.fabric8.kubernetes.api.model.Namespace) KubernetesInfrastructureException(org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException) InternalInfrastructureException(org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException) InfrastructureException(org.eclipse.che.api.workspace.server.spi.InfrastructureException)

Aggregations

InfrastructureException (org.eclipse.che.api.workspace.server.spi.InfrastructureException)242 InternalInfrastructureException (org.eclipse.che.api.workspace.server.spi.InternalInfrastructureException)64 Test (org.testng.annotations.Test)56 KubernetesInfrastructureException (org.eclipse.che.workspace.infrastructure.kubernetes.KubernetesInfrastructureException)44 RuntimeIdentity (org.eclipse.che.api.core.model.workspace.runtime.RuntimeIdentity)42 KubernetesClientException (io.fabric8.kubernetes.client.KubernetesClientException)38 CompletableFuture (java.util.concurrent.CompletableFuture)36 ExecutionException (java.util.concurrent.ExecutionException)36 TimeoutException (java.util.concurrent.TimeoutException)32 ServerException (org.eclipse.che.api.core.ServerException)32 Pod (io.fabric8.kubernetes.api.model.Pod)30 Map (java.util.Map)26 ValidationException (org.eclipse.che.api.core.ValidationException)22 Traced (org.eclipse.che.commons.annotation.Traced)20 Container (io.fabric8.kubernetes.api.model.Container)18 List (java.util.List)18 Set (java.util.Set)18 Inject (javax.inject.Inject)18 RuntimeStartInterruptedException (org.eclipse.che.api.workspace.server.spi.RuntimeStartInterruptedException)18 KubernetesEnvironment (org.eclipse.che.workspace.infrastructure.kubernetes.environment.KubernetesEnvironment)18