Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,14 @@ public List<ProcessProfile> getNodeNetworkAndLogInfo(JsonNode nodesInfo) {
}
}
if (notLoopBack) {
addr = addr.substring(0, addr.indexOf(":"));
if (addr.startsWith("[")) {
// IPv6 bracket notation: [address]:port → strip port and brackets
int closingBracket = addr.indexOf("]");
addr = addr.substring(1, closingBracket);
} else {
// IPv4: address:port → strip port
addr = addr.substring(0, addr.indexOf(":"));
}
diagNode.boundAddresses.add(addr);
}
}
Expand Down Expand Up @@ -350,6 +357,20 @@ private ProcessProfile findTargetNode(Set<String> localAddrs, List<ProcessProfil
}
}

// Fallback: boundAddresses may be empty (field absent in older ES versions, or all-loopback)
// or may contain wildcards (0.0.0.0) that never match a specific IP.
// Try matching directly against the node's reported ip and httpPublishAddr.
for (String localAddr : localAddrs) {
for (ProcessProfile node : nodeAddrs) {
if (localAddr.equals(node.ip) || localAddr.equals(node.httpPublishAddr)) {
logger.warn(Constants.CONSOLE,
"Matched node '{}' via ip/httpPublishAddr fallback (boundAddresses did not match).",
node.name);
return node;
}
}
}

// If we got this far and came up empty, signal our displeasure
logger.error("Comparison did not result in an IP or Host match. {} {}", localAddrs, nodeAddrs);
throw new RuntimeException("Could not find the target node.");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
package co.elastic.support.diagnostics.commands;

import co.elastic.support.diagnostics.ProcessProfile;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Set;

import static org.junit.jupiter.api.Assertions.*;

class CheckPlatformDetailsTest {

private CheckPlatformDetails checker;

@BeforeEach
void setUp() {
checker = new CheckPlatformDetails();
}

// -----------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------

private ProcessProfile makeNode(String name, String ip, String httpPublishAddr,
Set<String> boundAddresses) {
ProcessProfile p = new ProcessProfile();
p.name = name;
p.ip = ip;
p.host = ip;
p.httpPublishAddr = httpPublishAddr;
p.boundAddresses = boundAddresses;
return p;
}

// -----------------------------------------------------------------------
// findLocalTargetNode — loopback input uses NIC-based matching
// -----------------------------------------------------------------------

/** When the input host is a loopback address the code must fall through
* to NIC scanning; with our fallback it should still find the node via ip. */
@Test
void loopbackInput_fallsBackToNicScan_matchesViaIp() {
// Simulate node whose ip matches what getNetworkInterfaces() would return
// We can't mock the real NIC scan, so we exercise findLocalTargetNode with
// a non-loopback host that equals the node ip directly.
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
Comment on lines +53 to +54

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61", new HashSet<>());

// Non-loopback host that equals the node ip → added to localNetworkInterfaces
ProcessProfile result = checker.findLocalTargetNode("172.16.1.61", List.of(node));
assertNotNull(result);
assertEquals("NTG-PRO-ELA-01", result.name);
}

// -----------------------------------------------------------------------
// findTargetNode — primary: boundAddresses match
// -----------------------------------------------------------------------

@Test
void matchViaBoundAddresses_returnsCorrectNode() {
ProcessProfile node1 = makeNode("node-1", "10.0.0.1", "10.0.0.1",
new java.util.HashSet<>(Set.of("10.0.0.1")));
ProcessProfile node2 = makeNode("node-2", "10.0.0.2", "10.0.0.2",
new java.util.HashSet<>(Set.of("10.0.0.2")));
Comment on lines +67 to +70

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile node1 = makeNode("node-1", "10.0.0.1", "10.0.0.1",
new java.util.HashSet<>(Set.of("10.0.0.1")));
ProcessProfile node2 = makeNode("node-2", "10.0.0.2", "10.0.0.2",
new java.util.HashSet<>(Set.of("10.0.0.2")));
ProcessProfile node1 = makeNode("node-1", "10.0.0.1", "10.0.0.1", new HashSet<>(Set.of("10.0.0.1")));
ProcessProfile node2 = makeNode("node-2", "10.0.0.2", "10.0.0.2", new HashSet<>(Set.of("10.0.0.2")));


ProcessProfile result = checker.findLocalTargetNode("10.0.0.2", List.of(node1, node2));
assertEquals("node-2", result.name);
}

// -----------------------------------------------------------------------
// findTargetNode — fallback: boundAddresses empty, match via node.ip
// -----------------------------------------------------------------------

@Test
void emptyBoundAddresses_matchViaIpFallback() {
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
Comment on lines +82 to +83

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61", new HashSet<>());


ProcessProfile result = checker.findLocalTargetNode("172.16.1.61", List.of(node));
assertNotNull(result);
assertEquals("NTG-PRO-ELA-01", result.name);
}

@Test
void emptyBoundAddresses_matchViaHttpPublishAddrFallback() {
// ip and httpPublishAddr differ (NAT / publish_host override scenario)
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "10.0.0.5", "172.16.1.61",
new java.util.HashSet<>());
Comment on lines +93 to +94

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "10.0.0.5", "172.16.1.61",
new java.util.HashSet<>());
ProcessProfile node = makeNode("NTG-PRO-ELA-01", "10.0.0.5", "172.16.1.61", new HashSet<>());


// local address matches httpPublishAddr, not ip
ProcessProfile result = checker.findLocalTargetNode("172.16.1.61", List.of(node));
assertNotNull(result);
assertEquals("NTG-PRO-ELA-01", result.name);
}

// -----------------------------------------------------------------------
// findTargetNode — multiple nodes, only one matches (mirrors the bug report)
// -----------------------------------------------------------------------

@Test
void multipleNodes_emptyBoundAddresses_returnsCorrectOne() {
ProcessProfile ela01 = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
ProcessProfile ela02 = makeNode("NTG-PRO-ELA-02", "172.16.1.62", "172.16.1.62",
new java.util.HashSet<>());
ProcessProfile ela03 = makeNode("NTG-PRO-ELA-03", "172.16.1.63", "172.16.1.63",
new java.util.HashSet<>());
ProcessProfile ela04 = makeNode("NTG-PRO-ELA-04", "172.16.1.64", "172.16.1.64",
new java.util.HashSet<>());
Comment on lines +108 to +115

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile ela01 = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61",
new java.util.HashSet<>());
ProcessProfile ela02 = makeNode("NTG-PRO-ELA-02", "172.16.1.62", "172.16.1.62",
new java.util.HashSet<>());
ProcessProfile ela03 = makeNode("NTG-PRO-ELA-03", "172.16.1.63", "172.16.1.63",
new java.util.HashSet<>());
ProcessProfile ela04 = makeNode("NTG-PRO-ELA-04", "172.16.1.64", "172.16.1.64",
new java.util.HashSet<>());
ProcessProfile ela01 = makeNode("NTG-PRO-ELA-01", "172.16.1.61", "172.16.1.61", new HashSet<>());
ProcessProfile ela02 = makeNode("NTG-PRO-ELA-02", "172.16.1.62", "172.16.1.62", new HashSet<>());
ProcessProfile ela03 = makeNode("NTG-PRO-ELA-03", "172.16.1.63", "172.16.1.63", new HashSet<>());
ProcessProfile ela04 = makeNode("NTG-PRO-ELA-04", "172.16.1.64", "172.16.1.64", new HashSet<>());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


// The local machine is NTG-PRO-ELA-01 (172.16.1.61)
ProcessProfile result = checker.findLocalTargetNode("172.16.1.61",
List.of(ela01, ela02, ela03, ela04));
Comment on lines +118 to +119

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile result = checker.findLocalTargetNode("172.16.1.61",
List.of(ela01, ela02, ela03, ela04));
ProcessProfile result = checker.findLocalTargetNode("172.16.1.61", List.of(ela01, ela02, ela03, ela04));

assertNotNull(result);
assertEquals("NTG-PRO-ELA-01", result.name);
}

// -----------------------------------------------------------------------
// findTargetNode — no match throws RuntimeException
// -----------------------------------------------------------------------

@Test
void noMatch_throwsRuntimeException() {
ProcessProfile node = makeNode("node-1", "10.0.0.1", "10.0.0.1",
new java.util.HashSet<>());
Comment on lines +130 to +131

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessProfile node = makeNode("node-1", "10.0.0.1", "10.0.0.1",
new java.util.HashSet<>());
ProcessProfile node = makeNode("node-1", "10.0.0.1", "10.0.0.1", new HashSet<>());


assertThrows(RuntimeException.class,
() -> checker.findLocalTargetNode("192.168.99.99", List.of(node)));
}
}
Loading