Skip to content

Commit

Permalink
fix: dont 'fatal IDE error' when cluster is not reachable (redhat-dev…
Browse files Browse the repository at this point in the history
…eloper#621)

Signed-off-by: Andre Dietisheim <[email protected]>
  • Loading branch information
adietish committed Nov 24, 2023
1 parent f3d41b1 commit 5ed41d7
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ protected void tearDown() throws Exception {

protected void createProject(String project) throws IOException, ExecutionException, InterruptedException {
odo.createProject(project);
// need to refresh kubernetes client with the correct namespace
//resetOdo();
odo = ToolFactory.getInstance().createOdo(getProject()).get();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import com.redhat.devtools.intellij.common.utils.ConfigWatcher;
import com.redhat.devtools.intellij.common.utils.ExecHelper;
import io.fabric8.kubernetes.api.model.Config;
import org.jboss.tools.intellij.openshift.ui.SwingUtils;
import org.jboss.tools.intellij.openshift.utils.ProjectUtils;
import org.jboss.tools.intellij.openshift.utils.ToolFactory;
import org.jboss.tools.intellij.openshift.utils.helm.Helm;
Expand Down Expand Up @@ -183,22 +182,24 @@ private void addContext(Odo odo, VirtualFile modulePathFile) {
);
} catch (IOException ex) {
//filter out some common exception when no logged or no authorizations
if (doNotLogFromMessage(ex.getMessage())) {
LOGGER.error(ex.getLocalizedMessage(), ex);
if (shouldLogMessage(ex.getMessage())) {
LOGGER.warn(ex.getLocalizedMessage(), ex);
}
}
}
}

private static boolean doNotLogFromMessage(String message) {
private static boolean shouldLogMessage(String message) {
return !(message.contains("Unauthorized") ||
message.contains("unable to access the cluster: servicebindings.binding.operators.coreos.com") ||
message.contains("the server has asked for the client to provide credentials") ||
message.contains("connect: no route to host"));
}

public void addContext(String modulePath) {
addContext(getOdo().getNow(null), LocalFileSystem.getInstance().refreshAndFindFileByPath(modulePath));
addContext(
getOdo().getNow(null),
LocalFileSystem.getInstance().refreshAndFindFileByPath(modulePath));
}

private void removeContextFromSettings(String modulePath) {
Expand Down Expand Up @@ -233,10 +234,7 @@ public void onUpdate(ConfigWatcher source, Config config) {

public synchronized void refresh() {
resetOdo();
CompletableFuture
.runAsync(() ->
getOdo((odo, err) -> structure.fireModified(ApplicationsRootNode.this)),
SwingUtils.EXECUTOR_BACKGROUND);
getOdo((odo, err) -> structure.fireModified(ApplicationsRootNode.this));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.redhat.devtools.intellij.common.tree.MutableModelSupport;
import io.fabric8.kubernetes.client.KubernetesClientException;
import org.jboss.tools.intellij.openshift.Constants;
import org.jboss.tools.intellij.openshift.utils.ExceptionUtils;
import org.jboss.tools.intellij.openshift.utils.helm.Helm;
import org.jboss.tools.intellij.openshift.utils.odo.Odo;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -68,23 +69,24 @@ public Object getApplicationsRoot() {
@NotNull
@Override
public Object @NotNull [] getChildElements(@NotNull Object element) {
Odo odo = root.getOdo().getNow(null);
if (odo != null) {
try {
if (element == this) {
return new Object[]{getApplicationsRoot(), registries};
return new Object[]{root, registries};
} else if (element instanceof ApplicationsRootNode) {
return getCurrentNamespace((ApplicationsRootNode) element, odo);
return getCurrentNamespace((ApplicationsRootNode) element);
} else if (element instanceof NamespaceNode) {
return createNamespaceChildren((NamespaceNode) element, odo);
return createNamespaceChildren((NamespaceNode) element);
} else if (element instanceof ComponentNode) {
return createComponentChildren((ComponentNode) element, odo);
return createComponentChildren((ComponentNode) element);
} else if (element instanceof DevfileRegistriesNode) {
return getRegistries(root, odo);
return getRegistries(root);
} else if (element instanceof DevfileRegistryNode) {
return getRegistryComponentTypes((DevfileRegistryNode) element, odo);
return getRegistryComponentTypes((DevfileRegistryNode) element);
} else if (element instanceof DevfileRegistryComponentTypeNode) {
return getRegistryComponentTypeStarters((DevfileRegistryComponentTypeNode) element, odo);
return getRegistryComponentTypeStarters((DevfileRegistryComponentTypeNode) element);
}
} catch (Exception e) {
return new Object[]{new MessageNode<>(root, root, ExceptionUtils.getMessage(e))};
}
return new Object[0];
}
Expand All @@ -103,31 +105,38 @@ public Object getApplicationsRoot() {
}

@NotNull
private Object[] createComponentChildren(ComponentNode element, @NotNull Odo odo) {
List<URLNode> urls = getURLs(element);
List<BindingNode> bindings = getBindings(element, odo);
private Object[] createComponentChildren(ComponentNode componentNode) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return new Object[] { new MessageNode<>(root, componentNode, "Could not get components") };
}
List<URLNode> urls = getURLs(componentNode);
List<BindingNode> bindings = getBindings(componentNode, odo);
return Stream.of(urls, bindings)
.filter(item -> !item.isEmpty())
.flatMap(Collection::stream)
.toArray();
}

@NotNull
private Object[] createNamespaceChildren(@NotNull NamespaceNode namespaceNode, @NotNull Odo odo) {
private Object[] createNamespaceChildren(@NotNull NamespaceNode namespaceNode) {
List<Object> nodes = new ArrayList<>();

nodes.addAll(getComponents(namespaceNode, odo));
nodes.addAll(getServices(namespaceNode, odo));
nodes.addAll(getComponents(namespaceNode));
nodes.addAll(getServices(namespaceNode));

Helm helm = namespaceNode.getRoot().getHelm(true).getNow(null);
nodes.addAll(getHelmReleases(namespaceNode, helm));
nodes.addAll(getHelmReleases(namespaceNode));

return nodes.toArray();
}

private Object[] getCurrentNamespace(ApplicationsRootNode element, @NotNull Odo odo) {
private Object[] getCurrentNamespace(ApplicationsRootNode element) {
List<Object> namespaces = new ArrayList<>();
try {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return new Object[] { new MessageNode<>(element, element, "Could not get current namespace") };
}
String ns = odo.getCurrentNamespace();
if (ns != null) {
namespaces.add(new NamespaceNode(element, ns));
Expand All @@ -142,58 +151,61 @@ private Object[] getCurrentNamespace(ApplicationsRootNode element, @NotNull Odo
return namespaces.toArray();
}

private static MessageNode<?> createErrorNode(ApplicationsRootNode element, Exception e) {
private MessageNode<?> createErrorNode(ParentableNode<?> parent, Exception e) {
if (e instanceof KubernetesClientException) {
KubernetesClientException kce = (KubernetesClientException) e;
if (kce.getCode() == 401) {
return new MessageNode<>(element, element, LOGIN);
return new MessageNode<>(root, parent, LOGIN);
} else if (kce.getCause() instanceof NoRouteToHostException) {
return new MessageNode<>(element, element, kce.getCause().getMessage());
return new MessageNode<>(root, parent, kce.getCause().getMessage());
} else if (kce.getCause().getMessage().contains(Constants.DEFAULT_KUBE_URL)) {
return new MessageNode<>(element, element, LOGIN);
return new MessageNode<>(root, parent, LOGIN);
}
}
return new MessageNode<>(element, element, "Unable to get namespaces: " + e.getMessage());
return new MessageNode<>(root, parent, "Could not get namespaces: " + ExceptionUtils.getMessage(e));
}

private List<BaseNode<?>> getComponents(NamespaceNode element, Odo odo) {
private List<BaseNode<?>> getComponents(NamespaceNode namespaceNode) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return Collections.emptyList();
return List.of(new MessageNode<>(root, namespaceNode, "Could not get components"));
}
List<BaseNode<?>> components = new ArrayList<>();
components.addAll(load(
() -> odo.getComponents(element.getName()).stream()
() -> odo.getComponents(namespaceNode.getName()).stream()
.filter(component -> !component.isManagedByHelm()) // dont display helm components
.map(component -> new ComponentNode(element, component))
.map(component -> new ComponentNode(namespaceNode, component))
.collect(Collectors.toList()),
element,
"Failed to load components"));
namespaceNode,
"Could not get components"));
if (components.isEmpty()) {
components.add(new CreateComponentLinkNode(element.getRoot(), element));
components.add(new CreateComponentLinkNode(namespaceNode.getRoot(), namespaceNode));
}
return components;
}

private List<BaseNode<?>> getServices(NamespaceNode element, Odo odo) {
private List<BaseNode<?>> getServices(NamespaceNode namespaceNode) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return Collections.emptyList();
return List.of(new MessageNode<>(root, namespaceNode, "Could not get application services"));
}
return load(() -> odo.getServices(element.getName()).stream()
.map(si -> new ServiceNode(element, si))
return load(() -> odo.getServices(namespaceNode.getName()).stream()
.map(si -> new ServiceNode(namespaceNode, si))
.collect(Collectors.toList()),
element,
"Failed to load application services");
namespaceNode,
"Could not get application services");
}

private List<BaseNode<?>> getHelmReleases(NamespaceNode element, Helm helm) {
private List<BaseNode<?>> getHelmReleases(NamespaceNode namespaceNode) {
Helm helm = namespaceNode.getRoot().getHelm(true).getNow(null);
if (helm == null) {
return Collections.emptyList();
return List.of(new MessageNode<>(root, namespaceNode, "Could not get chart releases"));
}
return load(() -> helm.list().stream()
.map(release -> new ChartReleaseNode(element, release))
.map(release -> new ChartReleaseNode(namespaceNode, release))
.collect(Collectors.toList()),
element,
"Failed to load chart releases");
namespaceNode,
"Could not get chart releases");
}

private List<BaseNode<?>> load(Callable<List<BaseNode<?>>> callable, NamespaceNode namespace, String errorMessage) {
Expand Down Expand Up @@ -234,7 +246,11 @@ private List<BindingNode> getBindings(ComponentNode element, @NotNull Odo odo) {
return results;
}

private Object[] getRegistries(ApplicationsRootNode root, @NotNull Odo odo) {
private Object[] getRegistries(ApplicationsRootNode root) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return new Object[] { new MessageNode<>(root, root, "Could not get registries") };
}
List<DevfileRegistryNode> result = new ArrayList<>();
try {
odo.listDevfileRegistries().forEach(registry ->
Expand All @@ -246,23 +262,31 @@ private Object[] getRegistries(ApplicationsRootNode root, @NotNull Odo odo) {
return result.toArray();
}

private Object[] getRegistryComponentTypes(DevfileRegistryNode element, @NotNull Odo odo) {
private Object[] getRegistryComponentTypes(DevfileRegistryNode registryNode) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return new Object[] { new MessageNode<>(root, registryNode, "Could not get registry component types") };
}
List<DevfileRegistryComponentTypeNode> result = new ArrayList<>();
try {
odo.getComponentTypes(element.getName()).forEach(type ->
result.add(new DevfileRegistryComponentTypeNode(root, element, type)));
odo.getComponentTypes(registryNode.getName()).forEach(type ->
result.add(new DevfileRegistryComponentTypeNode(root, registryNode, type)));
} catch (IOException e) {
LOGGER.error(e.getLocalizedMessage(), e);
}
return result.toArray();
}

private Object[] getRegistryComponentTypeStarters(DevfileRegistryComponentTypeNode element, @NotNull Odo odo) {
private Object[] getRegistryComponentTypeStarters(DevfileRegistryComponentTypeNode componentTypeNode) {
Odo odo = root.getOdo().getNow(null);
if (odo == null) {
return new Object[] { new MessageNode<>(root, componentTypeNode, "Could not get registry component starters") };
}
List<DevfileRegistryComponentTypeStarterNode> result = new ArrayList<>();
try {
odo.getComponentTypeInfo(element.getName(),
element.getComponentType().getDevfileRegistry().getName()).getStarters().forEach(starter ->
result.add(new DevfileRegistryComponentTypeStarterNode(element.getRoot(), element, starter)));
odo.getComponentTypeInfo(componentTypeNode.getName(),
componentTypeNode.getComponentType().getDevfileRegistry().getName()).getStarters().forEach(starter ->
result.add(new DevfileRegistryComponentTypeStarterNode(componentTypeNode.getRoot(), componentTypeNode, starter)));
} catch (IOException e) {
LOGGER.error(e.getLocalizedMessage(), e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2021 Red Hat, Inc.
* Copyright (c) 2023 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*******************************************************************************
* Copyright (c) 2023 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.intellij.openshift.utils;

import java.util.concurrent.CompletionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExceptionUtils {

private static final Pattern PATTERN_COMPLETION_EXCEPTION_MESSAGE = Pattern.compile(
"\"message\": \"([\\s\\S]+?)\"\\n", Pattern.MULTILINE);

private ExceptionUtils() {}

public static String getMessage(Exception e) {
if (e instanceof CompletionException) {
return getMessage((CompletionException) e);
} else {
return e.getMessage();
}
}

public static String getMessage(CompletionException e) {
if (e.getMessage() == null) {
return null;
}
Matcher matcher = PATTERN_COMPLETION_EXCEPTION_MESSAGE.matcher(e.getMessage());
if (!matcher.find()) {
return e.getMessage();
}
return matcher.group(1);
}
}

0 comments on commit 5ed41d7

Please sign in to comment.