From 1981452108985c857283a35525c9fb7c8087ad3c Mon Sep 17 00:00:00 2001 From: Jan Horvath Date: Sun, 6 Oct 2024 17:46:31 +0200 Subject: [PATCH] Adding action for switching of a namespace on k8s cluster --- .../cloud/oracle/assets/KubernetesUtils.java | 143 ++++++++++++++++++ .../oracle/assets/RunInClusterAction.java | 124 +-------------- .../assets/SetClusterNamespaceAction.java | 126 +++++++++++++++ .../oracle/assets/SetReferenceNameAction.java | 1 + .../cloud/oracle/compute/ClusterItem.java | 11 ++ .../LspAssetsDecorationProvider.java | 8 + .../modules/nbcode/integration/layer.xml | 1 + java/java.lsp.server/vscode/package.json | 14 ++ java/java.lsp.server/vscode/src/extension.ts | 6 +- 9 files changed, 313 insertions(+), 121 deletions(-) create mode 100644 enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/KubernetesUtils.java create mode 100644 enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetClusterNamespaceAction.java diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/KubernetesUtils.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/KubernetesUtils.java new file mode 100644 index 000000000000..5c88b56dd95c --- /dev/null +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/KubernetesUtils.java @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.cloud.oracle.assets; + +import com.oracle.bmc.Region; +import com.oracle.bmc.http.Priorities; +import com.oracle.bmc.http.client.HttpClient; +import com.oracle.bmc.http.client.HttpRequest; +import com.oracle.bmc.http.client.Method; +import com.oracle.bmc.http.client.jersey.JerseyHttpProvider; +import com.oracle.bmc.http.signing.RequestSigningFilter; +import io.fabric8.kubernetes.client.Config; +import io.fabric8.kubernetes.client.KubernetesClient; +import io.fabric8.kubernetes.client.KubernetesClientBuilder; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import org.netbeans.modules.cloud.oracle.OCIManager; +import org.netbeans.modules.cloud.oracle.OCIProfile; +import org.netbeans.modules.cloud.oracle.compute.ClusterItem; +import org.openide.util.Exceptions; +import org.snakeyaml.engine.v2.api.Dump; +import org.snakeyaml.engine.v2.api.DumpSettings; +import org.snakeyaml.engine.v2.api.Load; +import org.snakeyaml.engine.v2.api.LoadSettings; + +/** + * + * @author Jan Horvath + */ +public class KubernetesUtils { + + static void runWithClient(ClusterItem cluster, Consumer consumer) { + if (cluster.getConfig() == null) { + cluster.update(); + } + if (cluster.getConfig() == null) { + throw new RuntimeException("Invalid cluster configuration"); + } + Config config = prepareConfig(cluster.getConfig(), cluster); + try (KubernetesClient client = new KubernetesClientBuilder().withConfig(config).build();) { + consumer.accept(client); + } catch (Exception e) { + Exceptions.printStackTrace(e); + } + } + + private static Config prepareConfig(String content, ClusterItem cluster) { + String token = getBearerToken(cluster); + LoadSettings settings = LoadSettings.builder().build(); + Load load = new Load(settings); + Map data = (Map) load.loadFromString(content); + + List> users = (List>) data.get("users"); //NOI18N + if (users == null) { + throw new RuntimeException("Invalid cluster configuration"); + } + Map exec = null; + for (Map userEntry : users) { + Map user = (Map) userEntry.get("user"); //NOI18N + if (user != null && user.containsKey("exec")) { //NOI18N + exec = (Map) user.remove("exec"); //NOI18N + } + } + String clusterId = null; + if (exec != null && "oci".equals(exec.get("command"))) { //NOI18N + List commandArgs = (List) exec.get("args"); //NOI18N + boolean clusterIdNext = false; + for (Object arg : commandArgs) { + if ("--cluster-id".equals(arg)) { + clusterIdNext = true; + continue; + } + if (clusterIdNext) { + clusterId = (String) arg; + break; + } + + } + } + if (!cluster.getKey().getValue().equals(clusterId)) { + throw new RuntimeException("Failed to read cluster config"); //NOI18N + } + Dump dump = new Dump(DumpSettings.builder().build()); + String noExec = dump.dumpToString(data); + Config config = Config.fromKubeconfig(noExec); + config.setOauthToken(token); + return config; + } + + private static String getBearerToken(ClusterItem cluster) { + try { + OCIProfile profile = OCIManager.getDefault().getActiveProfile(cluster); + Region region = Region.fromRegionCodeOrId(cluster.getRegionCode()); + URI uri = new URI(String.format( + "https://containerengine.%s.oraclecloud.com/cluster_request/%s", //NOI18N + region.getRegionId(), cluster.getKey().getValue() + )); + + RequestSigningFilter requestSigningFilter + = RequestSigningFilter.fromAuthProvider(profile.getAuthenticationProvider()); + + HttpClient client = JerseyHttpProvider.getInstance().newBuilder() + .registerRequestInterceptor(Priorities.AUTHENTICATION, requestSigningFilter) + .baseUri(uri).build(); + + HttpRequest request = client.createRequest(Method.GET); + + request.execute().toCompletableFuture(); + List tokenUrlList = request.headers().get("authorization"); //NOI18N + String authorization = URLEncoder.encode(tokenUrlList.get(0), "UTF-8"); //NOI18N + List dateList = request.headers().get("date"); //NOI18N + String date = URLEncoder.encode(dateList.get(0), "UTF-8"); //NOI18N + String baseString = String.format("%s?authorization=%s&date=%s", uri.toASCIIString(), authorization, date); //NOI18N + byte[] urlBytes = baseString.getBytes(StandardCharsets.UTF_8); + return Base64.getUrlEncoder().encodeToString(urlBytes); + } catch (URISyntaxException | UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/RunInClusterAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/RunInClusterAction.java index 48f28f50f6cd..70157bade064 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/RunInClusterAction.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/RunInClusterAction.java @@ -18,51 +18,25 @@ */ package org.netbeans.modules.cloud.oracle.assets; -import com.oracle.bmc.Region; -import com.oracle.bmc.http.Priorities; -import com.oracle.bmc.http.client.HttpClient; -import com.oracle.bmc.http.client.HttpRequest; -import com.oracle.bmc.http.client.Method; -import com.oracle.bmc.http.client.jersey.JerseyHttpProvider; -import com.oracle.bmc.http.signing.RequestSigningFilter; import io.fabric8.kubernetes.api.model.apps.Deployment; import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder; import io.fabric8.kubernetes.api.model.apps.DeploymentList; -import io.fabric8.kubernetes.client.Config; -import io.fabric8.kubernetes.client.KubernetesClient; -import io.fabric8.kubernetes.client.KubernetesClientBuilder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.time.Instant; -import java.util.Base64; -import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.function.Consumer; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.project.Project; import org.netbeans.api.project.ProjectInformation; import org.netbeans.api.project.ProjectUtils; -import org.netbeans.modules.cloud.oracle.OCIManager; -import org.netbeans.modules.cloud.oracle.OCIProfile; import org.netbeans.modules.cloud.oracle.compute.ClusterItem; import org.netbeans.modules.cloud.oracle.developer.ContainerTagItem; import org.netbeans.modules.cloud.oracle.steps.ProjectStep; import org.openide.awt.ActionID; import org.openide.awt.ActionRegistration; -import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; -import org.snakeyaml.engine.v2.api.Dump; -import org.snakeyaml.engine.v2.api.DumpSettings; -import org.snakeyaml.engine.v2.api.Load; -import org.snakeyaml.engine.v2.api.LoadSettings; /** * @@ -85,7 +59,6 @@ public class RunInClusterAction implements ActionListener { private final ContainerTagItem context; private static final String APP = "app"; //NOI18N - private static final String DEFAULT = "default"; //NOI18N private static final RequestProcessor RP = new RequestProcessor(RunInClusterAction.class); public RunInClusterAction(ContainerTagItem context) { @@ -99,12 +72,6 @@ public void actionPerformed(ActionEvent e) { private void runInCluster() { ClusterItem cluster = CloudAssets.getDefault().getItem(ClusterItem.class); - if (cluster.getConfig() == null) { - cluster.update(); - } - if (cluster.getConfig() == null) { - throw new RuntimeException("Invalid cluster configuration"); - } ProgressHandle h; String projectName; try { @@ -122,7 +89,7 @@ private void runInCluster() { } try { h.start(); - runWithClient(cluster, client -> { + KubernetesUtils.runWithClient(cluster, client -> { Deployment existingDeployment = null; DeploymentList dList = client.apps().deployments().list(); for (Deployment deployment : dList.getItems()) { @@ -133,7 +100,7 @@ private void runInCluster() { if (existingDeployment != null) { client.apps() .deployments() - .inNamespace(DEFAULT) + .inNamespace(cluster.getNamespace()) .withName(projectName) .edit(d -> new DeploymentBuilder(d) .editSpec() @@ -149,7 +116,7 @@ private void runInCluster() { client.apps() .deployments() - .inNamespace(DEFAULT) + .inNamespace(cluster.getNamespace()) .withName(projectName) .edit(d -> new DeploymentBuilder(d) .editSpec() @@ -192,7 +159,7 @@ private void runInCluster() { client.apps() .deployments() - .inNamespace(DEFAULT) + .inNamespace(cluster.getNamespace()) .resource(newDeployment) .create(); } @@ -202,87 +169,4 @@ private void runInCluster() { } } - private void runWithClient(ClusterItem cluster, Consumer consumer) { - Config config = prepareConfig(cluster.getConfig(), cluster); - try (KubernetesClient client = new KubernetesClientBuilder().withConfig(config).build();) { - consumer.accept(client); - } catch (Exception e) { - Exceptions.printStackTrace(e); - } - } - - private Config prepareConfig(String content, ClusterItem cluster) { - String token = getBearerToken(cluster); - LoadSettings settings = LoadSettings.builder().build(); - Load load = new Load(settings); - Map data = (Map) load.loadFromString(content); - - List> users = (List>) data.get("users"); //NOI18N - if (users == null) { - throw new RuntimeException("Invalid cluster configuration"); - } - Map exec = null; - for (Map userEntry : users) { - Map user = (Map) userEntry.get("user"); //NOI18N - if (user != null && user.containsKey("exec")) { //NOI18N - exec = (Map) user.remove("exec"); //NOI18N - } - } - String clusterId = null; - if (exec != null && "oci".equals(exec.get("command"))) { //NOI18N - List commandArgs = (List) exec.get("args"); //NOI18N - boolean clusterIdNext = false; - for (Object arg : commandArgs) { - if ("--cluster-id".equals(arg)) { - clusterIdNext = true; - continue; - } - if (clusterIdNext) { - clusterId = (String) arg; - break; - } - - } - } - if (!cluster.getKey().getValue().equals(clusterId)) { - throw new RuntimeException("Failed to read cluster config"); //NOI18N - } - Dump dump = new Dump(DumpSettings.builder().build()); - String noExec = dump.dumpToString(data); - Config config = Config.fromKubeconfig(noExec); - config.setOauthToken(token); - return config; - } - - private String getBearerToken(ClusterItem cluster) { - try { - OCIProfile profile = OCIManager.getDefault().getActiveProfile(cluster); - Region region = Region.fromRegionCodeOrId(cluster.getRegionCode()); - URI uri = new URI(String.format( - "https://containerengine.%s.oraclecloud.com/cluster_request/%s", //NOI18N - region.getRegionId(), cluster.getKey().getValue() - )); - - RequestSigningFilter requestSigningFilter - = RequestSigningFilter.fromAuthProvider(profile.getAuthenticationProvider()); - - HttpClient client = JerseyHttpProvider.getInstance().newBuilder() - .registerRequestInterceptor(Priorities.AUTHENTICATION, requestSigningFilter) - .baseUri(uri).build(); - - HttpRequest request = client.createRequest(Method.GET); - - request.execute().toCompletableFuture(); - List tokenUrlList = request.headers().get("authorization"); //NOI18N - String authorization = URLEncoder.encode(tokenUrlList.get(0), "UTF-8"); //NOI18N - List dateList = request.headers().get("date"); //NOI18N - String date = URLEncoder.encode(dateList.get(0), "UTF-8"); //NOI18N - String baseString = String.format("%s?authorization=%s&date=%s", uri.toASCIIString(), authorization, date); //NOI18N - byte[] urlBytes = baseString.getBytes(StandardCharsets.UTF_8); - return Base64.getUrlEncoder().encodeToString(urlBytes); - } catch (URISyntaxException | UnsupportedEncodingException ex) { - throw new RuntimeException(ex); - } - } - } diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetClusterNamespaceAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetClusterNamespaceAction.java new file mode 100644 index 000000000000..bf0ba3581c38 --- /dev/null +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetClusterNamespaceAction.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.cloud.oracle.assets; + +import io.fabric8.kubernetes.api.model.Namespace; +import io.fabric8.kubernetes.api.model.NamespaceList; +import io.fabric8.kubernetes.api.model.apps.Deployment; +import io.fabric8.kubernetes.api.model.apps.DeploymentList; +import io.fabric8.kubernetes.client.dsl.MixedOperation; +import io.fabric8.kubernetes.client.dsl.NonNamespaceOperation; +import io.fabric8.kubernetes.client.dsl.Resource; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import org.netbeans.api.progress.ProgressHandle; +import org.netbeans.api.project.Project; +import org.netbeans.modules.cloud.oracle.compute.ClusterItem; +import org.netbeans.modules.cloud.oracle.items.OCIItem; +import org.netbeans.modules.cloud.oracle.items.TenancyItem; +import org.netbeans.modules.cloud.oracle.steps.ProjectStep; +import org.openide.DialogDescriptor; +import org.openide.DialogDisplayer; +import org.openide.NotifyDescriptor; +import org.openide.awt.ActionID; +import org.openide.awt.ActionRegistration; +import org.openide.util.Lookup; +import org.openide.util.NbBundle; + +/** + * + * @author Jan Horvath + */ +@ActionID( + category = "Tools", + id = "org.netbeans.modules.cloud.oracle.actions.SetClusterNamespace" +) +@ActionRegistration( + displayName = "#ClusterNamespace", + asynchronous = true +) + +@NbBundle.Messages({ + "ClusterNamespace=Set a cluster namespace", + "Namespace=Namespace" +}) +public class SetClusterNamespaceAction implements ActionListener { + + private final ClusterItem context; + + public SetClusterNamespaceAction(ClusterItem context) { + this.context = context; + } + + @Override + public void actionPerformed(ActionEvent e) { + Steps.getDefault() + .executeMultistep(new NamespaceStep(context), Lookup.EMPTY) + .thenAccept(values -> context.setNamespace(values.getValueForStep(NamespaceStep.class))); + } + + public static final class NamespaceStep extends AbstractStep { + + private final ClusterItem cluster; + private final List namespaces = new ArrayList<>(); + private String selectedNamespace = null; + + public NamespaceStep(ClusterItem cluster) { + this.cluster = cluster; + } + + @Override + public void prepare(ProgressHandle handle, Steps.Values values) { + KubernetesUtils.runWithClient(cluster, client -> { + NonNamespaceOperation> namespaceOperation = client.namespaces(); + NamespaceList namespaceList = namespaceOperation.list(); + for (Namespace ns : namespaceList.getItems()) { + namespaces.add(ns.getMetadata().getName()); + } + }); + } + + @Override + public NotifyDescriptor createInput() { + List items = new ArrayList<>(namespaces.size()); + for (String namespace : namespaces) { + items.add(new NotifyDescriptor.QuickPick.Item(namespace, "")); + } + return new NotifyDescriptor.QuickPick(Bundle.Namespace(), Bundle.Namespace(), items, false); + } + + @Override + public boolean onlyOneChoice() { + return namespaces.size() == 1; + } + + @Override + public void setValue(String selected) { + selectedNamespace = selected; + } + + @Override + public String getValue() { + return selectedNamespace; + } + + } + +} diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetReferenceNameAction.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetReferenceNameAction.java index 6cd2a6b651c4..c4f8778b6849 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetReferenceNameAction.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/SetReferenceNameAction.java @@ -61,6 +61,7 @@ public void actionPerformed(ActionEvent e) { oldRefName = ""; } NotifyDescriptor.InputLine inp = new NotifyDescriptor.InputLine(oldRefName, Bundle.ReferenceName()); + inp.setInputText(oldRefName); Object selected = DialogDisplayer.getDefault().notify(inp); if (DialogDescriptor.OK_OPTION != selected) { return; diff --git a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/compute/ClusterItem.java b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/compute/ClusterItem.java index a07df1c04612..d736fdf363be 100644 --- a/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/compute/ClusterItem.java +++ b/enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/compute/ClusterItem.java @@ -35,6 +35,7 @@ */ public final class ClusterItem extends OCIItem { private String config = null; + private String namespace = "default"; //NOI8N public ClusterItem(OCID id, String compartmentId, String name, String tenancyId, String regionCode) { super(id, compartmentId, name, tenancyId, regionCode); @@ -51,6 +52,16 @@ public String getConfig() { public void setConfig(String config) { this.config = config; } + + public String getNamespace() { + return namespace; + } + + public void setNamespace(String namespace) { + String oldNamespace = this.namespace; + this.namespace = namespace; + firePropertyChange("namespace", oldNamespace, namespace); //NOI18N + } public void update() { OCIProfile profile = OCIManager.getDefault().getActiveProfile(this); diff --git a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspAssetsDecorationProvider.java b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspAssetsDecorationProvider.java index ee26691ac21e..038dcb02e023 100644 --- a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspAssetsDecorationProvider.java +++ b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/LspAssetsDecorationProvider.java @@ -53,6 +53,7 @@ public class LspAssetsDecorationProvider implements TreeDataProvider.Factory { public static final String CTXVALUE_PREFIX_IMAGE_COUNT = "imageCount:"; // NOI18N public static final String CTXVALUE_PREFIX_REPOSITORY_PUBLIC = "repositoryPublic:"; // NOI18N public static final String CTXVALUE_PREFIX_SECRET_LIFECYCLE_STATE = "lifecycleState:"; // NOI18N + public static final String CTXVALUE_PREFIX_CLUSTER_NAMESPACE = "clusterNamespace:"; // NOI18N @Override public synchronized TreeDataProvider createProvider(String treeId) { @@ -78,6 +79,13 @@ public TreeItemData createDecorations(Node n, boolean expanded) { d.addContextValues(CTXVALUE_PREFIX_REFERENCE_NAME + refName); set = true; } + if (item instanceof ClusterItem) { + String namespace = ((ClusterItem) item).getNamespace(); + if (namespace != null) { + d.addContextValues(CTXVALUE_PREFIX_CLUSTER_NAMESPACE + namespace); + set = true; + } + } if (item instanceof ComputeInstanceItem) { String publicIp = ((ComputeInstanceItem) item).getPublicIp(); if (publicIp != null) { diff --git a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml index 67936ff6faeb..58bfe5184558 100644 --- a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml +++ b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/layer.xml @@ -62,6 +62,7 @@ + diff --git a/java/java.lsp.server/vscode/package.json b/java/java.lsp.server/vscode/package.json index 57865e40b00e..e9d41f302d66 100644 --- a/java/java.lsp.server/vscode/package.json +++ b/java/java.lsp.server/vscode/package.json @@ -615,6 +615,11 @@ "title": "Set a Reference Name", "icon": "$(edit)" }, + { + "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.SetClusterNamespace", + "title": "Set a Cluster Namespace", + "icon": "$(edit)" + }, { "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.RemoveFromProject", "title": "Remove from Oracle Cloud Assets", @@ -898,6 +903,10 @@ "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.SetReferenceName", "when": "false" }, + { + "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.SetClusterNamespace", + "when": "false" + }, { "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.RemoveFromProject", "when": "false" @@ -1149,6 +1158,11 @@ "when": "viewItem =~ /cap:refName/ && view == cloud.assets", "group": "inline@14" }, + { + "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.SetClusterNamespace", + "when": "viewItem =~ /clusterNamespace:.*/ && view == cloud.assets", + "group": "inline@14" + }, { "command": "nbls:Tools:org.netbeans.modules.cloud.oracle.actions.RemoveFromProject", "when": "viewItem =~ /^(?!.*(Suggested|ContainerTagItem)).*/ && view == cloud.assets", diff --git a/java/java.lsp.server/vscode/src/extension.ts b/java/java.lsp.server/vscode/src/extension.ts index 5dde4b5e553e..3baa7c3549a9 100644 --- a/java/java.lsp.server/vscode/src/extension.ts +++ b/java/java.lsp.server/vscode/src/extension.ts @@ -1552,7 +1552,11 @@ function doActivateWithJDK(specifiedJDK: string | null, context: ExtensionContex if (lifecycleState) { item.description = lifecycleState === "PENDING_DELETION" ? '(pending deletion)' : undefined; } - + const clusterNamespace = getValueAfterPrefix(item.contextValue, "clusterNamespace:"); + if (clusterNamespace !== undefined && clusterNamespace !== null && clusterNamespace.length > 0) { + item.description = clusterNamespace; + return item; + } return item; }