Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: dont refresh tree if binary is not downloaded (#802) #809

Merged
merged 1 commit into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ dependencies {
'io.fabric8:openshift-client:6.12.0',
'org.apache.commons:commons-compress:1.26.1',
'org.apache.commons:commons-exec:1.4.0',
'com.redhat.devtools.intellij:intellij-common:1.9.5',
'com.redhat.devtools.intellij:intellij-common:1.9.6-SNAPSHOT',
'io.jsonwebtoken:jjwt-impl:0.12.5',
'io.jsonwebtoken:jjwt-jackson:0.12.5',
'org.keycloak:keycloak-installed-adapter:24.0.3',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,22 @@
package org.jboss.tools.intellij.openshift.utils;

import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import java.util.concurrent.ExecutionException;
import org.jboss.tools.intellij.openshift.utils.ToolFactory.Tool;
import org.jboss.tools.intellij.openshift.utils.helm.Helm;
import org.jboss.tools.intellij.openshift.utils.odo.Odo;

import java.util.concurrent.ExecutionException;

public class ToolFactoryTest extends BasePlatformTestCase {

public void testGetOdo() throws ExecutionException, InterruptedException {
Odo odo = ToolFactory.getInstance().createOdo(getProject()).get();
Tool<Odo> tool = ToolFactory.getInstance().createOdo(getProject()).get();
Odo odo = tool.get();
assertNotNull(odo);
}

public void testGetHelm() throws ExecutionException, InterruptedException {
Helm helm = ToolFactory.getInstance().createHelm(getProject()).get();
Tool<Helm> tool = ToolFactory.getInstance().createHelm(getProject()).get();
Helm helm = tool.get();
assertNotNull(helm);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
package org.jboss.tools.intellij.openshift.utils.helm;

import com.intellij.testFramework.fixtures.BasePlatformTestCase;
import java.util.Random;
import org.jboss.tools.intellij.openshift.utils.OdoCluster;
import org.jboss.tools.intellij.openshift.utils.ToolFactory;
import org.jboss.tools.intellij.openshift.utils.ToolFactory.Tool;
import org.jboss.tools.intellij.openshift.utils.odo.Odo;

import java.util.Random;

public abstract class HelmCliTest extends BasePlatformTestCase {

protected Helm helm;
Expand All @@ -26,17 +26,21 @@ public abstract class HelmCliTest extends BasePlatformTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
Odo odo = ToolFactory.getInstance().createOdo(getProject()).get();
Tool<Odo> odoTool = ToolFactory.getInstance().createOdo(getProject()).get();
Odo odo = odoTool.get();
OdoCluster.INSTANCE.login(odo);
odo.createProject(projectName);
this.helm = ToolFactory.getInstance().createHelm(getProject()).get();
Tool<Helm> helmTool = ToolFactory.getInstance().createHelm(getProject()).get();
this.helm = helmTool.get();
Charts.addRepository(Charts.REPOSITORY_STABLE, helm);
}

@Override
protected void tearDown() throws Exception {
Odo odo = ToolFactory.getInstance().createOdo(getProject()).get();
odo.deleteProject(projectName);
ToolFactory.Tool<Odo> tool = ToolFactory.getInstance().createOdo(getProject()).getNow(null);
if (tool != null) {
tool.get().deleteProject(projectName);
}
super.tearDown();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ protected void tearDown() throws Exception {
}

private CompletableFuture<Odo> getOdo() {
return ToolFactory.getInstance().createOdo(getProject())
.thenApply(odoDelegate -> new ApplicationRootNodeOdo(odoDelegate, mock(ApplicationsRootNode.class), processHelper));
return ToolFactory.getInstance()
.createOdo(getProject())
.thenApply(tool -> new ApplicationRootNodeOdo(tool.get(), false, mock(ApplicationsRootNode.class), processHelper));
}

protected void createProject(String project) throws IOException, ExecutionException, InterruptedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object s

protected Helm getHelm(AnActionEvent anActionEvent) {
try {
return ActionUtils.getApplicationRootNode(anActionEvent).getHelm(true).getNow(null);
return ActionUtils.getApplicationRootNode(anActionEvent).getHelm(true);
} catch (Exception e) {
LOGGER.warn("Could not get helm: " + e.getMessage(), e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,18 @@

public class ApplicationRootNodeOdo implements Odo {
private final Odo delegate;
private final boolean isDownloaded;
private final OdoProcessHelper processHelper;
private final ApplicationsRootNode root;
private final FileOperations fileOperations;

public ApplicationRootNodeOdo(Odo delegate, ApplicationsRootNode root, OdoProcessHelper processHelper) {
this(delegate, processHelper, root, new FileOperations());
public ApplicationRootNodeOdo(Odo delegate, boolean isDownloaded, ApplicationsRootNode root, OdoProcessHelper processHelper) {
this(delegate, isDownloaded, processHelper, root, new FileOperations());
}

ApplicationRootNodeOdo(Odo delegate, OdoProcessHelper processHelper, ApplicationsRootNode root, FileOperations fileOperations) {
ApplicationRootNodeOdo(Odo delegate, boolean isDownloaded, OdoProcessHelper processHelper, ApplicationsRootNode root, FileOperations fileOperations) {
this.delegate = delegate;
this.isDownloaded = isDownloaded;
this.processHelper = processHelper;
this.root = root;
this.fileOperations = fileOperations;
Expand Down Expand Up @@ -374,6 +376,10 @@ public void migrateComponent(String name) {
delegate.migrateComponent(name);
}

public boolean isDownloaded() {
return isDownloaded;
}

/** for testing purposes **/
protected static class FileOperations {
protected File createTempDir(String prefix) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,17 @@
import com.redhat.devtools.intellij.common.utils.ConfigWatcher;
import com.redhat.devtools.intellij.common.utils.ExecHelper;
import io.fabric8.kubernetes.api.model.Config;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import org.jboss.tools.intellij.openshift.actions.NotificationUtils;
import org.jboss.tools.intellij.openshift.utils.ProjectUtils;
import org.jboss.tools.intellij.openshift.utils.ToolFactory;
import org.jboss.tools.intellij.openshift.utils.ToolFactory.Tool;
import org.jboss.tools.intellij.openshift.utils.helm.Helm;
import org.jboss.tools.intellij.openshift.utils.odo.ComponentDescriptor;
import org.jboss.tools.intellij.openshift.utils.odo.Odo;
Expand All @@ -34,15 +42,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;

public class ApplicationsRootNode
implements ModuleListener, ConfigWatcher.Listener, ProcessingNode, StructureAwareNode, ParentableNode<ApplicationsRootNode>, Disposable {

Expand All @@ -51,8 +50,8 @@ public class ApplicationsRootNode
private final ApplicationsTreeStructure structure;
private final ProcessingNodeImpl processingNode = new ProcessingNodeImpl();
private final Map<String, ComponentDescriptor> components = new HashMap<>();
private CompletableFuture<Odo> odoFuture;
private CompletableFuture<Helm> helmFuture;
private CompletableFuture<ApplicationRootNodeOdo> odoFuture;
private CompletableFuture<Tool<Helm>> helmFuture;
private boolean logged;
private Config config;
private final OdoProcessHelper processHelper;
Expand Down Expand Up @@ -81,39 +80,53 @@ public void setLogged(boolean logged) {
this.logged = logged;
}

private CompletableFuture<Odo> getOdo(BiConsumer<Odo, Throwable> whenComplete) {
private CompletableFuture<ApplicationRootNodeOdo> doGetOdo() {
if (odoFuture == null) {
this.odoFuture = ToolFactory.getInstance()
.createOdo(project)
.thenApply(odo -> (Odo) new ApplicationRootNodeOdo(odo, this, processHelper))
.whenComplete((odo, err) -> loadProjectModel(odo, project))
.whenComplete(whenComplete);
.createOdo(project)
.thenApply(tool -> {
ApplicationRootNodeOdo odo = new ApplicationRootNodeOdo(tool.get(), tool.isDownloaded(), this, processHelper);
loadProjectModel(odo, project);
return odo;
});
}
return odoFuture;
}

public CompletableFuture<Odo> getOdo() {
return getOdo((odo, err) -> structure.fireModified(this));
public CompletableFuture<? extends Odo> getOdo() {
return doGetOdo()
.whenComplete((ApplicationRootNodeOdo odo, Throwable err) -> {
if (odo.isDownloaded()) {
structure.fireModified(this);
}
});
}

public void resetOdo() {
this.odoFuture = null;
}

public CompletableFuture<Helm> getHelm(boolean notify) {
public CompletableFuture<ToolFactory.Tool<Helm>> getHelmTool(boolean notify) {
if (helmFuture == null) {
this.helmFuture = ToolFactory.getInstance()
.createHelm(project)
.whenComplete((odo, err) -> {
if (notify) {
.whenComplete((tool, err) -> {
if (notify && tool.isDownloaded()) {
structure.fireModified(this);
}
}
);
});
}
return helmFuture;
}

public Helm getHelm(boolean notify) {
Tool<Helm> tool = getHelmTool(notify).getNow(null);
if (tool == null) {
return null;
}
return tool.get();
}

public Project getProject() {
return project;
}
Expand Down Expand Up @@ -159,8 +172,7 @@ private void addContextToSettings(String path, ComponentDescriptor descriptor) {
}

private void migrateOdo(ComponentDescriptor descriptor) {
getOdo()
.thenAccept(odo -> {
doGetOdo().whenComplete((odo, err) -> {
if (odo != null) {
odo.migrateComponent(descriptor.getName());
}
Expand Down Expand Up @@ -228,7 +240,9 @@ public void onUpdate(ConfigWatcher source, Config config) {

public synchronized void refresh() {
resetOdo();
getOdo((odo, err) -> structure.fireModified(ApplicationsRootNode.this));
doGetOdo().whenComplete((odo, err) ->
structure.fireModified(ApplicationsRootNode.this)
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ private Object getCurrentNamespace(ApplicationsRootNode element) {
}

private Object[] createHelmRepositoriesChildren(HelmRepositoriesNode parent) {
Helm helm = root.getHelm(true).getNow(null);
Helm helm = root.getHelm(true);
if (helm == null) {
return new Object[] { new MessageNode<>(root, parent, "Could not list repositories: Helm binary missing.") };
}
Expand Down Expand Up @@ -226,7 +226,7 @@ private List<BaseNode<?>> getServices(NamespaceNode namespaceNode, Odo odo) {
}

private List<BaseNode<?>> getHelmReleases(NamespaceNode namespaceNode) {
Helm helm = namespaceNode.getRoot().getHelm(true).getNow(null);
Helm helm = namespaceNode.getRoot().getHelm(true);
if (helm == null) {
return List.of(new MessageNode<>(root, namespaceNode, "Could not get chart releases"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,16 @@

import com.intellij.openapi.project.Project;
import com.redhat.devtools.intellij.common.utils.DownloadHelper;
import java.net.URL;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import org.jboss.tools.intellij.openshift.utils.helm.Helm;
import org.jboss.tools.intellij.openshift.utils.helm.HelmCli;
import org.jboss.tools.intellij.openshift.utils.odo.Odo;
import org.jboss.tools.intellij.openshift.utils.odo.OdoCli;

import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;

public class ToolFactory {


private static final String TOOLS_JSON = "/tools.json";

private static ToolFactory INSTANCE;
Expand All @@ -34,41 +33,60 @@ public static ToolFactory getInstance() {
return INSTANCE;
}

private final Tool<Odo> odo = new Tool<>("odo", OdoCli::new);
private final Tool<Helm> helm = new Tool<>("helm", (project, command) -> new HelmCli(command));
private final Factory<Odo> odo = new Factory<>("odo", OdoCli::new);
private final Factory<Helm> helm = new Factory<>("helm", (project, command) -> new HelmCli(command));

private ToolFactory() {
}

public CompletableFuture<Odo> createOdo(Project project) {
public CompletableFuture<Tool<Odo>> createOdo(Project project) {
return odo.create(project);
}

public CompletableFuture<Helm> createHelm(Project project) {
public CompletableFuture<Tool<Helm>> createHelm(Project project) {
return helm.create(project);
}

private static class Tool<T> {
public static class Tool<T> {
private final T tool;
private final boolean isDownloaded;

private Tool(T tool, boolean isDownloaded) {
this.tool = tool;
this.isDownloaded = isDownloaded;
}

public T get() {
return tool;
}

public boolean isDownloaded() {
return isDownloaded;
}
}

private static class Factory<T> {

private final String name;
private final URL url = ToolFactory.class.getResource(TOOLS_JSON);

private final BiFunction<Project, String, T> toolFactory;

private Tool(String name, BiFunction<Project, String, T> toolFactory) {
private Factory(String name, BiFunction<Project, String, T> toolFactory) {
this.name = name;
this.toolFactory = toolFactory;
}

private CompletableFuture<T> create(Project project) {
private CompletableFuture<Tool<T>> create(Project project) {
return create(name, toolFactory, project);
}

private CompletableFuture<T> create(String name, BiFunction<Project, String, T> toolFactory, Project project) {
private CompletableFuture<Tool<T>> create(String name, BiFunction<Project, String, T> toolFactory, Project project) {
return DownloadHelper.getInstance()
.downloadIfRequiredAsync(name, ToolFactory.class.getResource(TOOLS_JSON))
.thenApply(command -> {
if (command != null) {
return toolFactory.apply(project, command);
.downloadIfRequiredAsync(name, url)
.thenApply(toolInstance -> {
if (toolInstance != null) {
return new Tool<>(toolFactory.apply(project, toolInstance.getCommand()), toolInstance.isDownloaded());
} else {
return null;
}
Expand Down
Loading
Loading