From eede8990263e8b9249da70d3d64b7207e0a54b7c Mon Sep 17 00:00:00 2001
From: Carlo Della Giusta <carlo.dellagiusta@suse.com>
Date: Mon, 16 Jun 2025 07:46:38 +0200
Subject: [PATCH] merge WIP: log exception and prevent NPE #26712

---
 .../webui/controllers/SystemsController.java  |  9 ++----
 .../webui/services/impl/SaltSSHService.java   | 30 ++++++++++++-------
 ...er-4.3-fix-1237536-remove-with-empty-proxy |  2 ++
 3 files changed, 25 insertions(+), 16 deletions(-)
 create mode 100644 java/spacewalk-java.changes.carlo.Manager-4.3-fix-1237536-remove-with-empty-proxy
#L3PD: bsc#1237536

diff --git a/java/code/src/com/suse/manager/webui/controllers/SystemsController.java b/java/code/src/com/suse/manager/webui/controllers/SystemsController.java
index 8ba7fbe3b01..bb1f0551c70 100644
--- a/java/code/src/com/suse/manager/webui/controllers/SystemsController.java
+++ b/java/code/src/com/suse/manager/webui/controllers/SystemsController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2024 SUSE LLC
+ * Copyright (c) 2024--2025 SUSE LLC
  *
  * This software is licensed to you under the GNU General Public License,
  * version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -7,10 +7,6 @@
  * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
  * along with this software; if not, see
  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * Red Hat trademarks are not licensed under GPLv2. No permission is
- * granted to use or replicate Red Hat trademarks that are incorporated
- * in this software or its documentation.
  */
 
 package com.suse.manager.webui.controllers;
@@ -340,7 +336,8 @@ public String delete(Request request, Response response, User user) {
                     Long.toString(sid));
         }
         catch (RuntimeException e) {
-            if (e.getMessage().contains("cobbler")) {
+            LOG.error("Deleting the server {} failed.", sid, e);
+            if (e.getMessage() != null && e.getMessage().contains("cobbler")) {
                 createErrorMessage(request.raw(), "message.servernotdeleted_cobbler",
                         Long.toString(sid));
             }
diff --git a/java/code/src/com/suse/manager/webui/services/impl/SaltSSHService.java b/java/code/src/com/suse/manager/webui/services/impl/SaltSSHService.java
index ce99b2e35d8..df3e3e0b364 100644
--- a/java/code/src/com/suse/manager/webui/services/impl/SaltSSHService.java
+++ b/java/code/src/com/suse/manager/webui/services/impl/SaltSSHService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 SUSE LLC
+ * Copyright (c) 2016--2025 SUSE LLC
  *
  * This software is licensed to you under the GNU General Public License,
  * version 2 (GPLv2). There is NO WARRANTY for this software, express or
@@ -7,10 +7,6 @@
  * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
  * along with this software; if not, see
  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
- *
- * Red Hat trademarks are not licensed under GPLv2. No permission is
- * granted to use or replicate Red Hat trademarks that are incorporated
- * in this software or its documentation.
  */
 package com.suse.manager.webui.services.impl;
 
@@ -25,9 +21,11 @@
 import com.redhat.rhn.domain.server.MinionServer;
 import com.redhat.rhn.domain.server.MinionServerFactory;
 import com.redhat.rhn.domain.server.MinionSummary;
+import com.redhat.rhn.domain.server.ProxyInfo;
 import com.redhat.rhn.domain.server.Server;
 import com.redhat.rhn.domain.server.ServerFactory;
 import com.redhat.rhn.domain.server.ServerPath;
+import com.redhat.rhn.domain.server.ServerPathId;
 import com.redhat.rhn.domain.token.ActivationKeyFactory;
 
 import com.suse.manager.utils.SaltUtils;
@@ -86,6 +84,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
@@ -393,11 +392,22 @@ public static List<String> proxyPathToHostnames(Set<ServerPath> serverPaths, Opt
         }
 
         List<ServerPath> proxyPath = sortServerPaths(serverPaths);
-        List<String> hostnamePath = proxyPath.stream().map(path -> {
-            String port = Optional.ofNullable(path.getId().getProxyServer().getProxyInfo().getSshPort())
-                    .map(p -> ":" + p.toString()).orElse("");
-            return path.getHostname() + port;
-        }).collect(Collectors.toList());
+        List<String> hostnamePath = proxyPath.stream()
+                .filter(Objects::nonNull)
+                .map(path -> {
+                    String port = Optional.of(path)
+                            .map(ServerPath::getId)
+                            .map(ServerPathId::getProxyServer)
+                            .map(Server::getProxyInfo)
+                            .map(ProxyInfo::getSshPort)
+                            .map(p -> ":" + p)
+                            .orElse("");
+
+                    if (port.isEmpty()) {
+                        LOG.warn("Unable to identify port for proxy path {}. Using default.", path);
+                    }
+                    return path.getHostname() + port;
+                }).collect(Collectors.toList());
 
         lastProxy.ifPresent(hostnamePath::add);
 
