From e3aeef5955df5ee158bcb22f05b904054677b28b Mon Sep 17 00:00:00 2001
From: Thomas Florio <thomas.florio@suse.com>
Date: Wed, 9 Apr 2025 17:42:53 +0200
Subject: [PATCH] Ensure null safety in the call chain and log all the
 intermediate values

---
 .../webui/services/impl/SaltSSHService.java   | 44 ++++++++++++++-----
 1 file changed, 34 insertions(+), 10 deletions(-)
#L3PD: bsc#1237536

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..9a25143da88 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,17 +392,42 @@ 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());
+        LOG.info("Sorted proxyPaths: {}", serverPaths);
+        List<String> hostnamePath = proxyPath.stream()
+            .filter(Objects::nonNull)
+            .map(path -> {
+                StringBuilder sb = new StringBuilder();
+                sb.append(path);
+
+                // Chain the call logging all values, to see where we have the null
+                String port = Optional.of(path)
+                    .map(serverPath -> logAndReturn(serverPath, ServerPath::getId, sb))
+                    .map(serverPathId -> logAndReturn(serverPathId, ServerPathId::getProxyServer, sb))
+                    .map(server -> logAndReturn(server, Server::getProxyInfo, sb))
+                    .map(proxyInfo -> logAndReturn(proxyInfo, ProxyInfo::getSshPort, sb))
+                    .map(p -> ":" + p)
+                    .orElse("");
+
+                String finalHostname = path.getHostname() + port;
+
+                LOG.info("ServerPath chain: {}", sb);
+                LOG.info("Hostname: {}", finalHostname);
+
+                return finalHostname;
+            }).collect(Collectors.toList());
 
         lastProxy.ifPresent(hostnamePath::add);
 
+        LOG.info("Final hostnamePath {}", hostnamePath);
         return hostnamePath;
     }
 
+    private static <T, U> T logAndReturn(U value, Function<U, T> mapper, StringBuilder logBuilder) {
+        T result = mapper.apply(value);
+        logBuilder.append(" / ").append(result);
+        return result;
+    }
+
     private static List<ServerPath> sortServerPaths(Set<ServerPath> serverPaths) {
         if (CollectionUtils.isEmpty(serverPaths)) {
             return new ArrayList<>();
