From 778e652399e930cd51e3812ac2c04bf327153fdb Mon Sep 17 00:00:00 2001 From: Andre Dietisheim Date: Tue, 3 Dec 2024 18:40:03 +0100 Subject: [PATCH] fix: bump kubernetes-client to 7.0.0 (#921) Signed-off-by: Andre Dietisheim --- gradle/libs.versions.toml | 2 +- .../openshift/utils/ToolFactoryTest.java | 7 +- .../openshift/utils/odo/OdoCliTest.java | 5 +- .../utils/odo/OdoKubernetesClientTest.java | 14 +- .../openshift/actions/HelmAction.java | 2 +- .../intellij/openshift/actions/OcAction.java | 17 +- .../project/ChangeActiveProjectAction.java | 6 + .../application/ApplicationsRootNode.java | 55 +++-- .../ApplicationsTreeStructure.java | 4 +- .../tools/intellij/openshift/utils/Cli.java | 50 +--- .../openshift/utils/ClientAwareCli.java | 23 ++ .../utils/KubernetesClientFactory.java | 47 ++++ .../intellij/openshift/utils/ToolFactory.java | 59 +++-- .../openshift/utils/helm/HelmCli.java | 7 +- .../intellij/openshift/utils/oc/OcCli.java | 22 +- .../intellij/openshift/utils/odo/OdoCli.java | 42 ++-- .../ApplicationTreeModelConfigUpdateTest.java | 218 ++++++++++-------- 17 files changed, 316 insertions(+), 264 deletions(-) create mode 100644 src/main/java/org/jboss/tools/intellij/openshift/utils/ClientAwareCli.java create mode 100644 src/main/java/org/jboss/tools/intellij/openshift/utils/KubernetesClientFactory.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7cc53a6b6..2a58146dc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] # libraries junit = "4.13.2" -openshift-client = "6.12.0" +openshift-client = "7.0.0" devtools-common = "1.9.7-SNAPSHOT" keycloak = "24.0.5" jsonwebtoken = "0.12.6" diff --git a/src/it/java/org/jboss/tools/intellij/openshift/utils/ToolFactoryTest.java b/src/it/java/org/jboss/tools/intellij/openshift/utils/ToolFactoryTest.java index ca332e5a1..40b7a95d0 100644 --- a/src/it/java/org/jboss/tools/intellij/openshift/utils/ToolFactoryTest.java +++ b/src/it/java/org/jboss/tools/intellij/openshift/utils/ToolFactoryTest.java @@ -18,23 +18,24 @@ import org.jboss.tools.intellij.openshift.utils.odo.OdoDelegate; import java.util.concurrent.ExecutionException; +import org.mockito.Mockito; public class ToolFactoryTest extends BasePlatformTestCase { public void testGetOdo() throws ExecutionException, InterruptedException { - Tool tool = ToolFactory.getInstance().createOdo(getProject()).get(); + Tool tool = ToolFactory.getInstance().createOdo(Mockito.mock(), getProject()).get(); Odo odo = tool.get(); assertNotNull(odo); } public void testGetHelm() throws ExecutionException, InterruptedException { - Tool tool = ToolFactory.getInstance().createHelm(getProject()).get(); + Tool tool = ToolFactory.getInstance().createHelm().get(); Helm helm = tool.get(); assertNotNull(helm); } public void testGetOc() throws ExecutionException, InterruptedException { - Tool tool = ToolFactory.getInstance().createOc(getProject()).get(); + Tool tool = ToolFactory.getInstance().createOc(Mockito.mock()).get(); Oc oc = tool.get(); assertNotNull(oc); } diff --git a/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCliTest.java b/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCliTest.java index 402310f5a..84cd67e3d 100644 --- a/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCliTest.java +++ b/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCliTest.java @@ -29,6 +29,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import org.mockito.Mockito; import static org.awaitility.Awaitility.with; import static org.jboss.tools.intellij.openshift.Constants.PLUGIN_FOLDER; @@ -68,7 +69,7 @@ public abstract class OdoCliTest extends BasePlatformTestCase { @Before public void init() throws Exception { previousTestDialog = MessagesHelper.setTestDialog(TestDialog.OK); - ToolFactory.getInstance().createOc(getProject()).whenComplete((ocTool, throwable) -> { + ToolFactory.getInstance().createOc(Mockito.mock()).whenComplete((ocTool, throwable) -> { try { OdoCluster.INSTANCE.login(ocTool.get()); } catch (IOException e) { @@ -85,7 +86,7 @@ public void cleanup() { private CompletableFuture getOdo() { return ToolFactory.getInstance() - .createOdo(getProject()) + .createOdo(Mockito.mock(), getProject()) .thenApply(tool -> new ApplicationRootNodeOdo(tool.get(), false, rootNode, processHelper)); } diff --git a/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoKubernetesClientTest.java b/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoKubernetesClientTest.java index eebe03a4e..b7e244eb3 100644 --- a/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoKubernetesClientTest.java +++ b/src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoKubernetesClientTest.java @@ -27,10 +27,6 @@ import io.fabric8.openshift.api.model.ProjectList; import io.fabric8.openshift.client.OpenShiftClient; import io.fabric8.openshift.client.dsl.ProjectOperation; -import org.jboss.tools.intellij.openshift.utils.Cli; -import org.junit.Before; -import org.junit.Test; - import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; @@ -40,7 +36,9 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import java.util.function.Supplier; +import org.jboss.tools.intellij.openshift.utils.Cli; +import org.junit.Before; +import org.junit.Test; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyString; @@ -250,17 +248,17 @@ public void isAuthorized_should_throw_if_listing_secrets_throws_other_Kubernetes } private OdoCli createOdo(KubernetesClient kubernetesClient, OpenShiftClient openShiftClient) { + KubernetesClient client = mock(KubernetesClient.class); Project project = mock(Project.class); String command = "Star Wars"; MessageBusConnection connection = mock(MessageBusConnection.class); MessageBus bus = mock(MessageBus.class); doReturn(connection) .when(bus).connect(); - Supplier kubernetesClientFactory = () -> kubernetesClient; - Function openShiftClientFactory = client -> openShiftClient; + Function openShiftClientFactory = kubeClient -> openShiftClient; Function> envVarFactory = url -> new HashMap<>(); Cli.TelemetryReport telemetryReport = mock(Cli.TelemetryReport.class); - return new OdoCli(project, command, bus, kubernetesClientFactory, openShiftClientFactory, envVarFactory, telemetryReport); + return new OdoCli(command, project, client, bus, openShiftClientFactory, envVarFactory, telemetryReport); } private static R mockResource(String name, Class clazz) { diff --git a/src/main/java/org/jboss/tools/intellij/openshift/actions/HelmAction.java b/src/main/java/org/jboss/tools/intellij/openshift/actions/HelmAction.java index b8ce0851c..c302a5c72 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/actions/HelmAction.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/actions/HelmAction.java @@ -57,7 +57,7 @@ public void actionPerformed(AnActionEvent anActionEvent, TreePath[] path, Object protected Helm getHelm(AnActionEvent anActionEvent) { try { - return ActionUtils.getApplicationRootNode(anActionEvent).getHelm(true); + return ActionUtils.getApplicationRootNode(anActionEvent).getHelm(); } catch (Exception e) { LOGGER.warn("Could not get helm: {}", e.getMessage(), e); return null; diff --git a/src/main/java/org/jboss/tools/intellij/openshift/actions/OcAction.java b/src/main/java/org/jboss/tools/intellij/openshift/actions/OcAction.java index fadc9c68f..633029833 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/actions/OcAction.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/actions/OcAction.java @@ -28,16 +28,17 @@ protected OcAction(Class... filters) { @Override public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object selected) { setTelemetrySender(new TelemetrySender(PREFIX_ACTION + getTelemetryActionName())); - ActionUtils.getApplicationRootNode(anActionEvent).getOcTool().whenComplete( - (ocTool, throwable) -> { - if (ocTool != null) { - Oc oc = ocTool.get(); - if (oc != null) { - this.actionPerformedOnSelectedObject(anActionEvent, getElement(selected), oc); + ActionUtils.getApplicationRootNode(anActionEvent).getOcTool() + .whenComplete( + (ocTool, throwable) -> { + if (ocTool != null) { + Oc oc = ocTool.get(); + if (oc != null) { + this.actionPerformedOnSelectedObject(anActionEvent, getElement(selected), oc); + } } } - } - ); + ); } public abstract void actionPerformedOnSelectedObject(AnActionEvent anActionEvent, Object selected, @NotNull Oc oc); diff --git a/src/main/java/org/jboss/tools/intellij/openshift/actions/project/ChangeActiveProjectAction.java b/src/main/java/org/jboss/tools/intellij/openshift/actions/project/ChangeActiveProjectAction.java index 497c0bcf0..61ef6dea4 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/actions/project/ChangeActiveProjectAction.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/actions/project/ChangeActiveProjectAction.java @@ -10,6 +10,7 @@ ******************************************************************************/ package org.jboss.tools.intellij.openshift.actions.project; +import com.intellij.openapi.actionSystem.ActionUpdateThread; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProgressIndicator; @@ -189,4 +190,9 @@ public void run() { ); } } + + @Override + public @NotNull ActionUpdateThread getActionUpdateThread() { + return ActionUpdateThread.BGT; + } } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsRootNode.java b/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsRootNode.java index 76d78fdb7..483ab0e95 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsRootNode.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsRootNode.java @@ -25,15 +25,17 @@ import com.redhat.devtools.intellij.common.utils.ConfigHelper; import com.redhat.devtools.intellij.common.utils.ConfigWatcher; import com.redhat.devtools.intellij.common.utils.ExecHelper; -import io.fabric8.kubernetes.api.model.Config; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.ConfigBuilder; +import io.fabric8.kubernetes.client.KubernetesClient; 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.KubernetesClientFactory; 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; @@ -59,14 +61,13 @@ public class ApplicationsRootNode private CompletableFuture> helmFuture; private CompletableFuture> ocFuture; private boolean logged; - private Config config; + private KubernetesClient client; private final OdoProcessHelper processHelper; public ApplicationsRootNode(Project project, ApplicationsTreeStructure structure, Disposable parent) { this.project = project; this.structure = structure; initConfigWatcher(); - this.config = loadConfig(); registerProjectListener(project); this.processHelper = new OdoProcessHelper(); Disposer.register(parent, this); @@ -91,7 +92,7 @@ private CompletableFuture doGetOdo() { if (odoFuture == null) { this.odoFuture = ReadAction.compute(() -> ToolFactory.getInstance() - .createOdo(project) + .createOdo(getClient(), project) .thenApply(tool -> { ApplicationRootNodeOdo odo = new ApplicationRootNodeOdo(tool.get(), tool.isDownloaded(), this, processHelper); loadProjectModel(odo, project); @@ -111,23 +112,24 @@ public CompletableFuture getOdo() { }); } - public void resetOdo() { + private void disposeClientAwareClis() { this.odoFuture = null; + this.ocFuture = null; } public CompletableFuture> getOcTool() { if (ocFuture == null) { - this.ocFuture = ToolFactory.getInstance().createOc(project); + this.ocFuture = ToolFactory.getInstance().createOc(getClient()); } return ocFuture; } - public CompletableFuture> getHelmTool(boolean notify) { + private CompletableFuture> getHelmTool() { if (helmFuture == null) { this.helmFuture = ToolFactory.getInstance() - .createHelm(project) + .createHelm() .whenComplete((tool, err) -> { - if (notify && tool.isDownloaded()) { + if (tool.isDownloaded()) { structure.fireModified(this); } }); @@ -135,8 +137,8 @@ public CompletableFuture> getHelmTool(boolean notify) { return helmFuture; } - public Helm getHelm(boolean notify) { - Tool tool = getHelmTool(notify).getNow(null); + public Helm getHelm() { + Tool tool = getHelmTool().getNow(null); if (tool == null) { return null; } @@ -148,11 +150,7 @@ public Project getProject() { } protected void initConfigWatcher() { - ExecHelper.submit(new ConfigWatcher(Paths.get(ConfigHelper.getKubeConfigPath()), this)); - } - - protected Config loadConfig() { - return ConfigHelper.safeLoadKubeConfig(); + ExecHelper.submit(new ConfigWatcher(this)); } public Map getLocalComponents() { @@ -247,15 +245,16 @@ protected void registerProjectListener(Project project) { } @Override - public void onUpdate(ConfigWatcher source, Config config) { - if (!ConfigHelper.areEqual(config, this.config)) { - this.config = config; + public void onUpdate(Config updated) { + Config current = getClient().getConfiguration(); + if (!ConfigHelper.areEqual(current, updated)) { + this.client = createClient(updated); refresh(); } } public synchronized void refresh() { - resetOdo(); + disposeClientAwareClis(); doGetOdo().whenComplete((odo, err) -> structure.fireModified(ApplicationsRootNode.this) ); @@ -303,6 +302,18 @@ public ApplicationsRootNode getRoot() { @Override public void dispose() { - resetOdo(); + disposeClientAwareClis(); + } + + protected KubernetesClient getClient() { + if (client == null) { + this.client = createClient(new ConfigBuilder().build()); + } + return client; + } + + protected KubernetesClient createClient(Config config) { + return new KubernetesClientFactory().apply(config); } + } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsTreeStructure.java b/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsTreeStructure.java index 683f21a4f..9d1cfb47a 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsTreeStructure.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsTreeStructure.java @@ -170,7 +170,7 @@ private Object getCurrentNamespace(ApplicationsRootNode element) { } private Object[] createHelmRepositoriesChildren(HelmRepositoriesNode parent) { - Helm helm = root.getHelm(true); + Helm helm = root.getHelm(); if (helm == null) { return new Object[]{new MessageNode<>(root, parent, "Could not list repositories: Helm binary missing.")}; } @@ -229,7 +229,7 @@ private List> getServices(NamespaceNode namespaceNode, Odo odo) { } private List> getHelmReleases(NamespaceNode namespaceNode) { - Helm helm = namespaceNode.getRoot().getHelm(true); + Helm helm = namespaceNode.getRoot().getHelm(); if (helm == null) { return List.of(new MessageNode<>(root, namespaceNode, "Could not get chart releases")); } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/Cli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/Cli.java index ec54da966..d40d58894 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/Cli.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/Cli.java @@ -14,35 +14,15 @@ import com.intellij.util.messages.MessageBus; import com.redhat.devtools.intellij.common.kubernetes.ClusterHelper; import com.redhat.devtools.intellij.common.kubernetes.ClusterInfo; -import com.redhat.devtools.intellij.common.ssl.IDEATrustManager; -import com.redhat.devtools.intellij.common.utils.ConfigHelper; import com.redhat.devtools.intellij.common.utils.NetworkUtils; import com.redhat.devtools.intellij.telemetry.core.configuration.TelemetryConfiguration; import com.redhat.devtools.intellij.telemetry.core.service.TelemetryMessageBuilder; -import io.fabric8.kubernetes.client.Config; import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; -import io.fabric8.kubernetes.client.http.HttpClient; -import io.fabric8.kubernetes.client.internal.SSLUtils; -import java.io.IOException; import java.net.URISyntaxException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.spec.InvalidKeySpecException; -import java.util.Arrays; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.function.Function; -import java.util.function.Supplier; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509ExtendedTrustManager; -import javax.net.ssl.X509TrustManager; import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static org.jboss.tools.intellij.openshift.telemetry.TelemetryService.IS_OPENSHIFT; import static org.jboss.tools.intellij.openshift.telemetry.TelemetryService.KUBERNETES_VERSION; @@ -52,34 +32,10 @@ public class Cli { - private static final Logger LOGGER = LoggerFactory.getLogger(Cli.class); + protected final String command; - protected final KubernetesClient client; - - protected Cli(Supplier kubernetesClientFactory) { - this.client = kubernetesClientFactory.get(); - } - - public static final class KubernetesClientFactory implements Supplier { - - @Override - public KubernetesClient get() { - String current = ConfigHelper.getCurrentContextName(); - Config config = Config.autoConfigure(current); - return new KubernetesClientBuilder().withConfig(config).withHttpClientBuilderConsumer(builder -> setSslContext(builder, config)).build(); - } - - private void setSslContext(HttpClient.Builder builder, Config config) { - try { - X509TrustManager externalTrustManager = new IDEATrustManager().configure(List.of(Arrays.stream(SSLUtils.trustManagers(config)) - .filter(X509ExtendedTrustManager.class::isInstance) - .map(X509ExtendedTrustManager.class::cast).toArray(X509ExtendedTrustManager[]::new))); - builder.sslContext(SSLUtils.keyManagers(config), List.of(externalTrustManager).toArray(new TrustManager[0])); - } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | - UnrecoverableKeyException | InvalidKeySpecException e) { - LOGGER.error(e.getMessage(), e); - } - } + protected Cli(String command) { + this.command = command; } public static final class EnvVarFactory implements Function> { diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/ClientAwareCli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/ClientAwareCli.java new file mode 100644 index 000000000..9ffb027fc --- /dev/null +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/ClientAwareCli.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2024 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 io.fabric8.kubernetes.client.KubernetesClient; + +public class ClientAwareCli extends Cli{ + + protected final KubernetesClient client; + + protected ClientAwareCli(String command, KubernetesClient client) { + super(command); + this.client = client; + } +} diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/KubernetesClientFactory.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/KubernetesClientFactory.java new file mode 100644 index 000000000..b4cc842e5 --- /dev/null +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/KubernetesClientFactory.java @@ -0,0 +1,47 @@ +package org.jboss.tools.intellij.openshift.utils; + +import com.redhat.devtools.intellij.common.ssl.IDEATrustManager; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import io.fabric8.kubernetes.client.http.HttpClient; +import io.fabric8.kubernetes.client.internal.SSLUtils; +import java.io.IOException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509ExtendedTrustManager; +import javax.net.ssl.X509TrustManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KubernetesClientFactory implements Function { + + private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesClientFactory.class); + + @Override + public KubernetesClient apply(Config config) { + return new KubernetesClientBuilder() + .withConfig(config) + .withHttpClientBuilderConsumer(builder -> setSslContext(builder, config)) + .build(); + } + + private void setSslContext(HttpClient.Builder builder, Config config) { + try { + X509TrustManager externalTrustManager = new IDEATrustManager().configure(List.of(Arrays.stream(SSLUtils.trustManagers(config)) + .filter(X509ExtendedTrustManager.class::isInstance) + .map(X509ExtendedTrustManager.class::cast).toArray(X509ExtendedTrustManager[]::new))); + builder.sslContext(SSLUtils.keyManagers(config), List.of(externalTrustManager).toArray(new TrustManager[0])); + } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | + UnrecoverableKeyException | InvalidKeySpecException e) { + LOGGER.error(e.getMessage(), e); + } + } + } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/ToolFactory.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/ToolFactory.java index d84f8242a..0a1f46b41 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/ToolFactory.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/ToolFactory.java @@ -12,6 +12,10 @@ import com.intellij.openapi.project.Project; import com.redhat.devtools.intellij.common.utils.DownloadHelper; +import io.fabric8.kubernetes.client.KubernetesClient; +import java.net.URL; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; 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.oc.Oc; @@ -19,10 +23,6 @@ import org.jboss.tools.intellij.openshift.utils.odo.OdoCli; import org.jboss.tools.intellij.openshift.utils.odo.OdoDelegate; -import java.net.URL; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiFunction; - public class ToolFactory { private static final String TOOLS_JSON = "/tools.json"; @@ -36,23 +36,21 @@ public static ToolFactory getInstance() { return INSTANCE; } - private final Factory odo = new Factory<>("odo", OdoCli::new); - private final Factory helm = new Factory<>("helm", (project, command) -> new HelmCli(command)); - private final Factory oc = new Factory<>("oc", (project, command) -> new OcCli(command)); + private ToolFactory() {} - private ToolFactory() { + public CompletableFuture> createOdo(KubernetesClient client, Project project) { + return new Downloadable("odo") + .downloadAndCreate(commandName -> new OdoCli(commandName, project, client)); } - public CompletableFuture> createOdo(Project project) { - return odo.create(project); + public CompletableFuture> createHelm() { + return new Downloadable("helm") + .downloadAndCreate(commandName -> new HelmCli(commandName)); } - public CompletableFuture> createHelm(Project project) { - return helm.create(project); - } - - public CompletableFuture> createOc(Project project) { - return oc.create(project); + public CompletableFuture> createOc(KubernetesClient client) { + return new Downloadable("helm") + .downloadAndCreate(commandName -> new OcCli(commandName, client)); } public static class Tool { @@ -73,31 +71,26 @@ public boolean isDownloaded() { } } - private static class Factory { + private static class Downloadable { private final String name; private final URL url = ToolFactory.class.getResource(TOOLS_JSON); - private final BiFunction toolFactory; - - private Factory(String name, BiFunction toolFactory) { + private Downloadable(String name) { this.name = name; - this.toolFactory = toolFactory; - } - - private CompletableFuture> create(Project project) { - return create(name, toolFactory, project); } - private CompletableFuture> create(String name, BiFunction toolFactory, Project project) { - return DownloadHelper.getInstance().downloadIfRequiredAsync(name, url).thenApply(toolInstance -> { - if (toolInstance != null) { - return new Tool<>(toolFactory.apply(project, toolInstance.getCommand()), toolInstance.isDownloaded()); - } else { - return null; - } - }); + private CompletableFuture> downloadAndCreate(Function factory) { + return DownloadHelper.getInstance() + .downloadIfRequiredAsync(name, url) + .thenApply(toolInstance -> { + if (toolInstance != null) { + return new Tool<>(factory.apply(toolInstance.getCommand()), toolInstance.isDownloaded()); + } else { + return null; + } + }); } } } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/helm/HelmCli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/helm/HelmCli.java index 461540612..4f0b0cbc4 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/helm/HelmCli.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/helm/HelmCli.java @@ -23,6 +23,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.jboss.tools.intellij.openshift.telemetry.TelemetryService; +import org.jboss.tools.intellij.openshift.utils.Cli; import org.jboss.tools.intellij.openshift.utils.Serialization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,14 +32,12 @@ import static org.jboss.tools.intellij.openshift.Constants.HOME_FOLDER; import static org.jboss.tools.intellij.openshift.telemetry.TelemetryService.asyncSend; -public class HelmCli implements Helm { +public class HelmCli extends Cli implements Helm { private static final Logger LOGGER = LoggerFactory.getLogger(HelmCli.class); - private final String command; - public HelmCli(String command) { - this.command = command; + super(command); } @Override diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/oc/OcCli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/oc/OcCli.java index c07543330..c59a9cad4 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/oc/OcCli.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/oc/OcCli.java @@ -14,50 +14,46 @@ import com.intellij.util.messages.MessageBus; import com.redhat.devtools.intellij.common.utils.ExecHelper; import io.fabric8.kubernetes.client.KubernetesClient; -import org.jboss.tools.intellij.openshift.utils.Cli; -import org.jetbrains.annotations.NotNull; - import java.io.File; import java.io.IOException; import java.net.URL; import java.util.Map; import java.util.function.Function; -import java.util.function.Supplier; +import org.jboss.tools.intellij.openshift.utils.Cli; +import org.jboss.tools.intellij.openshift.utils.ClientAwareCli; +import org.jetbrains.annotations.NotNull; import static org.jboss.tools.intellij.openshift.Constants.HOME_FOLDER; -public class OcCli extends Cli implements Oc { +public class OcCli extends ClientAwareCli implements Oc { - private final String command; private final Map envVars; - public OcCli(String command) { + public OcCli(String command, KubernetesClient client) { this(command, + client, ApplicationManager.getApplication().getMessageBus(), - new Cli.KubernetesClientFactory(), new Cli.EnvVarFactory(), new Cli.TelemetryReport()); } public OcCli( String command, + KubernetesClient client, MessageBus bus, - Supplier kubernetesClientFactory, Function> envVarFactory, Cli.TelemetryReport telemetryReport) { - super(kubernetesClientFactory); - this.command = command; + super(command, client); this.envVars = envVarFactory.apply(String.valueOf(client.getMasterUrl())); initTelemetry(telemetryReport, bus); } - private void initTelemetry(TelemetryReport telemetryReport, MessageBus bus) { + private void initTelemetry(Cli.TelemetryReport telemetryReport, MessageBus bus) { telemetryReport.addTelemetryVars(envVars); telemetryReport.subscribe(bus, envVars); telemetryReport.report(client); } - private static void execute(@NotNull File workingDirectory, String command, Map envs, String... args) throws IOException { ExecHelper.executeWithResult(command, true, workingDirectory, envs, args); } diff --git a/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java b/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java index ebb77cfc9..b3409d18e 100644 --- a/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java +++ b/src/main/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCli.java @@ -18,9 +18,11 @@ import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.Strings; import com.intellij.util.messages.MessageBus; +import com.redhat.devtools.intellij.common.kubernetes.ClusterHelper; import com.redhat.devtools.intellij.common.utils.ExecHelper; import io.fabric8.kubernetes.api.Pluralize; import io.fabric8.kubernetes.api.model.ConfigMap; @@ -37,15 +39,6 @@ import io.fabric8.openshift.client.OpenShiftClient; import io.fabric8.openshift.client.dsl.OpenShiftOperatorHubAPIGroupDSL; import io.fabric8.openshift.client.impl.OpenShiftOperatorHubAPIGroupClient; -import org.jboss.tools.intellij.openshift.KubernetesLabels; -import org.jboss.tools.intellij.openshift.utils.Cli; -import org.jboss.tools.intellij.openshift.utils.KubernetesClientExceptionUtils; -import org.jboss.tools.intellij.openshift.utils.Serialization; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -62,9 +55,16 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BinaryOperator; import java.util.function.Function; -import java.util.function.Supplier; +import org.jboss.tools.intellij.openshift.KubernetesLabels; +import org.jboss.tools.intellij.openshift.utils.Cli; +import org.jboss.tools.intellij.openshift.utils.ClientAwareCli; +import org.jboss.tools.intellij.openshift.utils.KubernetesClientExceptionUtils; +import org.jboss.tools.intellij.openshift.utils.Serialization; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import static io.fabric8.openshift.client.OpenShiftClient.BASE_API_GROUP; import static org.jboss.tools.intellij.openshift.Constants.HOME_FOLDER; import static org.jboss.tools.intellij.openshift.Constants.OCP3_CONFIG_NAMESPACE; import static org.jboss.tools.intellij.openshift.Constants.OCP3_WEBCONSOLE_CONFIG_MAP_NAME; @@ -74,7 +74,7 @@ import static org.jboss.tools.intellij.openshift.Constants.OCP4_CONSOLE_URL_KEY_NAME; import static org.jboss.tools.intellij.openshift.Constants.PLUGIN_FOLDER; -public class OdoCli extends Cli implements OdoDelegate { +public class OdoCli extends ClientAwareCli implements OdoDelegate { private static final Logger LOGGER = LoggerFactory.getLogger(OdoCli.class); @@ -86,7 +86,6 @@ public class OdoCli extends Cli implements OdoDelegate { private static final String NAMESPACE_FIELD = "namespace"; private static final String SPEC_FIELD = "spec"; private final com.intellij.openapi.project.Project project; - private final String command; private final OpenShiftClient openshiftClient; private final Map envVars; private final AtomicBoolean swaggerLoaded = new AtomicBoolean(); @@ -94,26 +93,25 @@ public class OdoCli extends Cli implements OdoDelegate { private JSonParser swagger; private CompletableFuture isPodmanPresent; - public OdoCli(com.intellij.openapi.project.Project project, String command) { - this(project, - command, + public OdoCli(String command, Project project, KubernetesClient client) { + this(command, + project, + client, ApplicationManager.getApplication().getMessageBus(), - new Cli.KubernetesClientFactory(), new OpenShiftClientFactory(), new Cli.EnvVarFactory(), new Cli.TelemetryReport()); } protected OdoCli( - com.intellij.openapi.project.Project project, String command, + Project project, + KubernetesClient client, MessageBus bus, - Supplier kubernetesClientFactory, Function openshiftClientFactory, Function> envVarFactory, Cli.TelemetryReport telemetryReport) { - super(kubernetesClientFactory); - this.command = command; + super(command, client); this.project = project; this.openshiftClient = openshiftClientFactory.apply(client); this.envVars = envVarFactory.apply(String.valueOf(client.getMasterUrl())); @@ -781,7 +779,7 @@ private static final class OpenShiftClientFactory implements Function contexts) { Config config = mock(Config.class); - doReturn(contextName).when(config).getCurrentContext(); - NamedContext namedContext = createNamedContext(contextName, context); - doReturn(Arrays.asList(namedContext)).when(config).getContexts(); - - if (authInfo != null) { - NamedAuthInfo namedAuthInfo = mock(NamedAuthInfo.class); - doReturn(user).when(namedAuthInfo).getName(); - doReturn(authInfo).when(namedAuthInfo).getUser(); - doReturn(Arrays.asList(namedAuthInfo)).when(config).getUsers(); - } + doReturn(token) + .when(config).getAutoOAuthToken(); + doReturn(current) + .when(config).getCurrentContext(); + doReturn(contexts) + .when(config).getContexts(); return config; } - private NamedContext createNamedContext(String contextName, Context context) { - NamedContext namedContext = mock(NamedContext.class); - doReturn(contextName).when(namedContext).getName(); - doReturn(context).when(namedContext).getContext(); - return namedContext; - } - - private Context createContext() { - return createContext(null, null); + private NamedContext createNamedContext(NamedContext namedContext) { + Context context = namedContext.getContext(); + return createNamedContext(namedContext.getName(), context.getCluster(), context.getNamespace(), context.getUser()); } - private Context createContext(String user, String cluster) { + private NamedContext createNamedContext(String name, String cluster, String namespace, String user) { Context context = mock(Context.class); - if (!StringUtil.isEmptyOrSpaces(user)) { - doReturn(user).when(context).getUser(); - } - if (!StringUtil.isEmptyOrSpaces(cluster)) { - doReturn(cluster).when(context).getCluster(); - } - return context; + doReturn(cluster) + .when(context).getCluster(); + doReturn(namespace) + .when(context).getNamespace(); + doReturn(user) + .when(context).getUser(); + + NamedContext namedContext = mock(NamedContext.class); + doReturn(name) + .when(namedContext).getName(); + doReturn(context) + .when(namedContext).getContext(); + return namedContext; } - private AuthInfo createAuthInfo(String token) { - AuthInfo authInfo = mock(AuthInfo.class); - doReturn(token).when(authInfo).getToken(); - return authInfo; + private KubernetesClient createKubernetesClient(Config config) throws MalformedURLException { + KubernetesClient client = mock(KubernetesClient.class); + doReturn(new URL("https://starwars.com")) // avoid "invalid master url" exception + .when(client).getMasterUrl(); + doReturn(config) + .when(client).getConfiguration(); + return client; } }