use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project che-server by eclipse-che.
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);
}
}
use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project che-server by eclipse-che.
the class KubernetesPersistentVolumeClaims method waitBound.
/**
* Waits until persistent volume claim state is bound. If used k8s Storage Class has
* 'volumeBindingMode: WaitForFirstConsumer', we don't wait to avoid deadlock.
*
* @param name name of persistent volume claim that should be watched
* @param timeoutMillis waiting timeout in milliseconds
* @return persistent volume claim that is bound or in waiting for consumer state
* @throws InfrastructureException when specified timeout is reached
* @throws InfrastructureException when {@link Thread} is interrupted while waiting
* @throws InfrastructureException when any other exception occurs
*/
public PersistentVolumeClaim waitBound(String name, long timeoutMillis) throws InfrastructureException {
try {
Resource<PersistentVolumeClaim> pvcResource = clientFactory.create(workspaceId).persistentVolumeClaims().inNamespace(namespace).withName(name);
PersistentVolumeClaim actualPvc = pvcResource.get();
if (actualPvc.getStatus().getPhase().equals(PVC_BOUND_PHASE)) {
return actualPvc;
}
CompletableFuture<PersistentVolumeClaim> future = new CompletableFuture<>();
// any of these watchers can finish the operation resolving the future
try (Watch boundWatcher = pvcIsBoundWatcher(future, pvcResource);
Watch waitingWatcher = pvcIsWaitingForConsumerWatcher(future, actualPvc)) {
return future.get(timeoutMillis, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
// should take a look.
throw new InternalInfrastructureException(e.getCause().getMessage(), e);
} catch (TimeoutException e) {
// issues that admin should take a look.
throw new InternalInfrastructureException("Waiting for persistent volume claim '" + name + "' reached timeout");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new InfrastructureException("Waiting for persistent volume claim '" + name + "' was interrupted");
}
} catch (KubernetesClientException e) {
throw new KubernetesInfrastructureException(e);
}
}
use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project che-server by eclipse-che.
the class KubernetesRecipeParser method parse.
/**
* Parses Kubernetes objects from recipe content.
*
* @param recipeContent recipe content that should be parsed
* @return parsed objects
* @throws IllegalArgumentException if recipe content is null
* @throws ValidationException if recipe content has broken format
* @throws ValidationException if recipe content has unrecognized objects
* @throws InfrastructureException when exception occurred during kubernetes client creation
*/
public List<HasMetadata> parse(String recipeContent) throws ValidationException, InfrastructureException {
checkNotNull(recipeContent, "Recipe content type must not be null");
try {
// Behavior:
// - If `content` is a single object like Deployment, load().get() will get the object in that
// list
// - If `content` is a Kubernetes List, load().get() will get the objects in that list
// - If `content` is an OpenShift template, load().get() will get the objects in the template
// with parameters substituted (e.g. with default values).
List<HasMetadata> parsed = clientFactory.create().load(new ByteArrayInputStream(recipeContent.getBytes())).get();
// needed because Che master namespace is set by K8s API during list loading
parsed.stream().filter(o -> o.getMetadata() != null).forEach(o -> o.getMetadata().setNamespace(null));
return parsed;
} catch (KubernetesClientException e) {
// KubernetesClient wraps the error when a JsonMappingException occurs so we need the cause
String message = e.getCause() == null ? e.getMessage() : e.getCause().getMessage();
if (message.contains("\n")) {
// Clean up message if it comes from JsonMappingException. Format is e.g.
// `No resource type found for:v1#Route1\n at [...]`
message = message.split("\\n", 2)[0];
}
throw new ValidationException(format("Could not parse Kubernetes recipe: %s", message));
}
}
use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project che-server by eclipse-che.
the class UserProfileConfigurator method prepareProfileSecret.
private Secret prepareProfileSecret(NamespaceResolutionContext namespaceResolutionContext) throws InfrastructureException {
User user;
try {
user = userManager.getById(namespaceResolutionContext.getUserId());
} catch (NotFoundException | ServerException e) {
throw new InfrastructureException(String.format("Could not find current user with id:%s.", namespaceResolutionContext.getUserId()), e);
}
Base64.Encoder enc = Base64.getEncoder();
final Map<String, String> userProfileData = new HashMap<>();
userProfileData.put("id", enc.encodeToString(user.getId().getBytes()));
userProfileData.put("name", enc.encodeToString(user.getName().getBytes()));
userProfileData.put("email", enc.encodeToString(user.getEmail().getBytes()));
return new SecretBuilder().addToData(userProfileData).withNewMetadata().withName(USER_PROFILE_SECRET_NAME).addToLabels(DEV_WORKSPACE_MOUNT_LABEL, "true").addToLabels(DEV_WORKSPACE_WATCH_SECRET_LABEL, "true").addToAnnotations(DEV_WORKSPACE_MOUNT_AS_ANNOTATION, "file").addToAnnotations(DEV_WORKSPACE_MOUNT_PATH_ANNOTATION, USER_PROFILE_SECRET_MOUNT_PATH).endMetadata().build();
}
use of org.eclipse.che.api.workspace.server.spi.InfrastructureException in project che-server by eclipse-che.
the class KubernetesServerExposer method exposeSecureServers.
private void exposeSecureServers(Map<String, ServerConfig> securedServers, Map<String, ServicePort> securedPorts) throws InfrastructureException {
if (securedPorts.isEmpty()) {
return;
}
Optional<Service> secureService = secureServerExposer.createService(securedPorts.values(), pod, machineName, securedServers);
String secureServiceName = secureService.map(s -> {
String n = s.getMetadata().getName();
k8sEnv.getServices().put(n, s);
return n;
}).orElse(null);
for (ServicePort servicePort : securedPorts.values()) {
// expose service port related secure servers if exist
Map<String, ServerConfig> matchedSecureServers = match(securedServers, servicePort);
if (!matchedSecureServers.isEmpty()) {
onEachExposableServerSet(matchedSecureServers, (serverId, srvrs) -> {
secureServerExposer.expose(k8sEnv, pod, machineName, secureServiceName, serverId, servicePort, srvrs);
});
}
}
}
Aggregations