sdedic commented on code in PR #8014:
URL: https://github.com/apache/netbeans/pull/8014#discussion_r1879456919


##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/KubernetesLoaders.java:
##########
@@ -0,0 +1,73 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.api.model.PodList;
+import io.fabric8.kubernetes.api.model.apps.Deployment;
+import java.util.ArrayList;
+import java.util.List;
+import org.netbeans.modules.cloud.oracle.compute.ClusterItem;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "ForwardingPorts=Forwarding http://localhost:{0} to a pod {1}"
+
+})
+public class KubernetesLoaders {
+
+    public static List<PodItem> loadPods(ClusterItem cluster, List<String> 
deploymentNames) {
+        final List<PodItem> result = new ArrayList<>();
+        KubernetesUtils.runWithClient(cluster, client -> {
+            for (String name : deploymentNames) {
+                Deployment deployment = client
+                        .apps()
+                        .deployments()
+                        .inNamespace(cluster.getNamespace())
+                        .withName(name)
+                        .get();
+                if (deployment == null) {
+                    continue;

Review Comment:
   no log / failed (ignored) result to the caller ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());

Review Comment:
   I18N



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());

Review Comment:
   I18N & message format, please.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {

Review Comment:
   Please use RequestProcessor as the runAsync exec service parameter, to 
retain default Lookup in the async processing.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());
+                    return;
+                }
+                try {
+                    for (Integer port : ports) {
+                        if (!isPortAvailable(port)) {
+                            
NotificationUtils.showErrorMessage(Bundle.PortNotFree(port));
+                            break;
+                        }
+                        LocalPortForward fwd = client.pods()
+                                .inNamespace(pod.getMetadata().getNamespace())
+                                .withName(pod.getMetadata().getName())
+                                .portForward(port, port);
+                        forwards.add(fwd);
+                        forwardItems.add(new PortForwardItem(podItem, 
fwd.getLocalPort(), port));
+
+                        
NotificationUtils.showMessage(Bundle.ForwardingPorts(port.toString(), 
podItem.getName()));
+                    }
+                    latches.put(podItem.getName(), latch);
+                    List<PortForwardItem> oldValue = 
activePortForwards.put(podItem.getName(), forwardItems);
+                    firePropertyChange(podItem, oldValue, forwardItems);
+                    latch.await();
+                    for (PortForward forward : forwards) {
+                        forward.close();
+                    }
+                    activePortForwards.remove(podItem.getName());
+                    firePropertyChange(podItem, forwardItems, oldValue);
+                } catch (InterruptedException | IOException ex) {
+                    Exceptions.printStackTrace(ex);
+                } catch (IllegalStateException e) {
+                    NotificationUtils.showErrorMessage(e.getMessage());
+                } finally {
+                    handle.finish();
+                }
+
+            });
+        });
+    }
+
+    /**
+     * Retrieves the list of active port forwards for the specified Pod.
+     *
+     * @param podName The name of the Pod.
+     * @return A list of active {@code PortForward} instances for the Pod, or 
an
+     * empty list if none are found.
+     */
+    public List<PortForwardItem> getActivePortForwards(String podName) {
+        return activePortForwards.getOrDefault(podName, 
Collections.emptyList());
+    }
+
+    /**
+     * Stops and closes all active port forwards for the specified Pod.
+     *
+     * <p>
+     * Resources associated with the port forwarding are released, and the port
+     * forward is removed from the active list.</p>
+     *
+     * @param podName The name of the Pod for which port forwarding should be
+     * stopped.
+     */
+    public void closePortForward(String podName) {
+        CountDownLatch latch = latches.get(podName);
+        if (latch != null) {
+            latch.countDown();
+        }
+        activePortForwards.remove(podName);

Review Comment:
   I suggest not to remove activePortForwards/latches here, but just request 
the shutdown using countDown, and let the closing code that call 
portForward.close() to remove the forward after it is closed (or fails to 
close).



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());
+                    return;
+                }
+                try {
+                    for (Integer port : ports) {
+                        if (!isPortAvailable(port)) {
+                            
NotificationUtils.showErrorMessage(Bundle.PortNotFree(port));
+                            break;
+                        }
+                        LocalPortForward fwd = client.pods()
+                                .inNamespace(pod.getMetadata().getNamespace())
+                                .withName(pod.getMetadata().getName())
+                                .portForward(port, port);
+                        forwards.add(fwd);
+                        forwardItems.add(new PortForwardItem(podItem, 
fwd.getLocalPort(), port));
+
+                        
NotificationUtils.showMessage(Bundle.ForwardingPorts(port.toString(), 
podItem.getName()));
+                    }
+                    latches.put(podItem.getName(), latch);
+                    List<PortForwardItem> oldValue = 
activePortForwards.put(podItem.getName(), forwardItems);
+                    firePropertyChange(podItem, oldValue, forwardItems);
+                    latch.await();
+                    for (PortForward forward : forwards) {
+                        forward.close();
+                    }
+                    activePortForwards.remove(podItem.getName());
+                    firePropertyChange(podItem, forwardItems, oldValue);
+                } catch (InterruptedException | IOException ex) {
+                    Exceptions.printStackTrace(ex);

Review Comment:
   Shouldn't this error notification be presented to the user somehow ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/KubernetesUtils.java:
##########
@@ -57,7 +54,7 @@
  */
 public class KubernetesUtils {
 
-    static void runWithClient(ClusterItem cluster, Consumer<KubernetesClient> 
consumer) {
+    public static void runWithClient(ClusterItem cluster, 
Consumer<KubernetesClient> consumer) {

Review Comment:
   I'd suggest to add some label and use Logger to log start/end of (labelled) 
operation and some client config info. Could be useful for future debugging.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());
+                    return;
+                }
+                try {
+                    for (Integer port : ports) {
+                        if (!isPortAvailable(port)) {
+                            
NotificationUtils.showErrorMessage(Bundle.PortNotFree(port));
+                            break;

Review Comment:
   This means that as soon as one port is not available, no more ports are 
forwarded - but forwardings established to this point remain active. Wouldn't 
it be more stable/expected  to just skip the failures and continue with next 
requested portforward ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;

Review Comment:
   Consider naming this as 'stopLatches' etc



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());

Review Comment:
   Log or NotificationUtils.showMessage ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());
+                    return;
+                }
+                try {
+                    for (Integer port : ports) {
+                        if (!isPortAvailable(port)) {
+                            
NotificationUtils.showErrorMessage(Bundle.PortNotFree(port));
+                            break;
+                        }
+                        LocalPortForward fwd = client.pods()
+                                .inNamespace(pod.getMetadata().getNamespace())
+                                .withName(pod.getMetadata().getName())
+                                .portForward(port, port);
+                        forwards.add(fwd);
+                        forwardItems.add(new PortForwardItem(podItem, 
fwd.getLocalPort(), port));
+
+                        
NotificationUtils.showMessage(Bundle.ForwardingPorts(port.toString(), 
podItem.getName()));
+                    }
+                    latches.put(podItem.getName(), latch);
+                    List<PortForwardItem> oldValue = 
activePortForwards.put(podItem.getName(), forwardItems);

Review Comment:
   The old value does not make much sense: even if old value is later restored, 
its `latch` is lost for good.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/compute/ClusterNode.java:
##########
@@ -87,5 +86,10 @@ public static ChildrenProvider.SessionAware<CompartmentItem, 
ClusterItem> getClu
                     .collect(Collectors.toList());
         };
     }
+
+    @Override

Review Comment:
   Leftover no-op ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {

Review Comment:
   This does not prevent from starting portforward for the same Pod twice: the 
method may run, and will spawn a forward thread, again until 
`activePortForwards.put` after communicating with the k8s client.
   
   If it was meant as sync/prevention of starting portforward twice, it should 
be fixed.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/RunInClusterAction.java:
##########
@@ -188,8 +197,18 @@ private void runInCluster() {
                             .create();
                 }
             });
+        } catch(Throwable t) {

Review Comment:
   Pass on ThreadDeath.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,235 @@
+/*
+ * 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.k8s;
+
+import io.fabric8.kubernetes.api.model.Pod;
+import io.fabric8.kubernetes.client.LocalPortForward;
+import io.fabric8.kubernetes.client.PortForward;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+import org.netbeans.api.progress.ProgressHandle;
+import org.netbeans.modules.cloud.oracle.NotificationUtils;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.modules.cloud.oracle.compute.PortForwardItem;
+import org.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+
+/**
+ * Manages port forwarding for Kubernetes Pods.
+ *
+ * <p>This class provides methods to start, list, and stop port forwards
+ * for specific Pods. It maintains the state of active port forwards
+ * and ensures thread-safe operations.</p>
+ *
+ * <p>Example Usage:</p>
+ * <pre>
+ * PortForwards manager = PortForwards.getDefault();
+ * manager.startPortForward(podItem);
+ * List<PortForwardItem> forwards = manager.getActivePortForwards("pod-name");
+ * manager.closePortForward("pod-name");
+ * </pre>
+ *
+ * @author Jan Horvath
+ */
[email protected]({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}"
+})
+public class PortForwards {
+
+    private static PortForwards instance = null;
+    private final Map<String, List<PortForwardItem>> activePortForwards;
+    private final Map<String, CountDownLatch> latches;
+    private final PropertyChangeSupport propertyChangeSupport;
+
+    private PortForwards() {
+        activePortForwards = new ConcurrentHashMap<>();
+        latches = new ConcurrentHashMap<>();
+        propertyChangeSupport = new PropertyChangeSupport(this);
+    }
+
+    public static synchronized PortForwards getDefault() {
+        if (instance == null) {
+            instance = new PortForwards();
+        }
+        return instance;
+    }
+    
+    /**
+     * Adds a {@code PropertyChangeListener} to listen for changes in port 
forwarding for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener is interested.
+     * @param listener The listener to be added.
+     */
+    public void addPropertyChangeListener(PodItem pod, PropertyChangeListener 
listener) {
+        propertyChangeSupport.addPropertyChangeListener(pod.getName(), 
listener);
+    }
+
+    /**
+     * Removes a {@code PropertyChangeListener} for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the listener should be removed.
+     * @param listener The listener to be removed.
+     */
+    public void removePropertyChangeListener(PodItem pod, 
PropertyChangeListener listener) {
+        propertyChangeSupport.removePropertyChangeListener(pod.getName(), 
listener);
+    }
+    
+    /**
+     * Notifies listeners of a property change for a specific Pod.
+     *
+     * @param pod The {@code PodItem} for which the change occurred.
+     * @param oldValue The old value of the property.
+     * @param newValue The new value of the property.
+     */
+    private void firePropertyChange(PodItem pod, Object oldValue, Object 
newValue) {
+        propertyChangeSupport.firePropertyChange(pod.getName(), oldValue, 
newValue);
+    }
+
+    /**
+     * Starts port forwarding for a specified Kubernetes Pod.
+     *
+     * <p>
+     * This method retrieves the Pod's ports and forwards them to the local
+     * machine. If any port is unavailable, the operation is halted for that
+     * port and a notification is displayed.</p>
+     *
+     * @param podItem The {@code PodItem} representing the Pod for which port
+     * forwarding should start.
+     */
+    public void startPortForward(PodItem podItem) {
+        if (activePortForwards.containsKey(podItem.getName())) {
+            NotificationUtils.showMessage("Port forwarding already active for: 
" + podItem.getName());
+            return;
+        }
+        CountDownLatch latch = new CountDownLatch(1);
+        ProgressHandle handle = 
ProgressHandle.createHandle(Bundle.Forwarding(podItem.getName()), () -> {
+            latch.countDown();
+            return true;
+        });
+        handle.start();
+        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+            KubernetesUtils.runWithClient(podItem.getCluster(), client -> {
+                Pod pod = 
client.pods().inNamespace(podItem.getNamespace()).withName(podItem.getName()).get();
+
+                if (pod == null) {
+                    System.out.println("Pod not found: " + podItem.getName());
+                    return;
+                }
+                List<Integer> ports = pod.getSpec().getContainers().stream()
+                        .flatMap(container -> container.getPorts().stream())
+                        .map(port -> port.getContainerPort())
+                        .collect(Collectors.toList());
+                List<PortForwardItem> forwardItems = new ArrayList<>();
+                List<PortForward> forwards = new ArrayList<>();
+                if (ports.isEmpty()) {
+                    NotificationUtils.showMessage("No ports found for pod: " + 
podItem.getName());
+                    return;
+                }
+                try {
+                    for (Integer port : ports) {
+                        if (!isPortAvailable(port)) {
+                            
NotificationUtils.showErrorMessage(Bundle.PortNotFree(port));
+                            break;
+                        }
+                        LocalPortForward fwd = client.pods()
+                                .inNamespace(pod.getMetadata().getNamespace())
+                                .withName(pod.getMetadata().getName())
+                                .portForward(port, port);
+                        forwards.add(fwd);
+                        forwardItems.add(new PortForwardItem(podItem, 
fwd.getLocalPort(), port));
+
+                        
NotificationUtils.showMessage(Bundle.ForwardingPorts(port.toString(), 
podItem.getName()));
+                    }
+                    latches.put(podItem.getName(), latch);
+                    List<PortForwardItem> oldValue = 
activePortForwards.put(podItem.getName(), forwardItems);
+                    firePropertyChange(podItem, oldValue, forwardItems);
+                    latch.await();

Review Comment:
   Consider using other approach than CDL here. Each Pod will block its thread 
until it is requested to close. Ideally the request to close should execute the 
closing procedure, eventually asynchronously.
   
   Please add `@OnStop` handler that closes port forwards upon NB shutdown. 
Eventually load *active* port forwards from the k8s after startup, if possible.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/KubernetesUtils.java:
##########
@@ -67,8 +64,8 @@ static void runWithClient(ClusterItem cluster, 
Consumer<KubernetesClient> consum
         Config config = prepareConfig(cluster.getConfig(), cluster);
         try (KubernetesClient client = new 
KubernetesClientBuilder().withConfig(config).build();) {
             consumer.accept(client);
-        } catch (Exception e) {
-            Exceptions.printStackTrace(e);
+        } catch (Throwable t) {

Review Comment:
   No op ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/ShowPodLogsAction.java:
##########
@@ -0,0 +1,65 @@
+/*
+ * 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.k8s;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import org.netbeans.api.io.InputOutput;
+import org.netbeans.modules.cloud.oracle.compute.PodItem;
+import org.netbeans.spi.io.InputOutputProvider;
+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.ShowPodLogsAction"
+)
+@ActionRegistration(
+        displayName = "#PodLogs",
+        asynchronous = true
+)
+
[email protected]({
+    "PodLogs=Start port forwarding"
+})
+public class ShowPodLogsAction implements ActionListener {
+    
+    private PodItem pod;
+
+    public ShowPodLogsAction(PodItem pod) {
+        this.pod = pod;
+    }
+    
+    @Override
+    public void actionPerformed(ActionEvent e) {
+//        KubernetesLoaders.startPortForward(pod);
+        
+        InputOutputProvider<?, ?, ?, ?> newSpiDef
+                    = Lookup.getDefault().lookup(InputOutputProvider.class);
+        Object io = newSpiDef.getIO("test io", true, Lookup.EMPTY);

Review Comment:
   This seems as an unfinished implementation ?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to