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


##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/Pods.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * 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.Watch;
+import io.fabric8.kubernetes.client.Watcher;
+import io.fabric8.kubernetes.client.WatcherException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.cloud.oracle.assets.OpenProjectsFinder;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Horvath
+ */
+public class Pods {
+    private final RequestProcessor RP = new RequestProcessor(Pods.class);
+    private final ClusterItem cluster;
+    private Set<String> names = null;
+    private final List<PodItem> pods = new ArrayList<> ();
+    private transient PropertyChangeSupport changeSupport = null;
+    private CountDownLatch latch = null;
+    
+    private Pods(ClusterItem cluster) {
+        this.cluster = cluster;
+    }
+    
+    public static Pods from(ClusterItem cluster) {
+        Pods instance = new Pods(cluster);
+        instance.init();
+        return instance;
+    }
+    
+    public List<PodItem> getItems() {
+        return Collections.unmodifiableList(pods);
+    }
+    
+    private void addPod(PodItem pod) {
+        pods.add(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() - 1);
+        
+    }
+    
+    private void removePod(PodItem pod) {
+        pods.remove(pod);
+        PortForwards.getDefault().closePortForward(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+    
+    private void removeAll() {
+        pods.clear();
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+
+    private void init() {
+        
+        try {
+            changeSupport = new PropertyChangeSupport(this);
+            cluster.addChangeListener((PropertyChangeEvent evt) -> {
+                if ("namespace".equals(evt.getPropertyName())) {
+                    watchNamespace((String) evt.getNewValue());
+                }
+            });
+            CompletableFuture<Project[]> projectsFuture = 
OpenProjectsFinder.getDefault().findTopLevelProjects();
+            projectsFuture.thenApply(projects -> {
+                List<String> projectNames = new ArrayList<>();
+                for (int i = 0; i < projects.length; i++) {
+                    ProjectInformation pi = 
ProjectUtils.getInformation(projects[i]);
+                    projectNames.add(pi.getDisplayName());
+                }
+                return projectNames;
+            }).thenAccept(projectNames -> {
+                names = new HashSet<> (projectNames);
+                
+            }).get();
+            watchNamespace(cluster.getNamespace());
+        } catch (InterruptedException | ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+    
+    private void watchNamespace(String namespace) {
+        removeAll();
+        if (latch != null) {
+            latch.countDown();
+        }
+        latch = new CountDownLatch(1);

Review Comment:
   watchNamespace() should synchronize access to `latch`;  the new latch should 
be copied to local variable before synchronized block terminates, 
Watcher::onClose  should use that local copy.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/Pods.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * 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.Watch;
+import io.fabric8.kubernetes.client.Watcher;
+import io.fabric8.kubernetes.client.WatcherException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.cloud.oracle.assets.OpenProjectsFinder;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Horvath
+ */
+public class Pods {
+    private final RequestProcessor RP = new RequestProcessor(Pods.class);
+    private final ClusterItem cluster;
+    private Set<String> names = null;
+    private final List<PodItem> pods = new ArrayList<> ();
+    private transient PropertyChangeSupport changeSupport = null;
+    private CountDownLatch latch = null;
+    
+    private Pods(ClusterItem cluster) {
+        this.cluster = cluster;
+    }
+    
+    public static Pods from(ClusterItem cluster) {
+        Pods instance = new Pods(cluster);
+        instance.init();
+        return instance;
+    }
+    
+    public List<PodItem> getItems() {
+        return Collections.unmodifiableList(pods);
+    }
+    
+    private void addPod(PodItem pod) {
+        pods.add(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() - 1);
+        
+    }
+    
+    private void removePod(PodItem pod) {
+        pods.remove(pod);
+        PortForwards.getDefault().closePortForward(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+    
+    private void removeAll() {
+        pods.clear();
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+
+    private void init() {
+        
+        try {
+            changeSupport = new PropertyChangeSupport(this);
+            cluster.addChangeListener((PropertyChangeEvent evt) -> {
+                if ("namespace".equals(evt.getPropertyName())) {
+                    watchNamespace((String) evt.getNewValue());
+                }
+            });
+            CompletableFuture<Project[]> projectsFuture = 
OpenProjectsFinder.getDefault().findTopLevelProjects();
+            projectsFuture.thenApply(projects -> {
+                List<String> projectNames = new ArrayList<>();
+                for (int i = 0; i < projects.length; i++) {
+                    ProjectInformation pi = 
ProjectUtils.getInformation(projects[i]);
+                    projectNames.add(pi.getDisplayName());
+                }
+                return projectNames;
+            }).thenAccept(projectNames -> {
+                names = new HashSet<> (projectNames);

Review Comment:
   Why is this in additional `thenAccept` ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/ShowPodLogsAction.java:
##########
@@ -0,0 +1,75 @@
+/*
+ * 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.client.dsl.PodResource;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.io.OutputStream;
+import org.netbeans.api.io.IOProvider;
+import org.netbeans.api.io.InputOutput;
+import org.netbeans.api.io.OutputWriter;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionRegistration;
+import org.openide.util.NbBundle;
+
+/**
+ *
+ * @author Jan Horvath
+ */
+@ActionID(
+        category = "Tools",
+        id = "org.netbeans.modules.cloud.oracle.actions.ShowPodLogsAction"
+)
+@ActionRegistration(
+        displayName = "#PodLogs",
+        asynchronous = true
+)
+
+@NbBundle.Messages({
+    "PodLogs=Start port forwarding",
+    "OutputName=Pod {0} Log"
+})
+public class ShowPodLogsAction implements ActionListener {
+
+    private PodItem podItem;
+
+    public ShowPodLogsAction(PodItem podItem) {
+        this.podItem = podItem;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+        InputOutput io = 
IOProvider.getDefault().getIO(Bundle.OutputName(podItem.getName()), true);
+        OutputWriter writer = io.getOut();
+        
+        OutputStream os = new OutputStream() {
+            @Override
+            public void write(int b) throws IOException {
+                writer.write(b);

Review Comment:
   Seems that a byte is written as a full character to the Writer -- won't work 
for multibyte-encoded characters in the stream.



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/PortForwards.java:
##########
@@ -0,0 +1,240 @@
+/*
+ * 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.openide.util.Exceptions;
+import org.openide.util.NbBundle;
+import org.openide.util.RequestProcessor;
+
+/**
+ * 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
+ */
+@NbBundle.Messages({
+    "PortNotFree=Port {0} is occupied by another process and cannot be used.",
+    "Forwarding=→ {0}",
+    "AlreadyActive=Port forwarding already active for: {0}",
+    "NoPorts=No ports found for pod: {0},",
+    "PodNotFound=Pod not found: {0}" 
+})
+public class PortForwards {
+    private static final RequestProcessor RP = new 
RequestProcessor(PortForwards.class.getName(), 6);

Review Comment:
   Note: this means you can have 6 port forwards at maximum, other forwardings 
will not spin their thread until the former ones stop. 



##########
java/java.lsp.server/vscode/src/extension.ts:
##########
@@ -1078,6 +1086,21 @@ export function activate(context: ExtensionContext): 
VSNetBeansAPI {
     });
 }
 
+let queryDocument: vscode.TextDocument | undefined;
+
+async function getRestDocument(): Promise<vscode.TextDocument> {

Review Comment:
   I couldn't find usage of this ?



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/Pods.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * 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.Watch;
+import io.fabric8.kubernetes.client.Watcher;
+import io.fabric8.kubernetes.client.WatcherException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.cloud.oracle.assets.OpenProjectsFinder;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Horvath
+ */
+public class Pods {
+    private final RequestProcessor RP = new RequestProcessor(Pods.class);
+    private final ClusterItem cluster;
+    private Set<String> names = null;
+    private final List<PodItem> pods = new ArrayList<> ();
+    private transient PropertyChangeSupport changeSupport = null;
+    private CountDownLatch latch = null;
+    
+    private Pods(ClusterItem cluster) {
+        this.cluster = cluster;
+    }
+    
+    public static Pods from(ClusterItem cluster) {
+        Pods instance = new Pods(cluster);
+        instance.init();
+        return instance;
+    }
+    
+    public List<PodItem> getItems() {
+        return Collections.unmodifiableList(pods);
+    }
+    
+    private void addPod(PodItem pod) {
+        pods.add(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() - 1);
+        
+    }
+    
+    private void removePod(PodItem pod) {
+        pods.remove(pod);
+        PortForwards.getDefault().closePortForward(pod);
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+    
+    private void removeAll() {
+        pods.clear();
+        changeSupport.firePropertyChange("pods", pods.size(), pods.size() + 1);
+    }
+
+    private void init() {
+        
+        try {
+            changeSupport = new PropertyChangeSupport(this);
+            cluster.addChangeListener((PropertyChangeEvent evt) -> {
+                if ("namespace".equals(evt.getPropertyName())) {
+                    watchNamespace((String) evt.getNewValue());
+                }
+            });
+            CompletableFuture<Project[]> projectsFuture = 
OpenProjectsFinder.getDefault().findTopLevelProjects();
+            projectsFuture.thenApply(projects -> {
+                List<String> projectNames = new ArrayList<>();
+                for (int i = 0; i < projects.length; i++) {
+                    ProjectInformation pi = 
ProjectUtils.getInformation(projects[i]);
+                    projectNames.add(pi.getDisplayName());
+                }
+                return projectNames;
+            }).thenAccept(projectNames -> {
+                names = new HashSet<> (projectNames);
+                
+            }).get();
+            watchNamespace(cluster.getNamespace());
+        } catch (InterruptedException | ExecutionException ex) {
+            Exceptions.printStackTrace(ex);
+        }
+    }
+    
+    private void watchNamespace(String namespace) {
+        removeAll();
+        if (latch != null) {
+            latch.countDown();
+        }
+        latch = new CountDownLatch(1);
+        addWatcher(cluster, namespace, new Watcher<Pod>() {
+            @Override
+            public void eventReceived(Watcher.Action action, Pod t) {
+                String app = t.getMetadata().getLabels().get("app");
+                if (!names.contains(app)) {
+                    return;
+                }
+                if (action == Watcher.Action.ADDED) {
+                    addPod(new PodItem(cluster, 
t.getMetadata().getNamespace(), t.getMetadata().getName()));
+                } else if (action == Watcher.Action.DELETED) {
+                    removePod(new PodItem(cluster, 
t.getMetadata().getNamespace(), t.getMetadata().getName()));
+                }
+            }
+
+            @Override
+            public void onClose(WatcherException we) {
+                System.out.println("close");

Review Comment:
   Leftover



##########
enterprise/cloud.oracle/src/org/netbeans/modules/cloud/oracle/assets/k8s/Pods.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * 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.Watch;
+import io.fabric8.kubernetes.client.Watcher;
+import io.fabric8.kubernetes.client.WatcherException;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.cloud.oracle.assets.OpenProjectsFinder;
+import org.openide.util.Exceptions;
+import org.openide.util.RequestProcessor;
+
+/**
+ *
+ * @author Jan Horvath
+ */
+public class Pods {
+    private final RequestProcessor RP = new RequestProcessor(Pods.class);
+    private final ClusterItem cluster;
+    private Set<String> names = null;
+    private final List<PodItem> pods = new ArrayList<> ();
+    private transient PropertyChangeSupport changeSupport = null;
+    private CountDownLatch latch = null;
+    
+    private Pods(ClusterItem cluster) {
+        this.cluster = cluster;
+    }
+    
+    public static Pods from(ClusterItem cluster) {
+        Pods instance = new Pods(cluster);
+        instance.init();
+        return instance;
+    }
+    
+    public List<PodItem> getItems() {
+        return Collections.unmodifiableList(pods);

Review Comment:
   add/removePod should synchronize with this, and the client should get a copy 
(since this.pods can be modified further asynchronously).



-- 
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: notifications-unsubscr...@netbeans.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@netbeans.apache.org
For additional commands, e-mail: notifications-h...@netbeans.apache.org

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

Reply via email to