in src/main/java/co/elastic/support/diagnostics/commands/CheckPlatformDetails.java [37:191]
public void execute(DiagnosticContext context) {
try {
// Cached from previous executions
RestClient restClient = context.resourceCache.getRestClient(Constants.restInputHost);
// Populate the node metadata
Map<String, RestEntry> calls = context.fullElasticRestCalls;
RestEntry entry = calls.get("nodes");
String url = entry.getUrl().replace("?human", "/os,process,settings,transport,http?human");
RestResult result = restClient.execQuery(url);
// Initialize to empty node which mimimizes NPE opportunities
JsonNode infoNodes = JsonYamlUtils.mapper.createObjectNode();
if (result.getStatus() == 200) {
infoNodes = JsonYamlUtils.createJsonNodeFromString(result.toString());
}
context.clusterName = infoNodes.path("cluster_name").asText();
List<ProcessProfile> nodeProfiles = getNodeNetworkAndLogInfo(infoNodes);
// See if this cluster is dockerized - if so, don't bother checking for a master
// to go to
// because the port information in its output is not reliable.
for (ProcessProfile profile : nodeProfiles) {
if (profile.isDocker) {
context.dockerPresent = true;
break;
}
}
// Removed temporarily until I put in an option to bypass this feature due to
// issue where master was inaccessible via http from another node even though it
// had http configured.
/*
* if (!context.dockerPresent) {
* // Get the master node id and flag the master node profile
* entry = calls.get("master");
* result = restClient.execQuery(entry.getUrl());
* JsonNode currentMaster = JsonYamlUtils.mapper.createObjectNode();
* if (result.getStatus() == 200) {
* // Strip off the array brackets since there's only one at each end
* String mod = result.toString();
* mod = mod.substring(1, (mod.length() - 1));
* currentMaster = JsonYamlUtils.createJsonNodeFromString(mod);
* }
* String currentMasterId = currentMaster.path("id").asText();
* ProcessProfile masterNode = findMasterNode(currentMasterId, nodeProfiles);
*
* // If the master node has an http listener configured then we'll use that for
* the
* // REST calls. Set up a rest client and add it to the resources.
* if (differentInstances(context.diagnosticInputs.host,
* context.diagnosticInputs.port, masterNode.host, masterNode.httpPort) &&
* masterNode.isHttp) {
* RestClient masterRestClient = RestClient.getClient(
* masterNode.host,
* masterNode.httpPort,
* context.diagnosticInputs.scheme,
* context.diagnosticInputs.user,
* context.diagnosticInputs.password,
* context.diagnosticInputs.proxyHost,
* context.diagnosticInputs.proxyPort,
* context.diagnosticInputs.proxyUser,
* context.diagnosticInputs.proxyPassword,
* context.diagnosticInputs.pkiKeystore,
* context.diagnosticInputs.pkiKeystorePass,
* context.diagnosticInputs.skipVerification,
* context.diagsConfig.connectionTimeout,
* context.diagsConfig.connectionRequestTimeout,
* context.diagsConfig.socketTimeout);
*
* ResourceCache.addRestClient(Constants.restTargetHost, masterRestClient);
* }
* }
*/
SystemCommand syscmd = null;
switch (context.diagnosticInputs.diagType) {
case Constants.remote:
// If Docker containers flag it for no syscalls or logs
String targetOS;
if (context.dockerPresent) {
context.runSystemCalls = false;
// We really don't have any way of really knowing
// what the enclosing platform is. So this may fail...
logger.warn(Constants.CONSOLE,
"Docker containers detected on remote platform - unable to determine host OS. Linux will be used but if another operating system is present the Docker diagnostic calls may fail.");
targetOS = Constants.linuxPlatform;
// break;
} else {
// check for input host in bound addresses
context.targetNode = findRemoteTargetNode(
context.diagnosticInputs.host, nodeProfiles);
targetOS = context.targetNode.os;
}
syscmd = new RemoteSystem(
targetOS,
context.diagnosticInputs.remoteUser,
context.diagnosticInputs.remotePassword,
context.diagnosticInputs.host,
context.diagnosticInputs.remotePort,
context.diagnosticInputs.keyfile,
context.diagnosticInputs.keyfilePassword,
context.diagnosticInputs.knownHostsFile,
context.diagnosticInputs.trustRemote,
context.diagnosticInputs.isSudo);
context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);
break;
case Constants.local:
if (context.dockerPresent) {
context.runSystemCalls = false;
// We do need a system command local to run the docker calls
syscmd = new LocalSystem(SystemUtils.parseOperatingSystemName(SystemProperties.osName));
context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);
break;
}
// Find out which node we're going to obtain logs and system commands from.
// First check: if it's a one node cluster, we're done.
if (nodeProfiles.size() == 1) {
context.targetNode = nodeProfiles.get(0);
}
// check against the local network interfaces
context.targetNode = findLocalTargetNode(
context.diagnosticInputs.host, nodeProfiles);
syscmd = new LocalSystem(context.targetNode.os);
context.resourceCache.addSystemCommand(Constants.systemCommands, syscmd);
break;
default:
// If it's not one of the above types it shouldn't be here but try to keep
// going...
context.runSystemCalls = false;
logger.warn(Constants.CONSOLE,
"Error occurred checking the network hosts information. Bypassing system calls.");
throw new RuntimeException("Host/Platform check error.");
}
} catch (Exception e) {
// Try to keep going even if this didn't work.
logger.error(Constants.CONSOLE, "Error: {}", e.getMessage());
logger.error("Error checking node metadata and deployment info.", e);
context.runSystemCalls = false;
}
}